devicetree.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: David Gibson <david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@public.gmane.org>
To: jdl-CYoMK+44s/E@public.gmane.org
Cc: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org
Subject: [PATCH 2/2] Allow toggling of semantic checks
Date: Sun,  8 Jul 2012 23:25:22 +1000	[thread overview]
Message-ID: <1341753922-3342-2-git-send-email-david@gibson.dropbear.id.au> (raw)
In-Reply-To: <1341753922-3342-1-git-send-email-david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@public.gmane.org>

This patch adds -W and -E options to dtc which allow toggling on and off
of the various built in semantic checks on the tree.

Signed-off-by: David Gibson <david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@public.gmane.org>
---
 checks.c                |   84 +++++++++++++++++++++++++++++++++++++++++++++--
 dtc.c                   |   13 +++++++-
 dtc.h                   |    1 +
 tests/dtc-checkfails.sh |   20 +++++++++--
 tests/dtc-fails.sh      |   30 +++++++++++++++++
 tests/run_tests.sh      |   12 +++++++
 6 files changed, 154 insertions(+), 6 deletions(-)
 create mode 100755 tests/dtc-fails.sh

diff --git a/checks.c b/checks.c
index 3080439..9061237 100644
--- a/checks.c
+++ b/checks.c
@@ -58,7 +58,7 @@ struct check {
 	struct check **prereq;
 };
 
