Attaching mentioned patches.
diff -ru deborphan-1.7.14/debian/changelog deborphan-1.7.14circ/debian/changelog
--- deborphan-1.7.14/debian/changelog	2004-12-06 19:17:43.000000000 +0100
+++ deborphan-1.7.14circ/debian/changelog	2004-12-13 21:11:07.000000000 +0100
@@ -1,3 +1,10 @@
+deborphan (1.7.14circ) unstable; urgency=low
+
+  * Added an option to detect orphaned circular dependencies. Orphaner
+    doesn't accept this option yet.
+
+ -- Daniel Dechelotte <[EMAIL PROTECTED]>  Mon, 13 Dec 2004 21:11:00 +0100
+
 deborphan (1.7.14) unstable; urgency=medium
 
   * Make the dependency on gettext-base versioned (>= 0.14.1-6).
diff -ru deborphan-1.7.14/doc/deborphan.1 deborphan-1.7.14circ/doc/deborphan.1
--- deborphan-1.7.14/doc/deborphan.1	2004-07-13 17:51:52.000000000 +0200
+++ deborphan-1.7.14circ/doc/deborphan.1	2004-12-13 21:09:09.000000000 +0100
@@ -55,7 +55,7 @@
 Show the installed size of the packages found.
 .TP
 \fB-s, \-\-show\-section\fP
-Show the sections the packages are in.
+Show the sections the packages are in. When \fB\-\-find\-circular\fR is activated, section is printed if common to all packages, "*" is printed otherwise (ie. packages belong to different sections).
 .TP
 \fB\-\-no\-show\-section\fP
 Override showing sections when the default is to show them (see \fB\-\-all-packages\fR).
@@ -68,6 +68,9 @@
 Nice-mode checks if there is a package `suggesting' or `recommending' the package.
 If one is found, the package will be marked as in use, or, when \fB\-\-show\-deps\fR is used, print out the package suggesting the package as if it were depending on it.
 .TP
+\fB\-c, \-\-find\-circular\fP
+Track circular dependencies as well.
+.TP
 \fB-a, \-\-all\-packages\fP
 Check all the packages, instead of only those in the libs section. Best used (if at all used) in combination with \fB\-\-priority\fR. This option implies \fB\-\-show-section\fR.
 .\"  , when compiled with ALL_PACKAGES_IMPLY_SECTION defined (default)
diff -ru deborphan-1.7.14/include/deborphan.h deborphan-1.7.14circ/include/deborphan.h
--- deborphan-1.7.14/include/deborphan.h	2004-04-21 14:20:43.000000000 +0200
+++ deborphan-1.7.14circ/include/deborphan.h	2004-12-13 21:09:09.000000000 +0100
@@ -64,6 +64,13 @@
 #define INIT_DEPENDS_COUNT 32
 #define INIT_PROVIDES_COUNT 4
 
+typedef enum {
+    NORMAL = 0,
+    DEACTIVATED,
+    UPHILL,
+    DOWNHILL
+} Activity;
+
 /* These arrays aren't exactly neat, but it seems they suffice. */
 typedef struct pkg_info {
      dep self;
@@ -80,6 +87,7 @@
      int  essential;
      int  dummy;
      int  config;
+     Activity activity;
      long installed_size;
      struct pkg_info *next;
 } pkg_info;
@@ -104,6 +112,7 @@
      ZERO_KEEP,
      FIND_CONFIG,
      SEARCH_LIBDEVEL,
+     FIND_CIRCULAR,
      NUM_OPTIONS /* THIS HAS TO BE THE LAST OF THIS ENUM! */
 };
 
@@ -149,6 +158,7 @@
 
 /* libdeps.c */
 void check_lib_deps(pkg_info *package, pkg_info *current_pkg);
+void find_remaining_circular_deps(pkg_info *package);
 
 /* exit.c */
 void error(int exit_status, int error_no, const char *format, ...);
diff -ru deborphan-1.7.14/po/deborphan.pot deborphan-1.7.14circ/po/deborphan.pot
--- deborphan-1.7.14/po/deborphan.pot	2004-12-06 19:20:19.000000000 +0100
+++ deborphan-1.7.14circ/po/deborphan.pot	2004-12-13 21:09:09.000000000 +0100
@@ -75,144 +75,149 @@
 
 #: src/exit.c:106
 #, c-format
+msgid "-c        Find orphaned circular dependencies.\n"
+msgstr ""
+
+#: src/exit.c:109
+#, c-format
 msgid "-a        Compare all packages, not just libs.\n"
 msgstr ""
 
-#: src/exit.c:108
+#: src/exit.c:111
 #, c-format
 msgid ""
 "--libdevel                  Search in libdevel in addition to libs and "
 "oldlibs.\n"
 msgstr ""
 
-#: src/exit.c:111
+#: src/exit.c:114
 #, c-format
 msgid "-e LIST   Work as if packages in LIST were not installed.\n"
 msgstr ""
 
-#: src/exit.c:114
+#: src/exit.c:117
 #, c-format
 msgid "-p PRIOR  Select only packages with priority >= PRIOR.\n"
 msgstr ""
 
-#: src/exit.c:117
+#: src/exit.c:120
 #, c-format
 msgid "-H        Ignore hold flags.\n"
 msgstr ""
 
-#: src/exit.c:119
+#: src/exit.c:122
 #, c-format
 msgid "--find-config               Find \"orphaned\" configuration files.\n"
 msgstr ""
 
