mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Roman Zippel <zippel@linux-m68k.org>
To: Sam Ravnborg <sam@ravnborg.org>
Cc: linux-kbuild <linux-kbuild@vger.kernel.org>,
	LKML <linux-kernel@vger.kernel.org>
Subject: Re: [PATCH 06/13] kconfig: print all locations when we see a recursive dependency
Date: Wed, 31 Dec 2008 03:55:00 +0100 (CET)	[thread overview]
Message-ID: <Pine.LNX.4.64.0812310346430.17013@localhost.localdomain> (raw)
In-Reply-To: <1230558803-7168-6-git-send-email-sam@ravnborg.org>

Hi,

On Mon, 29 Dec 2008, Sam Ravnborg wrote:

> It is nessesary to know all locations when trying to track
> a recursive dependency. So print out all locations for each symbol.

The problem is that this is little more than a better grep, although 
kconfig knows exactly what went wrong, but this info is scattered all over 
the stack.
We could either return more info to print more than just the symbol or 
maintain more info while traversing the tree. The patch below does the 
latter. The patch could use some small cleanups, so it's not final yet.

bye, Roman

---
 scripts/kconfig/symbol.c |  139 +++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 124 insertions(+), 15 deletions(-)

Index: linux-2.6-git/scripts/kconfig/symbol.c
===================================================================
--- linux-2.6-git.orig/scripts/kconfig/symbol.c	2008-12-31 03:42:05.000000000 +0100
+++ linux-2.6-git/scripts/kconfig/symbol.c	2008-12-31 03:43:34.000000000 +0100
@@ -760,6 +760,107 @@ struct symbol **sym_re_search(const char
 }
 
 
+static struct dep_stack {
+	struct dep_stack *prev, *next;
+	struct symbol *sym;
+	struct property *prop;
+	struct expr *expr;
+} *check_top;
+
+static void dep_stack_insert(struct dep_stack *stack, struct symbol *sym)
+{
+	memset(stack, 0, sizeof(*stack));
+	if (check_top)
+		check_top->next = stack;
+	stack->prev = check_top;
+	stack->sym = sym;
+	check_top = stack;
+}
+
+static void dep_stack_remove(void)
+{
+	check_top = check_top->prev;
+	if (check_top)
+		check_top->next = NULL;
+}
+
+static void sym_check_print_recursive(struct symbol *last_sym)
+{
+	struct dep_stack *stack;
+	struct symbol *sym, *next_sym;
+	struct menu *menu = NULL;
+	struct property *prop;
+	struct dep_stack cv_stack;
+
+	zconfnerrs++;
+	if (sym_is_choice_value(last_sym)) {
+		dep_stack_insert(&cv_stack, last_sym);
+		last_sym = prop_get_symbol(sym_get_choice_prop(last_sym));
+	}
+
+	for (stack = check_top; stack; stack = stack->prev)
+		if (stack->sym == last_sym)
+			break;
+	if (!stack) {
+		fprintf(stderr, "unexpected recursive dependency error\n");
+		return;
+	}
+
+	for (; stack; stack = stack->next) {
+		sym = stack->sym;
+		next_sym = stack->next ? stack->next->sym : last_sym;
+		prop = stack->prop;
+		if (sym_is_choice(sym) || sym_is_choice_value(sym)) {
+			for (prop = sym->prop; prop; prop = prop->next) {
+				menu = prop->menu;
+				if (prop->menu)
+					break;
+			}
+		} else if (!prop) {
+			for (prop = next_sym->prop; prop; prop = prop->next) {
+				if (prop->type != P_SELECT)
+					continue;
+				if (prop->expr->left.sym == sym)
+					break;
+			}
+		}
+		if (stack->sym == last_sym)
+			fprintf(stderr, "%s:%d:error: recursive dependency detected!\n",
+				prop->file->name, prop->lineno);
+		if (stack->expr) {
+			fprintf(stderr, "%s:%d:\tsymbol %s %s value contains %s\n",
+				prop->file->name, prop->lineno,
+				sym->name ? sym->name : "<choice>",
+				prop_get_type_name(prop->type),
+				next_sym->name ? next_sym->name : "<choice>");
+		} else if (stack->prop) {
+			fprintf(stderr, "%s:%d:\tsymbol %s %s depends on %s\n",
+				prop->file->name, prop->lineno,
+				sym->name ? sym->name : "<choice>",
+				prop_get_type_name(prop->type),
+				next_sym->name ? next_sym->name : "<choice>");
+		} else if (sym_is_choice(sym)) {
+			fprintf(stderr, "%s:%d:\tchoice %s contains symbol %s\n",
+				menu->file->name, menu->lineno,
+				sym->name ? sym->name : "<choice>",
+				next_sym->name ? next_sym->name : "<choice>");
+		} else if (sym_is_choice_value(sym)) {
+			fprintf(stderr, "%s:%d:\tsymbol %s is part of choice %s\n",
+				menu->file->name, menu->lineno,
+				sym->name ? sym->name : "<choice>",
+				next_sym->name ? next_sym->name : "<choice>");
+		} else {
+			fprintf(stderr, "%s:%d:\tsymbol %s is selected by %s\n",
+				prop->file->name, prop->lineno,
+				sym->name ? sym->name : "<choice>",
+				next_sym->name ? next_sym->name : "<choice>");
+		}
+	}
+
+	if (check_top == &cv_stack)
+		dep_stack_remove();
+}
+
 static struct symbol *sym_check_expr_deps(struct expr *e)
 {
 	struct symbol *sym;
@@ -795,24 +896,33 @@ static struct symbol *sym_check_sym_deps
 {
 	struct symbol *sym2;
 	struct property *prop;
+	struct dep_stack stack;
+
+	dep_stack_insert(&stack, sym);
 
 	sym2 = sym_check_expr_deps(sym->rev_dep.expr);
 	if (sym2)
-		return sym2;
+		goto out;
 
 	for (prop = sym->prop; prop; prop = prop->next) {
 		if (prop->type == P_CHOICE || prop->type == P_SELECT)
 			continue;
+		stack.prop = prop;
 		sym2 = sym_check_expr_deps(prop->visible.expr);
 		if (sym2)
 			break;
 		if (prop->type != P_DEFAULT || sym_is_choice(sym))
 			continue;
+		stack.expr = prop->expr;
 		sym2 = sym_check_expr_deps(prop->expr);
 		if (sym2)
 			break;
+		stack.expr = NULL;
 	}
 
+out:
+	dep_stack_remove();
+
 	return sym2;
 }
 
@@ -821,6 +931,9 @@ static struct symbol *sym_check_choice_d
 	struct symbol *sym, *sym2;
 	struct property *prop;
 	struct expr *e;
+	struct dep_stack stack;
+
+	dep_stack_insert(&stack, choice);
 
 	prop = sym_get_choice_prop(choice);
 	expr_list_for_each_sym(prop->expr, e, sym)
@@ -834,10 +947,8 @@ static struct symbol *sym_check_choice_d
 
 	expr_list_for_each_sym(prop->expr, e, sym) {
 		sym2 = sym_check_sym_deps(sym);
-		if (sym2) {
-			fprintf(stderr, " -> %s", sym->name);
+		if (sym2)
 			break;
-		}
 	}
 out:
 	expr_list_for_each_sym(prop->expr, e, sym)
@@ -847,6 +958,8 @@ out:
 	    prop_get_symbol(sym_get_choice_prop(sym2)) == choice)
 		sym2 = choice;
 