-#define CHECK(nm, tfn, nfn, pfn, d, w, e, ...)	       \
+#define CHECK_ENTRY(nm, tfn, nfn, pfn, d, w, e, ...)	       \
 	static struct check *nm##_prereqs[] = { __VA_ARGS__ }; \
 	static struct check nm = { \
 		.name = #nm, \
@@ -73,22 +73,30 @@ struct check {
 		.prereq = nm##_prereqs, \
 	};
 #define WARNING(nm, tfn, nfn, pfn, d, ...) \
-	CHECK(nm, tfn, nfn, pfn, d, true, false, __VA_ARGS__)
+	CHECK_ENTRY(nm, tfn, nfn, pfn, d, true, false, __VA_ARGS__)
 #define ERROR(nm, tfn, nfn, pfn, d, ...) \
-	CHECK(nm, tfn, nfn, pfn, d, false, true, __VA_ARGS__)
+	CHECK_ENTRY(nm, tfn, nfn, pfn, d, false, true, __VA_ARGS__)
+#define CHECK(nm, tfn, nfn, pfn, d, ...) \
+	CHECK_ENTRY(nm, tfn, nfn, pfn, d, false, false, __VA_ARGS__)
 
 #define TREE_WARNING(nm, d, ...) \
 	WARNING(nm, check_##nm, NULL, NULL, d, __VA_ARGS__)
 #define TREE_ERROR(nm, d, ...) \
 	ERROR(nm, check_##nm, NULL, NULL, d, __VA_ARGS__)
+#define TREE_CHECK(nm, d, ...) \
+	CHECK(nm, check_##nm, NULL, NULL, d, __VA_ARGS__)
 #define NODE_WARNING(nm, d, ...) \
 	WARNING(nm, NULL, check_##nm, NULL, d,  __VA_ARGS__)
 #define NODE_ERROR(nm, d, ...) \
 	ERROR(nm, NULL, check_##nm, NULL, d, __VA_ARGS__)
+#define NODE_CHECK(nm, d, ...) \
+	CHECK(nm, NULL, check_##nm, NULL, d, __VA_ARGS__)
 #define PROP_WARNING(nm, d, ...) \
 	WARNING(nm, NULL, NULL, check_##nm, d, __VA_ARGS__)
 #define PROP_ERROR(nm, d, ...) \
 	ERROR(nm, NULL, NULL, check_##nm, d, __VA_ARGS__)
+#define PROP_CHECK(nm, d, ...) \
+	CHECK(nm, NULL, NULL, check_##nm, d, __VA_ARGS__)
 
 #ifdef __GNUC__
 static inline void check_msg(struct check *c, const char *fmt, ...) __attribute__((format (printf, 2, 3)));
@@ -179,6 +187,13 @@ out:
  * Utility check functions
  */
 
+/* A check which always fails, for testing purposes only */
+static inline void check_always_fail(struct check *c, struct node *dt)
+{
+	FAIL(c, "always_fail check");
+}
+TREE_CHECK(always_fail, NULL);
+
 static void check_is_string(struct check *c, struct node *root,
 			    struct node *node)
 {
@@ -649,8 +664,71 @@ static struct check *check_table[] = {
 
 	&avoid_default_addr_size,
 	&obsolete_chosen_interrupt_controller,
+
+	&always_fail,
 };
 
+static void enable_warning_error(struct check *c, bool warn, bool error)
+{
+	int i;
+
+	/* Raising level, also raise it for prereqs */
+	if ((warn && !c->warn) || (error && !c->error))
+		for (i = 0; i < c->num_prereqs; i++)
+			enable_warning_error(c->prereq[i], warn, error);
+
+	c->warn = c->warn || warn;
+	c->error = c->error || error;
+}
+
+static void disable_warning_error(struct check *c, bool warn, bool error)
+{
+	int i;
+
+	/* Lowering level, also lower it for things this is the prereq
+	 * for */
+	if ((warn && c->warn) || (error && c->error)) {
+		for (i = 0; i < ARRAY_SIZE(check_table); i++) {
+			struct check *cc = check_table[i];
+			int j;
+
+			for (j = 0; j < cc->num_prereqs; j++)
+				if (cc->prereq[j] == c)
+					disable_warning_error(cc, warn, error);
+		}
+	}
+
+	c->warn = c->warn && !warn;
+	c->error = c->error && !error;
+}
+
+void parse_checks_option(bool warn, bool error, const char *optarg)
+{
+	int i;
+	const char *name = optarg;
+	bool enable = true;
+
+	if ((strncmp(optarg, "no-", 3) == 0)
+	    || (strncmp(optarg, "no_", 3) == 0)) {
+		name = optarg + 3;
+		enable = false;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(check_table); i++) {
+		struct check *c = check_table[i];
+
+		if (streq(c->name, name)) {
+			if (enable)
+				enable_warning_error(c, warn, error);
+			else
+				disable_warning_error(c, warn, error);
+			return;
+		}
+	}
+
+	die("Unrecognized check name \"%s\"\n", name);
+}
+
 void process_checks(int force, struct boot_info *bi)
 {
 	struct node *dt = bi->dt;
diff --git a/dtc.c b/dtc.c
index bee5085..a375683 100644
--- a/dtc.c
+++ b/dtc.c
@@ -93,6 +93,9 @@ static void  __attribute__ ((noreturn)) usage(void)
 	fprintf(stderr, "\t\t\tlegacy - \"linux,phandle\" properties only\n");
 	fprintf(stderr, "\t\t\tepapr - \"phandle\" properties only\n");
 	fprintf(stderr, "\t\t\tboth - Both \"linux,phandle\" and \"phandle\" properties\n");
+	fprintf(stderr, "\t-W [no-]<checkname>\n");
+	fprintf(stderr, "\t-E [no-]<checkname>\n");
+	fprintf(stderr, "\t\t\tenable or disable warnings and errors\n");
 	exit(3);
 }
 
@@ -115,7 +118,7 @@ int main(int argc, char *argv[])
 	minsize    = 0;
 	padsize    = 0;
 
-	while ((opt = getopt(argc, argv, "hI:O:o:V:d:R:S:p:fqb:i:vH:s"))
+	while ((opt = getopt(argc, argv, "hI:O:o:V:d:R:S:p:fqb:i:vH:sW:E:"))
 			!= EOF) {
 		switch (opt) {
 		case 'I':
@@ -173,6 +176,14 @@ int main(int argc, char *argv[])
 			sort = 1;
 			break;
 
+		case 'W':
+			parse_checks_option(true, false, optarg);
+			break;
+
+		case 'E':
+			parse_checks_option(false, true, optarg);
+			break;
+
 		case 'h':
 		default:
 			usage();
diff --git a/dtc.h b/dtc.h
index d57fbfc..7ee2d54 100644
--- a/dtc.h
+++ b/dtc.h
@@ -226,6 +226,7 @@ void sort_tree(struct boot_info *bi);
 
 /* Checks */
 
+void parse_checks_option(bool warn, bool error, const char *optarg);
 void process_checks(int force, struct boot_info *bi);
 
 /* Flattened trees */
diff --git a/tests/dtc-checkfails.sh b/tests/dtc-checkfails.sh
index 3f77b13..76ded15 100755
--- a/tests/dtc-checkfails.sh
+++ b/tests/dtc-checkfails.sh
@@ -4,10 +4,20 @@
 
 for x; do
     shift
+    if [ "$x" = "-n" ]; then
+	for x; do
+	    shift
+	    if [ "$x" = "--" ]; then
+		break;
+	    fi
+	    NOCHECKS="$NOCHECKS $x"
+	done
+	break;
+    fi
     if [ "$x" = "--" ]; then
 	break;
     fi
-    CHECKS="$CHECKS $x"
+    YESCHECKS="$YESCHECKS $x"
 done
 
 LOG=tmp.log.$$
@@ -19,10 +29,16 @@ ret="$?"
 
 FAIL_IF_SIGNAL $ret
 
-for c in $CHECKS; do
+for c in $YESCHECKS; do
     if ! grep -E "^(ERROR)|(Warning) \($c\):" $LOG > /dev/null; then
 	FAIL "Failed to trigger check \"$c\""
     fi
 done
 
+for c in $NOCHECKS; do
+    if grep -E "^(ERROR)|(Warning) \($c\):" $LOG > /dev/null; then
+	FAIL "Incorrectly triggered check \"$c\""
+    fi
+done
+
 PASS
diff --git a/tests/dtc-fails.sh b/tests/dtc-fails.sh
new file mode 100755
index 0000000..4ddcb27
--- /dev/null
+++ b/tests/dtc-fails.sh
@@ -0,0 +1,30 @@
+#! /bin/sh
+
+. ./tests.sh
+
+if [ "$1" = "-n" ]; then
+    NEG="$1"
+    shift
+fi
+
+OUTPUT="$1"
+shift
+
+verbose_run $VALGRIND "$DTC" -o "$OUTPUT" "$@"
+ret="$?"
+
+FAIL_IF_SIGNAL $ret
+
+if [ -n "$NEG" ]; then
+    if [ ! -e "$OUTPUT" ]; then
+	FAIL "Produced no output"
+    fi
+else
+    if [ -e "$OUTPUT" ]; then
+	FAIL "Incorrectly produced output"
+    fi
+fi
+
+rm -f "$OUTPUT"
+
+PASS
diff --git a/tests/run_tests.sh b/tests/run_tests.sh
index 9a2a7d9..998c422 100755
--- a/tests/run_tests.sh
+++ b/tests/run_tests.sh
@@ -394,6 +394,18 @@ dtc_tests () {
     run_sh_test dtc-checkfails.sh duplicate_label -- -I dts -O dtb reuse-label5.dts
     run_sh_test dtc-checkfails.sh duplicate_label -- -I dts -O dtb reuse-label6.dts
 
+    # Check warning options
+    run_sh_test dtc-checkfails.sh address_cells_is_cell interrupt_cells_is_cell -n size_cells_is_cell -- -Wno_size_cells_is_cell -I dts -O dtb bad-ncells.dts
+    run_sh_test dtc-fails.sh -n test-warn-output.test.dtb -I dts -O dtb bad-ncells.dts
+    run_sh_test dtc-fails.sh test-error-output.test.dtb -I dts -O dtb bad-ncells.dts -Esize_cells_is_cell
+    run_sh_test dtc-checkfails.sh always_fail -- -Walways_fail -I dts -O dtb test_tree1.dts
+    run_sh_test dtc-checkfails.sh -n always_fail -- -Walways_fail -Wno_always_fail -I dts -O dtb test_tree1.dts
+    run_sh_test dtc-fails.sh test-negation-1.test.dtb -Ealways_fail -I dts -O dtb test_tree1.dts
+    run_sh_test dtc-fails.sh -n test-negation-2.test.dtb -Ealways_fail -Eno_always_fail -I dts -O dtb test_tree1.dts
+    run_sh_test dtc-fails.sh test-negation-3.test.dtb -Ealways_fail -Wno_always_fail -I dts -O dtb test_tree1.dts
+    run_sh_test dtc-fails.sh -n test-negation-4.test.dtb -Esize_cells_is_cell -Eno_size_cells_is_cell -I dts -O dtb bad-ncells.dts
+    run_sh_test dtc-checkfails.sh size_cells_is_cell -- -Esize_cells_is_cell -Eno_size_cells_is_cell -I dts -O dtb bad-ncells.dts
+
     # Check for proper behaviour reading from stdin
     run_dtc_test -I dts -O dtb -o stdin_dtc_tree1.test.dtb - < test_tree1.dts
     run_wrap_test cmp stdin_dtc_tree1.test.dtb dtc_tree1.test.dtb
-- 
1.7.10

  parent reply	other threads:[~2012-07-08 13:25 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-07-08 13:25 [PATCH 1/2] Re-work level setting on checks code David Gibson
     [not found] ` <1341753922-3342-1-git-send-email-david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@public.gmane.org>
2012-07-08 13:25   ` David Gibson [this message]
     [not found]     ` <1341753922-3342-2-git-send-email-david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@public.gmane.org>
2012-07-08 18:46       ` [PATCH 2/2] Allow toggling of semantic checks Jon Loeliger
2012-07-08 18:45   ` [PATCH 1/2] Re-work level setting on checks code Jon Loeliger

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=1341753922-3342-2-git-send-email-david@gibson.dropbear.id.au \
    --to=david-xt8fgy+axnrb3ne2bgzf6laj5h9x9tb+@public.gmane.org \
    --cc=devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org \
    --cc=jdl-CYoMK+44s/E@public.gmane.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;
as well as URLs for NNTP newsgroup(s).