* Parse a whitespace-delimited attribute state (i.e., "attr", * "-attr", "!attr", or "attr=value") from the string starting at src. * If e is not NULL, write the results to *e. Return a pointer to the * remainder of the string (with leading whitespace removed), or NULL * if there was an error. */
| 274 | * if there was an error. |
| 275 | */ |
| 276 | static const char *parse_attr(const char *src, int lineno, const char *cp, |
| 277 | struct attr_state *e) |
| 278 | { |
| 279 | const char *ep, *equals; |
| 280 | size_t len; |
| 281 | |
| 282 | ep = cp + strcspn(cp, blank); |
| 283 | equals = strchr(cp, '='); |
| 284 | if (equals && ep < equals) |
| 285 | equals = NULL; |
| 286 | if (equals) |
| 287 | len = equals - cp; |
| 288 | else |
| 289 | len = ep - cp; |
| 290 | if (!e) { |
| 291 | if (*cp == '-' || *cp == '!') { |
| 292 | cp++; |
| 293 | len--; |
| 294 | } |
| 295 | if (!attr_name_valid(cp, len) || attr_name_reserved(cp)) { |
| 296 | report_invalid_attr(cp, len, src, lineno); |
| 297 | return NULL; |
| 298 | } |
| 299 | } else { |
| 300 | /* |
| 301 | * As this function is always called twice, once with |
| 302 | * e == NULL in the first pass and then e != NULL in |
| 303 | * the second pass, no need for attr_name_valid() |
| 304 | * check here. |
| 305 | */ |
| 306 | if (*cp == '-' || *cp == '!') { |
| 307 | e->setto = (*cp == '-') ? ATTR__FALSE : ATTR__UNSET; |
| 308 | cp++; |
| 309 | len--; |
| 310 | } |
| 311 | else if (!equals) |
| 312 | e->setto = ATTR__TRUE; |
| 313 | else { |
| 314 | e->setto = xmemdupz(equals + 1, ep - equals - 1); |
| 315 | } |
| 316 | e->attr = git_attr_internal(cp, len); |
| 317 | } |
| 318 | return ep + strspn(ep, blank); |
| 319 | } |
| 320 | |
| 321 | struct match_attr *parse_attr_line(const char *line, const char *src, |
| 322 | int lineno, unsigned flags) |
no test coverage detected