Add a structure to group actions by command
authorMichael Spang <mspang@csclub.uwaterloo.ca>
Sun, 13 Dec 2009 12:14:40 +0000 (07:14 -0500)
committerMichael Spang <mspang@csclub.uwaterloo.ca>
Tue, 22 Dec 2009 03:11:49 +0000 (22:11 -0500)
Previously "install foo bar" would be separated into two structures,
now it gets its own struct which has the old structs as children.

Signed-off-by: Michael Spang <mspang@csclub.uwaterloo.ca>
inapt.cc
inapt.h
parser.rl

index f2edb46..2541f6d 100644 (file)
--- a/inapt.cc
+++ b/inapt.cc
@@ -188,14 +188,14 @@ static bool test_macro(const char *macro, set<string> *defines) {
             || (*macro == '!' && defines->find(macro + 1) == defines->end());
 }
 
-static pkgCache::PkgIterator eval_pkg(inapt_action *action, pkgCacheFile &cachef) {
+static pkgCache::PkgIterator eval_pkg(inapt_action *action, inapt_package *package, pkgCacheFile &cachef) {
     pkgCache::PkgIterator pkg;
 
     pkgCache *cache = cachef;
 
     if (!pkg.end()) fatal("omg"); /* TODO */
 
-    for (std::vector<std::string>::iterator i = action->alternates.begin(); i != action->alternates.end(); i++) {
+    for (std::vector<std::string>::iterator i = package->alternates.begin(); i != package->alternates.end(); i++) {
         pkg = cache->FindPkg(*i);
 
         /* no such package */
@@ -227,16 +227,16 @@ static pkgCache::PkgIterator eval_pkg(inapt_action *action, pkgCacheFile &cachef
 
     if (pkg.end()) {
         /* todo: report all errors at the end */
-        if (action->alternates.size() == 1) {
-            fatal("%s:%d: No such package: %s", action->filename, action->linenum, action->alternates[0].c_str());
+        if (package->alternates.size() == 1) {
+            fatal("%s:%d: No such package: %s", package->filename, package->linenum, package->alternates[0].c_str());
         } else {
-            std::vector<std::string>::iterator i = action->alternates.begin();
+            std::vector<std::string>::iterator i = package->alternates.begin();
             std::string message = *(i++);
-            while (i != action->alternates.end()) {
+            while (i != package->alternates.end()) {
                 message.append(", ");
                 message.append(*(i++));
             }
-            fatal("%s:%d: No alternative available: %s", action->filename, action->linenum, message.c_str());
+            fatal("%s:%d: No alternative available: %s", package->filename, package->linenum, message.c_str());
         }
     }
 
@@ -249,8 +249,8 @@ static void eval_block(inapt_block *block, set<string> *defines, std::vector<ina
 
     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 (!test_macro(*j, defines)) {
+        for (vector<std::string>::iterator j = (*i)->predicates.begin(); j < (*i)->predicates.end(); j++) {
+            if (!test_macro((*j).c_str(), defines)) {
                 ok = false;
                 break;
             }
@@ -285,42 +285,47 @@ static void exec_actions(std::vector<inapt_action *> *final_actions) {
     pkgCache *cache = cachef;
     pkgDepCache *DCache = cachef;
 
-    for (vector<inapt_action *>::iterator i = final_actions->begin(); i < final_actions->end(); i++)
-        (*i)->pkg = eval_pkg(*i, cachef);
+    for (vector<inapt_action *>::iterator i = final_actions->begin(); i != final_actions->end(); i++)
+        for (vector<inapt_package *>::iterator j = (*i)->packages.begin(); j != (*i)->packages.end(); j++)
+            (*j)->pkg = eval_pkg(*i, *j, cachef);
 
     for (vector<inapt_action *>::iterator i = final_actions->begin(); i < final_actions->end(); i++) {
-        pkgCache::PkgIterator j = (*i)->pkg;
-        switch ((*i)->action) {
-            case inapt_action::INSTALL:
-                if (!j.CurrentVer() || cachef[j].Delete()) {
-                    printf("preinstall %s %s:%d\n", (*i)->pkg.Name(), (*i)->filename, (*i)->linenum);
-                    DCache->MarkInstall(j, true);
-                }
-                break;
-            case inapt_action::REMOVE:
-                break;
-            default:
-                fatal("uninitialized action");
+        for (vector<inapt_package *>::iterator j = (*i)->packages.begin(); j != (*i)->packages.end(); j++) {
+            pkgCache::PkgIterator k = (*j)->pkg;
+            switch ((*i)->action) {
+                case inapt_action::INSTALL:
+                    if (!k.CurrentVer() || cachef[k].Delete()) {
+                        printf("preinstall %s %s:%d\n", (*j)->pkg.Name(), (*j)->filename, (*j)->linenum);
+                        DCache->MarkInstall(k, true);
+                    }
+                    break;
+                case inapt_action::REMOVE:
+                    break;
+                default:
+                    fatal("uninitialized action");
+            }
         }
     }
 
     for (vector<inapt_action *>::iterator i = final_actions->begin(); i < final_actions->end(); i++) {
-        pkgCache::PkgIterator j = (*i)->pkg;
-        switch ((*i)->action) {
-            case inapt_action::INSTALL:
-                if ((!j.CurrentVer() && !cachef[j].Install()) || cachef[j].Delete()) {
-                    printf("install %s %s:%d\n", (*i)->pkg.Name(), (*i)->filename, (*i)->linenum);
-                    DCache->MarkInstall(j, false);
-                }
-                break;
-            case inapt_action::REMOVE:
-                if ((j.CurrentVer() && !cachef[j].Delete()) || cachef[j].Install()) {
-                    printf("remove %s %s:%d\n", (*i)->pkg.Name(), (*i)->filename, (*i)->linenum);
-                    DCache->MarkDelete(j, false);
-                }
-                break;
-            default:
-                fatal("uninitialized action");
+        for (vector<inapt_package *>::iterator j = (*i)->packages.begin(); j != (*i)->packages.end(); j++) {
+            pkgCache::PkgIterator k = (*j)->pkg;
+            switch ((*i)->action) {
+                case inapt_action::INSTALL:
+                    if ((!k.CurrentVer() && !cachef[k].Install()) || cachef[k].Delete()) {
+                        printf("install %s %s:%d\n", (*j)->pkg.Name(), (*j)->filename, (*j)->linenum);
+                        DCache->MarkInstall(k, false);
+                    }
+                    break;
+                case inapt_action::REMOVE:
+                    if ((k.CurrentVer() && !cachef[k].Delete()) || cachef[k].Install()) {
+                        printf("remove %s %s:%d\n", (*j)->pkg.Name(), (*j)->filename, (*j)->linenum);
+                        DCache->MarkDelete(k, false);
+                    }
+                    break;
+                default:
+                    fatal("uninitialized action");
+            }
         }
     }
 
@@ -352,7 +357,8 @@ static void exec_actions(std::vector<inapt_action *> *final_actions) {
     pkgProblemResolver fix (DCache);
 
     for (vector<inapt_action *>::iterator i = final_actions->begin(); i < final_actions->end(); i++)
-           fix.Protect((*i)->pkg);
+        for (vector<inapt_package *>::iterator j = (*i)->packages.begin(); j != (*i)->packages.end(); j++)
+           fix.Protect((*j)->pkg);
     fix.Resolve();
 
     fprintf(stderr, "\n");
diff --git a/inapt.h b/inapt.h
index a1a2cd6..de97ae9 100644 (file)
--- a/inapt.h
+++ b/inapt.h
@@ -3,13 +3,18 @@
 
 struct inapt_conditional;
 
-struct inapt_action {
+struct inapt_package {
     std::vector<std::string> alternates;
-    enum action_t { INSTALL, REMOVE, UNSET } action;
+    std::vector<std::string> predicates;
+    pkgCache::PkgIterator pkg;
     const char *filename;
     int linenum;
-    pkgCache::PkgIterator pkg;
-    std::vector<const char *> predicates;
+};
+
+struct inapt_action {
+    enum action_t { INSTALL, REMOVE } action;
+    std::vector<std::string> predicates;
+    std::vector<inapt_package *> packages;
 };
 
 struct inapt_block {
index f7a5243..2694df3 100644 (file)
--- a/parser.rl
+++ b/parser.rl
@@ -24,27 +24,27 @@ using namespace std;
         alternates.push_back(tmp);
     }
 
-    action add_action {
-        inapt_action *tmp_action = new inapt_action;
-        tmp_action->alternates.swap(alternates);
-        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;
-        }
+    action add_package {
+        inapt_package *tmp_package = new inapt_package;
+        tmp_package->alternates.swap(alternates);
+        tmp_package->linenum = curline;
+        tmp_package->filename = curfile;
+        tmp_package->predicates.swap(pkg_predicates);
+        tmp_action->packages.push_back(tmp_package);
+    }
+
+    action start_install {
+        tmp_action = new inapt_action;
+        tmp_action->action = inapt_action::INSTALL;
+        tmp_action->predicates.swap(cmd_predicates);
         block_stack.back()->actions.push_back(tmp_action);
     }
 
-    action install {
-        curaction = inapt_action::INSTALL;
-    }
-
-    action remove {
-        curaction = inapt_action::REMOVE;
+    action start_remove {
+        tmp_action = new inapt_action;
+        tmp_action->action = inapt_action::REMOVE;
+        tmp_action->predicates.swap(cmd_predicates);
+        block_stack.back()->actions.push_back(tmp_action);
     }
 
     action newline {
@@ -90,19 +90,13 @@ using namespace std;
     }
 
     action pkg_predicate {
-        if (pkg_predicate)
-            fatal("pkg_predicate already set");
-        pkg_predicate = xstrndup(ts, p - ts); ts = 0;
+        std::string tmp (ts, p - ts); ts = 0;
+        pkg_predicates.push_back(tmp);
     }
 
     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;
+        std::string tmp (ts, p - ts); ts = 0;
+        cmd_predicates.push_back(tmp);
     }
 
     newline = '\n' @newline;
@@ -113,9 +107,9 @@ using namespace std;
     pkg_predicate = '@' macro >strstart %pkg_predicate whitespace+;
     cmd_predicate = '@' macro >strstart %cmd_predicate whitespace+;
     package_alternates = package_name >strstart %add_alternate ('/' package_name >strstart %add_alternate)*;
-    package_list = ((whitespace+ pkg_predicate? package_alternates)+ %add_action whitespace*);
-    cmd_install = ('install' @install package_list ';' @clear_cmd_predicate);
-    cmd_remove = ('remove' @remove package_list ';' @clear_cmd_predicate);
+    package_list = ((whitespace+ pkg_predicate? package_alternates)+ %add_package whitespace*);
+    cmd_install = ('install' @start_install package_list ';');
+    cmd_remove = ('remove' @start_remove package_list ';');
     start_block = '{' @start_block;
     end_block = '}' @end_block;
     cmd_if = 'if' whitespace+ macro >strstart %start_conditional whitespace* start_block whitespace*
@@ -151,18 +145,19 @@ 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;
     std::vector<std::string> alternates;
+    std::vector<std::string> cmd_predicates;
+    std::vector<std::string> pkg_predicates;
     block_stack.push_back(top_block);
+    inapt_action *tmp_action = NULL;
 
     int stack[MAXDEPTH];
     int top = 0;
 
     const char *curfile = filename;
-    enum inapt_action::action_t curaction = inapt_action::UNSET;
 
     if (filename) {
         fd = open(filename, O_RDONLY);