* Internal helper function to parse an individual term from a failpoint. */
| 999 | * Internal helper function to parse an individual term from a failpoint. |
| 1000 | */ |
| 1001 | static char * |
| 1002 | parse_term(struct fail_point_setting *ents, char *p) |
| 1003 | { |
| 1004 | struct fail_point_entry *ent; |
| 1005 | |
| 1006 | ent = fail_point_entry_new(ents); |
| 1007 | |
| 1008 | /* |
| 1009 | * <term> :: |
| 1010 | * ( (<float> "%") | (<integer> "*" ) )* |
| 1011 | * <type> |
| 1012 | * [ "(" <integer> ")" ] |
| 1013 | * [ "[pid " <integer> "]" ] |
| 1014 | */ |
| 1015 | |
| 1016 | /* ( (<float> "%") | (<integer> "*" ) )* */ |
| 1017 | while (isdigit(*p) || *p == '.') { |
| 1018 | int units, decimal; |
| 1019 | |
| 1020 | p = parse_number(&units, &decimal, p); |
| 1021 | if (p == NULL) |
| 1022 | return (NULL); |
| 1023 | |
| 1024 | if (*p == '%') { |
| 1025 | if (units > 100) /* prevent overflow early */ |
| 1026 | units = 100; |
| 1027 | ent->fe_prob = units * (PROB_MAX / 100) + decimal; |
| 1028 | if (ent->fe_prob > PROB_MAX) |
| 1029 | ent->fe_prob = PROB_MAX; |
| 1030 | } else if (*p == '*') { |
| 1031 | if (!units || units < 0 || decimal) |
| 1032 | return (NULL); |
| 1033 | ent->fe_count = units; |
| 1034 | } else |
| 1035 | return (NULL); |
| 1036 | p++; |
| 1037 | } |
| 1038 | |
| 1039 | /* <type> */ |
| 1040 | p = parse_type(ent, p); |
| 1041 | if (p == NULL) |
| 1042 | return (NULL); |
| 1043 | if (*p == '\0') |
| 1044 | return (p); |
| 1045 | |
| 1046 | /* [ "(" <integer> ")" ] */ |
| 1047 | if (*p != '(') |
| 1048 | return (p); |
| 1049 | p++; |
| 1050 | if (!isdigit(*p) && *p != '-') |
| 1051 | return (NULL); |
| 1052 | ent->fe_arg = strtol(p, &p, 0); |
| 1053 | if (*p++ != ')') |
| 1054 | return (NULL); |
| 1055 | |
| 1056 | /* [ "[pid " <integer> "]" ] */ |
| 1057 | #define PID_STRING "[pid " |
| 1058 | if (strncmp(p, PID_STRING, sizeof(PID_STRING) - 1) != 0) |
no test coverage detected