From 9c8f7eafcad308792478c2636dff8fe9110e0d77 Mon Sep 17 00:00:00 2001
From: Armin Rigo <arigo@tunes.org>
Date: Tue, 28 Oct 2003 12:17:25 +0000
Subject: Fixed dis.disassemble_string(). Added dis.findlinestarts(). SF bug
 811294

---
 Lib/dis.py | 52 ++++++++++++++++++++++++----------------------------
 1 file changed, 24 insertions(+), 28 deletions(-)

diff --git a/Lib/dis.py b/Lib/dis.py
index f878d11..3208011 100644
--- a/Lib/dis.py
+++ b/Lib/dis.py
@@ -60,21 +60,8 @@ def distb(tb=None):
 def disassemble(co, lasti=-1):
     """Disassemble a code object."""
     code = co.co_code
-
-    byte_increments = [ord(c) for c in co.co_lnotab[0::2]]
-    line_increments = [ord(c) for c in co.co_lnotab[1::2]]
-    table_length = len(byte_increments) # == len(line_increments)
-
-    lineno = co.co_firstlineno
-    table_index = 0
-    while (table_index < table_length
-           and byte_increments[table_index] == 0):
-        lineno += line_increments[table_index]
-        table_index += 1
-    addr = 0
-    line_incr = 0
-
     labels = findlabels(code)
+    linestarts = dict(findlinestarts(co))
     n = len(code)
     i = 0
     extended_arg = 0
@@ -82,20 +69,10 @@ def disassemble(co, lasti=-1):
     while i < n:
         c = code[i]
         op = ord(c)
-
-        if i >= addr:
-            lineno += line_incr
-            while table_index < table_length:
-                addr += byte_increments[table_index]
-                line_incr = line_increments[table_index]
-                table_index += 1
-                if line_incr:
-                    break
-            else:
-                addr = sys.maxint
+        if i in linestarts:
             if i > 0:
                 print
-            print "%3d"%lineno,
+            print "%3d" % linestarts[i],
         else:
             print '   ',
 
@@ -137,8 +114,6 @@ def disassemble_string(code, lasti=-1, varnames=None, names=None,
     while i < n:
         c = code[i]
         op = ord(c)
-        if op == opmap['SET_LINENO'] and i > 0:
-            print # Extra blank line
         if i == lasti: print '-->',
         else: print '   ',
         if i in labels: print '>>',
@@ -199,6 +174,27 @@ def findlabels(code):
                     labels.append(label)
     return labels
 
+def findlinestarts(code):
+    """Find the offsets in a byte code which are start of lines in the source.
+
+    Generate pairs (offset, lineno) as described in Python/compile.c.
+
+    """
+    byte_increments = [ord(c) for c in code.co_lnotab[0::2]]
+    line_increments = [ord(c) for c in code.co_lnotab[1::2]]
+
+    lastlineno = None
+    lineno = code.co_firstlineno
+    addr = 0
+    for byte_incr, line_incr in zip(byte_increments, line_increments):
+        if byte_incr:
+            if lineno != lastlineno:
+                yield (addr, lineno)
+                lastlineno = lineno
+            addr += byte_incr
+        lineno += line_incr
+    if lineno != lastlineno:
+        yield (addr, lineno)
 
 def _test():
     """Simple test program to disassemble a file."""
-- 
cgit v0.12

