+/**
+ * Parse a string.
+ *
+ * Two arguments (ctx->args) are retrieved from the stack to store data and
+ * its length (in that order).
+ */
+static int
+parse_string(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len,
+ void *buf, unsigned int size)
+{
+ const struct arg *arg_data = pop_args(ctx);
+ const struct arg *arg_len = pop_args(ctx);
+ char tmp[16]; /* Ought to be enough. */
+ int ret;
+
+ /* Arguments are expected. */
+ if (!arg_data)
+ return -1;
+ if (!arg_len) {
+ push_args(ctx, arg_data);
+ return -1;
+ }
+ size = arg_data->size;
+ /* Bit-mask fill is not supported. */
+ if (arg_data->mask || size < len)
+ goto error;
+ if (!ctx->object)
+ return len;
+ /* Let parse_int() fill length information first. */
+ ret = snprintf(tmp, sizeof(tmp), "%u", len);
+ if (ret < 0)
+ goto error;
+ push_args(ctx, arg_len);
+ ret = parse_int(ctx, token, tmp, ret, NULL, 0);
+ if (ret < 0) {
+ pop_args(ctx);
+ goto error;
+ }
+ buf = (uint8_t *)ctx->object + arg_data->offset;
+ /* Output buffer is not necessarily NUL-terminated. */
+ memcpy(buf, str, len);
+ memset((uint8_t *)buf + len, 0x55, size - len);
+ if (ctx->objmask)
+ memset((uint8_t *)ctx->objmask + arg_data->offset, 0xff, len);
+ return len;
+error:
+ push_args(ctx, arg_len);
+ push_args(ctx, arg_data);
+ return -1;
+}
+
+/** Boolean values (even indices stand for false). */
+static const char *const boolean_name[] = {
+ "0", "1",
+ "false", "true",
+ "no", "yes",
+ "N", "Y",
+ NULL,
+};
+
+/**
+ * Parse a boolean value.
+ *
+ * Last argument (ctx->args) is retrieved to determine storage size and
+ * location.
+ */
+static int
+parse_boolean(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len,
+ void *buf, unsigned int size)
+{
+ const struct arg *arg = pop_args(ctx);
+ unsigned int i;
+ int ret;
+
+ /* Argument is expected. */
+ if (!arg)
+ return -1;
+ for (i = 0; boolean_name[i]; ++i)
+ if (!strncmp(str, boolean_name[i], len))
+ break;
+ /* Process token as integer. */
+ if (boolean_name[i])
+ str = i & 1 ? "1" : "0";
+ push_args(ctx, arg);
+ ret = parse_int(ctx, token, str, strlen(str), buf, size);
+ return ret > 0 ? (int)len : ret;
+}
+