summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUlf Magnusson <ulfalizer@gmail.com>2018-11-02 02:35:49 +0100
committerUlf Magnusson <ulfalizer@gmail.com>2018-11-02 03:52:46 +0100
commit0e6cd82908f5c649e15e6a63ad77a94f627449d2 (patch)
treec0d9b6afa0a4a46f0a70ec37d9acabfc4c8e0617
parentb0e4a4fda7d623284ac1949d6797b9f0a1995d88 (diff)
Fix removal of multiple consecutive 'if' nodes
Despite 'if' nodes being flattened before 'if' removal, consecutive 'if' nodes can still show up for code like the following: ... if X endif if X endif ... _remove_ifs() failed to remove the second 'if' node, leading to a crash e.g. when turning on show-all mode in the menuconfig in a menu with such code (due to the unexpected 'if' node). Stuff like the above could potentially result from 'osource's with no matches, though I just spotted the error while looking over the code. Fix the 'if' removal logic to properly handle consecutive 'if' nodes.
-rw-r--r--kconfiglib.py22
-rw-r--r--tests/Kifremoval99
-rw-r--r--testsuite.py19
3 files changed, 129 insertions, 11 deletions
diff --git a/kconfiglib.py b/kconfiglib.py
index eae271e..96e6b52 100644
--- a/kconfiglib.py
+++ b/kconfiglib.py
@@ -5822,17 +5822,17 @@ def _remove_ifs(node):
node.list = cur
while cur:
- if cur.next and not cur.next.item:
- # Equivalent to
- #
- # tmp = cur.next.next
- # cur.next = tmp
- # cur = tmp
- #
- # due to tricky Python semantics. The order matters.
- cur.next = cur = cur.next.next
- else:
- cur = cur.next
+ next = cur.next
+ while next and not next.item:
+ next = next.next
+
+ # Equivalent to
+ #
+ # cur.next = next
+ # cur = next
+ #
+ # due to tricky Python semantics. The order matters.
+ cur.next = cur = next
def _finalize_choice(node):
# Finalizes a choice, marking each symbol whose menu node has the choice as
diff --git a/tests/Kifremoval b/tests/Kifremoval
new file mode 100644
index 0000000..f94472c
--- /dev/null
+++ b/tests/Kifremoval
@@ -0,0 +1,99 @@
+# Test some tricky cases that give consecutive 'if' nodes even after
+# flattening. Simple cases are exercised a ton elsewhere.
+
+if X
+endif
+if X
+endif
+
+config A
+
+if X
+endif
+if X
+endif
+
+config B
+
+if X
+endif
+if X
+endif
+if X
+endif
+
+config C
+
+if X
+ if X
+ if X
+ endif
+ if X
+ endif
+ endif
+ if X
+ if X
+ endif
+ if X
+ endif
+ endif
+ config D
+endif
+if X
+endif
+
+menu "E"
+ if X
+ if X
+ endif
+ endif
+ if X
+ if X
+ endif
+ endif
+endmenu
+
+menu "F"
+ if X
+ endif
+ if X
+ endif
+ if X
+ if X
+ endif
+ if X
+ endif
+ menu "G"
+ endmenu
+ endif
+endmenu
+
+choice H
+ if X
+ if X
+ endif
+ endif
+ if X
+ if X
+ endif
+ endif
+endchoice
+
+choice I
+ if X
+ endif
+ if X
+ endif
+ if X
+ if X
+ endif
+ if X
+ endif
+ config J
+ endif
+endchoice
+
+if X
+endif
+if X
+endif
diff --git a/testsuite.py b/testsuite.py
index cca5dad..6f05b6a 100644
--- a/testsuite.py
+++ b/testsuite.py
@@ -2212,6 +2212,25 @@ CONFIG_G=-1
verify_is_normal_choice_symbol("WS9")
+ print("Testing 'if' node removal")
+
+ c = Kconfig("Kconfiglib/tests/Kifremoval", warn=False)
+
+ nodes = [node for node in c.node_iter()]
+ verify_equal(nodes[0].item.name, "A")
+ verify_equal(nodes[1].item.name, "B")
+ verify_equal(nodes[2].item.name, "C")
+ verify_equal(nodes[3].item.name, "D")
+ verify_equal(nodes[4].prompt[0], "E")
+ verify_equal(nodes[5].prompt[0], "F")
+ verify_equal(nodes[6].prompt[0], "G")
+ verify_equal(nodes[7].item.name, "H")
+ verify_equal(nodes[8].item.name, "I")
+ verify_equal(nodes[9].item.name, "J")
+ verify(len(nodes) == 10,
+ "Wrong number of nodes after 'if' removal")
+
+
print("Testing multi.def. property copying")
c = Kconfig("Kconfiglib/tests/Kdepcopy", warn=False)