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 ; 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 - list - 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 . t - 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 PetscAssertPointer(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()`, `PetscStrcmp()` 327 @*/ 328 PetscErrorCode PetscStrendswithwhich(const char a[], const char *const *bs, PetscInt *cnt) 329 { 330 PetscFunctionBegin; 331 PetscAssertPointer(bs, 2); 332 PetscAssertPointer(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 PetscAssertPointer(a, 1); 380 PetscAssertPointer(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 + a - 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 PetscAssertPointer(a, 1); 432 PetscAssertPointer(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 PetscAssertPointer(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 .seealso: `PetscGetArchType()` 509 @*/ 510 PetscErrorCode PetscGetPetscDir(const char *dir[]) 511 { 512 PetscFunctionBegin; 513 PetscAssertPointer(dir, 1); 514 *dir = PETSC_DIR; 515 PetscFunctionReturn(PETSC_SUCCESS); 516 } 517 518 /*@C 519 PetscStrreplace - Replaces substrings in string with other substrings 520 521 Not Collective; No Fortran Support 522 523 Input Parameters: 524 + comm - `MPI_Comm` of processors that are processing the string 525 . aa - the string to look in 526 . b - the resulting copy of a with replaced strings (`b` can be the same as `a`) 527 - len - the length of `b` 528 529 Level: developer 530 531 Notes: 532 Replaces ${PETSC_ARCH},${PETSC_DIR},${PETSC_LIB_DIR},${DISPLAY}, 533 ${HOMEDIRECTORY},${WORKINGDIRECTORY},${USERNAME}, ${HOSTNAME}, ${PETSC_MAKE} with appropriate values 534 as well as any environmental variables. 535 536 `PETSC_LIB_DIR` uses the environmental variable if it exists. `PETSC_ARCH` and `PETSC_DIR` use what 537 PETSc was built with and do not use environmental variables. 538 539 .seealso: `PetscStrcmp()` 540 @*/ 541 PetscErrorCode PetscStrreplace(MPI_Comm comm, const char aa[], char b[], size_t len) 542 { 543 int i = 0; 544 size_t l, l1, l2, l3; 545 char *work, *par, *epar = NULL, env[1024], *tfree, *a = (char *)aa; 546 const char *s[] = {"${PETSC_ARCH}", "${PETSC_DIR}", "${PETSC_LIB_DIR}", "${DISPLAY}", "${HOMEDIRECTORY}", "${WORKINGDIRECTORY}", "${USERNAME}", "${HOSTNAME}", "${PETSC_MAKE}", NULL}; 547 char *r[] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}; 548 PetscBool flag; 549 static size_t DISPLAY_LENGTH = 265, USER_LENGTH = 256, HOST_LENGTH = 256; 550 551 PetscFunctionBegin; 552 PetscAssertPointer(aa, 2); 553 PetscAssertPointer(b, 3); 554 if (aa == b) PetscCall(PetscStrallocpy(aa, (char **)&a)); 555 PetscCall(PetscMalloc1(len, &work)); 556 557 /* get values for replaced variables */ 558 PetscCall(PetscStrallocpy(PETSC_ARCH, &r[0])); 559 PetscCall(PetscStrallocpy(PETSC_DIR, &r[1])); 560 PetscCall(PetscStrallocpy(PETSC_LIB_DIR, &r[2])); 561 PetscCall(PetscMalloc1(DISPLAY_LENGTH, &r[3])); 562 PetscCall(PetscMalloc1(PETSC_MAX_PATH_LEN, &r[4])); 563 PetscCall(PetscMalloc1(PETSC_MAX_PATH_LEN, &r[5])); 564 PetscCall(PetscMalloc1(USER_LENGTH, &r[6])); 565 PetscCall(PetscMalloc1(HOST_LENGTH, &r[7])); 566 PetscCall(PetscGetDisplay(r[3], DISPLAY_LENGTH)); 567 PetscCall(PetscGetHomeDirectory(r[4], PETSC_MAX_PATH_LEN)); 568 PetscCall(PetscGetWorkingDirectory(r[5], PETSC_MAX_PATH_LEN)); 569 PetscCall(PetscGetUserName(r[6], USER_LENGTH)); 570 PetscCall(PetscGetHostName(r[7], HOST_LENGTH)); 571 PetscCall(PetscStrallocpy(PETSC_OMAKE, &r[8])); 572 573 /* replace that are in environment */ 574 PetscCall(PetscOptionsGetenv(comm, "PETSC_LIB_DIR", env, sizeof(env), &flag)); 575 if (flag) { 576 PetscCall(PetscFree(r[2])); 577 PetscCall(PetscStrallocpy(env, &r[2])); 578 } 579 580 /* replace the requested strings */ 581 PetscCall(PetscStrncpy(b, a, len)); 582 while (s[i]) { 583 PetscCall(PetscStrlen(s[i], &l)); 584 PetscCall(PetscStrstr(b, s[i], &par)); 585 while (par) { 586 *par = 0; 587 par += l; 588 589 PetscCall(PetscStrlen(b, &l1)); 590 PetscCall(PetscStrlen(r[i], &l2)); 591 PetscCall(PetscStrlen(par, &l3)); 592 PetscCheck(l1 + l2 + l3 < len, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "b len is not long enough to hold new values"); 593 PetscCall(PetscStrncpy(work, b, len)); 594 PetscCall(PetscStrlcat(work, r[i], len)); 595 PetscCall(PetscStrlcat(work, par, len)); 596 PetscCall(PetscStrncpy(b, work, len)); 597 PetscCall(PetscStrstr(b, s[i], &par)); 598 } 599 i++; 600 } 601 i = 0; 602 while (r[i]) { 603 tfree = (char *)r[i]; 604 PetscCall(PetscFree(tfree)); 605 i++; 606 } 607 608 /* look for any other ${xxx} strings to replace from environmental variables */ 609 PetscCall(PetscStrstr(b, "${", &par)); 610 while (par) { 611 *par = 0; 612 par += 2; 613 PetscCall(PetscStrncpy(work, b, len)); 614 PetscCall(PetscStrstr(par, "}", &epar)); 615 *epar = 0; 616 epar += 1; 617 PetscCall(PetscOptionsGetenv(comm, par, env, sizeof(env), &flag)); 618 PetscCheck(flag, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Substitution string ${%s} not found as environmental variable", par); 619 PetscCall(PetscStrlcat(work, env, len)); 620 PetscCall(PetscStrlcat(work, epar, len)); 621 PetscCall(PetscStrncpy(b, work, len)); 622 PetscCall(PetscStrstr(b, "${", &par)); 623 } 624 PetscCall(PetscFree(work)); 625 if (aa == b) PetscCall(PetscFree(a)); 626 PetscFunctionReturn(PETSC_SUCCESS); 627 } 628 629 /*@C 630 PetscStrcmpAny - Determines whether a string matches any of a list of strings. 631 632 Not Collective 633 634 Input Parameters: 635 + src - pointer to input the string 636 - cmp - list of non-null and non-empty strings to be compared against, pass the empty string "" to terminate the list 637 638 Output Parameter: 639 . match - `PETSC_TRUE` if the input string matches any in the list, else `PETSC_FALSE` 640 641 Level: intermediate 642 643 .seealso: `PetscStrcmp()` 644 @*/ 645 PetscErrorCode PetscStrcmpAny(const char src[], PetscBool *match, const char cmp[], ...) 646 { 647 va_list Argp; 648 649 PetscFunctionBegin; 650 PetscAssertPointer(match, 2); 651 *match = PETSC_FALSE; 652 if (!src) PetscFunctionReturn(PETSC_SUCCESS); 653 va_start(Argp, cmp); 654 while (cmp && cmp[0]) { 655 PetscBool found; 656 PetscCall(PetscStrcmp(src, cmp, &found)); 657 if (found) { 658 *match = PETSC_TRUE; 659 break; 660 } 661 cmp = va_arg(Argp, const char *); 662 } 663 va_end(Argp); 664 PetscFunctionReturn(PETSC_SUCCESS); 665 } 666 667 /*@C 668 PetscEListFind - searches list of strings for given string, using case insensitive matching 669 670 Not Collective; No Fortran Support 671 672 Input Parameters: 673 + n - number of strings in 674 . list - list of strings to search 675 - str - string to look for, empty string "" accepts default (first entry in list) 676 677 Output Parameters: 678 + value - index of matching string (if found) 679 - found - boolean indicating whether string was found (can be `NULL`) 680 681 Level: developer 682 683 .seealso: `PetscEnumFind()` 684 @*/ 685 PetscErrorCode PetscEListFind(PetscInt n, const char *const *list, const char *str, PetscInt *value, PetscBool *found) 686 { 687 PetscFunctionBegin; 688 if (found) { 689 PetscAssertPointer(found, 5); 690 *found = PETSC_FALSE; 691 } 692 for (PetscInt i = 0; i < n; ++i) { 693 PetscBool matched; 694 695 PetscCall(PetscStrcasecmp(str, list[i], &matched)); 696 if (matched || !str[0]) { 697 if (found) *found = PETSC_TRUE; 698 *value = i; 699 break; 700 } 701 } 702 PetscFunctionReturn(PETSC_SUCCESS); 703 } 704 705 /*@C 706 PetscEnumFind - searches enum list of strings for given string, using case insensitive matching 707 708 Not Collective; No Fortran Support 709 710 Input Parameters: 711 + enumlist - list of strings to search, followed by enum name, then enum prefix, then `NULL` 712 - str - string to look for 713 714 Output Parameters: 715 + value - index of matching string (if found) 716 - found - boolean indicating whether string was found (can be `NULL`) 717 718 Level: advanced 719 720 .seealso: `PetscEListFind()` 721 @*/ 722 PetscErrorCode PetscEnumFind(const char *const *enumlist, const char *str, PetscEnum *value, PetscBool *found) 723 { 724 PetscInt n = 0, evalue; 725 PetscBool efound; 726 727 PetscFunctionBegin; 728 PetscAssertPointer(enumlist, 1); 729 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"); 730 PetscCheck(n >= 3, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "List argument must have at least two entries: typename and type prefix"); 731 n -= 3; /* drop enum name, prefix, and null termination */ 732 PetscCall(PetscEListFind(n, enumlist, str, &evalue, &efound)); 733 if (efound) { 734 PetscAssertPointer(value, 3); 735 *value = (PetscEnum)evalue; 736 } 737 if (found) { 738 PetscAssertPointer(found, 4); 739 *found = efound; 740 } 741 PetscFunctionReturn(PETSC_SUCCESS); 742 } 743 744 /*@C 745 PetscCIFilename - returns the basename of a file name when the PETSc CI portable error output mode is enabled. 746 747 Not Collective; No Fortran Support 748 749 Input Parameter: 750 . file - the file name 751 752 Level: developer 753 754 Note: 755 PETSc CI mode is a mode of running PETSc where output (both error and non-error) is made portable across all systems 756 so that comparisons of output between runs are easy to make. 757 758 This mode is used for all tests in the test harness, it applies to both debug and optimized builds. 759 760 Use the option `-petsc_ci` to turn on PETSc CI mode. It changes certain output in non-error situations to be portable for 761 all systems, mainly the output of options. It is passed to all PETSc programs automatically by the test harness. 762 763 Always uses the Unix / as the file separate even on Microsoft Windows systems 764 765 The option `-petsc_ci_portable_error_output` attempts to output the same error messages on all systems for the test harness. 766 In particular the output of filenames and line numbers in PETSc stacks. This is to allow (limited) checking of PETSc 767 error handling by the test harness. This options also causes PETSc to attempt to return an error code of 0 so that the test 768 harness can process the output for differences in the usual manner as for successful runs. It should be provided to the test 769 harness in the args: argument for specific examples. It will not necessarily produce portable output if different errors 770 (or no errors) occur on a subset of the MPI ranks. 771 772 .seealso: `PetscCILinenumber()` 773 @*/ 774 const char *PetscCIFilename(const char *file) 775 { 776 if (!PetscCIEnabledPortableErrorOutput) return file; 777 return PetscBasename(file); 778 } 779 780 /*@C 781 PetscCILinenumber - returns a line number except if `PetscCIEnablePortableErrorOutput` is set when it returns 0 782 783 Not Collective; No Fortran Support 784 785 Input Parameter: 786 . linenumber - the initial line number 787 788 Level: developer 789 790 Note: 791 See `PetscCIFilename()` for details on usage 792 793 .seealso: `PetscCIFilename()` 794 @*/ 795 int PetscCILinenumber(int linenumber) 796 { 797 if (!PetscCIEnabledPortableErrorOutput) return linenumber; 798 return 0; 799 } 800 801 /*@C 802 PetscStrcat - Concatenates a string onto a given string 803 804 Not Collective, No Fortran Support 805 806 Input Parameters: 807 + s - string to be added to 808 - t - pointer to string to be added to end 809 810 Level: deprecated (since 3.18.5) 811 812 Notes: 813 It is recommended you use `PetscStrlcat()` instead of this routine. 814 815 .seealso: `PetscStrlcat()` 816 @*/ 817 PetscErrorCode PetscStrcat(char s[], const char t[]) 818 { 819 PetscFunctionBegin; 820 if (!t) PetscFunctionReturn(PETSC_SUCCESS); 821 PetscAssertPointer(s, 1); 822 strcat(s, t); 823 PetscFunctionReturn(PETSC_SUCCESS); 824 } 825 826 /*@C 827 PetscStrcpy - Copies a string 828 829 Not Collective, No Fortran Support 830 831 Input Parameter: 832 . t - pointer to string 833 834 Output Parameter: 835 . s - the copied string 836 837 Level: deprecated (since 3.18.5) 838 839 Notes: 840 It is recommended you use `PetscStrncpy()` (equivalently `PetscArraycpy()` or 841 `PetscMemcpy()`) instead of this routine. 842 843 `NULL` strings returns a string starting with zero. 844 845 .seealso: `PetscStrncpy()` 846 @*/ 847 PetscErrorCode PetscStrcpy(char s[], const char t[]) 848 { 849 PetscFunctionBegin; 850 if (t) { 851 PetscAssertPointer(s, 1); 852 PetscAssertPointer(t, 2); 853 strcpy(s, t); 854 } else if (s) { 855 s[0] = '\0'; 856 } 857 PetscFunctionReturn(PETSC_SUCCESS); 858 } 859