Permalink
Browse files

first crack at fast version solver in C

  • Loading branch information...
1 parent bc85e83 commit 472b1e5131c57626e9eb8e60849b2568ddebbcba @rtomayko committed Mar 21, 2010
Showing with 172 additions and 14 deletions.
  1. +9 −14 Makefile
  2. +163 −0 rpg-solve-fast.c
View
@@ -4,23 +4,13 @@
# Default make target
all::
-# XXX include isn't POSIX but I don't feel like dealing with it right now.
-# we'll move to a separate Makefile.in eventually.
include config.mk
NAME = rpg
TARNAME = $(NAME)
SHELL = /bin/sh
-# srcdir = .
-# prefix = /usr/local
-# exec_prefix = ${prefix}
-# bindir = ${exec_prefix}/bin
-# libexecdir = ${exec_prefix}/libexec
-# datarootdir = ${prefix}/share
-# datadir = ${datarootdir}
-# mandir = ${datarootdir}/man
-# docdir = $(datadir)/doc/$(TARNAME)
+CFLAGS = -Wall -pedantic
# ---- END OF CONFIGURATION ----
@@ -33,7 +23,7 @@ SOURCES = \
rpg-package-register.sh rpg-package-install.sh rpg-solve.sh rpg-unpack.sh \
rpg-package-spec.rb rpg-parse-index.rb rpg-shit-list.sh rpg-prepare.sh \
rpg-help.sh rpg-package-index.sh rpg-list.sh rpg-dependencies.sh \
- rpg-leaves.sh
+ rpg-leaves.sh rpg-solve-fast.c
DOCHTML = \
rpg-sh-setup.html rpg.html rpg-fetch.html rpg-version-test.html \
@@ -47,12 +37,12 @@ PROGRAMPROGRAMS = \
rpg-outdated rpg-package-list rpg-package-register rpg-package-install \
rpg-solve rpg-unpack rpg-package-spec rpg-parse-index rpg-shit-list \
rpg-prepare rpg-complete rpg-help rpg-package-index rpg-dependencies \
- rpg-leaves
+ rpg-leaves rpg-solve-fast
USERPROGRAMS = rpg rpg-sh-setup
PROGRAMS = $(USERPROGRAMS) $(PROGRAMPROGRAMS)
-.SUFFIXES: .sh .rb .html
+.SUFFIXES: .sh .rb .html .c
.sh:
printf "%13s %-30s" "[SH]" "$@"
@@ -81,6 +71,11 @@ PROGRAMS = $(USERPROGRAMS) $(PROGRAMPROGRAMS)
rocco $< >/dev/null
printf " OK\n"
+.c:
+ printf "%13s %-30s" "[CC]" "$@"
+ $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $<
+ printf " OK\n"
+
rpg-sh-setup: config.sh munge.rb
rpg: config.sh munge.rb
View
@@ -0,0 +1,163 @@
+/* Fast package list solver.
+ *
+ * TODO:
+ * [ ] use strnatcmp instead of strcmp
+ * [ ] support squiggly comparison
+ * [ ] support rpg-solve -u 1
+ * [ ] usage message
+ * [ ] default to release index file
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+
+enum OPER { lt, le, eq, ge, gt, st, err };
+
+/* A package list entry. */
+struct plent {
+ enum OPER oper;
+ char pack[100];
+ char vers[50];
+ struct plent *next;
+};
+
+/* Parse a comparison operator string and return the corresponding OPER
+ * value. The err value is returned if the string is not a valid operator.
+ */
+static inline enum OPER
+operparse (char * oper)
+{
+ enum OPER res = err;
+ if ( oper[0] == '<' ) {
+ if ( oper[1] == 0 ) {
+ res = lt;
+ } else if ( oper[1] == '=' ) {
+ res = le;
+ }
+ } else if ( oper[0] == '>' ) {
+ if ( oper[1] == 0 ) {
+ res = gt;
+ } else if ( oper[1] == '=' ) {
+ res = ge;
+ }
+ } else if ( oper[0] == '=' && oper[1] == 0 ) {
+ res = eq;
+ } else if ( oper[0] == '~' && oper[1] == '>' ) {
+ res = st;
+ }
+
+ return res;
+}
+
+/* Parse a package list from the stream. */
+static struct plent *
+plparse(FILE * stream)
+{
+ int res = 0, lineno = 0;
+ struct plent *pe, *ppe = NULL, *pfe = NULL;
+ char stroper[3];
+ const char * format = "%100s%*[ ]%2[~><=]%*[ ]%50s\n";
+
+ while (1) {
+ lineno++;
+ pe = malloc(sizeof(struct plent));
+
+ res = fscanf(stream, format, pe->pack, stroper, pe->vers);
+ if ( res == 3 ) {
+ pe->oper = operparse(stroper);
+ } else {
+ free(pe);
+ break;
+ }
+
+ pe->next = NULL;
+ if ( ppe ) {
+ ppe->next = pe;
+ } else {
+ pfe = pe;
+ }
+ ppe = pe;
+ }
+
+ return pfe;
+}
+
+/* Compare two versions. */
+static inline int
+verscmp(char const * v1, char const * v2)
+{
+ return strcmp(v1, v2);
+}
+
+/* Test if versions compare according to oper. */
+static inline int
+verstest(enum OPER oper, char const * v1, char const * v2)
+{
+ int res = 0;
+ int cmp = verscmp(v1, v2);
+ if ((cmp == 0 && (oper == eq || oper == le || oper == ge)) ||
+ (cmp < 0 && (oper == lt || oper == le)) ||
+ (cmp > 0 && (oper == gt || oper == ge)))
+ res = 1;
+ return res;
+}
+
+/* Run over all package list entries with the same name as ppack and compare
+ * versions.
+ */
+static int
+pdxrun(char * ppack, char * pvers, struct plent * pe)
+{
+ while ( pe && strcmp(ppack, pe->pack) == 0 ) {
+ if (verstest(pe->oper, pvers, pe->vers)) {
+ pe = pe->next;
+ } else {
+ return 0;
+ }
+ }
+ return 1;
+}
+
+#define MAXLINE 256
+
+static void
+pdxscan(FILE * stream, struct plent * pe)
+{
+ char line[MAXLINE];
+ char *ppack, *pvers;
+ int cmp;
+
+ while ( fgets(line, MAXLINE - 1, stream) ) {
+ if (pe->pack[0] > line[0]) continue;
+
+ pvers = line;
+ ppack = strsep(&pvers, " ");
+ while ((cmp = strcmp(pe->pack, ppack)) < 0) {
+ pe = pe->next;
+ if (pe == NULL) return;
+ }
+
+ if (cmp == 0) {
+ pvers = strsep(&pvers, " \n");
+ if( pdxrun(ppack, pvers, pe) )
+ printf("%s %s\n", ppack, pvers);
+ }
+ }
+}
+
+int main (int argc, char *argv[])
+{
+ struct plent * pe = plparse(stdin);
+ FILE * fidx;
+ int i;
+
+ for (i=1; i < argc; i++) {
+ if ((fidx = fopen(argv[i], "r"))) {
+ pdxscan(fidx, pe);
+ fclose(fidx);
+ }
+ }
+
+ return 0;
+}

0 comments on commit 472b1e5

Please sign in to comment.