mirror of
				https://git.launchpad.net/~ubuntu-release/britney/+git/britney2-ubuntu
				synced 2025-11-04 10:34:05 +00:00 
			
		
		
		
	Merge trunk up to 2013-12-06
This commit is contained in:
		
						commit
						6904969c7c
					
				
							
								
								
									
										10
									
								
								INSTALL
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								INSTALL
									
									
									
									
									
								
							@ -5,13 +5,5 @@ Requirements:
 | 
			
		||||
-------------
 | 
			
		||||
 | 
			
		||||
  * Python 2.7                  aptitude install python2.7
 | 
			
		||||
  * Python APT/DPKG bindings    aptitude install python2.7-apt libapt-pkg-dev dpkg-dev
 | 
			
		||||
  * Python dev headers          aptitude install python2.7-dev
 | 
			
		||||
 | 
			
		||||
Compiling:
 | 
			
		||||
----------
 | 
			
		||||
 | 
			
		||||
Run "make all" in the lib directory and add a symlink called
 | 
			
		||||
britneymodule.so pointing to the freshly generated britneymodule.so in
 | 
			
		||||
the lib directory.
 | 
			
		||||
  * Python APT/DPKG bindings    aptitude install python2.7-apt
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -33,7 +33,7 @@ MINDAYS_MEDIUM    = 0
 | 
			
		||||
MINDAYS_HIGH      = 0
 | 
			
		||||
MINDAYS_CRITICAL  = 0
 | 
			
		||||
MINDAYS_EMERGENCY = 0
 | 
			
		||||
DEFAULT_URGENCY   = low
 | 
			
		||||
DEFAULT_URGENCY   = medium
 | 
			
		||||
 | 
			
		||||
# hint permissions
 | 
			
		||||
HINTS_CJWATSON    = ALL
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										22
									
								
								britney.py
									
									
									
									
									
								
							
							
						
						
									
										22
									
								
								britney.py
									
									
									
									
									
								
							@ -215,7 +215,6 @@ from installability.builder import InstallabilityTesterBuilder
 | 
			
		||||
from excuse import Excuse
 | 
			
		||||
from migrationitem import MigrationItem
 | 
			
		||||
from hints import HintCollection
 | 
			
		||||
from britney import buildSystem
 | 
			
		||||
from britney_util import (old_libraries_format, same_source, undo_changes,
 | 
			
		||||
                          register_reverses, compute_reverse_tree,
 | 
			
		||||
                          read_nuninst, write_nuninst, write_heidi,
 | 
			
		||||
@ -264,6 +263,10 @@ class Britney(object):
 | 
			
		||||
        apt_pkg.init()
 | 
			
		||||
        self.sources = {}
 | 
			
		||||
        self.binaries = {}
 | 
			
		||||
        try:
 | 
			
		||||
            self.hints = self.read_hints(self.options.hintsdir)
 | 
			
		||||
        except AttributeError:
 | 
			
		||||
            self.hints = self.read_hints(self.options.unstable)
 | 
			
		||||
 | 
			
		||||
        if self.options.nuninst_cache:
 | 
			
		||||
            self.__log("Not building the list of non-installable packages, as requested", type="I")
 | 
			
		||||
@ -345,7 +348,6 @@ class Britney(object):
 | 
			
		||||
        # read additional data
 | 
			
		||||
        self.dates = self.read_dates(self.options.testing)
 | 
			
		||||
        self.urgencies = self.read_urgencies(self.options.testing)
 | 
			
		||||
        self.hints = self.read_hints(self.options.unstable)
 | 
			
		||||
        self.blocks = self.read_blocks(self.options.unstable)
 | 
			
		||||
        self.excuses = []
 | 
			
		||||
        self.dependencies = {}
 | 
			
		||||
@ -858,8 +860,8 @@ class Britney(object):
 | 
			
		||||
                if len(l) != 3: continue
 | 
			
		||||
 | 
			
		||||
                # read the minimum days associated with the urgencies
 | 
			
		||||
                urgency_old = urgencies.get(l[0], self.options.default_urgency)
 | 
			
		||||
                mindays_old = self.MINDAYS.get(urgency_old, self.MINDAYS[self.options.default_urgency])
 | 
			
		||||
                urgency_old = urgencies.get(l[0], None)
 | 
			
		||||
                mindays_old = self.MINDAYS.get(urgency_old, sys.maxint)
 | 
			
		||||
                mindays_new = self.MINDAYS.get(l[2], self.MINDAYS[self.options.default_urgency])
 | 
			
		||||
 | 
			
		||||
                # if the new urgency is lower (so the min days are higher), do nothing
 | 
			
		||||
@ -1417,9 +1419,10 @@ class Britney(object):
 | 
			
		||||
 | 
			
		||||
        # retrieve the urgency for the upload, ignoring it if this is a NEW package (not present in testing)
 | 
			
		||||
        urgency = self.urgencies.get(src, self.options.default_urgency)
 | 
			
		||||
        if not source_t and urgency != self.options.default_urgency:
 | 
			
		||||
            excuse.addhtml("Ignoring %s urgency setting for NEW package" % (urgency))
 | 
			
		||||
            urgency = self.options.default_urgency
 | 
			
		||||
        if not source_t:
 | 
			
		||||
            if self.MINDAYS[urgency] < self.MINDAYS[self.options.default_urgency]:
 | 
			
		||||
                excuse.addhtml("Ignoring %s urgency setting for NEW package" % (urgency))
 | 
			
		||||
                urgency = self.options.default_urgency
 | 
			
		||||
 | 
			
		||||
        # if there is a `remove' hint and the requested version is the same as the
 | 
			
		||||
        # version in testing, then stop here and return False
 | 
			
		||||
@ -2661,7 +2664,10 @@ class Britney(object):
 | 
			
		||||
                self.write_controlfiles(self.options.testing, 'testing')
 | 
			
		||||
 | 
			
		||||
            # write dates
 | 
			
		||||
            self.write_dates(self.options.testing, self.dates)
 | 
			
		||||
            try:
 | 
			
		||||
                self.write_dates(self.options.outputdir, self.dates)
 | 
			
		||||
            except AttributeError:
 | 
			
		||||
                self.write_dates(self.options.testing, self.dates)
 | 
			
		||||
 | 
			
		||||
            # write HeidiResult
 | 
			
		||||
            self.__log("Writing Heidi results to %s" % self.options.heidi_output)
 | 
			
		||||
 | 
			
		||||
@ -29,7 +29,8 @@ import time
 | 
			
		||||
from migrationitem import MigrationItem, UnversionnedMigrationItem
 | 
			
		||||
 | 
			
		||||
from consts import (VERSION, BINARIES, PROVIDES, DEPENDS, CONFLICTS,
 | 
			
		||||
                    RDEPENDS, RCONFLICTS, ARCHITECTURE, SECTION)
 | 
			
		||||
                    RDEPENDS, RCONFLICTS, ARCHITECTURE, SECTION,
 | 
			
		||||
                    SOURCE, SOURCEVER)
 | 
			
		||||
 | 
			
		||||
binnmu_re = re.compile(r'^(.*)\+b\d+$')
 | 
			
		||||
 | 
			
		||||
