int parse_boolean(const char *name, const char *s, const char *e)
{
size_t slen, nlen;
- int val = !!strncmp(s, "no-", 3);
+ bool has_neg_prefix = !strncmp(s, "no-", 3);
- if ( !val )
+ if ( has_neg_prefix )
s += 3;
slen = e ? ({ ASSERT(e >= s); e - s; }) : strlen(s);
/* Exact, unadorned name? Result depends on the 'no-' prefix. */
if ( slen == nlen )
- return val;
+ return !has_neg_prefix;
+
+ /* Inexact match with a 'no-' prefix? Not valid. */
+ if ( has_neg_prefix )
+ return -1;
/* =$SOMETHING? Defer to the regular boolean parsing. */
if ( s[nlen] == '=' )
- return parse_bool(&s[nlen + 1], e);
+ {
+ int b = parse_bool(&s[nlen + 1], e);
+
+ if ( b >= 0 )
+ return b;
+
+ /* Not a boolean, but the name matched. Signal specially. */
+ return -2;
+ }
/* Unrecognised. Give up. */
return -1;
/**
* Given a specific name, parses a string of the form:
* [no-]$NAME[=...]
- * returning 0 or 1 for a recognised boolean, or -1 for an error.
+ * returning 0 or 1 for a recognised boolean. Returns -1 for general errors,
+ * and -2 for "not a boolean, but $NAME= matches".
*/
int parse_boolean(const char *name, const char *s, const char *e);