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