* Try to parse value as an integer. The accepted formats are the * usual decimal, octal, or hexadecimal formats. */
| 2476 | * usual decimal, octal, or hexadecimal formats. |
| 2477 | */ |
| 2478 | static long |
| 2479 | parse_long(const char *value, bool blckszUnit, const char *optname) |
| 2480 | { |
| 2481 | long val; |
| 2482 | char *endptr; |
| 2483 | double m; |
| 2484 | |
| 2485 | errno = 0; |
| 2486 | val = strtol(value, &endptr, 0); |
| 2487 | |
| 2488 | if (errno || |
| 2489 | endptr == value) |
| 2490 | goto err; |
| 2491 | |
| 2492 | if (blckszUnit && endptr[0]) |
| 2493 | { |
| 2494 | switch (endptr[0]) |
| 2495 | { |
| 2496 | case 'k': |
| 2497 | case 'K': |
| 2498 | m = 1024; |
| 2499 | break; |
| 2500 | |
| 2501 | case 'm': |
| 2502 | case 'M': |
| 2503 | m = 1024*1024; |
| 2504 | break; |
| 2505 | |
| 2506 | case 'g': |
| 2507 | case 'G': |
| 2508 | m = 1024*1024*1024; |
| 2509 | break; |
| 2510 | |
| 2511 | default: |
| 2512 | goto err; |
| 2513 | } |
| 2514 | |
| 2515 | if (endptr[1] != 'b' && |
| 2516 | endptr[1] != 'B') |
| 2517 | goto err; |
| 2518 | |
| 2519 | endptr += 2; |
| 2520 | val = (long)(m * val / BLCKSZ); |
| 2521 | } |
| 2522 | |
| 2523 | /* error if extra trailing chars */ |
| 2524 | if (endptr[0]) |
| 2525 | goto err; |
| 2526 | |
| 2527 | return val; |
| 2528 | |
| 2529 | err: |
| 2530 | if (blckszUnit) |
| 2531 | pg_log_error("%s: '%s=%s' invalid; requires an integer value, " |
| 2532 | "optionally followed by kB/MB/GB suffix", |
| 2533 | progname, optname, value); |
| 2534 | else |
| 2535 | pg_log_error("%s: '%s=%s' invalid; requires an integer value", |