+ for (p = contents; *p; p++) {
+ char c = *p;
+
+ switch (state) {
+
+ case PRE_KEY:
+ if (strchr(COMMENTS, c))
+ state = COMMENT;
+ else if (!strchr(WHITESPACE, c)) {
+ state = KEY;
+ if (!greedy_realloc((void**) &key, &key_alloc, n_key+2)) {
+ r = -ENOMEM;
+ goto fail;
+ }
+
+ key[n_key++] = c;
+ }
+ break;
+
+ case KEY:
+ if (strchr(newline, c)) {
+ state = PRE_KEY;
+ n_key = 0;
+ } else if (c == '=')
+ state = PRE_VALUE;
+ else {
+ if (!greedy_realloc((void**) &key, &key_alloc, n_key+2)) {
+ r = -ENOMEM;
+ goto fail;
+ }
+
+ key[n_key++] = c;
+ }
+
+ break;
+
+ case PRE_VALUE:
+ if (strchr(newline, c) || strchr(COMMENTS, c)) {
+ state = PRE_KEY;
+ key[n_key] = 0;
+
+ if (value)
+ value[n_value] = 0;
+
+ /* strip trailing whitespace from key */
+ while(strchr(WHITESPACE, key[--n_key]))
+ key[n_key]=0;
+
+ r = push(key, value, userdata);
+ if (r < 0)
+ goto fail;
+
+ n_key = 0;
+ value = NULL;
+ value_alloc = n_value = 0;
+ } else if (c == '\'')
+ state = SINGLE_QUOTE_VALUE;
+ else if (c == '\"')
+ state = DOUBLE_QUOTE_VALUE;
+ else if (c == '\\')
+ state = VALUE_ESCAPE;
+ else if (!strchr(WHITESPACE, c)) {
+ state = VALUE;
+
+ if (!greedy_realloc((void**) &value, &value_alloc, n_value+2)) {
+ r = -ENOMEM;
+ goto fail;
+ }