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