summaryrefslogtreecommitdiffstats
path: root/discover
diff options
context:
space:
mode:
authorJeremy Kerr <jk@ozlabs.org>2013-09-13 14:50:19 +0800
committerJeremy Kerr <jk@ozlabs.org>2013-09-24 13:14:59 +0800
commitfb5a2b71f85614114663c86dbba62c5c491a11b9 (patch)
treeecacb9cc23f8507441b716da5431d59f0752e631 /discover
parent44e9d1d04a3120476ac50a14bfa34fbd091190c9 (diff)
downloadtalos-petitboot-fb5a2b71f85614114663c86dbba62c5c491a11b9.tar.gz
talos-petitboot-fb5a2b71f85614114663c86dbba62c5c491a11b9.zip
discover/grub2: Handle var tokens in lexer
Rather than post-processing to expand variables, use the lexer to identify variable tokens as a type of grub2_word. Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
Diffstat (limited to 'discover')
-rw-r--r--discover/grub2/grub2.h23
-rw-r--r--discover/grub2/lexer.l32
-rw-r--r--discover/grub2/parser-api.c18
-rw-r--r--discover/grub2/script.c80
4 files changed, 78 insertions, 75 deletions
diff --git a/discover/grub2/grub2.h b/discover/grub2/grub2.h
index 07a1e6c..cbd69dc 100644
--- a/discover/grub2/grub2.h
+++ b/discover/grub2/grub2.h
@@ -1,16 +1,23 @@
#ifndef GRUB2_H
#define GRUB2_H
-#include <regex.h>
#include <stdbool.h>
#include <list/list.h>
struct grub2_script;
struct grub2_word {
- const char *text;
- bool expand;
- bool split;
+ enum {
+ GRUB2_WORD_TEXT,
+ GRUB2_WORD_VAR,
+ } type;
+ union {
+ char *text;
+ struct {
+ const char *name;
+ bool split;
+ } var;
+ };
struct grub2_word *next;
struct list_item argv_list;
};
@@ -61,7 +68,6 @@ struct grub2_statement_block {
struct grub2_script {
struct grub2_statements *statements;
struct list environment;
- regex_t var_re;
};
struct grub2_parser {
@@ -85,8 +91,11 @@ struct grub2_statement *create_statement_if(struct grub2_parser *parser,
struct grub2_statement *create_statement_block(struct grub2_parser *parser,
struct grub2_statements *stmts);
-struct grub2_word *create_word(struct grub2_parser *parser, const char *text,
- bool expand, bool split);
+struct grub2_word *create_word_text(struct grub2_parser *parser,
+ const char *text);
+
+struct grub2_word *create_word_var(struct grub2_parser *parser,
+ const char *name, bool split);
struct grub2_argv *create_argv(struct grub2_parser *parser);
diff --git a/discover/grub2/lexer.l b/discover/grub2/lexer.l
index 64eee27..ab26f4b 100644
--- a/discover/grub2/lexer.l
+++ b/discover/grub2/lexer.l
@@ -51,15 +51,19 @@ VARNAME ([[:alpha:]][_[:alnum:]]*|[0-9]|[\?@\*#])
/* anything that's not a metachar: return as a plain word */
{WORD} {
- yylval->word = create_word(yyget_extra(yyscanner), yytext,
- false, false);
+ yylval->word = create_word_text(yyget_extra(yyscanner), yytext);
return TOKEN_WORD;
}
\${VARNAME} |
\$\{{VARNAME}\} {
- yylval->word = create_word(yyget_extra(yyscanner), yytext,
- true, true);
+ if (yytext[1] == '{') {
+ yytext[yyleng-1] = '\0';
+ yytext++;
+ }
+ yytext++;
+ yylval->word = create_word_var(yyget_extra(yyscanner), yytext,
+ true);
return TOKEN_WORD;
}
@@ -71,8 +75,7 @@ VARNAME ([[:alpha:]][_[:alnum:]]*|[0-9]|[\?@\*#])
yy_pop_state(yyscanner);
}
<sqstring>[^']+ {
- yylval->word = create_word(yyget_extra(yyscanner), yytext,
- false, false);
+ yylval->word = create_word_text(yyget_extra(yyscanner), yytext);
return TOKEN_WORD;
}
@@ -83,11 +86,22 @@ VARNAME ([[:alpha:]][_[:alnum:]]*|[0-9]|[\?@\*#])
<dqstring>\" {
yy_pop_state(yyscanner);
}
-<dqstring>([^"]|\\\")+ {
- yylval->word = create_word(yyget_extra(yyscanner), yytext,
- true, false);
+<dqstring>([^"\$]|\\\")+ {
+ yylval->word = create_word_text(yyget_extra(yyscanner), yytext);
return TOKEN_WORD;
}
+<dqstring>\${VARNAME} |
+<dqstring>\$\{{VARNAME}\} {
+ if (yytext[1] == '{') {
+ yytext[yyleng-1] = '\0';
+ yytext++;
+ }
+ yytext++;
+ yylval->word = create_word_var(yyget_extra(yyscanner), yytext,
+ false);
+ return TOKEN_WORD;
+ }
+
/* blocks */
diff --git a/discover/grub2/parser-api.c b/discover/grub2/parser-api.c
index 9ccf15e..765bd87 100644
--- a/discover/grub2/parser-api.c
+++ b/discover/grub2/parser-api.c
@@ -68,13 +68,23 @@ void statement_append(struct grub2_statements *stmts,
list_add_tail(&stmts->list, &stmt->list);
}
-struct grub2_word *create_word(struct grub2_parser *parser, const char *text,
- bool expand, bool split)
+struct grub2_word *create_word_text(struct grub2_parser *parser,
+ const char *text)
{
struct grub2_word *word = talloc(parser, struct grub2_word);
+ word->type = GRUB2_WORD_TEXT;
word->text = talloc_strdup(word, text);
- word->expand = expand;
- word->split = split;
+ word->next = NULL;
+ return word;
+}
+
+struct grub2_word *create_word_var(struct grub2_parser *parser,
+ const char *name, bool split)
+{
+ struct grub2_word *word = talloc(parser, struct grub2_word);
+ word->type = GRUB2_WORD_VAR;
+ word->var.name = talloc_strdup(word, name);
+ word->var.split = split;
word->next = NULL;
return word;
}
diff --git a/discover/grub2/script.c b/discover/grub2/script.c
index 3fee470..5361394 100644
--- a/discover/grub2/script.c
+++ b/discover/grub2/script.c
@@ -1,6 +1,5 @@
#include <sys/types.h>
-#include <regex.h>
#include <string.h>
#include <talloc/talloc.h>
@@ -19,50 +18,32 @@ struct env_entry {
};
static const char *env_lookup(struct grub2_script *script,
- const char *name, int name_len)
+ const char *name)
{
struct env_entry *entry;
list_for_each_entry(&script->environment, entry, list)
- if (!strncmp(entry->name, name, name_len)
- && entry->name[name_len] == '\0')
+ if (!strcmp(entry->name, name))
return entry->value;
return NULL;
}
-static bool expand_word(struct grub2_script *script, struct grub2_word *word)
+static bool expand_var(struct grub2_script *script, struct grub2_word *word)
{
- const char *val, *src;
- char *dest = NULL;
- regmatch_t match;
- int n, i;
+ const char *val;
- src = word->text;
-
- n = regexec(&script->var_re, src, 1, &match, 0);
- if (n != 0)
- return false;
-
- i = 0;
- if (src[match.rm_so + 1] == '{')
- i++;
-
- val = env_lookup(script, src + match.rm_so + 1 + i,
- match.rm_eo - match.rm_so - 1 - (i * 2));
+ val = env_lookup(script, word->var.name);
if (!val)
val = "";
- dest = talloc_strndup(script, src, match.rm_so);
- dest = talloc_asprintf_append(dest, "%s%s", val, src + match.rm_eo);
+ word->type = GRUB2_WORD_TEXT;
+ word->text = talloc_strdup(script, val);
- word->text = dest;
return true;
}
-/* iterate through the words in an argv, looking for expansions. If a
- * word is marked with expand == true, then we process any variable
- * substitutions.
+/* iterate through the words in an argv, looking for GRUB2_WORD_VAR expansions.
*
* Once that's done, we may (if split == true) have to split the word to create
* new argv items
@@ -70,13 +51,23 @@ static bool expand_word(struct grub2_script *script, struct grub2_word *word)
static void process_expansions(struct grub2_script *script,
struct grub2_argv *argv)
{
- struct grub2_word *word;
-
- list_for_each_entry(&argv->words, word, argv_list) {
- if (!word->expand)
- continue;
-
- expand_word(script, word);
+ struct grub2_word *top_word, *word;
+
+ list_for_each_entry(&argv->words, top_word, argv_list) {
+ /* expand vars and squash the list of words into the top struct.
+ * todo: splitting
+ */
+ for (word = top_word; word; word = word->next) {
+ if (word->type == GRUB2_WORD_VAR)
+ expand_var(script, word);
+
+ if (word == top_word)
+ continue;
+
+ top_word->text = talloc_asprintf_append(top_word->text,
+ "%s", word->text);
+ }
+ top_word->next = NULL;
}
}
@@ -147,33 +138,12 @@ void script_execute(struct grub2_script *script)
statements_execute(script, script->statements);
}
-static int script_destroy(void *p)
-{
- struct grub2_script *script = p;
- regfree(&script->var_re);
- return 0;
-}
-
struct grub2_script *create_script(void *ctx)
{
struct grub2_script *script;
- int rc;
script = talloc(ctx, struct grub2_script);
- rc = regcomp(&script->var_re,
- "\\$\\{?([[:alpha:]][_[:alnum:]]*|[0-9]|[\\?@\\*#])\\}?",
- REG_EXTENDED);
- if (rc) {
- char err[200];
- regerror(rc, &script->var_re, err, sizeof(err));
- fprintf(stderr, "RE error %d: %s\n", rc, err);
- talloc_free(script);
- return NULL;
-
- }
- talloc_set_destructor(script, script_destroy);
-
init_env(script);
return script;
OpenPOWER on IntegriCloud