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 _n_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 Do not change or free the value of `result` 374 375 .seealso: `PetscToken`, `PetscTokenCreate()`, `PetscTokenDestroy()` 376 @*/ 377 PetscErrorCode PetscTokenFind(PetscToken a, const char *result[]) 378 { 379 char *ptr, token; 380 381 PetscFunctionBegin; 382 PetscAssertPointer(a, 1); 383 PetscAssertPointer(result, 2); 384 *result = ptr = a->current; 385 if (ptr && !*ptr) { 386 *result = NULL; 387 PetscFunctionReturn(PETSC_SUCCESS); 388 } 389 token = a->token; 390 if (ptr && (*ptr == '"')) { 391 token = '"'; 392 (*result)++; 393 ptr++; 394 } 395 while (ptr) { 396 if (*ptr == token) { 397 *ptr++ = 0; 398 while (*ptr == a->token) ptr++; 399 a->current = ptr; 400 break; 401 } 402 if (!*ptr) { 403 a->current = NULL; 404 break; 405 } 406 ptr++; 407 } 408 PetscFunctionReturn(PETSC_SUCCESS); 409 } 410 411 /*@C 412 PetscTokenCreate - Creates a `PetscToken` used to find tokens in a string 413 414 Not Collective; No Fortran Support 415 416 Input Parameters: 417 + a - the string to look in 418 - b - the separator character 419 420 Output Parameter: 421 . t - the token object 422 423 Level: intermediate 424 425 Note: 426 This version is different from the system version in that 427 it allows you to pass a read-only string into the function. 428 429 .seealso: `PetscToken`, `PetscTokenFind()`, `PetscTokenDestroy()` 430 @*/ 431 PetscErrorCode PetscTokenCreate(const char a[], char b, PetscToken *t) 432 { 433 PetscFunctionBegin; 434 PetscAssertPointer(a, 1); 435 PetscAssertPointer(t, 3); 436 PetscCall(PetscNew(t)); 437 PetscCall(PetscStrallocpy(a, &(*t)->array)); 438 439 (*t)->current = (*t)->array; 440 (*t)->token = b; 441 PetscFunctionReturn(PETSC_SUCCESS); 442 } 443 444 /*@C 445 PetscTokenDestroy - Destroys a `PetscToken` 446 447 Not Collective; No Fortran Support 448 449 Input Parameter: 450 . a - pointer to token 451 452 Level: intermediate 453 454 .seealso: `PetscToken`, `PetscTokenCreate()`, `PetscTokenFind()` 455 @*/ 456 PetscErrorCode PetscTokenDestroy(PetscToken *a) 457 { 458 PetscFunctionBegin; 459 if (!*a) PetscFunctionReturn(PETSC_SUCCESS); 460 PetscCall(PetscFree((*a)->array)); 461 PetscCall(PetscFree(*a)); 462 PetscFunctionReturn(PETSC_SUCCESS); 463 } 464 465 /*@C 466 PetscStrInList - search for a string in character-delimited list 467 468 Not Collective; No Fortran Support 469 470 Input Parameters: 471 + str - the string to look for 472 . list - the list to search in 473 - sep - the separator character 474 475 Output Parameter: 476 . found - whether `str` is in `list` 477 478 Level: intermediate 479 480 .seealso: `PetscTokenCreate()`, `PetscTokenFind()`, `PetscStrcmp()` 481 @*/ 482 PetscErrorCode PetscStrInList(const char str[], const char list[], char sep, PetscBool *found) 483 { 484 PetscToken token; 485 const char *item; 486 487 PetscFunctionBegin; 488 PetscAssertPointer(found, 4); 489 *found = PETSC_FALSE; 490 PetscCall(PetscTokenCreate(list, sep, &token)); 491 PetscCall(PetscTokenFind(token, &item)); 492 while (item) { 493 PetscCall(PetscStrcmp(str, item, found)); 494 if (*found) break; 495 PetscCall(PetscTokenFind(token, &item)); 496 } 497 PetscCall(PetscTokenDestroy(&token)); 498 PetscFunctionReturn(PETSC_SUCCESS); 499 } 500 501 /*@C 502 PetscGetPetscDir - Gets the directory PETSc is installed in 503 504 Not Collective; No Fortran Support 505 506 Output Parameter: 507 . dir - the directory 508 509 Level: developer 510 511 .seealso: `PetscGetArchType()` 512 @*/ 513 PetscErrorCode PetscGetPetscDir(const char *dir[]) 514 { 515 PetscFunctionBegin; 516 PetscAssertPointer(dir, 1); 517 *dir = PETSC_DIR; 518 PetscFunctionReturn(PETSC_SUCCESS); 519 } 520 521 /*@C 522 PetscStrreplace - Replaces substrings in string with other substrings 523 524 Not Collective; No Fortran Support 525 526 Input Parameters: 527 + comm - `MPI_Comm` of processors that are processing the string 528 . aa - the string to look in 529 . b - the resulting copy of a with replaced strings (`b` can be the same as `a`) 530 - len - the length of `b` 531 532 Level: developer 533 534 Notes: 535 Replaces 536 .vb 537 ${PETSC_ARCH}, ${PETSC_DIR}, ${PETSC_LIB_DIR}, ${DISPLAY}, 538 ${HOMEDIRECTORY}, ${WORKINGDIRECTORY}, ${USERNAME}, ${HOSTNAME}, ${PETSC_MAKE} 539 .ve 540 with appropriate values as well as any environmental variables. 541 542 `PETSC_LIB_DIR` uses the environmental variable if it exists. `PETSC_ARCH` and `PETSC_DIR` use what 543 PETSc was built with and do not use environmental variables. 544 545 .seealso: `PetscStrcmp()` 546 @*/ 547 PetscErrorCode PetscStrreplace(MPI_Comm comm, const char aa[], char b[], size_t len) 548 { 549 int i = 0; 550 size_t l, l1, l2, l3; 551 char *work, *par, *epar = NULL, env[1024], *tfree, *a = (char *)aa; 552 const char *s[] = {"${PETSC_ARCH}", "${PETSC_DIR}", "${PETSC_LIB_DIR}", "${DISPLAY}", "${HOMEDIRECTORY}", "${WORKINGDIRECTORY}", "${USERNAME}", "${HOSTNAME}", "${PETSC_MAKE}", NULL}; 553 char *r[] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}; 554 PetscBool flag; 555 static size_t DISPLAY_LENGTH = 265, USER_LENGTH = 256, HOST_LENGTH = 256; 556 557 PetscFunctionBegin; 558 PetscAssertPointer(aa, 2); 559 PetscAssertPointer(b, 3); 560 if (aa == b) PetscCall(PetscStrallocpy(aa, &a)); 561 PetscCall(PetscMalloc1(len, &work)); 562 563 /* get values for replaced variables */ 564 PetscCall(PetscStrallocpy(PETSC_ARCH, &r[0])); 565 PetscCall(PetscStrallocpy(PETSC_DIR, &r[1])); 566 PetscCall(PetscStrallocpy(PETSC_LIB_DIR, &r[2])); 567 PetscCall(PetscMalloc1(DISPLAY_LENGTH, &r[3])); 568 PetscCall(PetscMalloc1(PETSC_MAX_PATH_LEN, &r[4])); 569 PetscCall(PetscMalloc1(PETSC_MAX_PATH_LEN, &r[5])); 570 PetscCall(PetscMalloc1(USER_LENGTH, &r[6])); 571 PetscCall(PetscMalloc1(HOST_LENGTH, &r[7])); 572 PetscCall(PetscGetDisplay(r[3], DISPLAY_LENGTH)); 573 PetscCall(PetscGetHomeDirectory(r[4], PETSC_MAX_PATH_LEN)); 574 PetscCall(PetscGetWorkingDirectory(r[5], PETSC_MAX_PATH_LEN)); 575 PetscCall(PetscGetUserName(r[6], USER_LENGTH)); 576 PetscCall(PetscGetHostName(r[7], HOST_LENGTH)); 577 PetscCall(PetscStrallocpy(PETSC_OMAKE, &r[8])); 578 579 /* replace that are in environment */ 580 PetscCall(PetscOptionsGetenv(comm, "PETSC_LIB_DIR", env, sizeof(env), &flag)); 581 if (flag) { 582 PetscCall(PetscFree(r[2])); 583 PetscCall(PetscStrallocpy(env, &r[2])); 584 } 585 586 /* replace the requested strings */ 587 PetscCall(PetscStrncpy(b, a, len)); 588 while (s[i]) { 589 PetscCall(PetscStrlen(s[i], &l)); 590 PetscCall(PetscStrstr(b, s[i], &par)); 591 while (par) { 592 *par = 0; 593 par += l; 594 595 PetscCall(PetscStrlen(b, &l1)); 596 PetscCall(PetscStrlen(r[i], &l2)); 597 PetscCall(PetscStrlen(par, &l3)); 598 PetscCheck(l1 + l2 + l3 < len, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "b len is not long enough to hold new values"); 599 PetscCall(PetscStrncpy(work, b, len)); 600 PetscCall(PetscStrlcat(work, r[i], len)); 601 PetscCall(PetscStrlcat(work, par, len)); 602 PetscCall(PetscStrncpy(b, work, len)); 603 PetscCall(PetscStrstr(b, s[i], &par)); 604 } 605 i++; 606 } 607 i = 0; 608 while (r[i]) { 609 tfree = r[i]; 610 PetscCall(PetscFree(tfree)); 611 i++; 612 } 613 614 /* look for any other ${xxx} strings to replace from environmental variables */ 615 PetscCall(PetscStrstr(b, "${", &par)); 616 while (par) { 617 *par = 0; 618 par += 2; 619 PetscCall(PetscStrncpy(work, b, len)); 620 PetscCall(PetscStrstr(par, "}", &epar)); 621 *epar = 0; 622 epar += 1; 623 PetscCall(PetscOptionsGetenv(comm, par, env, sizeof(env), &flag)); 624 PetscCheck(flag, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Substitution string ${%s} not found as environmental variable", par); 625 PetscCall(PetscStrlcat(work, env, len)); 626 PetscCall(PetscStrlcat(work, epar, len)); 627 PetscCall(PetscStrncpy(b, work, len)); 628 PetscCall(PetscStrstr(b, "${", &par)); 629 } 630 PetscCall(PetscFree(work)); 631 if (aa == b) PetscCall(PetscFree(a)); 632 PetscFunctionReturn(PETSC_SUCCESS); 633 } 634 635 /*@C 636 PetscStrcmpAny - Determines whether a string matches any of a list of strings. 637 638 Not Collective, No Fortran Support 639 640 Input Parameters: 641 + src - pointer to input the string 642 - cmp - list of non-null and non-empty strings to be compared against, pass the empty string "" to terminate the list 643 644 Output Parameter: 645 . match - `PETSC_TRUE` if the input string matches any in the list, else `PETSC_FALSE` 646 647 Level: intermediate 648 649 .seealso: `PetscStrcmp()` 650 @*/ 651 PetscErrorCode PetscStrcmpAny(const char src[], PetscBool *match, const char cmp[], ...) 652 { 653 va_list Argp; 654 655 PetscFunctionBegin; 656 PetscAssertPointer(match, 2); 657 *match = PETSC_FALSE; 658 if (!src) PetscFunctionReturn(PETSC_SUCCESS); 659 va_start(Argp, cmp); 660 while (cmp && cmp[0]) { 661 PetscBool found; 662 PetscCall(PetscStrcmp(src, cmp, &found)); 663 if (found) { 664 *match = PETSC_TRUE; 665 break; 666 } 667 cmp = va_arg(Argp, const char *); 668 } 669 va_end(Argp); 670 PetscFunctionReturn(PETSC_SUCCESS); 671 } 672 673 /*@C 674 PetscEListFind - searches list of strings for given string, using case insensitive matching 675 676 Not Collective; No Fortran Support 677 678 Input Parameters: 679 + n - number of strings in 680 . list - list of strings to search 681 - str - string to look for, empty string "" accepts default (first entry in list) 682 683 Output Parameters: 684 + value - index of matching string (if found) 685 - found - boolean indicating whether string was found (can be `NULL`) 686 687 Level: developer 688 689 .seealso: `PetscEnumFind()` 690 @*/ 691 PetscErrorCode PetscEListFind(PetscInt n, const char *const *list, const char *str, PetscInt *value, PetscBool *found) 692 { 693 PetscFunctionBegin; 694 if (found) { 695 PetscAssertPointer(found, 5); 696 *found = PETSC_FALSE; 697 } 698 for (PetscInt i = 0; i < n; ++i) { 699 PetscBool matched; 700 701 PetscCall(PetscStrcasecmp(str, list[i], &matched)); 702 if (matched || !str[0]) { 703 if (found) *found = PETSC_TRUE; 704 *value = i; 705 break; 706 } 707 } 708 PetscFunctionReturn(PETSC_SUCCESS); 709 } 710 711 /*@C 712 PetscEnumFind - searches enum list of strings for given string, using case insensitive matching 713 714 Not Collective; No Fortran Support 715 716 Input Parameters: 717 + enumlist - list of strings to search, followed by enum name, then enum prefix, then `NULL` 718 - str - string to look for 719 720 Output Parameters: 721 + value - index of matching string (if found) 722 - found - boolean indicating whether string was found (can be `NULL`) 723 724 Level: advanced 725 726 .seealso: `PetscEListFind()` 727 @*/ 728 PetscErrorCode PetscEnumFind(const char *const *enumlist, const char *str, PetscEnum *value, PetscBool *found) 729 { 730 PetscInt n = 0, evalue; 731 PetscBool efound; 732 733 PetscFunctionBegin; 734 PetscAssertPointer(enumlist, 1); 735 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"); 736 PetscCheck(n >= 3, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "List argument must have at least two entries: typename and type prefix"); 737 n -= 3; /* drop enum name, prefix, and null termination */ 738 PetscCall(PetscEListFind(n, enumlist, str, &evalue, &efound)); 739 if (efound) { 740 PetscAssertPointer(value, 3); 741 *value = (PetscEnum)evalue; 742 } 743 if (found) { 744 PetscAssertPointer(found, 4); 745 *found = efound; 746 } 747 PetscFunctionReturn(PETSC_SUCCESS); 748 } 749 750 /*@C 751 PetscCIFilename - returns the basename of a file name when the PETSc CI portable error output mode is enabled. 752 753 Not Collective; No Fortran Support 754 755 Input Parameter: 756 . file - the file name 757 758 Level: developer 759 760 Note: 761 PETSc CI mode is a mode of running PETSc where output (both error and non-error) is made portable across all systems 762 so that comparisons of output between runs are easy to make. 763 764 This mode is used for all tests in the test harness, it applies to both debug and optimized builds. 765 766 Use the option `-petsc_ci` to turn on PETSc CI mode. It changes certain output in non-error situations to be portable for 767 all systems, mainly the output of options. It is passed to all PETSc programs automatically by the test harness. 768 769 Always uses the Unix / as the file separate even on Microsoft Windows systems 770 771 The option `-petsc_ci_portable_error_output` attempts to output the same error messages on all systems for the test harness. 772 In particular the output of filenames and line numbers in PETSc stacks. This is to allow (limited) checking of PETSc 773 error handling by the test harness. This options also causes PETSc to attempt to return an error code of 0 so that the test 774 harness can process the output for differences in the usual manner as for successful runs. It should be provided to the test 775 harness in the args: argument for specific examples. It will not necessarily produce portable output if different errors 776 (or no errors) occur on a subset of the MPI ranks. 777 778 .seealso: `PetscCILinenumber()` 779 @*/ 780 const char *PetscCIFilename(const char *file) 781 { 782 if (!PetscCIEnabledPortableErrorOutput) return file; 783 return PetscBasename(file); 784 } 785 786 /*@C 787 PetscCILinenumber - returns a line number except if `PetscCIEnablePortableErrorOutput` is set when it returns 0 788 789 Not Collective; No Fortran Support 790 791 Input Parameter: 792 . linenumber - the initial line number 793 794 Level: developer 795 796 Note: 797 See `PetscCIFilename()` for details on usage 798 799 .seealso: `PetscCIFilename()` 800 @*/ 801 int PetscCILinenumber(int linenumber) 802 { 803 if (!PetscCIEnabledPortableErrorOutput) return linenumber; 804 return 0; 805 } 806 807 /*@C 808 PetscStrcat - Concatenates a string onto a given string 809 810 Not Collective, No Fortran Support 811 812 Input Parameters: 813 + s - string to be added to 814 - t - pointer to string to be added to end 815 816 Level: deprecated (since 3.18.5) 817 818 Notes: 819 It is recommended you use `PetscStrlcat()` instead of this routine. 820 821 .seealso: `PetscStrlcat()` 822 @*/ 823 PetscErrorCode PetscStrcat(char s[], const char t[]) 824 { 825 PetscFunctionBegin; 826 if (!t) PetscFunctionReturn(PETSC_SUCCESS); 827 PetscAssertPointer(s, 1); 828 strcat(s, t); 829 PetscFunctionReturn(PETSC_SUCCESS); 830 } 831 832 /*@C 833 PetscStrcpy - Copies a string 834 835 Not Collective, No Fortran Support 836 837 Input Parameter: 838 . t - pointer to string 839 840 Output Parameter: 841 . s - the copied string 842 843 Level: deprecated (since 3.18.5) 844 845 Notes: 846 It is recommended you use `PetscStrncpy()` (equivalently `PetscArraycpy()` or 847 `PetscMemcpy()`) instead of this routine. 848 849 `NULL` strings returns a string starting with zero. 850 851 .seealso: `PetscStrncpy()` 852 @*/ 853 PetscErrorCode PetscStrcpy(char s[], const char t[]) 854 { 855 PetscFunctionBegin; 856 if (t) { 857 PetscAssertPointer(s, 1); 858 PetscAssertPointer(t, 2); 859 strcpy(s, t); 860 } else if (s) { 861 s[0] = '\0'; 862 } 863 PetscFunctionReturn(PETSC_SUCCESS); 864 } 865