+ return talloc_strdup(script, val);
+}
+
+static bool is_delim(char c)
+{
+ return c == ' ' || c == '\t';
+}
+
+static bool option_is_default(struct grub2_script *script,
+ struct discover_boot_option *opt, const char *id)
+{
+ unsigned int default_idx;
+ const char *var;
+ char *end;
+
+ var = script_env_get(script, "default");
+ if (!var)
+ return false;
+
+ default_idx = strtoul(var, &end, 10);
+ if (end != var && *end == '\0')
+ return default_idx == script->n_options;
+
+ /* if we don't have an explicit id for this option, fall back to
+ * the name */
+ if (!id)
+ id = opt->option->name;
+
+ return !strcmp(id, var);
+}
+
+static void append_text_to_current_arg(struct grub2_argv *argv,
+ const char *text, int len)
+{
+ char *cur = argv->argv[argv->argc - 1];
+
+ if (cur) {
+ int curlen = strlen(cur);
+ cur = talloc_realloc(argv->argv, cur, char, len + curlen + 1);
+ memcpy(cur + curlen, text, len);
+ cur[len + curlen] = '\0';
+
+ } else {
+ cur = talloc_strndup(argv->argv, text, len);
+ }
+
+ argv->argv[argv->argc-1] = cur;
+}
+
+/* Add a word to the argv array. Depending on the word type, and presence of
+ * delimiter characters, we may add multiple items to the array.
+ */
+static void append_word_to_argv(struct grub2_script *script,
+ struct grub2_argv *argv, struct grub2_word *word)
+{
+ const char *text, *pos;
+ int i, len;
+
+ /* If it's a variable, perform substitution */
+ if (word->type == GRUB2_WORD_VAR)
+ text = expand_var(script, word);
+ else
+ text = word->text;
+
+ len = strlen(text);
+
+ /* If we have no text, we leave the current word as-is. The caller
+ * has allocated an empty string for the case where this is the
+ * first text token */
+ if (!len)
+ return;
+
+ /* If we're not splitting, we just add the entire block to the
+ * current argv item */
+ if (!word->split) {
+ append_text_to_current_arg(argv, text, len);
+ return;
+ }
+
+ /* Scan for delimiters. If we find a word-end boundary, add the word
+ * to the argv array, and start a new argv item */
+ pos = !is_delim(text[0]) ? text : NULL;
+ for (i = 0; i < len; i++) {
+
+ /* first delimiter after a word: add the accumulated word to
+ * argv */
+ if (pos && is_delim(text[i])) {
+ append_text_to_current_arg(argv, pos,
+ text + i - pos);
+ pos = NULL;
+
+ /* first non-delimeter after a delimiter: record the starting
+ * position, and create another argv item */
+ } else if (!pos && !is_delim(text[i])) {
+ pos = text + i;
+ argv->argc++;
+ argv->argv = talloc_realloc(argv, argv->argv, char *,
+ argv->argc);
+ argv->argv[argv->argc - 1] = NULL;
+ }
+ }