Add a "profiles" command to select profiles
authorMichael Spang <mspang@csclub.uwaterloo.ca>
Sun, 13 Dec 2009 13:27:03 +0000 (08:27 -0500)
committerMichael Spang <mspang@csclub.uwaterloo.ca>
Tue, 22 Dec 2009 03:14:01 +0000 (22:14 -0500)
Signed-off-by: Michael Spang <mspang@csclub.uwaterloo.ca>
inapt.cc
inapt.h
parser.rl

index b3a6ee6..54c5d6e 100644 (file)
--- a/inapt.cc
+++ b/inapt.cc
@@ -277,6 +277,23 @@ static void eval_block(inapt_block *block, set<string> *defines, vector<inapt_pa
     }
 }
 
+static void eval_profiles(inapt_block *block, set<string> *defines) {
+    if (!block)
+        return;
+
+    for (vector<inapt_profiles *>::iterator i = block->profiles.begin(); i < block->profiles.end(); i++)
+        if (test_macros(&(*i)->predicates, defines))
+            for (vector<std::string>::iterator j = (*i)->profiles.begin(); j != (*i)->profiles.end(); j++)
+                defines->insert(*j);
+
+    for (vector<inapt_conditional *>::iterator i = block->children.begin(); i < block->children.end(); i++) {
+        if (test_macro((*i)->condition, defines))
+            eval_profiles((*i)->then_block, defines);
+        else
+            eval_profiles((*i)->else_block, defines);
+    }
+}
+
 static void exec_actions(std::vector<inapt_package *> *final_actions) {
 
     pkgInitConfig(*_config);
@@ -410,15 +427,17 @@ int main(int argc, char *argv[]) {
     else if (argc - optind > 0)
         usage();
 
-    fprintf(stderr, "defines: ");
-    for (set<string>::iterator i = defines.begin(); i != defines.end(); i++)
-        fprintf(stderr, "%s  ", i->c_str());
-    fprintf(stderr, "\n");
-
     inapt_block context;
     vector<inapt_package *> final_actions;
 
     parser(filename, &context);
+    eval_profiles(&context, &defines);
+
+    fprintf(stderr, "defines: ");
+    for (set<string>::iterator i = defines.begin(); i != defines.end(); i++)
+        fprintf(stderr, "%s ", i->c_str());
+    fprintf(stderr, "\n");
+
     eval_block(&context, &defines, &final_actions);
     exec_actions(&final_actions);
 }
diff --git a/inapt.h b/inapt.h
index ee09121..4659b76 100644 (file)
--- a/inapt.h
+++ b/inapt.h
@@ -19,9 +19,15 @@ struct inapt_package {
     int linenum;
 };
 
+struct inapt_profiles {
+    std::vector<std::string> predicates;
+    std::vector<std::string> profiles;
+};
+
 struct inapt_block {
     std::vector<inapt_action *> actions;
     std::vector<inapt_conditional *> children;
+    std::vector<inapt_profiles *> profiles;
 };
 
 struct inapt_conditional {
index 2221c57..44ea587 100644 (file)
--- a/parser.rl
+++ b/parser.rl
@@ -48,6 +48,13 @@ using namespace std;
         block_stack.back()->actions.push_back(tmp_action);
     }
 
+    action add_profiles {
+        inapt_profiles *tmp_profiles = new inapt_profiles;
+        tmp_profiles->profiles.swap(profiles);
+        tmp_profiles->predicates.swap(cmd_predicates);
+        block_stack.back()->profiles.push_back(tmp_profiles);
+    }
+
     action newline {
         curline += 1;
     }
@@ -100,22 +107,29 @@ using namespace std;
         cmd_predicates.push_back(tmp);
     }
 
+    action profile {
+        std::string tmp (ts, p - ts); ts = 0;
+        profiles.push_back(tmp);
+    }
+
     newline = '\n' @newline;
     comment = '#' (any - '\n')* newline;
     whitespace = [\t\v\f\r ] | comment | newline;
-    profile = '!'? alpha (alpha | digit | '-' | '+' | '.')*;
+    profile = alpha (alpha | digit | '-' | '+' | '.')*;
     package_name = ((lower | digit) (lower | digit | '+' | '-' | '.')+) >strstart;
-    pkg_predicate = '@' profile >strstart %pkg_predicate whitespace+;
-    cmd_predicate = '@' profile >strstart %cmd_predicate whitespace+;
+    pkg_predicate = '@' ('!'? profile) >strstart %pkg_predicate whitespace+;
+    cmd_predicate = '@' ('!'? profile) >strstart %cmd_predicate whitespace+;
     package_alternates = package_name >strstart %add_alternate ('/' package_name >strstart %add_alternate)*;
     package_list = ((whitespace+ pkg_predicate? package_alternates)+ %add_package whitespace*);
+    profile_list = (whitespace+ profile >strstart %profile)* whitespace*;
     cmd_install = ('install' @start_install package_list ';');
     cmd_remove = ('remove' @start_remove package_list ';');
+    cmd_profiles = ('profiles' profile_list ';' @add_profiles);
     start_block = '{' @start_block;
     end_block = '}' @end_block;
     cmd_if = 'if' whitespace+ profile >strstart %start_conditional whitespace* start_block whitespace*
              ('else' whitespace* start_block whitespace* ';' @full_conditional | ';' @half_conditional);
-    cmd = whitespace* (cmd_predicate? (cmd_install | cmd_remove) | cmd_if);
+    cmd = whitespace* (cmd_predicate? (cmd_install | cmd_remove | cmd_profiles) | cmd_if);
     cmd_list = cmd* whitespace* end_block?;
     main := cmd_list;
 }%%
@@ -152,6 +166,7 @@ void parser(const char *filename, inapt_block *top_block)
     std::vector<std::string> alternates;
     std::vector<std::string> cmd_predicates;
     std::vector<std::string> pkg_predicates;
+    std::vector<std::string> profiles;
     block_stack.push_back(top_block);
     inapt_action *tmp_action = NULL;