Allow inline predicates before commands and packages
authorMichael Spang <mspang@csclub.uwaterloo.ca>
Sun, 13 Dec 2009 07:15:28 +0000 (02:15 -0500)
committerMichael Spang <mspang@csclub.uwaterloo.ca>
Tue, 22 Dec 2009 03:11:48 +0000 (22:11 -0500)
Signed-off-by: Michael Spang <mspang@csclub.uwaterloo.ca>
inapt.cc
inapt.h
parser.rl

index b4e6102..c74df8c 100644 (file)
--- a/inapt.cc
+++ b/inapt.cc
@@ -187,8 +187,17 @@ static void eval_block(inapt_block *block, set<string> *defines, std::vector<ina
     if (!block)
         return;
 
-    for (vector<inapt_action *>::iterator i = block->actions.begin(); i < block->actions.end(); i++)
-        final_actions->push_back(*i);
+    for (vector<inapt_action *>::iterator i = block->actions.begin(); i < block->actions.end(); i++) {
+        bool ok = true;
+        for (vector<const char *>::iterator j = (*i)->predicates.begin(); j < (*i)->predicates.end(); j++) {
+            if (defines->find(*j) == defines->end()) {
+                ok = false;
+                break;
+            }
+        }
+        if (ok)
+            final_actions->push_back(*i);
+    }
 
     for (vector<inapt_conditional *>::iterator i = block->children.begin(); i < block->children.end(); i++) {
         if (defines->find((*i)->condition) != defines->end())
@@ -263,16 +272,12 @@ static void exec_actions(std::vector<inapt_action *> *final_actions) {
                 if ((!j.CurrentVer() && !cachef[j].Install()) || cachef[j].Delete()) {
                     printf("install %s %s:%d\n", (*i)->package, (*i)->filename, (*i)->linenum);
                     DCache->MarkInstall(j, false);
-                } else {
-                    //printf("install %s %s:%d NTD\n", (*i)->package, (*i)->filename, (*i)->linenum);
                 }
                 break;
             case inapt_action::REMOVE:
                 if ((j.CurrentVer() && !cachef[j].Delete()) || cachef[j].Install()) {
                     printf("remove %s %s:%d\n", (*i)->package, (*i)->filename, (*i)->linenum);
                     DCache->MarkDelete(j, false);
-                } else {
-                    //printf("remove %s %s:%d NTD\n", (*i)->package, (*i)->filename, (*i)->linenum);
                 }
                 break;
             default:
diff --git a/inapt.h b/inapt.h
index c00f44e..3604050 100644 (file)
--- a/inapt.h
+++ b/inapt.h
@@ -9,6 +9,7 @@ struct inapt_action {
     const char *filename;
     int linenum;
     pkgCache::PkgIterator pkg;
+    std::vector<const char *> predicates;
 };
 
 struct inapt_block {
index b0e070f..f09a6e3 100644 (file)
--- a/parser.rl
+++ b/parser.rl
@@ -17,7 +17,7 @@ using namespace std;
 %%{
     machine inapt;
 
-    action pkgstart { ts = p; }
+    action strstart { ts = p; }
 
     action add_list {
         inapt_action *tmp_action = new inapt_action;
@@ -25,6 +25,12 @@ using namespace std;
         tmp_action->action = curaction;
         tmp_action->linenum = curline;
         tmp_action->filename = curfile;
+        if (cmd_predicate)
+            tmp_action->predicates.push_back(cmd_predicate);
+        if (pkg_predicate) {
+            tmp_action->predicates.push_back(pkg_predicate);
+            pkg_predicate = NULL;
+        }
         block_stack.back()->actions.push_back(tmp_action);
     }
 
@@ -78,19 +84,38 @@ using namespace std;
         block_stack.back()->children.push_back(cond);
     }
 
+    action pkg_predicate {
+        if (pkg_predicate)
+            fatal("pkg_predicate already set");
+        pkg_predicate = xstrndup(ts, p - ts); ts = 0;
+    }
+
+    action cmd_predicate {
+        if (cmd_predicate)
+            fatal("cmd_predicate already set");
+        cmd_predicate = xstrndup(ts, p - ts); ts = 0;
+    }
+
+    action clear_cmd_predicate {
+        cmd_predicate = NULL;
+    }
+
     newline = '\n' @newline;
     comment = '#' (any - '\n')* newline;
     whitespace = [\t\v\f\r ] | comment | newline;
-    package_name = ((lower | digit) (lower | digit | '+' | '-' | '.')+) >pkgstart;
-    package_list = ((whitespace+ package_name)+ %add_list whitespace*);
-    cmd_install = ('install' @install package_list ';');
-    cmd_remove = ('remove' @remove package_list ';');
+    macro = alpha (alpha | digit | '-' | '+' | '.')*;
+    package_name = ((lower | digit) (lower | digit | '+' | '-' | '.')+) >strstart;
+    pkg_predicate = '@' macro >strstart %pkg_predicate whitespace+;
+    cmd_predicate = '@' macro >strstart %cmd_predicate whitespace+;
+    package_list = ((whitespace+ pkg_predicate? package_name)+ %add_list whitespace*);
+    cmd_install = ('install' @install package_list ';' @clear_cmd_predicate);
+    cmd_remove = ('remove' @remove package_list ';' @clear_cmd_predicate);
     start_block = '{' @start_block;
     end_block = '}' @end_block;
-    macro = alpha (alpha | digit | '-' | '+' | '.')*;
-    cmd_if = 'if' whitespace+ macro >pkgstart %start_conditional whitespace* start_block whitespace*
+    cmd_if = 'if' whitespace+ macro >strstart %start_conditional whitespace* start_block whitespace*
              ('else' whitespace* start_block whitespace* ';' @full_conditional | ';' @half_conditional);
-    cmd_list = (cmd_install | cmd_remove | cmd_if | whitespace)* end_block?;
+    cmd = whitespace* (cmd_predicate? (cmd_install | cmd_remove) | cmd_if);
+    cmd_list = cmd* whitespace* end_block?;
     main := cmd_list;
 }%%
 
@@ -120,6 +145,7 @@ void parser(const char *filename, inapt_block *top_block)
     int done = 0;
     int curline = 1;
     char *ts = 0;
+    char *cmd_predicate = NULL, *pkg_predicate = NULL;
 
     std::vector<inapt_block *> block_stack;
     std::vector<inapt_conditional *> conditional_stack;