@ -385,6 +386,15 @@ def write_heidi(filename, sources_t, packages_t,
 | 
			
		||||
                pkgv = pkg[VERSION]
 | 
			
		||||
                pkgarch = pkg[ARCHITECTURE] or 'all'
 | 
			
		||||
                pkgsec = pkg[SECTION] or 'faux'
 | 
			
		||||
                if pkg[SOURCEVER] and pkgarch == 'all' and \
 | 
			
		||||
                    pkg[SOURCEVER] != sources_t[pkg[SOURCE]][VERSION]:
 | 
			
		||||
                    # when architectures are marked as "fucked", their binary
 | 
			
		||||
                    # versions may be lower than those of the associated
 | 
			
		||||
                    # source package in testing. the binary package list for
 | 
			
		||||
                    # such architectures will include arch:all packages
 | 
			
		||||
                    # matching those older versions, but we only want the
 | 
			
		||||
                    # newer arch:all in testing
 | 
			
		||||
                    continue
 | 
			
		||||
                f.write('%s %s %s %s\n' % (pkg_name, pkgv, pkgarch, pkgsec))
 | 
			
		||||
 | 
			
		||||
        # write sources
 | 
			
		||||
 | 
			
		||||
@ -33,7 +33,7 @@ class Excuse(object):
 | 
			
		||||
 | 
			
		||||
    ## @var reemail
 | 
			
		||||
    # Regular expression for removing the email address
 | 
			
		||||
    reemail = re.compile(r"<.*?>")
 | 
			
		||||
    reemail = re.compile(r" *<.*?>")
 | 
			
		||||
 | 
			
		||||
    def __init__(self, name):
 | 
			
		||||
        """Class constructor
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										33
									
								
								lib/Makefile
									
									
									
									
									
								
							
							
						
						
									
										33
									
								
								lib/Makefile
									
									
									
									
									
								
							@ -1,33 +0,0 @@
 | 
			
		||||
 | 
			
		||||
CC = gcc
 | 
			
		||||
CXX = g++
 | 
			
		||||
CFLAGS = -Wall -W -O2 -DNDEBUG -DMDEBUG0 -g -p -fPIC
 | 
			
		||||
CXXFLAGS += -fPIC
 | 
			
		||||
 | 
			
		||||
all : britneymodule.so # checklib aptvercmp freelist libajdpkg.a
 | 
			
		||||
 | 
			
		||||
clean :
 | 
			
		||||
	rm -f *.so *.o *~ Makefile.dep gmon.out 
 | 
			
		||||
	rm -f freelist aptvercmp checklib libajdpkg.a
 | 
			
		||||
 | 
			
		||||
checklib : checklib.o dpkg.o dpkg-lib.o memory3.o freelist.o assert.o
 | 
			
		||||
	$(CC) $(CFLAGS) -o checklib $^ -lapt-pkg # -lccmalloc -ldl
 | 
			
		||||
 | 
			
		||||
aptvercmp : dpkg-lib.cpp
 | 
			
		||||
	$(CXX) $(CFLAGS) -DTESTBIN -o aptvercmp dpkg-lib.cpp -lapt-pkg
 | 
			
		||||
 | 
			
		||||
freelist : freelist.c assert.o
 | 
			
		||||
	$(CC) $(CFLAGS) -DTESTBIN -o $@ $^
 | 
			
		||||
 | 
			
		||||
#libajdpkg.a : dpkg.o dpkg-lib.o memory3.o freelist.o assert.o
 | 
			
		||||
#	ar rv $@ $^
 | 
			
		||||
#	ranlib $@
 | 
			
		||||
 | 
			
		||||
britneymodule.so : britney-py.o dpkg.o dpkg-lib.o memory3.o freelist.o assert.o
 | 
			
		||||
	$(CC) -shared -o britneymodule.so $^ -lapt-pkg
 | 
			
		||||
 | 
			
		||||
Makefile.dep :
 | 
			
		||||
	@gcc -MM *.c *.cpp > Makefile.dep
 | 
			
		||||
	@echo Makefile.dep : Makefile *.c *.h >> Makefile.dep
 | 
			
		||||
 | 
			
		||||
-include Makefile.dep
 | 
			
		||||
							
								
								
									
										32
									
								
								lib/README
									
									
									
									
									
								
							
							
						
						
									
										32
									
								
								lib/README
									
									
									
									
									
								
							@ -1,32 +0,0 @@
 | 
			
		||||
 | 
			
		||||
BUILDING
 | 
			
		||||
========
 | 
			
		||||
 | 
			
		||||
Install libapt-pkg-dev
 | 
			
		||||
 | 
			
		||||
testing/ $ make
 | 
			
		||||
testing/ $ mkdir old cur out
 | 
			
		||||
testing/ $ cd testing
 | 
			
		||||
testing/testing/ $ perl Makefile.PL
 | 
			
		||||
testing/testing/ $ make
 | 
			
		||||
 | 
			
		||||
Add old and new packages files into old and cur, respectively.
 | 
			
		||||
 | 
			
		||||
testing/ $ ./checklib i386 alpha
 | 
			
		||||
 | 
			
		||||
Will generate some test stuff in out/
 | 
			
		||||
 | 
			
		||||
TODO
 | 
			
		||||
====
 | 
			
		||||
 | 
			
		||||
Need some way of actually updating archives.
 | 
			
		||||
Need some way of judging differences between Packages files.
 | 
			
		||||
  (so I can see what hasn't been updated and work out why;
 | 
			
		||||
   so I can check that Packages.gz matches dpkg-scanpackages output)
 | 
			
		||||
Need some way of automatically explaining why packages aren't upgraded.
 | 
			
		||||
  (shouldn't be hard?)
 | 
			
		||||
 | 
			
		||||
BUGS
 | 
			
		||||
====
 | 
			
		||||
 | 
			
		||||
out/ directory must exist for checklib, or segfault
 | 
			
		||||
							
								
								
									
										11
									
								
								lib/assert.c
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								lib/assert.c
									
									
									
									
									
								
							@ -1,11 +0,0 @@
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
 | 
			
		||||
int _myassertbug(int line, char *file, char *err) {
 | 
			
		||||
        fprintf(stderr, "Assertion failed: %s:%d: %s\n", file, line, err);
 | 
			
		||||
        fprintf(stderr, "I HATE YOU!!!");
 | 
			
		||||
        ((void(*)())0)();
 | 
			
		||||
        abort();
 | 
			
		||||
        return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										299
									
								
								lib/britney-py.c
									
									
									
									
									
								
							
							
						
						
									
										299
									
								
								lib/britney-py.c
									
									
									
									
									
								
							@ -1,299 +0,0 @@
 | 
			
		||||
#include <python2.7/Python.h>
 | 
			
		||||
 | 
			
		||||
#include "dpkg.h"
 | 
			
		||||
 | 
			
		||||
#define MAKE_PY_LIST(L,S,E,I,V)                 \
 | 
			
		||||
	do {                                    \
 | 
			
		||||
		L = PyList_New(0);              \
 | 
			
		||||
		if (!L) break;                  \
 | 
			
		||||
		for (S; E; I) {                 \
 | 
			
		||||
			PyObject *EL;           \
 | 
			
		||||
			EL = Py_BuildValue V;   \
 | 
			
		||||
			if (!EL) {              \
 | 
			
		||||
				Py_DECREF(L);   \
 | 
			
		||||
				L = NULL;       \
 | 
			
		||||
				break;          \
 | 
			
		||||
			}                       \
 | 
			
		||||
			PyList_Append(L, EL);   \
 | 
			
		||||
			Py_DECREF(EL);          \
 | 
			
		||||
		}                               \
 | 
			
		||||
		if (L) PyList_Sort(L);          \
 | 
			
		||||
	} while(0)
 | 
			
		||||
 | 
			
		||||
/**************************************************************************
 | 
			
		||||
 * britney.Packages -- dpkg_packages wrapper
 | 
			
		||||
 *******************************************/
 | 
			
		||||
 | 
			
		||||
typedef enum { DONTFREE, FREE } dpkgpackages_freeme;
 | 
			
		||||
typedef struct {
 | 
			
		||||
	PyObject_HEAD
 | 
			
		||||
	dpkg_packages		*pkgs;
 | 
			
		||||
	PyObject 		*ref; /* object packages are "in" */
 | 
			
		||||
	dpkgpackages_freeme	freeme; /* free pkgs when deallocing? */
 | 
			
		||||
} dpkgpackages;
 | 
			
		||||
 | 
			
		||||
staticforward PyTypeObject Packages_Type;
 | 
			
		||||
 | 
			
		||||
static void dpkgpackages_dealloc(dpkgpackages *self) {
 | 
			
		||||
	if (self->freeme == FREE) free_packages(self->pkgs);
 | 
			
		||||
	Py_XDECREF(self->ref);
 | 
			
		||||
	self->pkgs = NULL;
 | 
			
		||||
	self->ref = NULL;
 | 
			
		||||
	PyObject_DEL(self);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static PyObject *dpkgpackages_isinstallable(dpkgpackages *self, PyObject *args)
 | 
			
		||||
{
 | 
			
		||||
	char *pkgname;
 | 
			
		||||
	int r;
 | 
			
		||||
	if (!PyArg_ParseTuple(args, "s", &pkgname)) return NULL;
 | 
			
		||||
	if ((r=checkinstallable2(self->pkgs, pkgname))) {
 | 
			
		||||
		return Py_BuildValue("i", r);
 | 
			
		||||
	} else {
 | 
			
		||||
		return Py_BuildValue("");
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static PyObject *dpkgpackages_remove_binary(dpkgpackages *self, PyObject *args) {
 | 
			
		||||
    char *pkg_name;
 | 
			
		||||
 | 
			
		||||
	(void)self; /* unused */
 | 
			
		||||
 | 
			
		||||
    if (!PyArg_ParseTuple(args, "s", &pkg_name))
 | 
			
		||||
        return NULL;
 | 
			
		||||
 | 
			
		||||
    dpkg_collected_package *cpkg = lookup_packagetbl(self->pkgs->packages, pkg_name);
 | 
			
		||||
    if (cpkg == NULL) return Py_BuildValue("i", 0);
 | 
			
		||||
 | 
			
		||||
    remove_package(self->pkgs, cpkg);
 | 
			
		||||
    return Py_BuildValue("i", 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static PyObject *dpkgpackages_add_binary(dpkgpackages *self, PyObject *args) {
 | 
			
		||||
    char *pkg_name;
 | 
			
		||||
	PyObject *value, *pyString;
 | 
			
		||||
 | 
			
		||||
	(void)self; /* unused */
 | 
			
		||||
 | 
			
		||||
    if (!PyArg_ParseTuple(args, "sO", &pkg_name, &value) ||
 | 
			
		||||
        !PyList_Check(value)) return NULL;
 | 
			
		||||
 | 
			
		||||
    /* initialize the new package */
 | 
			
		||||
    dpkg_package *pkg;
 | 
			
		||||
    pkg = block_malloc(sizeof(dpkg_package));
 | 
			
		||||
    pkg->package = strdup(pkg_name);
 | 
			
		||||
    pkg->priority = 0;
 | 
			
		||||
    pkg->details    = NULL;
 | 
			
		||||
    pkg->depends[1] = NULL;
 | 
			
		||||
    pkg->depends[2] = NULL;
 | 
			
		||||
    pkg->depends[3] = NULL;
 | 
			
		||||
 | 
			
		||||
    pyString = PyList_GetItem(value, 0);
 | 
			
		||||
    if (pyString == NULL) return NULL;
 | 
			
		||||
    pkg->version = PyString_AsString(pyString);
 | 
			
		||||
 | 
			
		||||
    pyString = PyList_GetItem(value, 2);
 | 
			
		||||
    if (pyString == NULL) return NULL;
 | 
			
		||||
    pkg->source = PyString_AsString(pyString);
 | 
			
		||||
 | 
			
		||||
    pyString = PyList_GetItem(value, 3);
 | 
			
		||||
    if (pyString == NULL) return NULL;
 | 
			
		||||
    pkg->source_ver = PyString_AsString(pyString);
 | 
			
		||||
 | 
			
		||||
    pyString = PyList_GetItem(value, 4);
 | 
			
		||||
    if (pyString == NULL) return NULL;
 | 
			
		||||
    pkg->arch_all = (pyString == Py_None || strcmp(PyString_AsString(pyString), "all") ? 0 : 1);
 | 
			
		||||
 | 
			
		||||
    pyString = PyList_GetItem(value, 5);
 | 
			
		||||
    if (pyString == NULL) return NULL;
 | 
			
		||||
    if (pyString != Py_None) {
 | 
			
		||||
        pkg->multiarch = PyString_AsString(pyString);
 | 
			
		||||
    } else pkg->multiarch = NULL;
 | 
			
		||||
 | 
			
		||||
    pyString = PyList_GetItem(value, 6);
 | 
			
		||||
    if (pyString == NULL) return NULL;
 | 
			
		||||
    if (pyString != Py_None) {
 | 
			
		||||
        pkg->depends[0] = read_dep_andor(PyString_AsString(pyString));
 | 
			
		||||
    } else pkg->depends[0] = NULL;
 | 
			
		||||
 | 
			
		||||
    pyString = PyList_GetItem(value, 7);
 | 
			
		||||
    if (pyString == NULL) return NULL;
 | 
			
		||||
    if (pyString != Py_None) {
 | 
			
		||||
        pkg->conflicts = read_dep_and(PyString_AsString(pyString));
 | 
			
		||||
    } else pkg->conflicts = NULL;
 | 
			
		||||
 | 
			
		||||
    pyString = PyList_GetItem(value, 8);
 | 
			
		||||
    if (pyString == NULL) return NULL;
 | 
			
		||||
    if (pyString != Py_None) {
 | 
			
		||||
        pkg->provides = read_packagenames(PyString_AsString(pyString));
 | 
			
		||||
    } else pkg->provides = NULL;
 | 
			
		||||
 | 
			
		||||
    add_package(self->pkgs, pkg);
 | 
			
		||||
 | 
			
		||||
    return Py_BuildValue("i", 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static PyObject *dpkgpackages_getattr(dpkgpackages *self, char *name) {
 | 
			
		||||
	static struct PyMethodDef dpkgsources_methods[] = {
 | 
			
		||||
		{ "is_installable", (binaryfunc) dpkgpackages_isinstallable, 
 | 
			
		||||
			METH_VARARGS, NULL },
 | 
			
		||||
                { "remove_binary", (binaryfunc) dpkgpackages_remove_binary,
 | 
			
		||||
                       METH_VARARGS, NULL },
 | 
			
		||||
                { "add_binary", (binaryfunc) dpkgpackages_add_binary,
 | 
			
		||||
                       METH_VARARGS, NULL },
 | 
			
		||||
 | 
			
		||||
		{ NULL, NULL, 0, NULL }
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	if (strcmp(name, "packages") == 0) {
 | 
			
		||||
		PyObject *packages;
 | 
			
		||||
		packagetbl_iter it;
 | 
			
		||||
		MAKE_PY_LIST(packages, 
 | 
			
		||||
		             it = first_packagetbl(self->pkgs->packages),
 | 
			
		||||
		             !done_packagetbl(it), it = next_packagetbl(it),
 | 
			
		||||
			     ("s", it.k)
 | 
			
		||||
			    );
 | 
			
		||||
		return packages;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return Py_FindMethod(dpkgsources_methods, (PyObject *)self, name);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static PyTypeObject Packages_Type = {
 | 
			
		||||
	PyObject_HEAD_INIT(&PyType_Type)
 | 
			
		||||
 | 
			
		||||
	0,                     /* ob_size (0) */
 | 
			
		||||
	"Packages",            /* type name */
 | 
			
		||||
	sizeof(dpkgpackages),  /* basicsize */
 | 
			
		||||
	0,                     /* itemsize (0) */
 | 
			
		||||
 | 
			
		||||
	(destructor)  dpkgpackages_dealloc,
 | 
			
		||||
	(printfunc)   0,
 | 
			
		||||
	(getattrfunc) dpkgpackages_getattr,
 | 
			
		||||
	(setattrfunc) 0,
 | 
			
		||||
	(cmpfunc)     0,
 | 
			
		||||
	(reprfunc)    0,
 | 
			
		||||
 | 
			
		||||
	0,                     /* number methods */
 | 
			
		||||
	0,                     /* sequence methods */
 | 
			
		||||
	0,                     /* mapping methods */
 | 
			
		||||
 | 
			
		||||
	(hashfunc)    0,       /* dict[x] ?? */
 | 
			
		||||
	(ternaryfunc) 0,       /* x() */
 | 
			
		||||
	(reprfunc)    0        /* str(x) */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**************************************************************************
 | 
			
		||||
 * britney.buildSystem() -- build a fake package system, with the only purpose of
 | 
			
		||||
 *                          calling the is_installable method on the packages.
 | 
			
		||||
 ******************************************************/
 | 
			
		||||
 | 
			
		||||
static PyObject *build_system(PyObject *self, PyObject *args) {
 | 
			
		||||
    Py_ssize_t pos = 0;
 | 
			
		||||
    char *arch;
 | 
			
		||||
	PyObject *pkgs, *key, *value, *pyString;
 | 
			
		||||
 | 
			
		||||
	(void)self; /* unused */
 | 
			
		||||
 | 
			
		||||
    if (!PyArg_ParseTuple(args, "sO", &arch, &pkgs) ||
 | 
			
		||||
        !PyDict_Check(pkgs)) return NULL;
 | 
			
		||||
 | 
			
		||||
    /* Fields and positions for the binary package:
 | 
			
		||||
       # VERSION = 0
 | 
			
		||||
       # SECTION = 1
 | 
			
		||||
       # SOURCE = 2
 | 
			
		||||
       # SOURCEVER = 3
 | 
			
		||||
       # ARCHITECTURE = 4
 | 
			
		||||
       # MULTIARCH = 5
 | 
			
		||||
       # DEPENDS = 6
 | 
			
		||||
       # CONFLICTS = 7
 | 
			
		||||
       # PROVIDES = 8
 | 
			
		||||
       # RDEPENDS = 9
 | 
			
		||||
       # RCONFLICTS = 10
 | 
			
		||||
    */
 | 
			
		||||
 | 
			
		||||
    dpkg_packages *dpkg_pkgs = new_packages(arch);
 | 
			
		||||
 | 
			
		||||
    /* loop on the dictionary keys to build the packages */
 | 
			
		||||
    while (PyDict_Next(pkgs, &pos, &key, &value)) {
 | 
			
		||||
 | 
			
		||||
        /* initialize the new package */
 | 
			
		||||
        dpkg_package *pkg;
 | 
			
		||||
        pkg = block_malloc(sizeof(dpkg_package));
 | 
			
		||||
        pkg->package = strdup(PyString_AsString(key));
 | 
			
		||||
        pkg->priority = 0;
 | 
			
		||||
        pkg->details    = NULL;
 | 
			
		||||
        pkg->depends[1] = NULL;
 | 
			
		||||
        pkg->depends[2] = NULL;
 | 
			
		||||
        pkg->depends[3] = NULL;
 | 
			
		||||
 | 
			
		||||
        pyString = PyList_GetItem(value, 0);
 | 
			
		||||
        if (pyString == NULL) continue;
 | 
			
		||||
        pkg->version = PyString_AsString(pyString);
 | 
			
		||||
 | 
			
		||||
        pyString = PyList_GetItem(value, 2);
 | 
			
		||||
        if (pyString == NULL) continue;
 | 
			
		||||
        pkg->source = PyString_AsString(pyString);
 | 
			
		||||
 | 
			
		||||
        pyString = PyList_GetItem(value, 3);
 | 
			
		||||
        if (pyString == NULL) continue;
 | 
			
		||||
        pkg->source_ver = PyString_AsString(pyString);
 | 
			
		||||
 | 
			
		||||
        pyString = PyList_GetItem(value, 4);
 | 
			
		||||
        if (pyString == NULL) continue;
 | 
			
		||||
        pkg->arch_all = (pyString == Py_None || strcmp(PyString_AsString(pyString), "all") ? 0 : 1);
 | 
			
		||||
 | 
			
		||||
        pyString = PyList_GetItem(value, 5);
 | 
			
		||||
        if (pyString == NULL) continue;
 | 
			
		||||
        if (pyString != Py_None) {
 | 
			
		||||
            pkg->multiarch = PyString_AsString(pyString);
 | 
			
		||||
        } else pkg->multiarch = NULL;
 | 
			
		||||
 | 
			
		||||
        pyString = PyList_GetItem(value, 6);
 | 
			
		||||
        if (pyString == NULL) continue;
 | 
			
		||||
        if (pyString != Py_None) {
 | 
			
		||||
            pkg->depends[0] = read_dep_andor(PyString_AsString(pyString));
 | 
			
		||||
        } else pkg->depends[0] = NULL;
 | 
			
		||||
 | 
			
		||||
        pyString = PyList_GetItem(value, 7);
 | 
			
		||||
        if (pyString == NULL) continue;
 | 
			
		||||
        if (pyString != Py_None) {
 | 
			
		||||
            pkg->conflicts = read_dep_and(PyString_AsString(pyString));
 | 
			
		||||
        } else pkg->conflicts = NULL;
 | 
			
		||||
 | 
			
		||||
        pyString = PyList_GetItem(value, 8);
 | 
			
		||||
        if (pyString == NULL) continue;
 | 
			
		||||
        if (pyString != Py_None) {
 | 
			
		||||
            pkg->provides = read_packagenames(PyString_AsString(pyString));
 | 
			
		||||
        } else pkg->provides = NULL;
 | 
			
		||||
 | 
			
		||||
        add_package(dpkg_pkgs, pkg);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    dpkgpackages *res;
 | 
			
		||||
    res = PyObject_NEW(dpkgpackages, &Packages_Type);
 | 
			
		||||
    if (res == NULL) return NULL;
 | 
			
		||||
 | 
			
		||||
    res->pkgs = dpkg_pkgs;
 | 
			
		||||
    res->freeme = FREE;
 | 
			
		||||
    res->ref = NULL;
 | 
			
		||||
 | 
			
		||||
    return (PyObject *)res;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**************************************************************************
 | 
			
		||||
 * module initialisation
 | 
			
		||||
 ***********************/
 | 
			
		||||
 | 
			
		||||
static PyMethodDef britneymethods[] = {
 | 
			
		||||
	{ "buildSystem", build_system, METH_VARARGS, NULL },
 | 
			
		||||
 | 
			
		||||
	{ NULL, NULL, 0, NULL }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void initbritney(void) {
 | 
			
		||||
	Py_InitModule("britney", britneymethods);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										185
									
								
								lib/checklib.c
									
									
									
									
									
								
							
							
						
						
									
										185
									
								
								lib/checklib.c
									
									
									
									
									
								
							@ -1,185 +0,0 @@
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
 | 
			
		||||
#include <assert.h>
 | 
			
		||||
 | 
			
		||||
#include "dpkg.h"
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
static void checknewsrc(sourcetbl *srcstbl, dpkg_source *cur, void *data) {
 | 
			
		||||
    dpkg_sources *oldsrc = data;
 | 
			
		||||
    dpkg_source *old;
 | 
			
		||||
    old = lookup_sourcetbl(oldsrc->sources, cur->package);
 | 
			
		||||
    if (old == NULL) {
 | 
			
		||||
	printf("New: %s (%s)\n", cur->package, cur->version );
 | 
			
		||||
    } else if (strcmp(old->version, cur->version) != 0) {
 | 
			
		||||
	printf("Updated: %s (%s, was %s)\n",
 | 
			
		||||
	       cur->package, cur->version, old->version );
 | 
			
		||||
    } else {
 | 
			
		||||
	dpkg_source *src2;
 | 
			
		||||
	src2 = remove_sourcetbl(srcstbl, cur->package);
 | 
			
		||||
	assert(cur == src2);
 | 
			
		||||
	free_source(cur);
 | 
			
		||||
    }	
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void checkoldsrc(sourcetbl *oldsrctbl, dpkg_source *old, void *data) {
 | 
			
		||||
    dpkg_sources *src = data;
 | 
			
		||||
    dpkg_source *cur;
 | 
			
		||||
    (void)oldsrctbl;
 | 
			
		||||
    cur = lookup_sourcetbl(src->sources, old->package);
 | 
			
		||||
    if (cur == NULL) {
 | 
			
		||||
	printf("Removed: %s (was %s)\n", old->package, old->version );
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void checkuptodate(sourcetbl *srctbl, dpkg_source *src, void *data) {
 | 
			
		||||
    int i;
 | 
			
		||||
    int remove;
 | 
			
		||||
    ownedpackagelist **p;
 | 
			
		||||
    dpkg_sources *srcs = data;
 | 
			
		||||
 | 
			
		||||
    (void)srctbl;
 | 
			
		||||
 | 
			
		||||
    remove = 0;
 | 
			
		||||
    for (i = 0; i < srcs->n_arches; i++) {
 | 
			
		||||
	p = &src->packages[i];
 | 
			
		||||
	while(*p != NULL) {
 | 
			
		||||
	    if (strcmp((*p)->value->source_ver, src->version) != 0) {
 | 
			
		||||
		if (cmpversions((*p)->value->source_ver, GT, src->version)) {
 | 
			
		||||
		    printf("ALERT: old source: ");
 | 
			
		||||
		} else {
 | 
			
		||||
		    printf("WARN: out of date: ");
 | 
			
		||||
		}
 | 
			
		||||
		printf("%s %s: %s binary: %s %s from %s\n",
 | 
			
		||||
		       src->package, src->version, srcs->archname[i],
 | 
			
		||||
		       (*p)->value->package, (*p)->value->version,
 | 
			
		||||
		       (*p)->value->source_ver);
 | 
			
		||||
		delete_ownedpackagelist(p);
 | 
			
		||||
	    } else {
 | 
			
		||||
		p = &(*p)->next;
 | 
			
		||||
	    }
 | 
			
		||||
	}
 | 
			
		||||
	if (src->packages[i] == NULL) {
 | 
			
		||||
	    printf("%s missing uptodate binaries for %s\n",
 | 
			
		||||
		   src->package, srcs->archname[i]);
 | 
			
		||||
	    remove = 1;
 | 
			
		||||
	}
 | 
			
		||||
    }
 | 
			
		||||
    if (remove) {
 | 
			
		||||
	dpkg_source *src2;
 | 
			
		||||
	src2 = remove_sourcetbl(srcs->sources, src->package);
 | 
			
		||||
	assert(src == src2);
 | 
			
		||||
	free_source(src);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
#endif 
 | 
			
		||||
 | 
			
		||||
static void upgrade(sourcetbl *srctbl, dpkg_source *src, void *data) {
 | 
			
		||||
    static int i = 0;
 | 
			
		||||
    dpkg_sources_note *srcsn = data;
 | 
			
		||||
    (void)srctbl;
 | 
			
		||||
    i++; i %= 1000;
 | 
			
		||||
    if (can_undo(srcsn)) {
 | 
			
		||||
        if (i % 29 == 1 || i % 31 == 1 || i % 7 == 5)
 | 
			
		||||
            undo_change(srcsn);
 | 
			
		||||
        if (i % 33 == 0) commit_changes(srcsn);
 | 
			
		||||
    }
 | 
			
		||||
    upgrade_source(data, src);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void checkpkgs(packagetbl *pkgtbl, dpkg_collected_package *cpkg, 
 | 
			
		||||
		      void *data) 
 | 
			
		||||
{
 | 
			
		||||
    dpkg_packages *pkgs = data;
 | 
			
		||||
    assert(pkgs->packages == pkgtbl);
 | 
			
		||||
    printf("Trying %s (%s, %s)\n", cpkg->pkg->package, cpkg->pkg->version, pkgs->arch);
 | 
			
		||||
    if (!checkinstallable2(pkgs, cpkg->pkg->package)) {
 | 
			
		||||
 	printf("Package: %s (%s, %s) is uninstallable\n",
 | 
			
		||||
	       cpkg->pkg->package, cpkg->pkg->version, pkgs->arch);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void print_memblock_summary(void);
 | 
			
		||||
 | 
			
		||||
int main(int argc, char **argv) {
 | 
			
		||||
    dpkg_sources *src = NULL, *oldsrc = NULL;
 | 
			
		||||
    dpkg_sources_note *srcsn;
 | 
			
		||||
    dpkg_source *srcpkg;
 | 
			
		||||
    dpkg_packages *pkgs[10];
 | 
			
		||||
    int n_pkgs;
 | 
			
		||||
    int i,j;
 | 
			
		||||
    int reps;
 | 
			
		||||
    
 | 
			
		||||
    if (argc < 3) {
 | 
			
		||||
	printf("Usage: %s <reps> <arch>...\n", argv[0]);
 | 
			
		||||
	exit(EXIT_FAILURE);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    reps = atoi(argv[1]);
 | 
			
		||||
    if (reps < 1) {
 | 
			
		||||
        printf("reps must be >= 1\n");
 | 
			
		||||
        exit(EXIT_FAILURE);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    src = read_directory("cur", argc - 2, argv + 2);
 | 
			
		||||
    oldsrc = read_directory("old", argc - 2, argv + 2); 
 | 
			
		||||
    srcsn = new_sources_note(argc - 2, argv + 2);
 | 
			
		||||
 | 
			
		||||
    printf("FINISHED LOADING\n"); fflush(stdout); /* sleep(5); */
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
    iterate_sourcetbl(oldsrc->sources, checkoldsrc, src);
 | 
			
		||||
 | 
			
		||||
    printf("FIRST\n");
 | 
			
		||||
    iterate_sourcetbl(src->sources, checkuptodate, src);
 | 
			
		||||
    printf("SECOND\n");
 | 
			
		||||
    iterate_sourcetbl(src->sources, checkuptodate, src);
 | 
			
		||||
    printf("END\n");
 | 
			
		||||
 | 
			
		||||
    iterate_sourcetbl(src->sources, checknewsrc, oldsrc);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    n_pkgs = 0;
 | 
			
		||||
    for (i = argc - 1; i > 1; i--) {
 | 
			
		||||
	pkgs[n_pkgs++] = get_architecture(oldsrc, argv[i]);
 | 
			
		||||
    }
 | 
			
		||||
    for (j = 0; j < reps; j++) {
 | 
			
		||||
	printf("Round %d/%d starting...\n", j + 1, reps);
 | 
			
		||||
        for (i = 0; i < n_pkgs; i++) {
 | 
			
		||||
            iterate_packagetbl(pkgs[i]->packages, checkpkgs, pkgs[i]);
 | 
			
		||||
        }
 | 
			
		||||
	printf("Round %d ended.\n", j+1);
 | 
			
		||||
    }
 | 
			
		||||
    iterate_sourcetbl(src->sources, upgrade, srcsn);
 | 
			
		||||
    iterate_sourcetbl(oldsrc->sources, upgrade, srcsn);
 | 
			
		||||
 | 
			
		||||
    for (i = 0; i < n_pkgs; i++) {
 | 
			
		||||
	free_packages(pkgs[i]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    srcpkg = lookup_sourcetbl(oldsrc->sources, "omirr");
 | 
			
		||||
    if (srcpkg != NULL) {
 | 
			
		||||
        printf("Adding old\n");
 | 
			
		||||
	upgrade_source(srcsn, srcpkg);
 | 
			
		||||
    }
 | 
			
		||||
    srcpkg = lookup_sourcetbl(src->sources, "omirr");
 | 
			
		||||
    if (srcpkg != NULL) {
 | 
			
		||||
        printf("Adding cur\n");
 | 
			
		||||
	upgrade_source(srcsn, srcpkg);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    printf("FINISHED PROCESSING\n"); fflush(stdout); /* sleep(5); */
 | 
			
		||||
 | 
			
		||||
    write_directory("out", oldsrc);
 | 
			
		||||
 | 
			
		||||
    printf("FINISHED WRITING\n"); fflush(stdout); /* sleep(5); */
 | 
			
		||||
 | 
			
		||||
    free_sources_note(srcsn);
 | 
			
		||||
    free_sources(src);
 | 
			
		||||
    free_sources(oldsrc);
 | 
			
		||||
 | 
			
		||||
    DEBUG_ONLY( print_memblock_summary(); )
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
@ -1,30 +0,0 @@
 | 
			
		||||
 | 
			
		||||
#include <apt-pkg/debversion.h>
 | 
			
		||||
 | 
			
		||||
extern "C" {
 | 
			
		||||
 | 
			
		||||
#include "dpkg.h"
 | 
			
		||||
 | 
			
		||||
int cmpversions(char *left, int op, char *right) {
 | 
			
		||||
	int i = debVS.CmpVersion(left, right);
 | 
			
		||||
 | 
			
		||||
	switch(op) {
 | 
			
		||||
		case dr_LT:    return i <  0;
 | 
			
		||||
		case dr_LTEQ:  return i <= 0;
 | 
			
		||||
		case dr_EQ:    return i == 0;
 | 
			
		||||
		case dr_GTEQ:  return i >= 0;
 | 
			
		||||
		case dr_GT:    return i >  0;
 | 
			
		||||
	}
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef TESTBIN
 | 
			
		||||
int main(int argc, char **argv) {
 | 
			
		||||
	if (argc != 3) { printf("Usage: %s <ver> <ver>\n", argv[0]); exit(1); }
 | 
			
		||||
 | 
			
		||||
	printf("%d\n", versioncmp(argv[1], argv[2]));
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										966
									
								
								lib/dpkg.c
									
									
									
									
									
								
							
							
						
						
									
										966
									
								
								lib/dpkg.c
									
									
									
									
									
								
							@ -1,966 +0,0 @@
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <ctype.h>
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
 | 
			
		||||
#include "dpkg.h"
 | 
			
		||||
#include "memory.h"
 | 
			
		||||
 | 
			
		||||
// enlarge this if britney has issues parsing packages
 | 
			
		||||
// (e.g. very slow installability checks)
 | 
			
		||||
#define SIZEOFHASHMAP 16
 | 
			
		||||
 | 
			
		||||
/* #define DIAGNOSE 1 */
 | 
			
		||||
 | 
			
		||||
#define insert_packagenamelist(x,y) insert_l_packagenamelist(x,y,__LINE__)
 | 
			
		||||
 | 
			
		||||
static void free_dependency(dependency *dep);
 | 
			
		||||
static void free_collected_package(dpkg_collected_package *pkg);
 | 
			
		||||
static collpackagelist **get_matching_low(collpackagelist **addto, 
 | 
			
		||||
		                          dpkg_packages *pkgs, dependency *dep, int line);
 | 
			
		||||
static collpackagelist *get_matching(dpkg_packages *pkgs, deplist *depopts, int line);
 | 
			
		||||
 | 
			
		||||
static deplist *read_deplist(char **buf, char sep, char end);
 | 
			
		||||
static dependency *read_dependency(char **buf, char *end);
 | 
			
		||||
static void add_virtualpackage(virtualpkgtbl *vpkgs, char *package, 
 | 
			
		||||
                               char *version, char *multiarch,
 | 
			
		||||
                               dpkg_collected_package *cpkg);
 | 
			
		||||
static void remove_virtualpackage(virtualpkgtbl *vpkgs, char *pkgname,
 | 
			
		||||
			          dpkg_collected_package *cpkg);
 | 
			
		||||
static char *read_packagename(char **buf, char *end);
 | 
			
		||||
static char *read_until_char(char **buf, char *end);
 | 
			
		||||
static int checkinstallable(dpkg_packages *pkgs, collpackagelist *instoneof);
 | 
			
		||||
 | 
			
		||||
// implemented in dpkg-lib.c
 | 
			
		||||
int cmpversions(char *left, int op, char *right);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#define block_malloc(s) block_malloc2(s, __LINE__)
 | 
			
		||||
 | 
			
		||||
static int dependency_counts[] = { 1, 1, 0, 0 };
 | 
			
		||||
 | 
			
		||||
#define SMB_SIZE (1<<22)
 | 
			
		||||
struct stringmemblock {
 | 
			
		||||
	struct stringmemblock *next;
 | 
			
		||||
	size_t last;
 | 
			
		||||
	char mem[SMB_SIZE];
 | 
			
		||||
};
 | 
			
		||||
static struct stringmemblock *stringmemory = NULL;
 | 
			
		||||
static int stringmemorycount = 0;
 | 
			
		||||
static const unsigned long stringmemblocksizekib = (unsigned long) sizeof(struct stringmemblock) / 1024;
 | 
			
		||||
 | 
			
		||||
static char *my_strdup(char *foo) {
 | 
			
		||||
	struct stringmemblock *which;
 | 
			
		||||
	size_t len;
 | 
			
		||||
 | 
			
		||||
	if (!foo) return NULL;
 | 
			
		||||
 | 
			
		||||
	len = strlen(foo) + 1;
 | 
			
		||||
 | 
			
		||||
	if (len > SMB_SIZE) return strdup(foo);
 | 
			
		||||
 | 
			
		||||
	for (which = stringmemory; which; which = which->next) {
 | 
			
		||||
		if (SMB_SIZE - which->last > len + 1) {
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if (!which) {
 | 
			
		||||
		which = malloc(sizeof(struct stringmemblock));
 | 
			
		||||
		if (!which) return NULL;
 | 
			
		||||
		MDEBUG1_ONLY(fprintf(stderr, 
 | 
			
		||||
			"ALLOC: string memblock %d (%lu KiB, %lu KiB total)\n", 
 | 
			
		||||
			stringmemorycount, stringmemblocksizekib,
 | 
			
		||||
                        (stringmemorycount+1) * stringmemblocksizekib));
 | 
			
		||||
		memset(which->mem, 0, SMB_SIZE);
 | 
			
		||||
		which->last = 0;
 | 
			
		||||
		which->next = stringmemory;
 | 
			
		||||
		stringmemory = which;
 | 
			
		||||
		stringmemorycount++;
 | 
			
		||||
	}
 | 
			
		||||
	strcpy(&which->mem[which->last], foo);
 | 
			
		||||
	foo = &which->mem[which->last];
 | 
			
		||||
	which->last += len;
 | 
			
		||||
	return foo;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* DIE **/
 | 
			
		||||
 | 
			
		||||
static void die(char *orig_msg) {
 | 
			
		||||
        char *msg = my_strdup(orig_msg);
 | 
			
		||||
        if (*msg && msg[strlen(msg)-1] == ':') {
 | 
			
		||||
                msg[strlen(msg)-1] = '\0';
 | 
			
		||||
                perror(msg);
 | 
			
		||||
        } else {
 | 
			
		||||
                printf("%s\n", msg);
 | 
			
		||||
        }
 | 
			
		||||
        abort();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*************************************************************************
 | 
			
		||||
 * Basic Package Operations
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
static dpkg_collected_package *new_collected_package(dpkg_package *pkg) {
 | 
			
		||||
    dpkg_collected_package *result;
 | 
			
		||||
 | 
			
		||||
    result = block_malloc(sizeof(dpkg_collected_package));
 | 
			
		||||
    if (result == NULL) die("new_collected_package alloc:");
 | 
			
		||||
 | 
			
		||||
    result->pkg = pkg;
 | 
			
		||||
 | 
			
		||||
    result->installed  = 0;
 | 
			
		||||
    result->conflicted = 0;
 | 
			
		||||
 | 
			
		||||
    result->installable = UNKNOWN;
 | 
			
		||||
    result->mayaffect = NULL;
 | 
			
		||||
 | 
			
		||||
    return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void free_collected_package(dpkg_collected_package *cpkg) {
 | 
			
		||||
    if (cpkg == NULL) return;
 | 
			
		||||
    cpkg->pkg = NULL;
 | 
			
		||||
    free_packagenamelist(cpkg->mayaffect);
 | 
			
		||||
    cpkg->mayaffect = NULL;
 | 
			
		||||
    block_free(cpkg, sizeof(dpkg_collected_package));
 | 
			
		||||
}   
 | 
			
		||||
 | 
			
		||||
LIST_IMPL(deplist, dependency*, free_dependency, block_malloc, block_free);
 | 
			
		||||
LIST_IMPL(deplistlist, deplist*, free_deplist, block_malloc, block_free);
 | 
			
		||||
 | 
			
		||||
LIST_IMPLX(packagenamelist, char*, KEEP(char*));
 | 
			
		||||
 | 
			
		||||
LIST_IMPL(ownedpackagenamelist, char*, KEEP(char*), block_malloc, block_free);
 | 
			
		||||
	/* ownedpackagenamelist stores the packagename in the string store */
 | 
			
		||||
 | 
			
		||||
static int packagecmp(dpkg_package *l, dpkg_package *r) {
 | 
			
		||||
    if (l->priority < r->priority) return -1;
 | 
			
		||||
    if (l->priority > r->priority) return +1;
 | 
			
		||||
    return strcmp(l->package, r->package);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* container for existing pkgs */
 | 
			
		||||
LIST_IMPL(packagelist, dpkg_package *, KEEP(dpkg_package *), block_malloc, block_free);
 | 
			
		||||
 | 
			
		||||
LIST_IMPLX(collpackagelist, dpkg_collected_package *, 
 | 
			
		||||
	  KEEP(dpkg_collected_package *))
 | 
			
		||||
#define insert_collpackagelist(x,y) insert_l_collpackagelist(x,y,__LINE__)
 | 
			
		||||
 | 
			
		||||
/*************************************************************************
 | 
			
		||||
 * Operations on distributions (collections of packages)
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
dpkg_packages *new_packages(char *arch) {
 | 
			
		||||
    dpkg_packages *result;
 | 
			
		||||
 | 
			
		||||
    result = block_malloc(sizeof(dpkg_packages));
 | 
			
		||||
    if (result == NULL) die("new_packages alloc:");
 | 
			
		||||
    
 | 
			
		||||
    result->arch = my_strdup(arch);
 | 
			
		||||
    result->packages = new_packagetbl();
 | 
			
		||||
    result->virtualpkgs = new_virtualpkgtbl();
 | 
			
		||||
 | 
			
		||||
    return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void add_package(dpkg_packages *pkgs, dpkg_package *pkg) 
 | 
			
		||||
{
 | 
			
		||||
    ownedpackagenamelist *v;
 | 
			
		||||
    dpkg_collected_package *cpkg;
 | 
			
		||||
 | 
			
		||||
    if (lookup_packagetbl(pkgs->packages, pkg->package) != NULL) 
 | 
			
		||||
	return;
 | 
			
		||||
 | 
			
		||||
    cpkg = new_collected_package(pkg);
 | 
			
		||||
 | 
			
		||||
    add_packagetbl(pkgs->packages, cpkg->pkg->package, cpkg);
 | 
			
		||||
	
 | 
			
		||||
    add_virtualpackage(pkgs->virtualpkgs, cpkg->pkg->package, 
 | 
			
		||||
		       cpkg->pkg->version, cpkg->pkg->multiarch, cpkg);
 | 
			
		||||
    for (v = cpkg->pkg->provides; v != NULL; v = v->next) {
 | 
			
		||||
	add_virtualpackage(pkgs->virtualpkgs, v->value, NULL, NULL, cpkg);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void remove_package(dpkg_packages *pkgs, dpkg_collected_package *cpkg) {
 | 
			
		||||
    ownedpackagenamelist *v;
 | 
			
		||||
    packagenamelist *aff;
 | 
			
		||||
    dpkg_collected_package *p;
 | 
			
		||||
 | 
			
		||||
    for (aff = cpkg->mayaffect; aff != NULL; aff = aff->next) {
 | 
			
		||||
	p = lookup_packagetbl(pkgs->packages, aff->value);
 | 
			
		||||
	if (p == NULL) continue;
 | 
			
		||||
	p->installable = UNKNOWN;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    p = remove_packagetbl(pkgs->packages, cpkg->pkg->package);
 | 
			
		||||
    if (p != cpkg) return;
 | 
			
		||||
	
 | 
			
		||||
    remove_virtualpackage(pkgs->virtualpkgs, cpkg->pkg->package, cpkg);
 | 
			
		||||
    for (v = cpkg->pkg->provides; v != NULL; v = v->next) {
 | 
			
		||||
	remove_virtualpackage(pkgs->virtualpkgs, v->value, cpkg);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    free_collected_package(cpkg);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void free_packages(dpkg_packages *pkgs) {
 | 
			
		||||
    if (pkgs == NULL) return;
 | 
			
		||||
    /* block_free(pkgs->arch); */
 | 
			
		||||
    free_packagetbl(pkgs->packages);
 | 
			
		||||
    free_virtualpkgtbl(pkgs->virtualpkgs);
 | 
			
		||||
    block_free(pkgs, sizeof(dpkg_packages));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
HASH_IMPL(packagetbl, char *, dpkg_collected_package *, SIZEOFHASHMAP, strhash, strcmp,
 | 
			
		||||
	  KEEP(char*),free_collected_package);
 | 
			
		||||
HASH_IMPL(virtualpkgtbl, char *, virtualpkg *, SIZEOFHASHMAP, strhash, strcmp,
 | 
			
		||||
	  KEEP(char*), free_virtualpkg);
 | 
			
		||||
 | 
			
		||||
/* dpkg_provision refers to memory allocated elsewhere */
 | 
			
		||||
LIST_IMPL(virtualpkg, dpkg_provision, KEEP(dpkg_provision), block_malloc, block_free);
 | 
			
		||||
 | 
			
		||||
static void remove_virtualpackage(virtualpkgtbl *vpkgs, char *pkgname,
 | 
			
		||||
			          dpkg_collected_package *cpkg)
 | 
			
		||||
{
 | 
			
		||||
    virtualpkg *list;
 | 
			
		||||
    virtualpkg **where;
 | 
			
		||||
    list = lookup_virtualpkgtbl(vpkgs, pkgname);
 | 
			
		||||
    assert(list != NULL);
 | 
			
		||||
 | 
			
		||||
    where = &list;
 | 
			
		||||
    while((*where)->value.pkg != cpkg) {
 | 
			
		||||
	where = &(*where)->next;
 | 
			
		||||
	assert(*where != NULL);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    delete_virtualpkg(where);
 | 
			
		||||
 | 
			
		||||
    if (list == NULL) {
 | 
			
		||||
	remove_virtualpkgtbl(vpkgs, pkgname);
 | 
			
		||||
    } else {
 | 
			
		||||
	replace_virtualpkgtbl(vpkgs, pkgname, list);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void add_virtualpackage(virtualpkgtbl *vpkgs, char *package, 
 | 
			
		||||
                               char *version, char *multiarch,
 | 
			
		||||
                               dpkg_collected_package *cpkg)
 | 
			
		||||
{
 | 
			
		||||
    dpkg_provision value;
 | 
			
		||||
    virtualpkg *list, **addto;
 | 
			
		||||
    int shouldreplace;
 | 
			
		||||
   
 | 
			
		||||
    value.pkg = cpkg;
 | 
			
		||||
    value.version = version;
 | 
			
		||||
    value.multiarch = multiarch;
 | 
			
		||||
    
 | 
			
		||||
    list = lookup_virtualpkgtbl(vpkgs, package);
 | 
			
		||||
    shouldreplace = (list != NULL);
 | 
			
		||||
 | 
			
		||||
    addto = &list;
 | 
			
		||||
    while (*addto != NULL
 | 
			
		||||
	   && packagecmp(cpkg->pkg, (*addto)->value.pkg->pkg) >= 0) 
 | 
			
		||||
    {
 | 
			
		||||
	addto = &(*addto)->next;
 | 
			
		||||
    }
 | 
			
		||||
    insert_virtualpkg(addto, value);
 | 
			
		||||
 | 
			
		||||
    if (shouldreplace) {
 | 
			
		||||
	replace_virtualpkgtbl(vpkgs, package, list);
 | 
			
		||||
	/* old list is included in new list, so we don't need to free */
 | 
			
		||||
    } else {
 | 
			
		||||
	add_virtualpkgtbl(vpkgs, package, list);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*************************************************************************
 | 
			
		||||
 * Parsing Helper Functions
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
ownedpackagenamelist *read_packagenames(char *buf) {
 | 
			
		||||
    ownedpackagenamelist *result = NULL;
 | 
			
		||||
    ownedpackagenamelist **addto = &result;
 | 
			
		||||
 | 
			
		||||
    DEBUG_ONLY( char *strend = buf + strlen(buf); )
 | 
			
		||||
    
 | 
			
		||||
    char *sub;
 | 
			
		||||
    
 | 
			
		||||
    while ((sub = my_strdup(read_packagename(&buf, ",")))) {
 | 
			
		||||
	insert_ownedpackagenamelist(addto, sub);
 | 
			
		||||
	addto = &(*addto)->next;
 | 
			
		||||
	
 | 
			
		||||
	while(isspace(*buf)) buf++;
 | 
			
		||||
	if (*buf == ',') {
 | 
			
		||||
	    buf++;
 | 
			
		||||
	    continue;
 | 
			
		||||
	}
 | 
			
		||||
	if (*buf == '\0') {
 | 
			
		||||
	    break;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	die("read_packagenames no/bad seperator");
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    DEBUG_ONLY( assert(buf <= strend); )
 | 
			
		||||
    
 | 
			
		||||
    return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static char *read_until_char(char **buf, char *end) {
 | 
			
		||||
    static char *result = NULL;
 | 
			
		||||
    char *start;
 | 
			
		||||
    DEBUG_ONLY( char *strend = *buf + strlen(*buf); )
 | 
			
		||||
    int n;
 | 
			
		||||
    
 | 
			
		||||
    while(isspace(**buf)) (*buf)++;
 | 
			
		||||
    
 | 
			
		||||
    start = *buf;
 | 
			
		||||
    while (**buf && !isspace(**buf) && strchr(end, **buf) == NULL) {
 | 
			
		||||
	(*buf)++;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    n = *buf - start;
 | 
			
		||||
    if (n == 0) return NULL;
 | 
			
		||||
    
 | 
			
		||||
    result = realloc(result, n + 1);
 | 
			
		||||
    if (result == NULL) die("read_until_char alloc:");
 | 
			
		||||
    
 | 
			
		||||
    strncpy(result, start, n);
 | 
			
		||||
    result[n] = '\0';
 | 
			
		||||
    
 | 
			
		||||
    while(isspace(**buf)) (*buf)++;
 | 
			
		||||
    
 | 
			
		||||
    DEBUG_ONLY( assert(*buf <= strend); )
 | 
			
		||||
    
 | 
			
		||||
    return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static char *read_packagename(char **buf, char *end) {
 | 
			
		||||
    return read_until_char(buf, end);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
deplist *read_dep_and(char *buf) {
 | 
			
		||||
    return read_deplist(&buf, ',', '\0'); 
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static deplist *read_deplist(char **buf, char sep, char end) {
 | 
			
		||||
    deplist *result = NULL;
 | 
			
		||||
    deplist **addto = &result;
 | 
			
		||||
    
 | 
			
		||||
    char separs[3] = { sep, end, '\0' };
 | 
			
		||||
    
 | 
			
		||||
    DEBUG_ONLY( char *strend = *buf + strlen(*buf); )
 | 
			
		||||
    
 | 
			
		||||
    dependency *sub;
 | 
			
		||||
    
 | 
			
		||||
    while ((sub = read_dependency(buf, separs))) {
 | 
			
		||||
	insert_deplist(addto, sub);
 | 
			
		||||
	addto = &(*addto)->next;
 | 
			
		||||
	
 | 
			
		||||
	while(isspace(**buf)) (*buf)++;
 | 
			
		||||
	if (**buf == sep) {
 | 
			
		||||
	    (*buf)++;
 | 
			
		||||
	    continue;
 | 
			
		||||
	}
 | 
			
		||||
	if (**buf == '\0' || **buf == end) {
 | 
			
		||||
	    break;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	die("read_deplist no/bad seperator");
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    DEBUG_ONLY( assert(*buf <= strend); )
 | 
			
		||||
    
 | 
			
		||||
    return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
deplistlist *read_dep_andor(char *buf) {
 | 
			
		||||
    deplistlist *result = NULL;
 | 
			
		||||
    deplistlist **addto = &result;
 | 
			
		||||
    
 | 
			
		||||
    deplist *sub;
 | 
			
		||||
    
 | 
			
		||||
    DEBUG_ONLY( char *strend = buf + strlen(buf); )
 | 
			
		||||
    
 | 
			
		||||
    while ((sub = read_deplist(&buf, '|', ','))) {
 | 
			
		||||
	insert_deplistlist(addto, sub);
 | 
			
		||||
	addto = &(*addto)->next;
 | 
			
		||||
	
 | 
			
		||||
	if (*buf == ',') buf++;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    DEBUG_ONLY( assert(buf <= strend); )
 | 
			
		||||
    
 | 
			
		||||
    return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static dependency *read_dependency(char **buf, char *end) {
 | 
			
		||||
    dependency *dep;
 | 
			
		||||
    char *name;
 | 
			
		||||
    char newend[11];
 | 
			
		||||
    DEBUG_ONLY( char *strend = *buf + strlen(*buf); )
 | 
			
		||||
    
 | 
			
		||||
    assert(strlen(end) <= 8);
 | 
			
		||||
    newend[0] = '('; newend[1] = ':'; strcpy(newend + 2, end);
 | 
			
		||||
    
 | 
			
		||||
    name = my_strdup(read_until_char(buf, newend));
 | 
			
		||||
    if (name == NULL) return NULL;
 | 
			
		||||
    
 | 
			
		||||
    dep = block_malloc(sizeof(dependency));
 | 
			
		||||
    if (dep == NULL) die("read_dependency alloc 1:");
 | 
			
		||||
    
 | 
			
		||||
    dep->package = name;
 | 
			
		||||
 | 
			
		||||
    if (**buf == ':') {
 | 
			
		||||
	(*buf)++;
 | 
			
		||||
	dep->archqual = my_strdup(read_until_char(buf, newend));
 | 
			
		||||
	if (dep->archqual == NULL) return NULL;
 | 
			
		||||
    } else
 | 
			
		||||
	dep->archqual = NULL;
 | 
			
		||||
    
 | 
			
		||||
    while(isspace(**buf)) (*buf)++;
 | 
			
		||||
    
 | 
			
		||||
    if (**buf != '(') {
 | 
			
		||||
	dep->op = dr_NOOP;
 | 
			
		||||
	dep->version = NULL;
 | 
			
		||||
    } else {
 | 
			
		||||
	(*buf)++;
 | 
			
		||||
	while(isspace(**buf)) (*buf)++;
 | 
			
		||||
	/* << , <= , = , >= , >> */
 | 
			
		||||
	if (**buf == '<') {
 | 
			
		||||
	    (*buf)++;
 | 
			
		||||
	    if (**buf == '<') {
 | 
			
		||||
		dep->op = dr_LT;
 | 
			
		||||
		(*buf)++;
 | 
			
		||||
	    } else if (**buf == '=') {
 | 
			
		||||
		dep->op = dr_LTEQ;
 | 
			
		||||
		(*buf)++;
 | 
			
		||||
	    } else {
 | 
			
		||||
		/* The forms `<' and `>' were used to mean earlier/later or 
 | 
			
		||||
		 * equal, rather than strictly earlier/later, so they should 
 | 
			
		||||
		 * not appear in new packages (though `dpkg' still supports 
 | 
			
		||||
		 * them).
 | 
			
		||||
		 */
 | 
			
		||||
		dep->op = dr_LTEQ;
 | 
			
		||||
	    }
 | 
			
		||||
	} else if (**buf == '>') {
 | 
			
		||||
	    (*buf)++;
 | 
			
		||||
	    if (**buf == '>') {
 | 
			
		||||
		dep->op = dr_GT;
 | 
			
		||||
		(*buf)++;
 | 
			
		||||
	    } else if (**buf == '=') {
 | 
			
		||||
		dep->op = dr_GTEQ;
 | 
			
		||||
		(*buf)++;
 | 
			
		||||
	    } else {
 | 
			
		||||
		dep->op = dr_GTEQ;
 | 
			
		||||
	    }
 | 
			
		||||
	} else if (**buf == '=') {
 | 
			
		||||
	    dep->op = dr_EQ;
 | 
			
		||||
	    (*buf)++;
 | 
			
		||||
	    if (**buf == '>') {
 | 
			
		||||
		dep->op = dr_GTEQ;
 | 
			
		||||
		(*buf)++;
 | 
			
		||||
	    } else if (**buf == '<') {
 | 
			
		||||
		dep->op = dr_LTEQ;
 | 
			
		||||
		(*buf)++;
 | 
			
		||||
	    }
 | 
			
		||||
	} else {
 | 
			
		||||
	    /* treat it as an implicit = :( */
 | 
			
		||||
	    dep->op = dr_EQ;
 | 
			
		||||
	    /* would prefer to: die("read_dependency unknown version op"); */
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	while (isspace(**buf)) (*buf)++;
 | 
			
		||||
	newend[0] = ')'; strcpy(newend + 1, end);
 | 
			
		||||
	dep->version = my_strdup(read_until_char(buf, newend));
 | 
			
		||||
	while (isspace(**buf)) (*buf)++;
 | 
			
		||||
	
 | 
			
		||||
	if (dep->version == NULL) die("read_dependency: no version");
 | 
			
		||||
	if (**buf != ')') die("read_dependency: unterminated version");
 | 
			
		||||
	(*buf)++;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    DEBUG_ONLY( assert(*buf <= strend); )
 | 
			
		||||
    
 | 
			
		||||
    return dep;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void free_dependency(dependency *dep) {
 | 
			
		||||
    if (dep == NULL) return;
 | 
			
		||||
    /* block_free(dep->package); */
 | 
			
		||||
    /* if (dep->version) block_free(dep->version); */
 | 
			
		||||
    block_free(dep, sizeof(dependency));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*************************************************************************
 | 
			
		||||
 * Installability Checking
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
static collpackagelist **get_matching_low(collpackagelist **addto, 
 | 
			
		||||
		                          dpkg_packages *pkgs, dependency *dep, int line)
 | 
			
		||||
{
 | 
			
		||||
    virtualpkg *vpkg;
 | 
			
		||||
    for (vpkg = lookup_virtualpkgtbl(pkgs->virtualpkgs, dep->package);
 | 
			
		||||
	 vpkg != NULL;
 | 
			
		||||
	 vpkg = vpkg->next)
 | 
			
		||||
    {
 | 
			
		||||
	int add;
 | 
			
		||||
 | 
			
		||||
	add = 0;
 | 
			
		||||
	if (dep->op == dr_NOOP) {
 | 
			
		||||
	    add = 1;
 | 
			
		||||
	} else if (vpkg->value.version != NULL) {
 | 
			
		||||
	    if (cmpversions(vpkg->value.version, dep->op, dep->version)) {
 | 
			
		||||
		add = 1;
 | 
			
		||||
	    }
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (dep->archqual != NULL) {
 | 
			
		||||
	    if (strcmp(dep->archqual, "any") == 0) {
 | 
			
		||||
		if (vpkg->value.multiarch == NULL || strcmp(vpkg->value.multiarch, "allowed") != 0)
 | 
			
		||||
		    add = 0;
 | 
			
		||||
	    } else
 | 
			
		||||
		add = 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (add) {
 | 
			
		||||
	    insert_l_collpackagelist(addto, vpkg->value.pkg, line);
 | 
			
		||||
	    addto = &(*addto)->next;
 | 
			
		||||
	}
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return addto;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static collpackagelist *get_matching(dpkg_packages *pkgs, deplist *depopts, int line) {
 | 
			
		||||
    collpackagelist *list = NULL;
 | 
			
		||||
    collpackagelist **addto = &list;
 | 
			
		||||
    
 | 
			
		||||
    for(; depopts != NULL; depopts = depopts->next) {
 | 
			
		||||
	addto = get_matching_low(addto, pkgs, depopts->value, line);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return list;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
typedef struct instonelist instonelist;
 | 
			
		||||
struct instonelist {
 | 
			
		||||
    collpackagelist *curX;
 | 
			
		||||
    collpackagelist *instoneX;
 | 
			
		||||
    int expandedX;
 | 
			
		||||
    struct instonelist *nextX, *prevX, *cutoffX;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define I1CUR(i1)      ((i1)->curX)
 | 
			
		||||
#define I1INSTONE(i1)  ((i1)->instoneX)
 | 
			
		||||
#define I1CUTOFF(i1)   ((i1)->cutoffX)
 | 
			
		||||
#define I1NEXT(i1)     ((i1)->nextX) /* can be modified ! */
 | 
			
		||||
#define I1PREV(i1)     ((i1)->prevX)
 | 
			
		||||
#define I1EXPANDED(i1) ((i1)->expandedX)
 | 
			
		||||
 | 
			
		||||
static instonelist *insert_instonelist(instonelist *where, collpackagelist *instone);
 | 
			
		||||
static void trim_instonelist_after(instonelist *first);
 | 
			
		||||
static void free_instonelist(instonelist *l);
 | 
			
		||||
 | 
			
		||||
static instonelist *insert_instonelist(instonelist *old, collpackagelist *instone)
 | 
			
		||||
{
 | 
			
		||||
    instonelist *n = block_malloc(sizeof(instonelist));
 | 
			
		||||
    if (n == NULL)
 | 
			
		||||
        die("insert_instonelist alloc:");
 | 
			
		||||
 | 
			
		||||
    n->curX = NULL;
 | 
			
		||||
    n->instoneX = instone;
 | 
			
		||||
    n->cutoffX = NULL;
 | 
			
		||||
    n->nextX = (old ? old->nextX : NULL);
 | 
			
		||||
    n->prevX = old;
 | 
			
		||||
    n->expandedX = 0;
 | 
			
		||||
 | 
			
		||||
    if (old) old->nextX = n;
 | 
			
		||||
    if (n->nextX) n->nextX->prevX = n;
 | 
			
		||||
 | 
			
		||||
    return n;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void trim_instonelist_after(instonelist *first) {
 | 
			
		||||
    if (!first->nextX) return;
 | 
			
		||||
    first->nextX->prevX = NULL;
 | 
			
		||||
    free_instonelist(first->nextX);
 | 
			
		||||
    first->nextX = NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void free_instonelist(instonelist *l) {
 | 
			
		||||
    instonelist *p, *k;
 | 
			
		||||
    if (!l) return;
 | 
			
		||||
    for (p = l; p->nextX; p = p->nextX);
 | 
			
		||||
    do {
 | 
			
		||||
        k = p;
 | 
			
		||||
        p = k->prevX;
 | 
			
		||||
        free_collpackagelist(k->instoneX);
 | 
			
		||||
        block_free(k, sizeof(instonelist));
 | 
			
		||||
    } while (k != l);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int caninstall(dpkg_packages *pkgs, dpkg_collected_package *cpkg) {
 | 
			
		||||
    collpackagelist *conflicts;
 | 
			
		||||
    collpackagelist *conf;
 | 
			
		||||
    int okay;
 | 
			
		||||
 | 
			
		||||
    if (cpkg->installed > 0) return 1;
 | 
			
		||||
    if (cpkg->conflicted > 0) return 0;
 | 
			
		||||
 | 
			
		||||
    conflicts = get_matching(pkgs, cpkg->pkg->conflicts, __LINE__);
 | 
			
		||||
 | 
			
		||||
    okay = 1;
 | 
			
		||||
    for (conf = conflicts; conf != NULL; conf = conf->next) {
 | 
			
		||||
	if (conf->value->installed > 0) {
 | 
			
		||||
	    okay = 0;
 | 
			
		||||
	    break;
 | 
			
		||||
	}
 | 
			
		||||
    }
 | 
			
		||||
    free_collpackagelist(conflicts);
 | 
			
		||||
    return okay;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void install(dpkg_packages *pkgs, dpkg_collected_package *cpkg) {
 | 
			
		||||
    if (cpkg->installed == 0) {
 | 
			
		||||
	collpackagelist *conflicts = get_matching(pkgs, cpkg->pkg->conflicts, __LINE__);
 | 
			
		||||
	collpackagelist *conf;
 | 
			
		||||
	for (conf = conflicts; conf != NULL; conf = conf->next) {
 | 
			
		||||
	    if (conf->value == cpkg) continue;
 | 
			
		||||
	    assert(conf->value->installed == 0);
 | 
			
		||||
	    conf->value->conflicted++;
 | 
			
		||||
	}
 | 
			
		||||
	free_collpackagelist(conflicts);
 | 
			
		||||
    }
 | 
			
		||||
    assert(cpkg->conflicted == 0);
 | 
			
		||||
    cpkg->installed++;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void uninstall(dpkg_packages *pkgs, dpkg_collected_package *cpkg) {
 | 
			
		||||
    assert(cpkg->installed > 0);
 | 
			
		||||
    assert(cpkg->conflicted == 0);
 | 
			
		||||
    cpkg->installed--;
 | 
			
		||||
    if (cpkg->installed == 0) {
 | 
			
		||||
	collpackagelist *conflicts = get_matching(pkgs, cpkg->pkg->conflicts, __LINE__);
 | 
			
		||||
	collpackagelist *conf;
 | 
			
		||||
	for (conf = conflicts; conf != NULL; conf = conf->next) {
 | 
			
		||||
	    if (conf->value == cpkg) continue;
 | 
			
		||||
	    assert(conf->value->installed == 0);
 | 
			
		||||
	    assert(conf->value->conflicted > 0);
 | 
			
		||||
	    conf->value->conflicted--;
 | 
			
		||||
	}
 | 
			
		||||
	free_collpackagelist(conflicts);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int checkinstallable2(dpkg_packages *pkgs, char *pkgname) {
 | 
			
		||||
    dpkg_collected_package *cpkg = lookup_packagetbl(pkgs->packages, pkgname);
 | 
			
		||||
    collpackagelist *cpl = NULL;
 | 
			
		||||
 | 
			
		||||
    if (cpkg == NULL) return 0;
 | 
			
		||||
 | 
			
		||||
    insert_collpackagelist(&cpl, cpkg);
 | 
			
		||||
    /* cpl gets freed in checkinstallable :-/ */
 | 
			
		||||
    return checkinstallable(pkgs, cpl);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void debug_checkinstallable(FILE *out, instonelist *list, 
 | 
			
		||||
	instonelist *last, instonelist *pointer) 
 | 
			
		||||
{
 | 
			
		||||
    instonelist *l;
 | 
			
		||||
    fprintf(out, "Status:");
 | 
			
		||||
 | 
			
		||||
    /* codes:   | = multiple options here
 | 
			
		||||
     *          @ = no options can satisfy this dep
 | 
			
		||||
     *          + = dependencies that can be expanded have been
 | 
			
		||||
     *          * = nothing selected yet
 | 
			
		||||
     *          > = where pointer points
 | 
			
		||||
     *          ^ = the cut point for where we are
 | 
			
		||||
     */
 | 
			
		||||
 | 
			
		||||
    for (l = list; ; l = I1NEXT(l)) {
 | 
			
		||||
	fprintf(out, " ");
 | 
			
		||||
	if (l == pointer)           fprintf(out, ">");
 | 
			
		||||
	if (l == I1CUTOFF(pointer)) fprintf(out, "^");
 | 
			
		||||
	if (I1INSTONE(l) == NULL) {
 | 
			
		||||
	    fprintf(out, "@");
 | 
			
		||||
	} else {
 | 
			
		||||
	    if (I1INSTONE(l)->next != NULL) {
 | 
			
		||||
		fprintf(out, "|");
 | 
			
		||||
	    }
 | 
			
		||||
	    if (I1EXPANDED(l)) {
 | 
			
		||||
		fprintf(out, "+");
 | 
			
		||||
	    }
 | 
			
		||||
	    if (I1CUR(l) == NULL) {
 | 
			
		||||
	        fprintf(out, "*%s", I1INSTONE(l)->value->pkg->package);
 | 
			
		||||
	    } else {
 | 
			
		||||
		fprintf(out, "%s", I1CUR(l)->value->pkg->package);
 | 
			
		||||
	    }
 | 
			
		||||
	}
 | 
			
		||||
	if (l == last) break;
 | 
			
		||||
    }
 | 
			
		||||
    fprintf(out, " ###\n");
 | 
			
		||||
    fflush(out);
 | 
			
		||||
}    
 | 
			
		||||
 | 
			
		||||
static int checkinstallable(dpkg_packages *pkgs, collpackagelist *instoneof) {
 | 
			
		||||
    /* We use pkg->installed, pkg->conflicted to note how many
 | 
			
		||||
     * times we've used this pkg to satisfy a dependency or installed
 | 
			
		||||
     * a package that conflicts with it.
 | 
			
		||||
     *    Thus: pkg->installed == 0, or pkg->conflicted == 0
 | 
			
		||||
     *
 | 
			
		||||
     * We assume these are okay initially, aren't being played with
 | 
			
		||||
     * concurrently elsewhere, and make sure they're still okay when
 | 
			
		||||
     * we return.
 | 
			
		||||
     */
 | 
			
		||||
   
 | 
			
		||||
    instonelist *list;
 | 
			
		||||
    instonelist *last;
 | 
			
		||||
    
 | 
			
		||||
    instonelist *pointer;
 | 
			
		||||
 | 
			
		||||
    unsigned long counter = 10000000;
 | 
			
		||||
 | 
			
		||||
    {
 | 
			
		||||
	collpackagelist *cpkg;
 | 
			
		||||
        for (cpkg = instoneof; cpkg; cpkg = cpkg->next) {
 | 
			
		||||
	    if (cpkg->value->installable == YES) {
 | 
			
		||||
		free_collpackagelist(instoneof);
 | 
			
		||||
		return 1;
 | 
			
		||||
	    }
 | 
			
		||||
	}
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    list = insert_instonelist(NULL, instoneof);
 | 
			
		||||
 | 
			
		||||
    last = list;
 | 
			
		||||
    pointer = list;
 | 
			
		||||
    
 | 
			
		||||
    while(--counter > 0 && pointer) {
 | 
			
		||||
	deplistlist *dep;
 | 
			
		||||
	dpkg_collected_package *instpkg; /* convenient alias */
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
#ifndef NDEBUG
 | 
			
		||||
	{
 | 
			
		||||
	    instonelist *p;
 | 
			
		||||
	    for (p = list; p != pointer; p = I1NEXT(p)) {
 | 
			
		||||
		assert(p != NULL);
 | 
			
		||||
		assert(I1CUR(p) != NULL);
 | 
			
		||||
		assert(I1CUR(p)->value != NULL);
 | 
			
		||||
		assert(I1CUR(p)->value->installed > 0);
 | 
			
		||||
		assert(I1CUR(p)->value->conflicted == 0);
 | 
			
		||||
	    }
 | 
			
		||||
	    if (I1NEXT(pointer) == NULL) {
 | 
			
		||||
		assert(pointer == last);
 | 
			
		||||
	    } else {
 | 
			
		||||
		for (p = I1NEXT(pointer); p; p = I1NEXT(p)) {
 | 
			
		||||
		    if (I1NEXT(p) == NULL) {
 | 
			
		||||
 			assert(p == last);
 | 
			
		||||
		    }
 | 
			
		||||
		    assert(I1CUR(p) == NULL);
 | 
			
		||||
		}
 | 
			
		||||
	    }
 | 
			
		||||
	}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef DIAGNOSE
 | 
			
		||||
        debug_checkinstallable(stdout, list, last, pointer);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	if (I1CUR(pointer) == NULL) {
 | 
			
		||||
	    I1CUR(pointer) = I1INSTONE(pointer);
 | 
			
		||||
	    /* try to choose an already installed package if there is one */
 | 
			
		||||
	    while (I1CUR(pointer) != NULL) {
 | 
			
		||||
		if (I1CUR(pointer)->value->installed != 0) {
 | 
			
		||||
		    break;
 | 
			
		||||
		}
 | 
			
		||||
		I1CUR(pointer) = I1CUR(pointer)->next;
 | 
			
		||||
	    }
 | 
			
		||||
	    if (I1CUR(pointer) == NULL) {
 | 
			
		||||
		I1CUR(pointer) = I1INSTONE(pointer);
 | 
			
		||||
	    }
 | 
			
		||||
	    assert(I1CUR(pointer) || !I1INSTONE(pointer));
 | 
			
		||||
 | 
			
		||||
	    I1CUTOFF(pointer) = last;
 | 
			
		||||
	} else {
 | 
			
		||||
	    uninstall(pkgs, I1CUR(pointer)->value);
 | 
			
		||||
	    trim_instonelist_after(I1CUTOFF(pointer));
 | 
			
		||||
	    last = I1CUTOFF(pointer);
 | 
			
		||||
	    
 | 
			
		||||
	    if (I1CUR(pointer)->value->installed > 0) {
 | 
			
		||||
		/* this dependency isn't the issue -- even doing
 | 
			
		||||
		 * nothing to satisfy it (ie, using an already
 | 
			
		||||
		 * installed package) doesn't do any good. So give up.  
 | 
			
		||||
		 */
 | 
			
		||||
		I1CUR(pointer) = NULL;
 | 
			
		||||
	    } else {
 | 
			
		||||
		I1CUR(pointer) = I1CUR(pointer)->next;
 | 
			
		||||
	    }
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	while(I1CUR(pointer) && !caninstall(pkgs, I1CUR(pointer)->value)) {
 | 
			
		||||
	    I1CUR(pointer) = I1CUR(pointer)->next;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	if (I1CUR(pointer) == NULL) {
 | 
			
		||||
	    if (I1PREV(pointer) == NULL) break;
 | 
			
		||||
	    pointer = I1PREV(pointer);
 | 
			
		||||
	    continue;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	instpkg = I1CUR(pointer)->value;
 | 
			
		||||
	
 | 
			
		||||
	install(pkgs, instpkg);
 | 
			
		||||
	
 | 
			
		||||
	assert(instpkg->installed > 0);
 | 
			
		||||
	if (instpkg->installed == 1) {
 | 
			
		||||
            /* if it's been installed exactly once, then this must've been
 | 
			
		||||
	     * the first time it was touched, so we need to look at the 
 | 
			
		||||
	     * dependencies. If it's the second or later, then we don't care 
 | 
			
		||||
	     * about them.
 | 
			
		||||
	     */
 | 
			
		||||
 | 
			
		||||
	    /* if any of the deps can't be satisfied, don't move on */
 | 
			
		||||
	    int bother = 1;
 | 
			
		||||
 | 
			
		||||
	    int expanded = I1EXPANDED(pointer);
 | 
			
		||||
 | 
			
		||||
	    for (i = 0; i < 4; i++) {
 | 
			
		||||
		if (!dependency_counts[i]) continue;
 | 
			
		||||
		for (dep = instpkg->pkg->depends[i];
 | 
			
		||||
		     dep != NULL; dep = dep->next)
 | 
			
		||||
		{
 | 
			
		||||
		    collpackagelist *thisdep = get_matching(pkgs, dep->value, __LINE__);
 | 
			
		||||
 | 
			
		||||
		    if (thisdep == NULL)  {
 | 
			
		||||
			bother = 0;
 | 
			
		||||
 | 
			
		||||
		    } else if (thisdep != NULL && thisdep->next == NULL) {
 | 
			
		||||
			collpackagelist *x;
 | 
			
		||||
 | 
			
		||||
			/* if there's only one way of fulfilling this dep,
 | 
			
		||||
			 * do it "ASAP"
 | 
			
		||||
			 */
 | 
			
		||||
 | 
			
		||||
			/* optimisation: if thisdep == foo, but the parent
 | 
			
		||||
			 * was foo|bar, then we already know "foo" is not going
 | 
			
		||||
			 * to work in this combination, and we can skip it.
 | 
			
		||||
			 *
 | 
			
		||||
			 * This deals with cases like X deps: Y|bar, bar deps: Y
 | 
			
		||||
			 * where bar is a virtual package; cf xlibs
 | 
			
		||||
			 */
 | 
			
		||||
			for (x = I1INSTONE(pointer); x != I1CUR(pointer); x = x->next) {
 | 
			
		||||
			    if (x->value == thisdep->value) {
 | 
			
		||||
			        bother = 0;
 | 
			
		||||
			        break;
 | 
			
		||||
			    }
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
		        if (I1INSTONE(pointer)->next == NULL) {
 | 
			
		||||
		            /* the parent of this entry essentially depends 
 | 
			
		||||
			     * on this too, so we'll get it out of the way 
 | 
			
		||||
			     * ASAP, to reduce the degree of exponentiation 
 | 
			
		||||
			     * in bad cases.
 | 
			
		||||
			     *
 | 
			
		||||
			     * _However_ we only want to do this _once_ for
 | 
			
		||||
			     * any particular node.
 | 
			
		||||
			     */
 | 
			
		||||
			    if (expanded) {
 | 
			
		||||
				/* thisdep isn't used! */
 | 
			
		||||
				free_collpackagelist(thisdep);
 | 
			
		||||
			    } else {
 | 
			
		||||
				insert_instonelist(pointer, thisdep);
 | 
			
		||||
	    			I1EXPANDED(pointer) = 1;
 | 
			
		||||
			    }
 | 
			
		||||
			} else {
 | 
			
		||||
			    insert_instonelist(I1CUTOFF(pointer), thisdep);
 | 
			
		||||
			}
 | 
			
		||||
			if (I1NEXT(last)) last = I1NEXT(last);
 | 
			
		||||
			assert(!I1NEXT(last));
 | 
			
		||||
 | 
			
		||||
		    } else {
 | 
			
		||||
			/* otherwise it's a multi possibility dep, so do it
 | 
			
		||||
			 * at the end
 | 
			
		||||
			 */
 | 
			
		||||
 | 
			
		||||
		        last = insert_instonelist(last, thisdep);
 | 
			
		||||
		    }
 | 
			
		||||
		}
 | 
			
		||||
	    }
 | 
			
		||||
	    if (!bother) {
 | 
			
		||||
		/* stay where we are, and try the next possibility */
 | 
			
		||||
		continue;
 | 
			
		||||
	    }
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	pointer = I1NEXT(pointer);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (counter == 0) {
 | 
			
		||||
	unsigned int package_count = 0;
 | 
			
		||||
	fprintf(stderr, "AIEEE: counter overflow:");
 | 
			
		||||
	assert(pointer != NULL);
 | 
			
		||||
	if (I1CUR(pointer) == NULL || I1CUR(pointer)->value == NULL) {
 | 
			
		||||
	    /* we're not guaranteed that pointer will make sense here */
 | 
			
		||||
	    pointer = I1PREV(pointer);
 | 
			
		||||
	}
 | 
			
		||||
	for (; pointer != NULL; pointer = I1PREV(pointer)) {
 | 
			
		||||
	    if (I1CUR(pointer) == NULL) {
 | 
			
		||||
		/* should only happen at pointer, so not here */
 | 
			
		||||
		fprintf(stderr, " >> eep, no packages at pointer <<");
 | 
			
		||||
		continue;
 | 
			
		||||
	    }
 | 
			
		||||
	    if (I1CUR(pointer)->value == NULL) {
 | 
			
		||||
		/* should never happen */
 | 
			
		||||
		fprintf(stderr, " >> eep, no package selected <<");
 | 
			
		||||
		continue;
 | 
			
		||||
	    }
 | 
			
		||||
	    /* the full list is no as interesting as the "guilty" package,
 | 
			
		||||
	     * display the number of involved packages instead */
 | 
			
		||||
#if 0
 | 
			
		||||
	    fprintf(stderr, " %s%s", 
 | 
			
		||||
		(I1INSTONE(pointer)->next == NULL ? "" : "|"),
 | 
			
		||||
		I1CUR(pointer)->value->pkg->package);
 | 
			
		||||
#endif
 | 
			
		||||
	    package_count++;
 | 
			
		||||
	    uninstall(pkgs, I1CUR(pointer)->value);
 | 
			
		||||
	}	
 | 
			
		||||
	fprintf(stderr, " %u involved packages.\n", package_count);
 | 
			
		||||
	free_instonelist(list);
 | 
			
		||||
	/* let the caller know we hit a bad failure */
 | 
			
		||||
	return -1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (pointer == NULL) {
 | 
			
		||||
	dpkg_collected_package *cpkg = I1CUR(list)->value;
 | 
			
		||||
	assert(cpkg->installable != YES);
 | 
			
		||||
	cpkg->installable = YES;
 | 
			
		||||
	for (pointer = last; pointer != NULL; pointer = I1PREV(pointer)) {
 | 
			
		||||
	    if (I1CUR(pointer)->value->installed == 1) {
 | 
			
		||||
		packagenamelist **p = &I1CUR(pointer)->value->mayaffect;
 | 
			
		||||
#if 0
 | 
			
		||||
		while ( *p && (*p)->value < cpkg->pkg->package ) {
 | 
			
		||||
		    p = &(*p)->next;
 | 
			
		||||
		}
 | 
			
		||||
                if (*p == NULL || (*p)->value > cpkg->pkg->package)
 | 
			
		||||
#endif
 | 
			
		||||
		{
 | 
			
		||||
		    insert_packagenamelist(p, cpkg->pkg->package);
 | 
			
		||||
		}
 | 
			
		||||
	    }
 | 
			
		||||
	    uninstall(pkgs, I1CUR(pointer)->value);
 | 
			
		||||
	}
 | 
			
		||||
	free_instonelist(list);
 | 
			
		||||
	return 1;
 | 
			
		||||
    } else {
 | 
			
		||||
	assert(I1CUR(list) == NULL);
 | 
			
		||||
	free_instonelist(list);
 | 
			
		||||
	return 0;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										139
									
								
								lib/dpkg.h
									
									
									
									
									
								
							
							
						
						
									
										139
									
								
								lib/dpkg.h
									
									
									
									
									
								
							@ -1,139 +0,0 @@
 | 
			
		||||
#ifndef DPKG_H
 | 
			
		||||
#define DPKG_H
 | 
			
		||||
 | 
			
		||||
#include "templates.h"
 | 
			
		||||
#include "memory.h"
 | 
			
		||||
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
 | 
			
		||||
/**************************************************************************
 | 
			
		||||
 * Coping with an rfc822-esque field 
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
typedef struct dpkg_entry dpkg_entry;
 | 
			
		||||
struct dpkg_entry {
 | 
			
		||||
    char *name;
 | 
			
		||||
    char *value;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef struct dpkg_paragraph dpkg_paragraph;
 | 
			
		||||
struct dpkg_paragraph {
 | 
			
		||||
    int n_entries;
 | 
			
		||||
    int n_allocated;
 | 
			
		||||
    dpkg_entry *entry;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**************************************************************************
 | 
			
		||||
 * Coping with a package (or many pkgs) as an abstract entity 
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
typedef enum {dr_NOOP,dr_LT,dr_LTEQ,dr_EQ,dr_GTEQ,dr_GT} dependency_relation;
 | 
			
		||||
extern char *dependency_relation_sym[];
 | 
			
		||||
 | 
			
		||||
typedef struct dependency dependency;
 | 
			
		||||
struct dependency {
 | 
			
		||||
    char *package;
 | 
			
		||||
    char *archqual;
 | 
			
		||||
    dependency_relation op;
 | 
			
		||||
    char *version;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
LIST(deplist, dependency*);
 | 
			
		||||
LIST(deplistlist, deplist*);
 | 
			
		||||
 | 
			
		||||
LIST(packagenamelist, char*);
 | 
			
		||||
LIST(ownedpackagenamelist, char*);
 | 
			
		||||
 | 
			
		||||
typedef struct dpkg_package dpkg_package;
 | 
			
		||||
 | 
			
		||||
struct dpkg_package {
 | 
			
		||||
    char *package;
 | 
			
		||||
    char *version;
 | 
			
		||||
    char *multiarch;
 | 
			
		||||
    
 | 
			
		||||
    char *source;
 | 
			
		||||
    char *source_ver;
 | 
			
		||||
    
 | 
			
		||||
    int priority;
 | 
			
		||||
 | 
			
		||||
    int arch_all;
 | 
			
		||||
    
 | 
			
		||||
    deplistlist          *depends[4];
 | 
			
		||||
    deplist              *conflicts;    
 | 
			
		||||
    ownedpackagenamelist *provides;
 | 
			
		||||
	
 | 
			
		||||
    dpkg_paragraph *details;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
LIST(packagelist, dpkg_package *);
 | 
			
		||||
LIST(ownedpackagelist, dpkg_package *);
 | 
			
		||||
 | 
			
		||||
/**************************************************************************
 | 
			
		||||
 * Coping with a source package (and collections thereof) as an abstract 
 | 
			
		||||
 * entity, owning a bunch of binary packages 
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**************************************************************************
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
typedef struct dpkg_collected_package dpkg_collected_package;
 | 
			
		||||
struct dpkg_collected_package {
 | 
			
		||||
    dpkg_package *pkg;
 | 
			
		||||
 | 
			
		||||
    int installed, conflicted;
 | 
			
		||||
 | 
			
		||||
    enum { UNKNOWN, YES } installable;
 | 
			
		||||
    packagenamelist *mayaffect;
 | 
			
		||||
 | 
			
		||||
    /* on update, the installability_checked of each /mayaffect/ed package
 | 
			
		||||
     * is cleared, and the mayaffect list is cleared.
 | 
			
		||||
     * 
 | 
			
		||||
     * note that installable = NO couldn't be maintained over adding a package
 | 
			
		||||
     * to testing. installable = YES can be, thanks to the mayaffect list
 | 
			
		||||
     * (once a package is removed, everything it mayaffect must be set back
 | 
			
		||||
     * to unknown, but everything else is okay)
 | 
			
		||||
     */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
LIST(collpackagelist, dpkg_collected_package *);
 | 
			
		||||
 | 
			
		||||
/**************************************************************************
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
typedef struct dpkg_provision dpkg_provision;
 | 
			
		||||
struct dpkg_provision {
 | 
			
		||||
    char *version;
 | 
			
		||||
    char *multiarch;
 | 
			
		||||
    dpkg_collected_package *pkg;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
LIST(virtualpkg, dpkg_provision);
 | 
			
		||||
 | 
			
		||||
HASH(virtualpkgtbl,char *,virtualpkg *);
 | 
			
		||||
HASH(packagetbl,char *,dpkg_collected_package *);
 | 
			
		||||
 | 
			
		||||
typedef struct dpkg_packages dpkg_packages;
 | 
			
		||||
struct dpkg_packages {
 | 
			
		||||
    char *arch;
 | 
			
		||||
    packagetbl *packages;
 | 
			
		||||
    virtualpkgtbl *virtualpkgs;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// Used by britney-py.c
 | 
			
		||||
 | 
			
		||||
void add_package(dpkg_packages *pkgs, dpkg_package *pkg);
 | 
			
		||||
void remove_package(dpkg_packages *pkgs, dpkg_collected_package *pkg);
 | 
			
		||||
dpkg_packages *new_packages(char *arch);
 | 
			
		||||
void free_packages(dpkg_packages *pkgs);
 | 
			
		||||
 | 
			
		||||
deplistlist *read_dep_andor(char *buf);
 | 
			
		||||
deplist *read_dep_and(char *buf);
 | 
			
		||||
ownedpackagenamelist *read_packagenames(char *buf);
 | 
			
		||||
 | 
			
		||||
int checkinstallable2(dpkg_packages *pkgs, char *pkgname);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
@ -1,28 +0,0 @@
 | 
			
		||||
#!/usr/bin/env python
 | 
			
		||||
 | 
			
		||||
import sys
 | 
			
		||||
import britney
 | 
			
		||||
 | 
			
		||||
# VERSION = 0
 | 
			
		||||
# SECTION = 1
 | 
			
		||||
# SOURCE = 2
 | 
			
		||||
# SOURCEVER = 3
 | 
			
		||||
# ARCHITECTURE = 4
 | 
			
		||||
# MULTIARCH = 5
 | 
			
		||||
# PREDEPENDS = 6
 | 
			
		||||
# DEPENDS = 7
 | 
			
		||||
# CONFLICTS = 8
 | 
			
		||||
# PROVIDES = 9
 | 
			
		||||
# RDEPENDS = 10
 | 
			
		||||
# RCONFLICTS = 11
 | 
			
		||||
 | 
			
		||||
packages = {'phpldapadmin': ['1.0', 'web', 'phpldapadmin', '1.0', 'all', None, '', 'apache2 (>= 2.0)', '', '', [], []],
 | 
			
		||||
            'apache2': ['2.0', 'web', 'apache2', '2.0', 'i386', None, '', '', 'phpldapadmin (<= 1.0~)', '', [], []],
 | 
			
		||||
           }
 | 
			
		||||
 | 
			
		||||
system = britney.buildSystem('i386', packages)
 | 
			
		||||
print system.is_installable('phpldapadmin'), system.packages
 | 
			
		||||
system.remove_binary('apache2')
 | 
			
		||||
print system.is_installable('phpldapadmin'), system.packages
 | 
			
		||||
system.add_binary('apache2', ['2.0', 'web', 'apache2', '2.0', 'i386', None, '', '', 'phpldapadmin (<= 1.0~)', '', [], []])
 | 
			
		||||
print system.is_installable('phpldapadmin'), system.packages
 | 
			
		||||
							
								
								
									
										188
									
								
								lib/freelist.c
									
									
									
									
									
								
							
							
						
						
									
										188
									
								
								lib/freelist.c
									
									
									
									
									
								
							@ -1,188 +0,0 @@
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include "templates.h"
 | 
			
		||||
 | 
			
		||||
typedef unsigned long ul;
 | 
			
		||||
 | 
			
		||||
#define SIZE          (sizeof(ul) * 8)
 | 
			
		||||
#define ROUND_DOWN(x) ((x) & ~(SIZE-1))
 | 
			
		||||
#define ROUND_UP(x)   ROUND_DOWN((x) + (SIZE-1))
 | 
			
		||||
#define NEXT_UP(x)    ROUND_DOWN((x) + SIZE)
 | 
			
		||||
#define NEXT_DOWN(x)  ROUND_DOWN((x) - 1)
 | 
			
		||||
 | 
			
		||||
#define SETBIT(s,p) \
 | 
			
		||||
		assert( (bits[(s)/SIZE] & (p)) == (setp ? 0 : (p)) ); \
 | 
			
		||||
		if (setp) bits[(s)/SIZE] |= (p); \
 | 
			
		||||
		else      bits[(s)/SIZE] &= ~(p)
 | 
			
		||||
 | 
			
		||||
#define GETBIT(s) (bits[ROUND_DOWN(s)/SIZE] & (1ul << (NEXT_UP(s) - s - 1)))
 | 
			
		||||
 | 
			
		||||
size_t count_free_bits_back(ul *bits, size_t s) {
 | 
			
		||||
	size_t cnt = 0;
 | 
			
		||||
	ul w = ROUND_DOWN(s) / SIZE;
 | 
			
		||||
	size_t add = s % SIZE;
 | 
			
		||||
	ul off = (~0ul) << (SIZE - add);
 | 
			
		||||
	ul H, d;
 | 
			
		||||
 | 
			
		||||
	while ((bits[w] & off) == 0) {
 | 
			
		||||
		cnt += add;
 | 
			
		||||
		add = SIZE;
 | 
			
		||||
		off = ~0ul;
 | 
			
		||||
		if (w == 0)
 | 
			
		||||
			return cnt;
 | 
			
		||||
		w--;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	H = add;
 | 
			
		||||
	add = 0;
 | 
			
		||||
	while ((d = (H - add) / 2) > 0) {
 | 
			
		||||
		ul offM = (off >> d) & off;
 | 
			
		||||
		if (bits[w] & offM) {
 | 
			
		||||
			off = offM;
 | 
			
		||||
			H = H - d;
 | 
			
		||||
		} else {
 | 
			
		||||
			add = H - d;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	cnt += add;
 | 
			
		||||
	return cnt;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
size_t count_free_bits_after(ul *bits, size_t s, size_t end) {
 | 
			
		||||
	size_t cnt = 0;
 | 
			
		||||
	ul w = ROUND_DOWN(s) / SIZE;
 | 
			
		||||
	size_t add = SIZE - s % SIZE;
 | 
			
		||||
	ul off = (~0ul) >> (SIZE - add);
 | 
			
		||||
	ul H, d;
 | 
			
		||||
 | 
			
		||||
	end /= SIZE;
 | 
			
		||||
 | 
			
		||||
	while ((bits[w] & off) == 0) {
 | 
			
		||||
		cnt += add;
 | 
			
		||||
		add = SIZE;
 | 
			
		||||
		off = ~0ul;
 | 
			
		||||
		w++;
 | 
			
		||||
		if (w == end)
 | 
			
		||||
			return cnt;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	H = add;
 | 
			
		||||
	add = 0;
 | 
			
		||||
	while ((d = (H - add) / 2) > 0) {
 | 
			
		||||
		ul offM = off << d;
 | 
			
		||||
		if (bits[w] & offM) {
 | 
			
		||||
			off = offM;
 | 
			
		||||
			H = H - d;
 | 
			
		||||
		} else {
 | 
			
		||||
			add = H - d;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	cnt += add;
 | 
			
		||||
	return cnt;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void find_long_freebits(ul *bits, size_t s, ul *start, size_t *size) {
 | 
			
		||||
        ul clen = 0;
 | 
			
		||||
        ul bstart = 0, blen = 0;
 | 
			
		||||
        ul i, k;
 | 
			
		||||
 | 
			
		||||
        for (i = 0; i < s; i++) {
 | 
			
		||||
                if (bits[i] == 0) {
 | 
			
		||||
			clen++;
 | 
			
		||||
		} else {
 | 
			
		||||
			if (clen > blen) {
 | 
			
		||||
				bstart = i - clen;
 | 
			
		||||
				blen = clen;
 | 
			
		||||
			}
 | 
			
		||||
			clen = 0;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (blen == 0) return;
 | 
			
		||||
 | 
			
		||||
	bstart *= SIZE; blen *= SIZE;
 | 
			
		||||
	k = count_free_bits_back(bits, bstart);
 | 
			
		||||
	bstart -= k; blen += k;
 | 
			
		||||
 | 
			
		||||
	blen += count_free_bits_after(bits, bstart + blen, s*SIZE);
 | 
			
		||||
 | 
			
		||||
	*start = bstart; *size = blen;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void mark_bits(ul *bits, ul s, size_t size, int setp) {
 | 
			
		||||
	ul e = s+size;
 | 
			
		||||
 | 
			
		||||
	ul rds = ROUND_DOWN(s);
 | 
			
		||||
	ul nus = rds + SIZE;
 | 
			
		||||
	ul rue = ROUND_UP(e);
 | 
			
		||||
 | 
			
		||||
	ul patl = (~0UL) >> (s % SIZE);
 | 
			
		||||
	ul patr = (~0UL) << (rue - e);
 | 
			
		||||
 | 
			
		||||
	assert(size > 0);
 | 
			
		||||
 | 
			
		||||
	/* bits[s1..e1] get touched, but bits[s1], bits[e1] only partially
 | 
			
		||||
	 *
 | 
			
		||||
	 * if s1 == e1, then bits[s1] get touched from [s%SIZE, e%SIZE)
 | 
			
		||||
	 * else
 | 
			
		||||
	 *     bits[s1] gets touched from [s%SIZE, SIZE)
 | 
			
		||||
	 *     bits[s2..e1) get reset completely
 | 
			
		||||
	 *     bits[e1] gets touched from [0, e%SIZE)
 | 
			
		||||
	 */
 | 
			
		||||
 | 
			
		||||
	if (nus >= e) {
 | 
			
		||||
		/* ROUND_DOWN(s) <= s < e <= NEXT_UP(s) */
 | 
			
		||||
		SETBIT(rds, patl & patr);
 | 
			
		||||
	} else {
 | 
			
		||||
		/* ROUND_DOWN(s) <= s < NEXT_UP(s) <= NEXT_DOWN(e) < e */
 | 
			
		||||
		ul rde = ROUND_DOWN(e);
 | 
			
		||||
 | 
			
		||||
		SETBIT(rds, patl);
 | 
			
		||||
		SETBIT(rde, patr);
 | 
			
		||||
		while (nus < rde) {	
 | 
			
		||||
			SETBIT(nus, ~0UL);
 | 
			
		||||
			nus += SIZE;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void print_bits(ul *bits, ul s) {
 | 
			
		||||
	ul i;
 | 
			
		||||
	putchar(' ');
 | 
			
		||||
	for (i = 0; i < s * SIZE; i++) {
 | 
			
		||||
		putchar( GETBIT(i) ? '1' : '0' );
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
	
 | 
			
		||||
#ifdef TESTBIN
 | 
			
		||||
 | 
			
		||||
#define X 2
 | 
			
		||||
int main(void) {
 | 
			
		||||
	ul memory[X];
 | 
			
		||||
	ul l, r;
 | 
			
		||||
	ul k = 5;
 | 
			
		||||
 | 
			
		||||
	memset(memory, 0, sizeof(memory));
 | 
			
		||||
	for (l = 0; l < X*SIZE; l += k) {
 | 
			
		||||
		for (r = 1; l+(r*r) < X*SIZE; r++) {
 | 
			
		||||
 | 
			
		||||
			printf("%lu %lu (%lu %lu", l, r*r,
 | 
			
		||||
			    (unsigned long) count_free_bits_back(memory, X*SIZE), (unsigned long) X*SIZE);
 | 
			
		||||
			mark_bits(memory, l, r*r, 1);
 | 
			
		||||
			printf("; %lu %lu %lu; %lu %lu %lu;): ", 
 | 
			
		||||
			    (unsigned long) count_free_bits_back(memory, X*SIZE) + l + r*r, 
 | 
			
		||||
			    (unsigned long) count_free_bits_after(memory, l + r*r, X*SIZE) + l + r*r,
 | 
			
		||||
			    (unsigned long) X*SIZE,
 | 
			
		||||
			    (unsigned long) count_free_bits_back(memory, l), 
 | 
			
		||||
			    (unsigned long) count_free_bits_after(memory, 0, X*SIZE), 
 | 
			
		||||
			    l);
 | 
			
		||||
			print_bits(memory, X);
 | 
			
		||||
			printf("\n");
 | 
			
		||||
 | 
			
		||||
			mark_bits(memory, l, r*r, 0);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
@ -1,14 +0,0 @@
 | 
			
		||||
 | 
			
		||||
#ifndef FREELIST_H
 | 
			
		||||
#define FREELIST_H
 | 
			
		||||
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
 | 
			
		||||
typedef unsigned long flb_t;
 | 
			
		||||
 | 
			
		||||
void mark_bits(flb_t *bits, flb_t s, size_t size, int setp);
 | 
			
		||||
size_t count_free_bits_back(flb_t *bits, size_t s);
 | 
			
		||||
size_t count_free_bits_after(flb_t *bits, size_t s, size_t end);
 | 
			
		||||
void find_long_freebits(flb_t *bits, flb_t s, flb_t *start, size_t *size);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
@ -1,18 +0,0 @@
 | 
			
		||||
<a href="README">README</a><br>
 | 
			
		||||
<a href="Makefile">Makefile</a><br>
 | 
			
		||||
<a href="assert.c">assert.c</a><br>
 | 
			
		||||
<a href="britney-py.c">britney-py.c</a><br>
 | 
			
		||||
<a href="checklib.c">checklib.c</a><br>
 | 
			
		||||
<a href="dpkg.c">dpkg.c</a><br>
 | 
			
		||||
<a href="freelist.c">freelist.c</a><br>
 | 
			
		||||
<a href="memory.c">memory.c</a><br>
 | 
			
		||||
<a href="memory2.c">memory2.c</a><br>
 | 
			
		||||
<a href="memory3.c">memory3.c</a><br>
 | 
			
		||||
<a href="dpkg-lib.cpp">dpkg-lib.cpp</a><br>
 | 
			
		||||
<a href="dpkg.h">dpkg.h</a><br>
 | 
			
		||||
<a href="freelist.h">freelist.h</a><br>
 | 
			
		||||
<a href="memory.h">memory.h</a><br>
 | 
			
		||||
<a href="templates.h">templates.h</a><br>
 | 
			
		||||
<a href="check_out.py">check_out.py</a><br>
 | 
			
		||||
<a href="check_uptodate.py">check_uptodate.py</a><br>
 | 
			
		||||
<a href="update_out.py">update_out.py</a><br>
 | 
			
		||||
							
								
								
									
										47
									
								
								lib/memory.h
									
									
									
									
									
								
							
							
						
						
									
										47
									
								
								lib/memory.h
									
									
									
									
									
								
							@ -1,47 +0,0 @@
 | 
			
		||||
#ifndef MEMORY_H
 | 
			
		||||
#define MEMORY_H
 | 
			
		||||
 | 
			
		||||
#if 1
 | 
			
		||||
 | 
			
		||||
void *block_malloc(size_t size);
 | 
			
		||||
void *block_malloc2(size_t size, int pool);
 | 
			
		||||
void block_free(void *vmem, size_t size);
 | 
			
		||||
 | 
			
		||||
#if defined(MDEBUG)
 | 
			
		||||
#define MDEBUG1
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define MDEBUG1_ONLY(x)
 | 
			
		||||
#define MDEBUG2_ONLY(x)
 | 
			
		||||
#define MDEBUG3_ONLY(x)
 | 
			
		||||
 | 
			
		||||
#ifdef MDEBUG3
 | 
			
		||||
#define MDEBUG1
 | 
			
		||||
#define MDEBUG2
 | 
			
		||||
#undef MDEBUG3_ONLY
 | 
			
		||||
#define MDEBUG3_ONLY(x) x
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef MDEBUG2
 | 
			
		||||
#define MDEBUG1
 | 
			
		||||
#undef MDEBUG2_ONLY
 | 
			
		||||
#define MDEBUG2_ONLY(x) x
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef MDEBUG1
 | 
			
		||||
#undef MDEBUG1_ONLY
 | 
			
		||||
#define MDEBUG1_ONLY(x) x
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
MDEBUG1_ONLY( void print_memblock_summary(void); )
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
 | 
			
		||||
#define block_malloc(x) malloc(x)
 | 
			
		||||
#define block_free(x, s) free(x)
 | 
			
		||||
 | 
			
		||||
static void print_memblock_summary(void) {}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif /* MEMORY_H */
 | 
			
		||||
							
								
								
									
										209
									
								
								lib/memory3.c
									
									
									
									
									
								
							
							
						
						
									
										209
									
								
								lib/memory3.c
									
									
									
									
									
								
							@ -1,209 +0,0 @@
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
 | 
			
		||||
#include "memory.h"
 | 
			
		||||
#include "templates.h"
 | 
			
		||||
#include "freelist.h"
 | 
			
		||||
 | 
			
		||||
typedef struct chunk chunk;
 | 
			
		||||
struct chunk {
 | 
			
		||||
    chunk *next; /* only used when in free_lists */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define GRAN             (sizeof (struct chunk))
 | 
			
		||||
#define ALLOC_SIZE       (1 << 20)
 | 
			
		||||
#define MAX_CHUNK_SIZE   256
 | 
			
		||||
#define NUM_BLOCK_TYPES  (MAX_CHUNK_SIZE / GRAN)
 | 
			
		||||
 | 
			
		||||
#ifdef MDEBUG1
 | 
			
		||||
#define MAX_POOLS        100
 | 
			
		||||
#else
 | 
			
		||||
#define MAX_POOLS        1
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef MDEBUG1
 | 
			
		||||
static void freesize(void *p, size_t s) { (void)s; free(p); }
 | 
			
		||||
static void die(char *blah) { perror(blah); abort(); }
 | 
			
		||||
 | 
			
		||||
LIST(alloclist, chunk *);
 | 
			
		||||
LIST_IMPL(alloclist, chunk *, KEEP(chunk *), malloc, freesize);
 | 
			
		||||
 | 
			
		||||
void print_memblock_summary2(int size);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
struct chunkpool {
 | 
			
		||||
    chunk *ch;
 | 
			
		||||
    MDEBUG1_ONLY( int pool_id; )
 | 
			
		||||
    MDEBUG1_ONLY( alloclist *all; )
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static struct chunkpool free_lists[NUM_BLOCK_TYPES][MAX_POOLS];
 | 
			
		||||
 | 
			
		||||
#ifdef MDEBUG1
 | 
			
		||||
static int total[NUM_BLOCK_TYPES][MAX_POOLS];
 | 
			
		||||
static int used[NUM_BLOCK_TYPES][MAX_POOLS];
 | 
			
		||||
static int allocs[NUM_BLOCK_TYPES][MAX_POOLS];
 | 
			
		||||
static int total_mallocs = 0;
 | 
			
		||||
static int total_alloc = 0;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
void *block_malloc(size_t size) {
 | 
			
		||||
    return block_malloc2(size, -1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void *block_malloc2(size_t size, int pool_id) {
 | 
			
		||||
    chunk **fl = NULL;
 | 
			
		||||
    void *result;
 | 
			
		||||
    int granmult;
 | 
			
		||||
    int pool = 0;
 | 
			
		||||
   
 | 
			
		||||
    if (size > MAX_CHUNK_SIZE || size % GRAN != 0) {
 | 
			
		||||
	MDEBUG1_ONLY( total_mallocs++; )
 | 
			
		||||
        return malloc(size);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    granmult = size / GRAN;
 | 
			
		||||
 | 
			
		||||
#ifdef MDEBUG1
 | 
			
		||||
    for (pool = 0; pool + 1 < MAX_POOLS; pool++) {
 | 
			
		||||
	if (free_lists[granmult - 1][pool].pool_id == 0) {
 | 
			
		||||
		free_lists[granmult - 1][pool].pool_id = pool_id;
 | 
			
		||||
	} 
 | 
			
		||||
	if (free_lists[granmult - 1][pool].pool_id == pool_id) {
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    fl = &free_lists[granmult - 1][pool].ch;
 | 
			
		||||
    if (*fl == NULL)
 | 
			
		||||
    {
 | 
			
		||||
        chunk *new_block = malloc(ALLOC_SIZE);
 | 
			
		||||
	chunk *p;
 | 
			
		||||
	MDEBUG1_ONLY( int old_size = total[granmult-1][pool]; )
 | 
			
		||||
 | 
			
		||||
	if (!new_block) return NULL;
 | 
			
		||||
 | 
			
		||||
	MDEBUG1_ONLY( insert_alloclist(&free_lists[granmult - 1][pool].all, new_block); )
 | 
			
		||||
 | 
			
		||||
        for (p = new_block; (char*)(p + granmult) <= ((char*)new_block) + ALLOC_SIZE; p += granmult) {
 | 
			
		||||
	    /* each iteration adds a new chunk to the list */
 | 
			
		||||
	    MDEBUG1_ONLY( total[granmult-1][pool]++; )
 | 
			
		||||
	    *fl = p;
 | 
			
		||||
	    fl = &p->next;
 | 
			
		||||
	}
 | 
			
		||||
	*fl = NULL;
 | 
			
		||||
        fl = &free_lists[granmult - 1][pool].ch;
 | 
			
		||||
	MDEBUG1_ONLY( assert((total[granmult-1][pool]-old_size)*size <= ALLOC_SIZE); )
 | 
			
		||||
	MDEBUG1_ONLY( assert(total[granmult-1][pool]*(int)size - old_size > ALLOC_SIZE - (int) size); )
 | 
			
		||||
 | 
			
		||||
#ifdef MDEBUG1
 | 
			
		||||
        // print some info
 | 
			
		||||
        MDEBUG2_ONLY(
 | 
			
		||||
	  fprintf(stderr, "ALLOC: for size %2ld (%d:line %d), %4ld B of %4ld B used, total alloced is %8ld KiB\n", (long int) size, pool, pool_id, (long int) used[granmult-1][pool] * size, (long int) total[granmult-1][pool] * size, (long int) total_alloc / 1024);
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
        assert( used[granmult-1][pool] <= (signed long) total[granmult-1][pool] );
 | 
			
		||||
 | 
			
		||||
        total_alloc += ALLOC_SIZE;
 | 
			
		||||
#endif
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#ifdef MDEBUG1
 | 
			
		||||
    {
 | 
			
		||||
	static unsigned long cnt = 0, cnt2 = 0;
 | 
			
		||||
        if (++cnt % (1L << 20) == 0) {
 | 
			
		||||
            if (++cnt2 % 10 == 0) {
 | 
			
		||||
  	        print_memblock_summary2(0);
 | 
			
		||||
	    } else {
 | 
			
		||||
	        print_memblock_summary();
 | 
			
		||||
	    }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    MDEBUG1_ONLY( used[granmult-1][pool]++; )
 | 
			
		||||
    MDEBUG1_ONLY( allocs[granmult-1][pool]++; )
 | 
			
		||||
 | 
			
		||||
    result = *fl;
 | 
			
		||||
    *fl = (*fl)->next;
 | 
			
		||||
    *(int *)result = ~0;
 | 
			
		||||
    return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef MDEBUG1
 | 
			
		||||
static int find_closest(void *vmem, size_t size, chunk **ch, int *p) {
 | 
			
		||||
    int pool;
 | 
			
		||||
    *ch = NULL;
 | 
			
		||||
 | 
			
		||||
    for (pool = 0; pool < MAX_POOLS; pool++) {
 | 
			
		||||
	alloclist *a;
 | 
			
		||||
	if (!free_lists[size/GRAN - 1][pool].all) break;
 | 
			
		||||
	for (a = free_lists[size/GRAN - 1][pool].all; a; a = a->next) {
 | 
			
		||||
	    if (*ch < a->value && a->value <= (chunk*)vmem) {
 | 
			
		||||
		*ch = a->value;
 | 
			
		||||
		*p = pool;
 | 
			
		||||
	    }
 | 
			
		||||
	}
 | 
			
		||||
    }
 | 
			
		||||
    assert((char*)*ch <= (char*)vmem);
 | 
			
		||||
    if ((char*)vmem - (char*)*ch < ALLOC_SIZE) {
 | 
			
		||||
	return 1;
 | 
			
		||||
    } else {
 | 
			
		||||
	return 0;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
void block_free(void *vmem, size_t size) {
 | 
			
		||||
    int pool = 0;
 | 
			
		||||
 | 
			
		||||
    if (size > MAX_CHUNK_SIZE || size % GRAN != 0) {
 | 
			
		||||
        free(vmem);
 | 
			
		||||
	return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#if MDEBUG1
 | 
			
		||||
    { chunk *closest;
 | 
			
		||||
    if (!find_closest(vmem, size, &closest, &pool)) {
 | 
			
		||||
	fprintf(stderr, "AIEE: %p + %lx < %p\n", closest, (unsigned long) ALLOC_SIZE, vmem);
 | 
			
		||||
	assert(0);
 | 
			
		||||
    }
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
		    
 | 
			
		||||
    MDEBUG1_ONLY( used[size/GRAN-1][pool]--; )
 | 
			
		||||
 | 
			
		||||
    {
 | 
			
		||||
	chunk **fl, *x;
 | 
			
		||||
        fl = &free_lists[size/GRAN - 1][pool].ch;
 | 
			
		||||
        x = (chunk *) vmem;
 | 
			
		||||
        x->next = *fl;
 | 
			
		||||
        *fl = x;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef MDEBUG1
 | 
			
		||||
 | 
			
		||||
void print_memblock_summary(void) {
 | 
			
		||||
    print_memblock_summary2(5*1024*1024);
 | 
			
		||||
}
 | 
			
		||||
void print_memblock_summary2(int size) {
 | 
			
		||||
    unsigned int i, j;
 | 
			
		||||
    fprintf(stderr, "MEMORY SUMMARY:\n");
 | 
			
		||||
    for (i = 0; i < NUM_BLOCK_TYPES; i++) {
 | 
			
		||||
        for (j = 0; j < MAX_POOLS; j++) {
 | 
			
		||||
	    if (total[i][j] * GRAN * (i+1) < size) continue;
 | 
			
		||||
	    if (free_lists[i][j].all != NULL) {
 | 
			
		||||
	        fprintf(stderr, " pool %dB/%d:%d; %d used %d allocated (%0.1f%% of %d MiB, %0.2f%% current)\n",
 | 
			
		||||
				(i+1) * GRAN, j, free_lists[i][j].pool_id,
 | 
			
		||||
				used[i][j], total[i][j],
 | 
			
		||||
				(100.0 * used[i][j]) / total[i][j],
 | 
			
		||||
				total[i][j] * GRAN * (i+1) / 1024 / 1024,
 | 
			
		||||
				(100.0 * used[i][j]) / allocs[i][j]);
 | 
			
		||||
	    }
 | 
			
		||||
	}
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
	
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										277
									
								
								lib/templates.h
									
									
									
									
									
								
							
							
						
						
									
										277
									
								
								lib/templates.h
									
									
									
									
									
								
							@ -1,277 +0,0 @@
 | 
			
		||||
#ifndef TEMPLATE_H
 | 
			
		||||
#define TEMPLATE_H
 | 
			
		||||
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include "memory.h"
 | 
			
		||||
 | 
			
		||||
#undef assert
 | 
			
		||||
   /* gcc-3.0 sucks */
 | 
			
		||||
 | 
			
		||||
#if defined(DEBUG) && defined(NDEBUG)
 | 
			
		||||
#error "Can't debug and notdebug both"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if !defined(DEBUG) && !defined(NDEBUG)
 | 
			
		||||
#define NDEBUG
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef NDEBUG
 | 
			
		||||
# define DEBUG_ONLY( stmt )
 | 
			
		||||
# define assert(x) (void)0
 | 
			
		||||
#else
 | 
			
		||||
# define DEBUG_ONLY( stmt ) stmt
 | 
			
		||||
# define assert(x) ((x) ? 1 : _myassertbug(__LINE__, __FILE__, #x))
 | 
			
		||||
 | 
			
		||||
extern int _myassertbug(int line, char *file, char *err);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef __STRICT_ANSI__
 | 
			
		||||
#define inline __inline__
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static inline unsigned long strhash(const char *x, unsigned char pow) {
 | 
			
		||||
    unsigned long i = 0;
 | 
			
		||||
    while (*x) {
 | 
			
		||||
        i = (i * 39 + *x) % (1UL << pow);
 | 
			
		||||
        x++;
 | 
			
		||||
    }
 | 
			
		||||
    return i;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#define KEEP(TYPE)  ((void(*)(TYPE))NULL)
 | 
			
		||||
 | 
			
		||||
#define LIST(NAME,TYPE)                                            \
 | 
			
		||||
    typedef struct NAME NAME;                                      \
 | 
			
		||||
    struct NAME { TYPE value; struct NAME *next; };                \
 | 
			
		||||
    void insert_##NAME(NAME **where, TYPE v);                      \
 | 
			
		||||
    void insert_l_##NAME(NAME **where, TYPE v, int line);          \
 | 
			
		||||
    TYPE remove_##NAME(NAME **where);                              \
 | 
			
		||||
    void delete_##NAME(NAME **where);                              \
 | 
			
		||||
    void free_##NAME(NAME *l)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#define LIST_IMPL_2(NAME,TYPE,FREE,LFREE)                          \
 | 
			
		||||
    TYPE remove_##NAME(NAME **where) {                             \
 | 
			
		||||
        NAME *next;                                                \
 | 
			
		||||
        TYPE res;                                                  \
 | 
			
		||||
        assert(*where != NULL);                                    \
 | 
			
		||||
        next = (*where)->next;                                     \
 | 
			
		||||
        res = (*where)->value;                                     \
 | 
			
		||||
        LFREE(*where, sizeof(NAME));                               \
 | 
			
		||||
        *where = next;                                             \
 | 
			
		||||
        return res;                                                \
 | 
			
		||||
    }                                                              \
 | 
			
		||||
    void delete_##NAME(NAME **where) {                             \
 | 
			
		||||
        NAME *next;                                                \
 | 
			
		||||
        assert(*where != NULL);                                    \
 | 
			
		||||
        next = (*where)->next;                                     \
 | 
			
		||||
        if (FREE != NULL) (FREE)((*where)->value);                 \
 | 
			
		||||
        LFREE(*where, sizeof(NAME));                               \
 | 
			
		||||
        *where = next;                                             \
 | 
			
		||||
    }                                                              \
 | 
			
		||||
    void free_##NAME(NAME *l) {                                    \
 | 
			
		||||
	NAME *n;                                                   \
 | 
			
		||||
	while (l != NULL) {                                        \
 | 
			
		||||
	    n = l->next;                                           \
 | 
			
		||||
	    if (FREE != NULL) (FREE)(l->value);                    \
 | 
			
		||||
	    LFREE(l, sizeof(NAME));                                \
 | 
			
		||||
	    l = n;                                                 \
 | 
			
		||||
	}                                                          \
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#define LIST_IMPL(NAME,TYPE,FREE,LMALLOC,LFREE)                    \
 | 
			
		||||
    void insert_##NAME(NAME **where, TYPE v) {                     \
 | 
			
		||||
	NAME *n = *where;                                          \
 | 
			
		||||
	*where = LMALLOC(sizeof(NAME));                            \
 | 
			
		||||
	if (*where == NULL)                                        \
 | 
			
		||||
		die("insert_" #NAME " malloc:");                   \
 | 
			
		||||
	(*where)->value = v;                                       \
 | 
			
		||||
	(*where)->next = n;                                        \
 | 
			
		||||
    }                                                              \
 | 
			
		||||
    LIST_IMPL_2(NAME,TYPE,FREE,LFREE)
 | 
			
		||||
 | 
			
		||||
#define LIST_IMPLX(NAME,TYPE,FREE)                                 \
 | 
			
		||||
    void insert_l_##NAME(NAME **where, TYPE v, int line) {         \
 | 
			
		||||
	NAME *n = *where;                                          \
 | 
			
		||||
	*where = block_malloc2(sizeof(NAME), line);                \
 | 
			
		||||
	if (*where == NULL)                                        \
 | 
			
		||||
		die("insert_" #NAME " malloc:");                   \
 | 
			
		||||
	(*where)->value = v;                                       \
 | 
			
		||||
	(*where)->next = n;                                        \
 | 
			
		||||
    }                                                              \
 | 
			
		||||
    LIST_IMPL_2(NAME,TYPE,FREE,block_free)
 | 
			
		||||
 | 
			
		||||
#define HASH(TYPE, KEY, VALUE)                                     \
 | 
			
		||||
    typedef struct TYPE TYPE;                                      \
 | 
			
		||||
    typedef struct TYPE##_iter TYPE##_iter;                        \
 | 
			
		||||
    struct TYPE##_iter {                                           \
 | 
			
		||||
        unsigned long i; TYPE *h; KEY k; VALUE v;                  \
 | 
			
		||||
    };                                                             \
 | 
			
		||||
    TYPE *new_##TYPE(void);                                        \
 | 
			
		||||
    void free_##TYPE(TYPE *h);                                     \
 | 
			
		||||
    TYPE##_iter first_##TYPE(TYPE *h);                             \
 | 
			
		||||
    TYPE##_iter next_##TYPE(TYPE##_iter i);                        \
 | 
			
		||||
    int done_##TYPE(TYPE##_iter i);                                \
 | 
			
		||||
                                                                   \
 | 
			
		||||
    void iterate_##TYPE(TYPE *h, void (*itf)(TYPE*,VALUE,void*),   \
 | 
			
		||||
                        void *data);                               \
 | 
			
		||||
    VALUE lookup_##TYPE(TYPE *h, KEY k);                           \
 | 
			
		||||
    void add_##TYPE(TYPE *h, KEY k, VALUE v);                      \
 | 
			
		||||
    VALUE replace_##TYPE(TYPE *h, KEY k, VALUE v);                 \
 | 
			
		||||
    VALUE remove_##TYPE(TYPE *h, KEY k)
 | 
			
		||||
 | 
			
		||||
#define HASH_MAGIC (0x22DEAD22)
 | 
			
		||||
 | 
			
		||||
#define HASH_IMPL(TYPE, KEY, VALUE, POW2, HASH, CMP, FREEK, FREEV) \
 | 
			
		||||
    struct TYPE {                                                  \
 | 
			
		||||
        unsigned long magic;                                       \
 | 
			
		||||
        unsigned long size;                                        \
 | 
			
		||||
        unsigned long n_used;                                      \
 | 
			
		||||
        unsigned long n_collisions;                                \
 | 
			
		||||
        struct { KEY key; VALUE value; } *hash;                    \
 | 
			
		||||
    };                                                             \
 | 
			
		||||
    TYPE *new_##TYPE(void) {                                       \
 | 
			
		||||
        size_t i;                                                  \
 | 
			
		||||
        TYPE *h = malloc(sizeof(TYPE));                            \
 | 
			
		||||
        if (h == NULL) die("new_" #TYPE " malloc:");               \
 | 
			
		||||
                                                                   \
 | 
			
		||||
        h->magic = HASH_MAGIC;                                     \
 | 
			
		||||
        h->size = (1 << POW2);                                     \
 | 
			
		||||
        h->n_used = 0;                                             \
 | 
			
		||||
        h->n_collisions = 0;                                       \
 | 
			
		||||
        h->hash = malloc(sizeof(*h->hash) * h->size );             \
 | 
			
		||||
        if (h == NULL) die("new_" #TYPE " hash malloc:");          \
 | 
			
		||||
                                                                   \
 | 
			
		||||
        for (i = 0; i < h->size; i++) {                            \
 | 
			
		||||
            h->hash[i].key   = NULL;                               \
 | 
			
		||||
            h->hash[i].value = NULL;                               \
 | 
			
		||||
        }                                                          \
 | 
			
		||||
                                                                   \
 | 
			
		||||
        return h;                                                  \
 | 
			
		||||
    }                                                              \
 | 
			
		||||
                                                                   \
 | 
			
		||||
    void free_##TYPE(TYPE *h) {                                    \
 | 
			
		||||
        size_t i;                                                  \
 | 
			
		||||
        if (h == NULL) return;                                     \
 | 
			
		||||
        assert(h->magic == HASH_MAGIC);                            \
 | 
			
		||||
    /*  printf("Freeing: size: %lu used: %lu coll: %lu\n", */      \
 | 
			
		||||
    /*         h->size, h->n_used, h->n_collisions);       */      \
 | 
			
		||||
        h->magic = ~HASH_MAGIC;                                    \
 | 
			
		||||
        for (i = 0; i < h->size; i++) {                            \
 | 
			
		||||
            if (FREEK && h->hash[i].key)                           \
 | 
			
		||||
                (FREEK)(h->hash[i].key);                           \
 | 
			
		||||
            if (FREEV && h->hash[i].value)                         \
 | 
			
		||||
                (FREEV)(h->hash[i].value);                         \
 | 
			
		||||
        }                                                          \
 | 
			
		||||
        free(h->hash);                                             \
 | 
			
		||||
        free(h);                                                   \
 | 
			
		||||
    }                                                              \
 | 
			
		||||
                                                                   \
 | 
			
		||||
    void iterate_##TYPE(TYPE *h, void (*itf)(TYPE*,VALUE,void*),   \
 | 
			
		||||
                        void *data)                                \
 | 
			
		||||
    {                                                              \
 | 
			
		||||
        TYPE##_iter x;                                             \
 | 
			
		||||
        for (x = first_##TYPE(h);                                  \
 | 
			
		||||
             !done_##TYPE(x);                                      \
 | 
			
		||||
             x = next_##TYPE(x))                                   \
 | 
			
		||||
        {                                                          \
 | 
			
		||||
            itf(h, x.v, data);                                     \
 | 
			
		||||
        }                                                          \
 | 
			
		||||
    }                                                              \
 | 
			
		||||
                                                                   \
 | 
			
		||||
    TYPE##_iter first_##TYPE(TYPE *h) {                            \
 | 
			
		||||
        TYPE##_iter i;                                             \
 | 
			
		||||
        i.i = 0;                                                   \
 | 
			
		||||
        i.h = h;                                                   \
 | 
			
		||||
        return next_##TYPE(i);                                     \
 | 
			
		||||
    }                                                              \
 | 
			
		||||
                                                                   \
 | 
			
		||||
    TYPE##_iter next_##TYPE(TYPE##_iter i) {                       \
 | 
			
		||||
        assert(i.h->magic == HASH_MAGIC);                          \
 | 
			
		||||
        while(i.i < i.h->size) {                                   \
 | 
			
		||||
            if (i.h->hash[i.i].value != NULL) {                    \
 | 
			
		||||
                i.k = i.h->hash[i.i].key;                          \
 | 
			
		||||
                i.v = i.h->hash[i.i].value;                        \
 | 
			
		||||
                i.i++;                                             \
 | 
			
		||||
                return i;                                          \
 | 
			
		||||
            }                                                      \
 | 
			
		||||
            i.i++;                                                 \
 | 
			
		||||
        }                                                          \
 | 
			
		||||
        i.h = NULL;                                                \
 | 
			
		||||
        return i;                                                  \
 | 
			
		||||
    }                                                              \
 | 
			
		||||
                                                                   \
 | 
			
		||||
    int done_##TYPE(TYPE##_iter i) {                               \
 | 
			
		||||
        assert(i.h == NULL || i.h->magic == HASH_MAGIC);           \
 | 
			
		||||
        assert(i.h == NULL || (i.k != NULL && i.v != NULL));       \
 | 
			
		||||
        assert(i.h == NULL || (0 < i.i && i.i <= i.h->size));      \
 | 
			
		||||
        return i.h == NULL;                                        \
 | 
			
		||||
    }                                                              \
 | 
			
		||||
                                                                   \
 | 
			
		||||
    VALUE lookup_##TYPE(TYPE *h, KEY k) {                          \
 | 
			
		||||
        int i = HASH(k, POW2);                                     \
 | 
			
		||||
        assert(h->magic == HASH_MAGIC);                            \
 | 
			
		||||
        assert(h->n_used < h->size); /* ensure termination */      \
 | 
			
		||||
        while(h->hash[i].key) {                                    \
 | 
			
		||||
            if ((CMP)(h->hash[i].key, k) == 0) {                   \
 | 
			
		||||
                if (h->hash[i].value != NULL) {                    \
 | 
			
		||||
                    return h->hash[i].value;                       \
 | 
			
		||||
                }                                                  \
 | 
			
		||||
            }                                                      \
 | 
			
		||||
            i = (i + 1) % (1 << POW2);                             \
 | 
			
		||||
        }                                                          \
 | 
			
		||||
        return NULL;                                               \
 | 
			
		||||
    }                                                              \
 | 
			
		||||
                                                                   \
 | 
			
		||||
    void add_##TYPE(TYPE *h, KEY k, VALUE v) {                     \
 | 
			
		||||
        int i = HASH(k, POW2);                                     \
 | 
			
		||||
        assert(h->magic == HASH_MAGIC);                            \
 | 
			
		||||
        assert(h->n_used < h->size); /* ensure termination */      \
 | 
			
		||||
        assert(v != NULL);                                         \
 | 
			
		||||
        while(h->hash[i].value) {                                  \
 | 
			
		||||
            assert((CMP)(h->hash[i].key, k) != 0);                 \
 | 
			
		||||
            i = (i + 1) % (1 << POW2);                             \
 | 
			
		||||
            h->n_collisions++;                                     \
 | 
			
		||||
        }                                                          \
 | 
			
		||||
        if (FREEK != NULL && h->hash[i].key)                       \
 | 
			
		||||
            FREEK(h->hash[i].key);                                 \
 | 
			
		||||
        h->n_used++;                                               \
 | 
			
		||||
        h->hash[i].key = k;                                        \
 | 
			
		||||
        h->hash[i].value = v;                                      \
 | 
			
		||||
    }                                                              \
 | 
			
		||||
                                                                   \
 | 
			
		||||
    VALUE replace_##TYPE(TYPE *h, KEY k, VALUE v) {                \
 | 
			
		||||
        VALUE tmp;                                                 \
 | 
			
		||||
        int i = HASH(k,POW2);                                      \
 | 
			
		||||
        assert(h->magic == HASH_MAGIC);                            \
 | 
			
		||||
        assert(v != NULL);                                         \
 | 
			
		||||
        while(h->hash[i].key) {                                    \
 | 
			
		||||
            if ((CMP)(h->hash[i].key, k) == 0) break;              \
 | 
			
		||||
            i = (i + 1) % (1 << POW2);                             \
 | 
			
		||||
        }                                                          \
 | 
			
		||||
        assert(h->hash[i].value != NULL);                          \
 | 
			
		||||
        tmp = h->hash[i].value;                                    \
 | 
			
		||||
        h->hash[i].key = k;                                        \
 | 
			
		||||
        h->hash[i].value = v;                                      \
 | 
			
		||||
        return tmp;                                                \
 | 
			
		||||
    }                                                              \
 | 
			
		||||
                                                                   \
 | 
			
		||||
    VALUE remove_##TYPE(TYPE *h, KEY k) {                          \
 | 
			
		||||
        VALUE tmp;                                                 \
 | 
			
		||||
        int i = HASH(k, POW2);                                     \
 | 
			
		||||
        assert(h->magic == HASH_MAGIC);                            \
 | 
			
		||||
        while(h->hash[i].key) {                                    \
 | 
			
		||||
            if ((CMP)(h->hash[i].key, k) == 0) break;              \
 | 
			
		||||
            i = (i + 1) % (1 << POW2);                             \
 | 
			
		||||
        }                                                          \
 | 
			
		||||
        tmp = h->hash[i].value;                                    \
 | 
			
		||||
        h->hash[i].value = NULL;                                   \
 | 
			
		||||
        if (tmp != NULL) h->n_used--;                              \
 | 
			
		||||
        return tmp;                                                \
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										13
									
								
								lib/thoughts
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								lib/thoughts
									
									
									
									
									
								
							@ -1,13 +0,0 @@
 | 
			
		||||
remove_source(name)                      source exists
 | 
			
		||||
	remove_sourcetbl
 | 
			
		||||
	remove the binaries?? but how?
 | 
			
		||||
upgrade_source(dpkg_source)              source may exist
 | 
			
		||||
	remove_source(src->name)
 | 
			
		||||
	add the new source to the table thing
 | 
			
		||||
	foreach arch, binary: add binary to arch pkgs
 | 
			
		||||
upgrade_architecture(dpkg_source, arch)  source exists, binary may
 | 
			
		||||
	find source
 | 
			
		||||
	foreach binary in <arch>: remove it
 | 
			
		||||
	foreach binary in new <arch>: add it
 | 
			
		||||
 | 
			
		||||
(remove_architecture, upgrade_source_only; could also be used, theoretically)
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user