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