88import subprocess
99import dis
1010from symtable import symtable
11-
12- # FIXME test errors too
11+ try :
12+ # run ./build.sh in the readsymtab directory to create this module
13+ from readsymtab import readsymtab
14+ use_readsymtab = True
15+ except ImportError :
16+ import ctypes
17+ use_readsymtab = False
18+ print ("Using compiler dependent code to read bitfields - compile readsymtab module to be sure!" )
1319
1420inp = [
1521 ('''1''' , "eval" ),
@@ -103,12 +109,36 @@ def dump_symtable(st):
103109 out += 'Lineno:%s,\n ' % st .get_lineno () # Return the number of the first line in the block this table represents.
104110 out += 'Unoptimized:%s,\n ' % dump_flags (st ._table .optimized , OPT_FLAGS ) # Return False if the locals in this table can be optimized.
105111 out += 'Nested:%s,\n ' % dump_bool (st .is_nested ()) # Return True if the block is a nested class or function.
112+
113+ if use_readsymtab :
114+ # Use readsymtab modules to read the bitfields which aren't normally exported
115+ free , child_free , generator , varargs , varkeywords , returns_value , needs_class_closure = readsymtab (st ._table )
116+ out += 'Free:%s,\n ' % dump_bool (free )
117+ out += 'ChildFree:%s,\n ' % dump_bool (child_free )
118+ out += 'Generator:%s,\n ' % dump_bool (generator )
119+ out += 'Varargs:%s,\n ' % dump_bool (varargs )
120+ out += 'Varkeywords:%s,\n ' % dump_bool (varkeywords )
121+ out += 'ReturnsValue:%s,\n ' % dump_bool (returns_value )
122+ out += 'NeedsClassClosure:%s,\n ' % dump_bool (needs_class_closure )
123+ else :
124+ # Use ctypes to read the bitfields which aren't normally exported
125+ # FIXME compiler dependent!
126+ base_addr = id (st ._table ) + ctypes .sizeof (ctypes .c_long )* 8 + ctypes .sizeof (ctypes .c_int )* 3
127+ flags = int .from_bytes (ctypes .c_int .from_address (base_addr ), sys .byteorder )
128+ out += 'Free:%s,\n ' % dump_bool (flags & (1 << 0 ))
129+ out += 'ChildFree:%s,\n ' % dump_bool (flags & (1 << 1 ))
130+ out += 'Generator:%s,\n ' % dump_bool (flags & (1 << 2 ))
131+ out += 'Varargs:%s,\n ' % dump_bool (flags & (1 << 3 ))
132+ out += 'Varkeywords:%s,\n ' % dump_bool (flags & (1 << 4 ))
133+ out += 'ReturnsValue:%s,\n ' % dump_bool (flags & (1 << 5 ))
134+ out += 'NeedsClassClosure:%s,\n ' % dump_bool (flags & (1 << 6 ))
135+
106136 #out += 'Exec:%s,\n' % dump_bool(st.has_exec()) # Return True if the block uses exec.
107137 #out += 'ImportStar:%s,\n' % dump_bool(st.has_import_star()) # Return True if the block uses a starred from-import.
108138 out += 'Varnames:%s,\n ' % dump_strings (st ._table .varnames )
109139 out += 'Symbols: Symbols{\n '
110140 children = dict ()
111- for name in st .get_identifiers ():
141+ for name in sorted ( st .get_identifiers () ):
112142 s = st .lookup (name )
113143 out += '"%s":%s,\n ' % (name , dump_symbol (s ))
114144 ns = s .get_namespaces ()
@@ -120,7 +150,7 @@ def dump_symtable(st):
120150 raise AssertionError ("More than one namespace" )
121151 out += '},\n '
122152 out += 'Children:map[string]*SymTable{\n '
123- for name , symtable in children .items ():
153+ for name , symtable in sorted ( children .items () ):
124154 out += '"%s":%s,\n ' % (name , dump_symtable (symtable ))
125155 out += '},\n '
126156 out += "}"
0 commit comments