+static bool is_delim(char c)
+{
+ return c == ' ' || c == '\t';
+}
+
+static bool option_is_default(struct grub2_script *script,
+ struct discover_boot_option *opt)
+{
+ 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;
+
+ return !strcmp(opt->option->name, var);
+}
+
+/* For non-double-quoted variable expansions, we may need to split the
+ * variable's value into multiple argv items.
+ *
+ * This function sets the word->text to the initial set of non-delimiter chars
+ * in the expanded var value. We then skip any delimiter chars, and (if
+ * required), create the new argv item with the remaining text, and
+ * add it to the argv list, after top_word.
+ */
+static void process_split(struct grub2_script *script,
+ struct grub2_word *top_word,
+ struct grub2_word *word)
+{
+ int i, len, delim_start = -1, delim_end = -1;
+ struct grub2_word *new_word;
+ char *remainder;
+
+ len = strlen(word->text);
+
+ /* Scan our string for the start of a delim (delim_start), and the
+ * start of any new text (delim_end). */
+ for (i = 0; i < len; i++) {
+ if (is_delim(word->text[i])) {
+ if (delim_start == -1)
+ delim_start = i;
+ } else if (delim_start != -1) {
+ delim_end = i;
+ break;
+ }
+ }
+
+ /* No delim? nothing to do. The process_expansions loop will
+ * append this word's text to the top word, if necessary
+ */
+ if (delim_start == -1)
+ return;
+
+ /* Set this word's text value to the text before the delimiter.
+ * this will get appended to the top word
+ */
+ word->text[delim_start] = '\0';
+
+ /* No trailing text? If there are no following word tokens, we're done.
+ * Otherwise, we need to start a new argv item with those tokens */
+ if (delim_end == -1) {
+ if (!word->next)
+ return;
+ remainder = "";
+ } else {
+ remainder = word->text + delim_end;
+ }
+
+ new_word = talloc(script, struct grub2_word);
+ new_word->type = GRUB2_WORD_TEXT;
+ /* if there's no trailing text, we know we don't need to re-split */
+ new_word->split = delim_end != -1;
+ new_word->next = word->next;
+ new_word->last = NULL;
+ new_word->text = talloc_strdup(new_word, remainder);
+
+ /* stitch it into the argv list before this word */
+ list_insert_after(&top_word->argv_list,
+ &new_word->argv_list);
+
+ /* terminate this word */
+ word->next = NULL;
+}
+
+/* iterate through the words in an argv_list, looking for GRUB2_WORD_VAR
+ * expansions.