-#: src/exit.c:124
+#: src/exit.c:127
 #, c-format
 msgid "-A PKGS.. Never report PKGS.\n"
 msgstr ""
 
-#: src/exit.c:127
+#: src/exit.c:130
 #, c-format
 msgid "-R PKGS.. Report PKGS if there are no dependencies.\n"
 msgstr ""
 
-#: src/exit.c:130
+#: src/exit.c:133
 #, c-format
 msgid "-L        List the packages that are never reported.\n"
 msgstr ""
 
-#: src/exit.c:133
+#: src/exit.c:136
 #, c-format
 msgid "-Z        Remove all packages from the \"keep\" file.\n"
 msgstr ""
 
-#: src/exit.c:136
+#: src/exit.c:139
 #, c-format
 msgid "-k FILE   Use FILE to get/store info about kept packages.\n"
 msgstr ""
 
-#: src/exit.c:139
+#: src/exit.c:142
 #, c-format
 msgid "--df-keep                   Read debfoster's \"keepers\" file.\n"
 msgstr ""
 
-#: src/exit.c:140
+#: src/exit.c:143
 #, c-format
 msgid "--no-df-keep                Do not read debfoster's \"keepers\" file.\n"
 msgstr ""
 
 #. guessing
-#: src/exit.c:145
+#: src/exit.c:148
 #, c-format
 msgid "--guess-perl                Try to report perl libraries.\n"
 msgstr ""
 
-#: src/exit.c:146
+#: src/exit.c:149
 #, c-format
 msgid "--guess-python              Try to report python libraries.\n"
 msgstr ""
 
-#: src/exit.c:147
+#: src/exit.c:150
 #, c-format
 msgid "--guess-pike                Try to report pike libraries.\n"
 msgstr ""
 
-#: src/exit.c:148
+#: src/exit.c:151
 #, c-format
 msgid "--guess-ruby                Try to report ruby libraries.\n"
 msgstr ""
 
-#: src/exit.c:149
+#: src/exit.c:152
 #, c-format
 msgid "--guess-interpreters        Try to report interpreter libraries.\n"
 msgstr ""
 
-#: src/exit.c:151
+#: src/exit.c:154
 #, c-format
 msgid ""
 "--guess-section             Try to report libraries in wrong sections.\n"
 msgstr ""
 
-#: src/exit.c:152
+#: src/exit.c:155
 #, c-format
 msgid "--guess-dev                 Try to report development packages.\n"
 msgstr ""
 
-#: src/exit.c:153
+#: src/exit.c:156
 #, c-format
 msgid "--guess-debug               Try to report debugging libraries.\n"
 msgstr ""
 
-#: src/exit.c:154
+#: src/exit.c:157
 #, c-format
 msgid "--guess-common              Try to report common packages.\n"
 msgstr ""
 
-#: src/exit.c:155
+#: src/exit.c:158
 #, c-format
 msgid "--guess-data                Try to report data packages.\n"
 msgstr ""
 
-#: src/exit.c:156
+#: src/exit.c:159
 #, c-format
 msgid "--guess-doc                 Try to report documentation packages.\n"
 msgstr ""
 
-#: src/exit.c:157
+#: src/exit.c:160
 #, c-format
 msgid "--guess-dummy               Try to report dummy packages.\n"
 msgstr ""
 
-#: src/exit.c:158
+#: src/exit.c:161
 #, c-format
 msgid "--guess-all                 Try all of the above.\n"
 msgstr ""
 
-#: src/exit.c:159
+#: src/exit.c:162
 #, c-format
 msgid "--guess-only                Use --guess options only.\n"
 msgstr ""
 
-#: src/exit.c:161
+#: src/exit.c:164
 #, c-format
 msgid ""
 "\n"
@@ -220,7 +225,7 @@
 "Report bugs to: Peter Palfrader <[EMAIL PROTECTED]>\n"
 msgstr ""
 
-#: src/exit.c:171
+#: src/exit.c:174
 #, c-format
 msgid ""
 "%s %s - Find packages without other packages depending on them\n"
@@ -234,7 +239,7 @@
 "Copyright (C) 2003, 2004 Peter Palfrader <[EMAIL PROTECTED]>.\n"
 msgstr ""
 
-#: src/exit.c:188
+#: src/exit.c:191
 #, c-format
 msgid "Usage: %s [OPTIONS] [PACKAGE]...\n"
 msgstr ""
diff -ru deborphan-1.7.14/src/deborphan.c deborphan-1.7.14circ/src/deborphan.c
--- deborphan-1.7.14/src/deborphan.c	2004-07-13 18:13:12.000000000 +0200
+++ deborphan-1.7.14circ/src/deborphan.c	2004-12-13 21:09:09.000000000 +0100
@@ -114,6 +114,7 @@
 	{"guess-doc", 0, 0, 16},
 	{"find-config", 0, 0, 17},
 	{"libdevel", 0, 0, 18},
+        {"find-circular", 0, 0, 'c'},
 	{"exclude", 1, 0, 'e'},
 	{0, 0, 0, 0}
     };
@@ -133,7 +134,7 @@
     textdomain(PACKAGE);
 #endif
 