+	dep_stack_remove();
+
 	return sym2;
 }
 
@@ -856,18 +969,20 @@ struct symbol *sym_check_deps(struct sym
 	struct property *prop;
 
 	if (sym->flags & SYMBOL_CHECK) {
-		fprintf(stderr, "%s:%d:error: found recursive dependency: %s",
-		        sym->prop->file->name, sym->prop->lineno,
-			sym->name ? sym->name : "<choice>");
+		sym_check_print_recursive(sym);
 		return sym;
 	}
 	if (sym->flags & SYMBOL_CHECKED)
 		return NULL;
 
 	if (sym_is_choice_value(sym)) {
+		struct dep_stack stack;
+
 		/* for choice groups start the check with main choice symbol */
+		dep_stack_insert(&stack, sym);
 		prop = sym_get_choice_prop(sym);
 		sym2 = sym_check_deps(prop_get_symbol(prop));
+		dep_stack_remove();
 	} else if (sym_is_choice(sym)) {
 		sym2 = sym_check_choice_deps(sym);
 	} else {
@@ -876,14 +991,8 @@ struct symbol *sym_check_deps(struct sym
 		sym->flags &= ~SYMBOL_CHECK;
 	}
 
-	if (sym2) {
-		fprintf(stderr, " -> %s", sym->name ? sym->name : "<choice>");
-		if (sym2 == sym) {
-			fprintf(stderr, "\n");
-			zconfnerrs++;
-			sym2 = NULL;
-		}
-	}
+	if (sym2 && sym2 == sym)
+		sym2 = NULL;
 
 	return sym2;
 }

  reply	other threads:[~2008-12-31  2:58 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-12-29 13:44 pending kbuild updates Sam Ravnborg
2008-12-29 13:53 ` [PATCH 01/13] m68k: fix recursive dependency in Kconfig Sam Ravnborg
2008-12-29 13:53 ` [PATCH 02/13] kconfig: explain symbol value defaults Sam Ravnborg
2008-12-29 13:53 ` [PATCH 03/13] kconfig: add comments to symbol flags Sam Ravnborg
2008-12-29 13:53 ` [PATCH 04/13] kconfig: struct property commented Sam Ravnborg
2008-12-29 13:53 ` [PATCH 05/13] kconfig: improve readout when we hit recursive dependencies Sam Ravnborg
2008-12-29 13:53 ` [PATCH 06/13] kconfig: print all locations when we see a recursive dependency Sam Ravnborg
2008-12-31  2:55   ` Roman Zippel [this message]
2008-12-31  9:05     ` Sam Ravnborg
2009-01-18 20:54     ` Sam Ravnborg
2008-12-29 13:53 ` [PATCH 07/13] kconfig: improve error messages for bad source statements Sam Ravnborg
2008-12-29 13:53 ` [PATCH 08/13] headers_check.pl: disallow extern's Sam Ravnborg
2008-12-29 13:53 ` [PATCH 09/13] kbuild: check for leaked CONFIG_ symbols to userspace Sam Ravnborg
2008-12-29 13:53 ` [PATCH 10/13] kbuild: in headers_install autoconvert asm/inline/volatile to __xxx__ Sam Ravnborg
2008-12-29 13:53 ` [PATCH 11/13] kbuild: disable sparse warning "returning void-valued expression" Sam Ravnborg
2008-12-29 13:53 ` [PATCH 12/13] kbuild: make *config usage docs Sam Ravnborg
2008-12-29 13:53 ` [PATCH 13/13] kbuild: document environment variables Sam Ravnborg

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=Pine.LNX.4.64.0812310346430.17013@localhost.localdomain \
    --to=zippel@linux-m68k.org \
    --cc=linux-kbuild@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=sam@ravnborg.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®