-    while ((i = _get_opt(argc, argv, "p:advhe:nf:sPzHk:ARLZ", 
+    while ((i = _get_opt(argc, argv, "p:advhe:nf:sPczHk:ARLZ", 
 			 longopts, NULL)) != EOF) {
 	switch (i) {
 	case 'd':
@@ -256,6 +257,9 @@
 	case 18:
 	    options[SEARCH_LIBDEVEL] = 1;
 	    break;
+        case 'c':
+            options[FIND_CIRCULAR] = 1;
+            break;
 	case 'e':
 	    while ( optarg ) {
 		    char *c_ptr;
@@ -437,6 +441,9 @@
     if (this->install)
 	check_lib_deps(package, this);
 
+    if (options[FIND_CIRCULAR])
+        find_remaining_circular_deps(package);
+
     free_pkg_regex();
 
     fflush(stdout);
diff -ru deborphan-1.7.14/src/exit.c deborphan-1.7.14circ/src/exit.c
--- deborphan-1.7.14/src/exit.c	2004-07-13 19:43:53.000000000 +0200
+++ deborphan-1.7.14circ/src/exit.c	2004-12-13 21:09:09.000000000 +0100
@@ -102,6 +102,9 @@
     printf(_("-n        Enable checks for `recommends' and `suggests'.\n"));
 #endif
 
+    printf("--find-circular,  ");
+    printf(_("-c        Find orphaned circular dependencies.\n"));
+
     printf("--all-packages,   ");
     printf(_("-a        Compare all packages, not just libs.\n"));
 
diff -ru deborphan-1.7.14/src/libdeps.c deborphan-1.7.14circ/src/libdeps.c
--- deborphan-1.7.14/src/libdeps.c	2004-04-21 14:20:43.000000000 +0200
+++ deborphan-1.7.14circ/src/libdeps.c	2004-12-13 21:09:09.000000000 +0100
@@ -24,14 +24,43 @@
 
 extern int options[];
 
+static void
+deactivate_deps(pkg_info *all_packages, pkg_info *current_pkg);
+static pkg_info**
+find_uphill_deps(pkg_info** uphill_deps,
+                 int *uphill_cnt, int *uphill_max,
+                 pkg_info *all_packages, pkg_info *current_pkg);
+static pkg_info**
+find_downhill_deps(pkg_info** downhill_deps,
+                   int *downhill_cnt, int *downhill_max,
+                   pkg_info *all_packages, pkg_info *current_pkg);
+
+/* Returns 1 iif child depends on father */
+static int
+depends_on(pkg_info *child, pkg_info *father)
+{
+    int dep, prov;
+
+    for (dep = 0; dep < child->deps_cnt; dep++) {
+        for (prov = 0; prov < father->provides_cnt; prov++) {
+            if (pkgcmp(father->provides[prov], child->deps[dep]))
+                return 1;
+        }
+        if (pkgcmp(father->self, child->deps[dep]))
+            return 1;
+    }
+    return 0;
+}
+
 /* For each package found, this scans the `package' structure, to
  * see if anything depends on it.
  */
 void
-check_lib_deps(pkg_info * package, pkg_info * current_pkg)
+check_lib_deps(pkg_info * all_packages, pkg_info * current_pkg)
 {
     int deps, prov, no_dep_found = 1, search_found = 1;
     int i;
+    pkg_info *package;
     static int j;
 
     extern char **search_for;
@@ -83,7 +112,7 @@
 
     /* Search all (installed) packages for dependencies. 
      */
-    for (; package && no_dep_found; package = package->next) {
+    for (package = all_packages; package && no_dep_found; package = package->next) {
 	for (deps = 0; deps < package->deps_cnt && no_dep_found; deps++) {
 	    for (prov = 0; prov < current_pkg->provides_cnt && no_dep_found;
 		 prov++) {
@@ -112,11 +141,171 @@
 	    printf("%-25s", current_pkg->section);
 
 	if (options[SHOW_PRIORITY])
-	    printf("%-24s%s", current_pkg->self.name,
+	    printf("%-24s %s", current_pkg->self.name,
 		   priority_to_string(current_pkg->priority));
 	else
 	    printf("%s", current_pkg->self.name);
 
 	printf("\n");
+
+        if (options[FIND_CIRCULAR])
+            deactivate_deps(all_packages, current_pkg);
+    }
+}
+
+static void
+deactivate_deps(pkg_info *all_packages, pkg_info *current_pkg)
+{
+    pkg_info *pkg;
+
+    current_pkg->activity = DEACTIVATED;
+    for (pkg = all_packages; pkg; pkg = pkg->next) {
+        if (pkg->activity == NORMAL && depends_on(current_pkg, pkg))
+            deactivate_deps(all_packages, pkg);
+    }
+}
+
+void find_remaining_circular_deps(pkg_info* all_packages)
+{
+    pkg_info *pkg;
+    pkg_info **downhill_deps, **uphill_deps;
+    int downhill_cnt, uphill_cnt;
+    int downhill_max, uphill_max;
+    int i, chars_written;
+
+    downhill_max = INIT_DEPENDS_COUNT;
+    downhill_cnt = 0;
+    downhill_deps = xmalloc(downhill_max * sizeof(pkg_info*));
+    memset(downhill_deps, '\0', downhill_max * sizeof(pkg_info*));
+    uphill_max = INIT_DEPENDS_COUNT;
+    uphill_cnt = 0;
+    uphill_deps = xmalloc(uphill_max * sizeof(pkg_info*));
+    memset(uphill_deps, '\0', uphill_max * sizeof(pkg_info*));
+
+    for (pkg = all_packages; pkg; pkg = pkg->next) {
+        if (pkg->activity == DEACTIVATED)
+            continue;
+        if (pkg->hold ||
+            pkg->priority < options[PRIORITY] ||
+            keep && mustkeep(pkg->self) ||
+            !is_library(pkg, options[SEARCH_LIBDEVEL])) {
+            deactivate_deps(all_packages, pkg);
+            continue;
+        }
+        // First, find all that depend on me
+        uphill_cnt = 0;
+        uphill_deps = find_uphill_deps(uphill_deps, &uphill_cnt, &uphill_max,
+                                       all_packages, pkg);
+        // Now, all that I depend on
+        downhill_cnt = 0;
+        downhill_deps = find_downhill_deps(downhill_deps, &downhill_cnt, &downhill_max,
+                                           all_packages, pkg);
+        // Make sure I depend on all that depend on me
+        for (i = 0; i < uphill_cnt; i++)
+            if (uphill_deps[i]->activity == UPHILL) // Pb: "should" have been turned to DOWNHILL
+                break;
+        if (i == uphill_cnt) { // Yes!
+            // Compute total installed size (if asked to)
+            if (options[SHOW_SIZE]) {
+                int total_size = 0;
+                for (i = 0; i < uphill_cnt; i++)
+                    total_size += uphill_deps[i]->installed_size; 
+                printf("%10ld ", total_size);
+            }
+            // Attempt to find common section (if asked to)
+            if (options[SHOW_SECTION]) {
+                char *section = NULL;
+                section = strdup(uphill_deps[0]->section);
+                for (i = 1; i < uphill_cnt; i++)
+                    if (strcmp(section, uphill_deps[i]->section) != 0) {
+                        free(section);
+                        section = strdup("*");
+                        break;
+                    }
+                printf("%-25s", section);
+                free(section);
+            }
+            // Print the names
+            chars_written = 0;
+            for (i = 0; i < uphill_cnt; i++) {
+                if (i) {
+                    printf(",");
+                    chars_written += 1;
+                }
+                printf(uphill_deps[i]->self.name);
+                chars_written += strlen(uphill_deps[i]->self.name);
+            }
+            // Print highest priority among the deps (if asked to)
+            if (options[SHOW_PRIORITY]) {
+                int highest_priority = 6; // 1 is higher than 5...
+                const char *priority_str;
+                for (i = 0; i < uphill_cnt; i++)
+                    if (highest_priority > uphill_deps[i]->priority)
+                        highest_priority = uphill_deps[i]->priority;
+                priority_str = priority_to_string(highest_priority);
+                printf(" %*s", (24 > chars_written ?
+                                24 - chars_written + strlen(priority_str) : 0),
+                       priority_str);
+            }
+            printf("\n");
+            // Deactivate everything
+            for (i = 0; i < downhill_cnt; i++)
+                downhill_deps[i]->activity = DEACTIVATED;
+        } else { // No: there is a smaller circular dependency
+            // Just like in the other branch, we should deactivate all
+            // downhill, as only those in uphill and not in downhill
+            // can have a smaller circular dependency
+            for (i = 0; i < downhill_cnt; i++)
+                downhill_deps[i]->activity = DEACTIVATED;
+            for (i = 0; i < uphill_cnt; i++)
+                if (uphill_deps[i]->activity == UPHILL) // thus, not in downhill
+                    uphill_deps[i]->activity = NORMAL;
+        }
+    }
+}
+
+static pkg_info**
+find_uphill_deps(pkg_info** uphill_deps,
+                 int *uphill_cnt, int *uphill_max,
+                 pkg_info *all_packages, pkg_info *current_pkg)
+{
+    pkg_info *pkg;
+
+    if (*uphill_cnt >= *uphill_max) {
+        *uphill_max *= 2;
+        uphill_deps = xrealloc(uphill_deps, *uphill_max * sizeof(pkg_info*));
+    }
+    uphill_deps[ (*uphill_cnt)++ ] = current_pkg;
+    current_pkg->activity = UPHILL;
+
+    for (pkg = all_packages; pkg; pkg = pkg->next) {
+        if (pkg->activity == NORMAL && depends_on(pkg, current_pkg))
+            uphill_deps = find_uphill_deps(uphill_deps, uphill_cnt, uphill_max,
+                                           all_packages, pkg);
+    }
+    return uphill_deps;
+}
+
+
+static pkg_info**
+find_downhill_deps(pkg_info** downhill_deps,
+                   int *downhill_cnt, int *downhill_max,
+                   pkg_info *all_packages, pkg_info *current_pkg)
+{
+    pkg_info *pkg;
+
+    if (*downhill_cnt >= *downhill_max) {
+        *downhill_max *= 2;
+        downhill_deps = xrealloc(downhill_deps, *downhill_max * sizeof(pkg_info*));
+    }
+    downhill_deps[ (*downhill_cnt)++ ] = current_pkg;
+    current_pkg->activity = DOWNHILL;
+
+    for (pkg = all_packages; pkg; pkg = pkg->next) {
+        if ((pkg->activity == NORMAL || pkg->activity == UPHILL) &&
+            depends_on(current_pkg, pkg))
+            downhill_deps = find_downhill_deps(downhill_deps, downhill_cnt,
+                                               downhill_max, all_packages, pkg);
     }
+    return downhill_deps;
 }
diff -Naur deborphan-1.7.16/debian/changelog deborphan-1.7.16circ/debian/changelog
--- deborphan-1.7.16/debian/changelog	2005-07-10 11:02:56.000000000 +0200
+++ deborphan-1.7.16circ/debian/changelog	2005-07-13 12:19:44.000000000 +0200
@@ -1,3 +1,10 @@
+deborphan (1.7.16circ) unstable; urgency=low
+
+  * Added an option to detect orphaned circular dependencies. Orphaner
+    doesn't accept this option yet.
+
+ -- Daniel D�chelotte <[EMAIL PROTECTED]>  Wed, 13 Jul 2005 12:16:39 +0200
+
 deborphan (1.7.16) unstable; urgency=low
 
   * Translation update for catalan by Jordi Mallach.
diff -Naur deborphan-1.7.16/doc/deborphan.1 deborphan-1.7.16circ/doc/deborphan.1
--- deborphan-1.7.16/doc/deborphan.1	2005-07-09 14:52:15.000000000 +0200
+++ deborphan-1.7.16circ/doc/deborphan.1	2005-07-13 12:15:29.000000000 +0200
@@ -55,7 +55,7 @@
 Show the installed size of the packages found.
 .TP
 \fB-s, \-\-show\-section\fP
-Show the sections the packages are in.
+Show the sections the packages are in. When \fB\-\-find\-circular\fR is activated, section is printed if common to all packages, "*" is printed otherwise (ie. packages belong to different sections).
 .TP
 \fB\-\-no\-show\-section\fP
 Override showing sections when the default is to show them (see \fB\-\-all-packages\fR).
@@ -68,6 +68,9 @@
 Nice-mode checks if there is a package `suggesting' or `recommending' the package.
 If one is found, the package will be marked as in use, or, when \fB\-\-show\-deps\fR is used, print out the package suggesting the package as if it were depending on it.
 .TP
+\fB\-c, \-\-find\-circular\fP
+Track circular dependencies as well.
+.TP
 \fB-a, \-\-all\-packages\fP
 Check all the packages, instead of only those in the libs section. Best used (if at all used) in combination with \fB\-\-priority\fR. This option implies \fB\-\-show-section\fR.
 .\"  , when compiled with ALL_PACKAGES_IMPLY_SECTION defined (default)
diff -Naur deborphan-1.7.16/include/deborphan.h deborphan-1.7.16circ/include/deborphan.h
--- deborphan-1.7.16/include/deborphan.h	2005-03-16 15:52:39.000000000 +0100
+++ deborphan-1.7.16circ/include/deborphan.h	2005-07-13 12:15:29.000000000 +0200
@@ -65,6 +65,13 @@
 #define INIT_PROVIDES_COUNT 4
 #define INIT_EXCLUDES_COUNT 4
 
+typedef enum {
+    NORMAL = 0,
+    DEACTIVATED,
+    UPHILL,
+    DOWNHILL
+} Activity;
+
 /* These arrays aren't exactly neat, but it seems they suffice. */
 typedef struct pkg_info {
      dep self;
@@ -81,6 +88,7 @@
      int  essential;
      int  dummy;
      int  config;
+     Activity activity;
      long installed_size;
      struct pkg_info *next;
 } pkg_info;
@@ -105,6 +113,7 @@
      ZERO_KEEP,
      FIND_CONFIG,
      SEARCH_LIBDEVEL,
+     FIND_CIRCULAR,
      NUM_OPTIONS /* THIS HAS TO BE THE LAST OF THIS ENUM! */
 };
 
@@ -150,6 +159,7 @@
 
 /* libdeps.c */
 void check_lib_deps(pkg_info *package, pkg_info *current_pkg);
+void find_remaining_circular_deps(pkg_info *package);
 
 /* exit.c */
 void error(int exit_status, int error_no, const char *format, ...);
diff -Naur deborphan-1.7.16/po/deborphan.pot deborphan-1.7.16circ/po/deborphan.pot
--- deborphan-1.7.16/po/deborphan.pot	2005-07-10 11:04:35.000000000 +0200
+++ deborphan-1.7.16circ/po/deborphan.pot	2005-07-13 12:15:29.000000000 +0200
@@ -75,144 +75,149 @@
 
 #: src/exit.c:106
 #, c-format
+msgid "-c        Find orphaned circular dependencies.\n"
+msgstr ""
+
+#: src/exit.c:109
+#, c-format
 msgid "-a        Compare all packages, not just libs.\n"
 msgstr ""
 
-#: src/exit.c:108
+#: src/exit.c:111
 #, c-format
 msgid ""
 "--libdevel                  Search in libdevel in addition to libs and "
 "oldlibs.\n"
 msgstr ""
 
-#: src/exit.c:111
+#: src/exit.c:114
 #, c-format
 msgid "-e LIST   Work as if packages in LIST were not installed.\n"
 msgstr ""
 
-#: src/exit.c:114
+#: src/exit.c:117
 #, c-format
 msgid "-p PRIOR  Select only packages with priority >= PRIOR.\n"
 msgstr ""
 
-#: src/exit.c:117
+#: src/exit.c:120
 #, c-format
 msgid "-H        Ignore hold flags.\n"
 msgstr ""
 
-#: src/exit.c:119
+#: src/exit.c:122
 #, c-format
 msgid "--find-config               Find \"orphaned\" configuration files.\n"
 msgstr ""
 
-#: src/exit.c:124
+#: src/exit.c:127
 #, c-format
 msgid "-A PKGS.. Never report PKGS.\n"
 msgstr ""
 
-#: src/exit.c:127
+#: src/exit.c:130
 #, c-format
 msgid "-R PKGS.. Report PKGS if there are no dependencies.\n"
 msgstr ""
 
-#: src/exit.c:130
+#: src/exit.c:133
 #, c-format
 msgid "-L        List the packages that are never reported.\n"
 msgstr ""
 
-#: src/exit.c:133
+#: src/exit.c:136
 #, c-format
 msgid "-Z        Remove all packages from the \"keep\" file.\n"
 msgstr ""
 
-#: src/exit.c:136
+#: src/exit.c:139
 #, c-format
 msgid "-k FILE   Use FILE to get/store info about kept packages.\n"
 msgstr ""
 
-#: src/exit.c:139
+#: src/exit.c:142
 #, c-format
 msgid "--df-keep                   Read debfoster's \"keepers\" file.\n"
 msgstr ""
 
-#: src/exit.c:140
+#: src/exit.c:143
 #, c-format
 msgid "--no-df-keep                Do not read debfoster's \"keepers\" file.\n"
 msgstr ""
 
 #. guessing
-#: src/exit.c:145
+#: src/exit.c:148
 #, c-format
 msgid "--guess-perl                Try to report perl libraries.\n"
 msgstr ""
 
-#: src/exit.c:146
+#: src/exit.c:149
 #, c-format
 msgid "--guess-python              Try to report python libraries.\n"
 msgstr ""
 
-#: src/exit.c:147
+#: src/exit.c:150
 #, c-format
 msgid "--guess-pike                Try to report pike libraries.\n"
 msgstr ""
 
-#: src/exit.c:148
+#: src/exit.c:151
 #, c-format
 msgid "--guess-ruby                Try to report ruby libraries.\n"
 msgstr ""
 
-#: src/exit.c:149
+#: src/exit.c:152
 #, c-format
 msgid "--guess-interpreters        Try to report interpreter libraries.\n"
 msgstr ""
 
-#: src/exit.c:151
+#: src/exit.c:154
 #, c-format
 msgid ""
 "--guess-section             Try to report libraries in wrong sections.\n"
 msgstr ""
 
-#: src/exit.c:152
+#: src/exit.c:155
 #, c-format
 msgid "--guess-dev                 Try to report development packages.\n"
 msgstr ""
 
-#: src/exit.c:153
+#: src/exit.c:156
 #, c-format
 msgid "--guess-debug               Try to report debugging libraries.\n"
 msgstr ""
 
-#: src/exit.c:154
+#: src/exit.c:157
 #, c-format
 msgid "--guess-common              Try to report common packages.\n"
 msgstr ""
 
-#: src/exit.c:155
+#: src/exit.c:158
 #, c-format
 msgid "--guess-data                Try to report data packages.\n"
 msgstr ""
 
-#: src/exit.c:156
+#: src/exit.c:159
 #, c-format
 msgid "--guess-doc                 Try to report documentation packages.\n"
 msgstr ""
 
-#: src/exit.c:157
+#: src/exit.c:160
 #, c-format
 msgid "--guess-dummy               Try to report dummy packages.\n"
 msgstr ""
 
-#: src/exit.c:158
+#: src/exit.c:161
 #, c-format
 msgid "--guess-all                 Try all of the above.\n"
 msgstr ""
 
-#: src/exit.c:159
+#: src/exit.c:162
 #, c-format
 msgid "--guess-only                Use --guess options only.\n"
 msgstr ""
 
-#: src/exit.c:161
+#: src/exit.c:164
 #, c-format
 msgid ""
 "\n"
@@ -220,7 +225,7 @@
 "Report bugs to: Peter Palfrader <[EMAIL PROTECTED]>\n"
 msgstr ""
 
-#: src/exit.c:171
+#: src/exit.c:174
 #, c-format
 msgid ""
 "%s %s - Find packages without other packages depending on them\n"
@@ -234,7 +239,7 @@
 "Copyright (C) 2003, 2004 Peter Palfrader <[EMAIL PROTECTED]>.\n"
 msgstr ""
 
-#: src/exit.c:188
+#: src/exit.c:191
 #, c-format
 msgid "Usage: %s [OPTIONS] [PACKAGE]...\n"
 msgstr ""
diff -Naur deborphan-1.7.16/src/deborphan.c deborphan-1.7.16circ/src/deborphan.c
--- deborphan-1.7.16/src/deborphan.c	2005-03-16 15:52:39.000000000 +0100
+++ deborphan-1.7.16circ/src/deborphan.c	2005-07-13 12:15:29.000000000 +0200
@@ -114,6 +114,7 @@
 	{"guess-doc", 0, 0, 16},
 	{"find-config", 0, 0, 17},
 	{"libdevel", 0, 0, 18},
+        {"find-circular", 0, 0, 'c'},
 	{"exclude", 1, 0, 'e'},
 	{0, 0, 0, 0}
     };
@@ -133,7 +134,7 @@
     textdomain(PACKAGE);
 #endif
 
-    while ((i = _get_opt(argc, argv, "p:advhe:nf:sPzHk:ARLZ", 
+    while ((i = _get_opt(argc, argv, "p:advhe:nf:sPczHk:ARLZ", 
 			 longopts, NULL)) != EOF) {
 	switch (i) {
 	case 'd':
@@ -256,6 +257,9 @@
 	case 18:
 	    options[SEARCH_LIBDEVEL] = 1;
 	    break;
+        case 'c':
+            options[FIND_CIRCULAR] = 1;
+            break;
 	case 'e':
 	    while ( optarg ) {
 		    char *c_ptr;
@@ -445,6 +449,9 @@
     if (this->install)
 	check_lib_deps(package, this);
 
+    if (options[FIND_CIRCULAR])
+        find_remaining_circular_deps(package);
+
     free_pkg_regex();
 
     fflush(stdout);
diff -Naur deborphan-1.7.16/src/exit.c deborphan-1.7.16circ/src/exit.c
--- deborphan-1.7.16/src/exit.c	2004-07-13 19:43:53.000000000 +0200
+++ deborphan-1.7.16circ/src/exit.c	2005-07-13 12:15:29.000000000 +0200
@@ -102,6 +102,9 @@
     printf(_("-n        Enable checks for `recommends' and `suggests'.\n"));
 #endif
 
+    printf("--find-circular,  ");
+    printf(_("-c        Find orphaned circular dependencies.\n"));
+
     printf("--all-packages,   ");
     printf(_("-a        Compare all packages, not just libs.\n"));
 
diff -Naur deborphan-1.7.16/src/libdeps.c deborphan-1.7.16circ/src/libdeps.c
--- deborphan-1.7.16/src/libdeps.c	2004-04-21 14:20:43.000000000 +0200
+++ deborphan-1.7.16circ/src/libdeps.c	2005-07-13 12:15:29.000000000 +0200
@@ -24,14 +24,43 @@
 
 extern int options[];
 
+static void
+deactivate_deps(pkg_info *all_packages, pkg_info *current_pkg);
+static pkg_info**
+find_uphill_deps(pkg_info** uphill_deps,
+                 int *uphill_cnt, int *uphill_max,
+                 pkg_info *all_packages, pkg_info *current_pkg);
+static pkg_info**
+find_downhill_deps(pkg_info** downhill_deps,
+                   int *downhill_cnt, int *downhill_max,
+                   pkg_info *all_packages, pkg_info *current_pkg);
+
+/* Returns 1 iif child depends on father */
+static int
+depends_on(pkg_info *child, pkg_info *father)
+{
+    int dep, prov;
+
+    for (dep = 0; dep < child->deps_cnt; dep++) {
+        for (prov = 0; prov < father->provides_cnt; prov++) {
+            if (pkgcmp(father->provides[prov], child->deps[dep]))
+                return 1;
+        }
+        if (pkgcmp(father->self, child->deps[dep]))
+            return 1;
+    }
+    return 0;
+}
+
 /* For each package found, this scans the `package' structure, to
  * see if anything depends on it.
  */
 void
-check_lib_deps(pkg_info * package, pkg_info * current_pkg)
+check_lib_deps(pkg_info * all_packages, pkg_info * current_pkg)
 {
     int deps, prov, no_dep_found = 1, search_found = 1;
     int i;
+    pkg_info *package;
     static int j;
 
     extern char **search_for;
@@ -83,7 +112,7 @@
 
     /* Search all (installed) packages for dependencies. 
      */
-    for (; package && no_dep_found; package = package->next) {
+    for (package = all_packages; package && no_dep_found; package = package->next) {
 	for (deps = 0; deps < package->deps_cnt && no_dep_found; deps++) {
 	    for (prov = 0; prov < current_pkg->provides_cnt && no_dep_found;
 		 prov++) {
@@ -112,11 +141,171 @@
 	    printf("%-25s", current_pkg->section);
 
 	if (options[SHOW_PRIORITY])
-	    printf("%-24s%s", current_pkg->self.name,
+	    printf("%-24s %s", current_pkg->self.name,
 		   priority_to_string(current_pkg->priority));
 	else
 	    printf("%s", current_pkg->self.name);
 
 	printf("\n");
+
+        if (options[FIND_CIRCULAR])
+            deactivate_deps(all_packages, current_pkg);
+    }
+}
+
+static void
+deactivate_deps(pkg_info *all_packages, pkg_info *current_pkg)
+{
+    pkg_info *pkg;
+
+    current_pkg->activity = DEACTIVATED;
+    for (pkg = all_packages; pkg; pkg = pkg->next) {
+        if (pkg->activity == NORMAL && depends_on(current_pkg, pkg))
+            deactivate_deps(all_packages, pkg);
+    }
+}
+
+void find_remaining_circular_deps(pkg_info* all_packages)
+{
+    pkg_info *pkg;
+    pkg_info **downhill_deps, **uphill_deps;
+    int downhill_cnt, uphill_cnt;
+    int downhill_max, uphill_max;
+    int i, chars_written;
+
+    downhill_max = INIT_DEPENDS_COUNT;
+    downhill_cnt = 0;
+    downhill_deps = xmalloc(downhill_max * sizeof(pkg_info*));
+    memset(downhill_deps, '\0', downhill_max * sizeof(pkg_info*));
+    uphill_max = INIT_DEPENDS_COUNT;
+    uphill_cnt = 0;
+    uphill_deps = xmalloc(uphill_max * sizeof(pkg_info*));
+    memset(uphill_deps, '\0', uphill_max * sizeof(pkg_info*));
+
+    for (pkg = all_packages; pkg; pkg = pkg->next) {
+        if (pkg->activity == DEACTIVATED)
+            continue;
+        if (pkg->hold ||
+            pkg->priority < options[PRIORITY] ||
+            keep && mustkeep(pkg->self) ||
+            !is_library(pkg, options[SEARCH_LIBDEVEL])) {
+            deactivate_deps(all_packages, pkg);
+            continue;
+        }
+        // First, find all that depend on me
+        uphill_cnt = 0;
+        uphill_deps = find_uphill_deps(uphill_deps, &uphill_cnt, &uphill_max,
+                                       all_packages, pkg);
+        // Now, all that I depend on
+        downhill_cnt = 0;
+        downhill_deps = find_downhill_deps(downhill_deps, &downhill_cnt, &downhill_max,
+                                           all_packages, pkg);
+        // Make sure I depend on all that depend on me
+        for (i = 0; i < uphill_cnt; i++)
+            if (uphill_deps[i]->activity == UPHILL) // Pb: "should" have been turned to DOWNHILL
+                break;
+        if (i == uphill_cnt) { // Yes!
+            // Compute total installed size (if asked to)
+            if (options[SHOW_SIZE]) {
+                int total_size = 0;
+                for (i = 0; i < uphill_cnt; i++)
+                    total_size += uphill_deps[i]->installed_size; 
+                printf("%10ld ", total_size);
+            }
+            // Attempt to find common section (if asked to)
+            if (options[SHOW_SECTION]) {
+                char *section = NULL;
+                section = strdup(uphill_deps[0]->section);
+                for (i = 1; i < uphill_cnt; i++)
+                    if (strcmp(section, uphill_deps[i]->section) != 0) {
+                        free(section);
+                        section = strdup("*");
+                        break;
+                    }
+                printf("%-25s", section);
+                free(section);
+            }
+            // Print the names
+            chars_written = 0;
+            for (i = 0; i < uphill_cnt; i++) {
+                if (i) {
+                    printf(",");
+                    chars_written += 1;
+                }
+                printf(uphill_deps[i]->self.name);
+                chars_written += strlen(uphill_deps[i]->self.name);
+            }
+            // Print highest priority among the deps (if asked to)
+            if (options[SHOW_PRIORITY]) {
+                int highest_priority = 6; // 1 is higher than 5...
+                const char *priority_str;
+                for (i = 0; i < uphill_cnt; i++)
+                    if (highest_priority > uphill_deps[i]->priority)
+                        highest_priority = uphill_deps[i]->priority;
+                priority_str = priority_to_string(highest_priority);
+                printf(" %*s", (24 > chars_written ?
+                                24 - chars_written + strlen(priority_str) : 0),
+                       priority_str);
+            }
+            printf("\n");
+            // Deactivate everything
+            for (i = 0; i < downhill_cnt; i++)
+                downhill_deps[i]->activity = DEACTIVATED;
+        } else { // No: there is a smaller circular dependency
+            // Just like in the other branch, we should deactivate all
+            // downhill, as only those in uphill and not in downhill
+            // can have a smaller circular dependency
+            for (i = 0; i < downhill_cnt; i++)
+                downhill_deps[i]->activity = DEACTIVATED;
+            for (i = 0; i < uphill_cnt; i++)
+                if (uphill_deps[i]->activity == UPHILL) // thus, not in downhill
+                    uphill_deps[i]->activity = NORMAL;
+        }
+    }
+}
+
+static pkg_info**
+find_uphill_deps(pkg_info** uphill_deps,
+                 int *uphill_cnt, int *uphill_max,
+                 pkg_info *all_packages, pkg_info *current_pkg)
+{
+    pkg_info *pkg;
+
+    if (*uphill_cnt >= *uphill_max) {
+        *uphill_max *= 2;
+        uphill_deps = xrealloc(uphill_deps, *uphill_max * sizeof(pkg_info*));
+    }
+    uphill_deps[ (*uphill_cnt)++ ] = current_pkg;
+    current_pkg->activity = UPHILL;
+
+    for (pkg = all_packages; pkg; pkg = pkg->next) {
+        if (pkg->activity == NORMAL && depends_on(pkg, current_pkg))
+            uphill_deps = find_uphill_deps(uphill_deps, uphill_cnt, uphill_max,
+                                           all_packages, pkg);
+    }
+    return uphill_deps;
+}
+
+
+static pkg_info**
+find_downhill_deps(pkg_info** downhill_deps,
+                   int *downhill_cnt, int *downhill_max,
+                   pkg_info *all_packages, pkg_info *current_pkg)
+{
+    pkg_info *pkg;
+
+    if (*downhill_cnt >= *downhill_max) {
+        *downhill_max *= 2;
+        downhill_deps = xrealloc(downhill_deps, *downhill_max * sizeof(pkg_info*));
+    }
+    downhill_deps[ (*downhill_cnt)++ ] = current_pkg;
+    current_pkg->activity = DOWNHILL;
+
+    for (pkg = all_packages; pkg; pkg = pkg->next) {
+        if ((pkg->activity == NORMAL || pkg->activity == UPHILL) &&
+            depends_on(current_pkg, pkg))
+            downhill_deps = find_downhill_deps(downhill_deps, downhill_cnt,
+                                               downhill_max, all_packages, pkg);
     }
+    return downhill_deps;
 }

Reply via email to