#!/usr/bin/env python
# encoding: iso-8859-15
#
# typo.py: Warn of typographical errors in a Python script
#

#
#	One of the common annoyances with using Python is that it does
# not report typographical errors in variable names at compile time.
#
#	typo.py does a 2-pass interpretive analysis of the script bytecode
# looking for undefined variables or attributes.   An object is
# considered undefined if all the following are true:
#
# 1. It does not appear on the left-hand-side (LHS) of an assignment
# statement within the scope of the reference.
#
# 2. It is not defined by a def or class statement.
#
# 3. It is not defined in an imported module.
#
# 4. It is not defined in an extension or built-in module.
#
#
#	It is possible to fool typo.py with dynamically generated code,
# e.g., using an exec statement, __getattr__, __setattr__, __import__, etc.
#
#	typo.py is compatible with Python 1.5.2 and Python 2.x.
#

#
# Usage:
#	python typo.py [-d] myfile.py
#
# The -d option will disassemble the file
#

#
# Make initial script
# 30 Jun 01  Alan E. Klietz  (alank@algintech.com)
# http://utools.com/typo.htm
#
# Copyright (c) 2001, Alan E. Klietz
# Unlimited redistribution permitted
#

import os, sys, types, string, py_compile

disasm = 0

suffix = (__debug__ and '.pyc' or '.pyo')

CO_OPTIMIZED = 1   # CO_OPTIMIZED indicates an optimized function
CO_NEWLOCALS = 2   # CO_NEWLOCALS indicates not module level

builtin_attrs = {

	# dict object methods
	'clear':1, 'copy':1, 'get':1, 'has_key':1, 'items':1, 'keys':1, 
	'popitem':1, 'setdefault':1, 'update':1, 'values':1,

	# list object methods
	'append':1, 'count':1, 'extend':1, 'index':1, 'insert':1, 
	'pop':1, 'remove':1, 'reverse':1, 'sort':1,

	# string object methods
	'capitalize':1, 'center':1, 'count':1, 'encode':1, 'endswith':1,
	'expandtabs':1, 'find':1, 'index':1, 'isalnum':1, 'isalpha':1,
	'isdigit':1, 'islower':1, 'isspace':1, 'istitle':1, 'isupper':1,
	'join':1, 'ljust':1, 'lower':1, 'lstrip':1, 'replace':1, 'rfind':1,
	'rindex':1, 'rjust':1, 'rstrip':1, 'strip':1, 'split':1, 'splitlines':1,
	'startswith':1, 'strip':1, 'swapcase':1, 'title':1, 'translate':1,
	'upper':1,

	# unicode methods 
	'encode':1, 'maketrans':1, 'isdecimal':1, 'isnumeric':1,

	# file object methods
	'close':1, 'closed':1, 'fileno':1, 'flush':1, 'isatty':1,
	'mode':1, 'name':1, 'read':1, 'readinto':1, 'readline':1,
	'readlines':1, 'seek':1, 'softspace':1, 'tell':1, 'truncate':1,
	'write':1, 'writelines':1, 'xreadlines':1,

	# complex object attrs
	'conjugate':1, 'real':1, 'imag':1, '__members__':1,

	# range object attrs
	'tolist':1, 'step':1, 'start':1, 'stop':1,
	'__members__':1, # = ['start','stop','step']

	# exception object attrs
	'args':1, 'filename':1, 'errno':1, 'strerror':1, 'msg':1,

	# class object attrs
	'__dict__':1,  # method members
	'__bases__':1, '__module__':1, '__name__':1,

	# instance object attrs (also uses class)
	'__dict__':1,  # data members
	'__class__':1,

	# instancemethod and unboundmethod object attrs
	'__name__':1, '__doc__':1, '__dict__':1,
	'__members__':1, # = ['__doc__','__name__','__self__']
	'im_func':1, 'im_self':1, 'im_class':1, '__name__':1, '__doc__':1, '__dict__':1,
	
	# func object attrs
	'func_code':1, 'func_globals':1, 'func_name':1, '__name__':1,
	'func_closure':1, 'func_defaults':1, 'func_doc':1, '__doc__':1,
	'func_dict':1,

	# code object attrs
	'co_argcount':1, 'co_nlocals':1, 'co_stacksize':1, 'co_flags':1,
	'co_code':1, 'co_consts':1, 'co_names':1, 'co_varnames':1,
	'co_freevars':1, 'co_cellvars':1, 'co_filename':1,
	'co_name':1, 'co_firstlineno':1, 'co_lnotab':1,

	# frame object attrs
	'f_back':1, 'f_code':1, 'f_builtins':1, 'f_globals':1, 'f_locals':1,
	'f_lasti':1, 'f_lineno':1, 'f_restricted':1, 'f_trace':1,
	'f_exc_type':1, 'f_exc_value':1, 'f_exc_traceback':1,
	'f_locals':1,

	# traceback object attrs
	'tb_next':1, 'tb_frame':1, 'tb_lasti':1, 'tb_lineno':1,

	# module object attrs
	'__file__':1,

	# symtable object
	#'id':1, 'name':1, 'symbols':1, 'varnames':1, 'children':1,
	#'type':1, 'lineno':1, 'optimized':1, 'nested':1,

}

#####################################################################
#
# Explicitly enumerate extension attrs.  There is no other way (sigh)
#
def collect_extension_attrs(modname, attrs):
	d = None

	if modname == 'array':
		d = {
			'append':1, 'buffer_info':1, 
			'byteswap':1, 'count':1, 'extend':1,
			'fromfile':1, 'fromlist':1, 'fromstring':1,
			'index':1, 'insert':1, 'pop':1, 'read':1, 
			'remove':1, 'reverse':1, 'tofile':1, 
			'tolist':1, 'tostring':1, 'write':1,
			#
			'typecode':1, 'itemsize':1, '__members__':1,
		}

	elif modname == 'cd':
		d = {
			'allowremoval':1, 'bestreadsize':1,
			'close':1, 'eject':1, 'getstatus':1,
			'gettrackinfo':1, 'msftoblock':1,
			'play':1, 'playabs':1, 'playtrack':1,
			'playtrackabs':1, 'preventremoval':1,
			'readda':1, 'seek':1, 'seekblock':1, 'seektrack':1,
			'stop':1, 'togglepause':1,
			#
			'addcallback':1, 'deleteparser':1,
			'parseframe':1, 'removecallback':1,
			'resetparser':1, 'setcallback':1,
		}

	elif modname == 'cl':
		d = {
			'close':1, 'CloseDecompressor':1,
			'Decompress':1, 'GetDefault':1,
			'GetMinMax':1, 'GetName':1,
			'GetParam':1, 'GetParamID':1,
			'GetParams':1, 'ReadHeader':1,
			'QueryParams':1, 'QuerySchemeFromHandle':1,
			'SetParam':1, 'SetParams':1,
		}

	elif modname == 'cPickle':
		d = {
			'dump':1, 'clear_memo':1, 'getvalue':1,
			#
			'persistent_id':1, 'memo':1, 'PicklingError':1,
			'binary':1, 'fast':1, 'getvalue':1,
			#
			'load':1, 'noload':1,
			#
			'persistent_load':1, 'find_global':1,
			'UnpicklingError':1,
		}

	elif modname == 'bsddb':
		d = {
			'close':1, 'keys':1, 'has_key':1,
			'set_location':1, 'next':1, 'previous':1,
			'first':1, 'last':1, 'sync':1,
		}

	elif modname == '_curses':
		d = {
			'addch':1, 'addnstr':1, 'addstr':1,
			'attroff':1, 'attron':1, 'attrset':1,
			'bkgd':1, 'bkgdset':1, 'border':1,
			'box':1, 'clear':1, 'clearok':1, 'clrtobot':1,
			'clrtoeol':1, 'cursyncup':1, 'delch':1,
			'deleteln':1, 'derwin':1, 'echochar':1,
			'enclose':1, 'erase':1, 'getbegyx':1,
			'getch':1, 'getkey':1, 'getmaxyx':1, 'getparyx':1,
			'getstr':1, 'getyx':1, 'hline':1, 'idcok':1, 'idlok':1,
			'immedok':1, 'inch':1, 'insch':1, 'insdelln':1, 'insertln':1,
			'insnstr':1, 'insstr':1, 'instr':1, 
			'is_linetouched':1, 'is_wintouched':1,
			'keypad':1, 'leaveok':1, 'move':1,
			'mvderwin':1, 'mvwin':1, 'nodelay':1,
			'notimeout':1, 'noutrefresh':1,
			'overlay':1, 'overwrite':1, 'putwin':1,
			'redrawln':1, 'redrawwin':1, 'refresh':1,
			'resize':1, 'scroll':1, 'scrollok':1,
			'setscrreg':1, 'standend':1, 'standout':1,
			'subpad':1, 'subwin':1, 'syncdown':1,
			'syncok':1, 'syncup':1, 'timeout':1,
			'touchline':1, 'touchwin':1,
			'untouchwin':1, 'vline':1,
		}

	elif modname == '_curses_panel':
		d = {
			'above':1, 'below':1, 'bottom':1, 'hidden':1, 'hide':1,
			'move':1, 'replace':1, 'set_userptr':1, 'show':1, 'top':1,
			'userptr':1, 'window':1,
		}

	elif modname == 'cStringIO':
		d = {
			# same as file plus these
			'getvalue':1, 'reset':1,
		}
	
	elif modname == 'dl':
		d = {
			'call':1, 'sym':1, 'close':1,
		}

	elif modname == 'fl':
		d = {
			'objclass':1, 'type':1,
			'boxtype':1, 'x':1, 'y':1, 'w':1, 'h':1,
			'col1':1, 'col2':1, 'align':1, 'lcol':1,
			'lsize':1, 'label':1, 'lstyle':1, 'pushed':1,
			'focus':1, 'belowmouse':1, 'active':1, 
			'input':1, 'visible':1, 'radio':1, 'automatic':1,
		}
	elif modname == 'fm':
		d = {
			'scalefont':1, 'setfont':1, 'getfontname':1,
			'getcomment':1, 'getfontinfo':1, 'getstrwidth':1,
		}

	elif modname == 'gdbm':
		d = {
			'firstkey':1, 'nextkey':1, 'reorganize':1, 'sync':1,
		}

	elif modname == 'linuxaudiodev':
		d = {
			'read':1, 'write':1, 'setparameters':1,
			'bufsize':1, 'obufcount':1, 'obuffree':1,
			'flush':1, 'close':1, 'fileno':1, 'getptr':1,
		}

	elif modname == 'md5':
		d = {
			'update':1, 'digest':1, 'hexdigest':1, 'copy':1,
		}

	elif modname == 'mmap':
		d = {
			'find':1, 'move':1, 'read_byte':1, 'resize':1,
			'size':1, 'write_byte':1,
		}

	elif modname == 'mpz':
		d = {
			'binary':1,
		}

	elif modname == 'parser':
		d = {
			'compile':1, 'isexpr':1, 'issuite':1, 'tolist':1,
			'totuple':1,
		}

	elif modname == 'pcre':
		d = {
			'match':1,
		}

	elif modname == 'pyaelib':  # AEK local
		d = {
			# pyaedh.cpp
			'DoServer':1, 'DoClient':1, 'ComputeFinalKey':1,

			# pyaeminissl.cpp
			'connect':1, 'accept':1, 'send':1, 'recv':1,
			'close':1, 'get_peer_guid':1,
			'get_session_guid':1, 'set_session_guid':1,
			'get_cipher_suite':1,

			# pyaerc4.cpp
			'Encrypt':1, 'SetKey':1,

			# pyaereg.cpp
			'QueryValueDword':1, 'QueryValueStr':1, 
			'SetValueDword':1, 'SetValueStr':1, 
			'OpenKey':1, 'CreateKey':1,
			'HasValue':1, 'HasKey':1,
			'DeleteKey':1, 'DeleteValue':1,
			'EnumRewind':1, 'EnumKeyNext':1,
			'EnumValueNext':1,

			# pyaethread.cpp
			'handle':1, 'thread_id':1, 'result':1,
			'exc_type':1, 'exc_value':1, 'exc_traceback':1,
			'is_running':1, 'wait':1, 'snap_trackback':1, 'kill':1,
			'grab_lock':1, 
		}

	elif modname == 'pyexpat':
		d = {
			'ErrorCode':1, 'ErrorLineNumber':1,
			'ErrorColumnNumber':1, 'ErrorByteIndex':1,
			'ordered_attributes':1,
			'returns_unicode':1,
			'specified_attributes':1,
			'__members__':1,
			#
			# Note: dynamic attrs from XML tags are not supported!
			#
		}

	elif modname == 'regex':
		d = {
			'match':1, 'search':1, 'group':1, 'last':1, 'groupindex':1,
			'regs':1, 'translate':1, 'realpat':1, 'givenpat':1,
			'__members__':1,
		}

	elif modname == 'rotor':
		d = {
			'encrypt':1, 'encryptmore':1, 'decrypt':1, 'decryptmore':1,
			'setkey':1,
		}

	elif modname == 'select':
		d = {
			'register':1, 'unregister':1, 'poll':1,
		}

	elif modname == 'sha':
		d = {
			'digest':1, 'hexdigest':1, 'update':1,
		}

	elif modname == 'socket' or modname == '_socket':
		d = {
			'accept':1, 'bind':1, 'close':1, 'connect':1,
			'connect_ex':1, 'fileno':1, 'dup':1, 'getpeername':1,
			'getsockname':1, 'getsockopt':1, 'listen':1,
			'makefile':1, 'recv':1, 'recvfrom':1, 'send':1, 'sendto':1,
			'setblocking':1, 'setsockopt':1, 'shutdown':1,

			# SSL methods
			'write':1, 'read':1, 'server':1, 'issuer':1,
		}

	elif modname == '_sre':
		d = {
			# re object
			'match':1, 'search':1, 'sub':1, 'subn':1, 'split':1, 'findall':1,
			'scanner':1,

			# match object
			'group':1, 'start':1, 'end':1, 'span':1, 'groups':1, 'groupdict':1,
			'expand':1,

			# scanner object
			'pattern':1, 'match':1, 'search':1,
		}
	
	elif modname == 'sunaudiodev':
		d = {
			'ibufcount':1, 'obufcount':1, 'getinfo':1, 'setinfo':1,
			'drain':1, 'getdev':1, 'fileno':1,
			#
			'i_sample_rate':1, 'i_channels':1,
			'i_precision':1, 'i_encoding':1, 'i_gain':1, 
			'i_port':1, 'i_samples':1, 'i_eof':1, 
			'i_pause':1, 'i_error':1, 'i_waiting':1,
			'i_open':1, 'i_active':1, 'i_buffer_size':1,
			'i_balance':1, 'i_avail_ports':1, 
			'o_sample_rate':1, 'o_channels':1,
			'o_precision':1, 'o_encoding':1,
			'o_gain':1, 'o_port':1, 'o_samples':1,
			'o_eof':1, 'o_pause':1, 'o_waiting':1,
			'o_open':1, 'o_active':1, 'o_buffer_size':1,
			'o_balance':1, 'o_avail_ports':1, 'monitor_gain':1,
		}

	elif modname == 'sv':
		d = {
			'YUVtoRGB':1, 'RGB8toRGB32':1, 'InterleaveFields':1,
			'UnlockCaptureData':1, 'FindVisibleRegion':1,
			'GetFields':1, 'YUVtoYUV422DC':1,
			'YUVtoYUV422DC_quarter':1,
			'YUVtoYUV422DC_sixteenth':1,
			'lrectwrite':1, 'writefile':1,
			#
			'BindGLWindow':1, 'EndContinuousCapture':1,
			'IsVideoDisplayed':1, 'OutputOffset':1,
			'PutFrame':1, 'QuerySize':1, 'SetSize':1,
			'SetStdDefaults':1, 'UseExclusive':1,
			'WindowOffset':1, 'InitContinuousCapture':1,
			'CaptureBurst':1, 'CaptureOneFrame':1,
			'GetCaptureData':1, 'CloseVideo':1,
			'LoadMap':1, 'GetParam':1, 'GetParamRange':1, 'SetParam':1,
		}


	elif modname == 'sys':
		d = {
			# These are defined only after a toplevel exception
			'last_type':1, 'last_value':1, 'last_traceback':1,
			# These are defined only during an interactive session
			'ps1':1, 'ps2':1,
		}

	elif modname == '_tkinter':
		d = {
			'call':1, 'globalcall':1, 'eval':1, 'globaleval':1,
			'evalfile':1, 'record':1, 'adderrorinfo':1,
			'setvar':1, 'globalsetvar':1, 'getvar':1,
			'globalgetvar':1, 'unsetvar':1, 'globalunsetvar':1,
			'getint':1, 'getdouble':1, 'getboolean':1,
			'exprstring':1, 'exprlong':1, 'exprdouble':1,
			'exprboolean':1, 'splitlist':1, 'split':1,
			'merge':1, 'createcommand':1, 
			'deletecommand':1, 'createfilehandler':1,
			'deletefilehandler':1, 'createtimerhandle':1,
			'mainloop':1, 'dooneevent':1, 'quit':1, 'interpaddr':1,
			#
			'deletetimerhandler':1, 
		}

	elif modname == 'thread':
		d = {
			'acquire_lock':1, 'acquire':1, 
			'release_lock':1, 'release':1,
			'locked_lock':1, 'locked':1,
		}

	elif modname == 'zlib':
		d = {
			'compress':1, 'decompress':1, 'unused_data':1,
		}

	##################################################################
	#
	# win32all\win32
	#
	elif modname == 'dbi':
		d = {
			'value':1, 
		}

	elif modname == 'mmapfile':
		d = {
			'move':1, 'read_byte':1, 'resize':1,
			'write_byte':1,
		}

	elif modname == 'odbc':
		d = {
			'error':1, 'setautocommit':1, 'commit':1,
			'rollback':1, 'cursor':1, 'close':1,
			#
			'description':1, 'execute':1, 'fetchone':1,
			'fetchmany':1, 'fetchall':1, 'setinputsizes':1,
			'setoutputsize':1,
		}

	elif modname == 'pywintypes':
		d = {
			# PyACL.cpp
			'Initialize':1, 'AddAccessAllowedAce':1,
			'AddAccessDeniedAce':1,

			# PyHANDLE.cpp
			'handle':1, 'Close':1, 'Detach':1,

			# PyOVERLAPPED.cpp
			'hEvent':1, 'object':1,
			'Internal':1, 'InternalHigh':1,
			'Offset':1, 'OffsetHigh':1,

			# PySECURITY_ATTRIBUTES.cpp
			'Initialize':1, 'SetSecurityDescriptorDacl':1,

			# PySECURITY_DESCRIPTOR.cpp
			'Initialize':1, 'SetSecurityDescriptorDacl':1,
			'SetDacl':1,

			# PySID.cpp
			'Initialize':1, 'IsValid':1,
			'SetSubAuthority':1,

			# PyTime.cpp
			'Format':1,
			'year':1, 'month':1, 'weekday':1, 'day':1,
			'hour':1, 'minute':1, 'second':1, 'msec':1, 

			# PyUnicode.cpp
			'raw':1, 'upper':1, 'lower':1,
		}

	elif modname == 'win2kras':
		d = {
			'szUserName':1, 'userName':1,
			'pbEapInfo':1, 'eapInfo':1,
		}

	elif modname in ['win32event', 'win32file', 'win32pipe', 'win32security']:
		d = {
			# indirect via PyHANDLE.cpp
			'handle':1, 'Close':1, 'Detach':1,
		}

	elif modname == 'win32file_comm':
		d = {
			'fBinary':1, 'fParity':1,
			'fOutxCtsFlow':1,
			'fOutxDrsFlow':1,
			'fDtrControl':1,
			'fDsrSensitivity':1,
			'fTXContinueOnXoff':1,
			'fOutX':1, 'fInX':1, 'fErrorChar':1,
			'fNull':1, 'fRtsControl':1, 'fAbortOnError':1,
			'fDummy2':1,
			#
			'fCtsHold':1, 'fDsrHold':1, 'fRlsdHold':1,
			'fXoffHold':1, 'fXoffSent':1, 'fEof':1, 'fTxim':1,
			'fReserved':1,
			#
			'BaudRate':1, 'wReserved':1, 'XonLim':1,
			'XoffLim':1, 'ByteSize':1, 'Parity':1,
			'StopBits':1, 'XonChar':1, 'XoffChar':1,
			'ErrorChar':1, 'EofChar':1, 'EvtChar':1,
			'wReserved1':1,
			#
			'cbInQue':1, 'cbOutQue':1,
		}

	elif modname == 'win32gui':
		d = {
			'style':1, 'cbWndExtra':1, 'hInstance':1,
			'hIcon':1, 'hCursor':1, 'hbrBackground':1,
			'lpszMenuName':1, 'lpszClassName':1, 'lpfnWndProc':1,
			#
			'lfFaceName':1,
			'lfHeight':1, 'lfWidth':1,
			'lfEscapement':1, 'lfOrientation':1,
			'lfWeight':1, 'lfItalic':1, 'lfUnderline':1,
			'lfStrikeOut':1, 'lfCharSet':1, 'lfOutPrecision':1,
			'lfClipPrecision':1, 'lfQuality':1, 'lfPitchAndFamily':1,
		}

	elif modname == 'win32help':
		d = {
			'typeName':1, 'caption':1, 'toc':1, 'index':1,
			'file':1, 'home':1, 'jump1':1, 'jump2':1,
			'urlJump1':1, 'urlJump2':1, 'windowPos':1,
			'HTMLPos':1,
			#
			'hdr':1, 'url':1, 'curUrl':1, 'winType':1,
			#
			'keywords':1, 'url':1, 'msgText':1, 'msgTitle':1,
			'window':1,
			#
			'searchQuery':1,
			#
			'text':1,'font':1,'pt':1,'margins':1,
			#
			'indexOnFail':1, 'uniCodeStrings':1, 'proximity':1,
			'stemmedSearch':1, 'titleOnly':1, 'execute':1, 'searchQuery':1,
			#
			'hinst':1, 'idString':1, 'clrForeground':1, 
			'clrBackground':1, 'text':1, 'font':1, 'pt':1,
			'margins':1,
			#
			'validMembers':1, 'winProperties':1, 'exStyles':1,
			'showState':1, 'hwndHelp':1, 'hwndCaller':1,
			'hwndToolBar':1, 'hwndNavigation':1, 'hwndHTML':1,
			'navWidth':1, 'toolBarFlags':1, 'notExpanded':1,
			'curNavType':1, 'idNotify':1, 'typename':1,
			'caption':1, 'windowPos':1, 'HTMLPos':1,
			#
			'hwndFrom':1, 'idFrom':1, 'code':1, 
			#
			'action':1, 'winType':1,
		}

	elif modname == 'win32process':
		d = {
			'hStdInput':1, 'hStdOutput':1, 'hStdError':1,
			'lpDesktop':1, 'lpTitle':1, 
			'dwX':1, 'dwY':1, 'dwXSize':1,
			'dwYSize':1, 'dwXCountChars':1,
			'dwYCountChars':1, 'dwFillAttribute':1,
			'dwFlags':1, 'wShowWindow':1,
			# indirect via PyHANDLE.cpp
			'handle':1, 'Close':1, 'Detach':1,
		}

	elif modname == 'win32ras':
		d = {
			'dwfOptions':1, 'hwndParent':1, 'reserved':1,
			'reserved1':1, 'RasEapInfo':1,
		}


	elif modname == 'win32wnet':
		d = {
			'Callname':1, 'Name':1, 'Buffer':1, 
			'Command':1, 'Retcode':1, 'Lsn':1,
			'Num':1, 'Bufflen':1, 'Callname':1,
			'Name':1, 'Rto':1, 'Sto':1, 
			'Lana_num':1, 'Cmd_cplt':1,
			'Event':1, 'Post':1,
			#
			'lpProvider':1, 'lpRemoteName':1,
			'lpLocalName':1, 'lpComment':1,
			'dwScope':1, 'dwType':1, 'dwDisplayType':1,
			'dwUsage':1, 
		}

	# omitted: PerfMon

	##################################################################
	#
	# win32all\com
	#
	elif modname == 'pythoncom':
		d = {
			# PyFUNCDESC.cpp
			'memid':1, 'scodeArray':1, 'args':1,
			'funckind':1, 'invkind':1, 'callconv':1,
			'cParamsOpt':1, 'oVft':1, 'rettype':1, 'wFuncFlags':1,

			# PyTYPEATTR.cpp
			'iid':1, 'lcid':1, 'memidConstructor':1,
			'memidDestructor':1, 'cbSizeInstance':1,
			'typekind':1, 'cFuncs':1, 'cVars':1,
			'cImplTypes':1, 'cbSizeVft':1,
			'cbAlighment':1, 'wTypeFlags':1, 'wMajorVerNum':1,
			'wMinorVerNum':1, 'tdescAlias':1, 'idldescType':1,

			# PyVARDESC.cpp
			'memid':1, 'value':1, 'elemdescVar':1, 'wVarFlags':1,
			'varkind':1,
		}


	##################################################################
	#
	# win32all\Pythonwin
	#
	elif modname == 'win32ui':
		d = {
			# pythonpsheet.cpp
			'WindowProc':1, 'OnInitDialog':1,
			'OnCreate':1,

			# pythonview.cpp
			'OnPrepareDC':1, 'DrawItem':1, 

			# win32app.cpp
			'AddDocTemplate':1, 'FindOpenDocument':1,
			'GetDocTemplateList':1, 'InitMDIInstance':1,
			'InitDlgInstance':1, 'LoadCursor':1,
			'LoadStandardCursor':1, 'LoadOEMCursor':1,
			'LoadIcon':1, 'LoadStandardIcon':1, 'OpenDocumentFile':1,
			'OnFileNew':1, 'OnFileOpen':1, 'RemoveDocTemplate':1,
			'Run':1, 'IsInproc':1,

			# win32assoc.cpp
			'AttachObject':1, 

			# win32btmap.cpp
			'CreateCompatibleBitmap':1, 'GetSize':1, 'GetHandle':1,
			'LoadBitmap':1, 'LoadBitmapFile':1, 'LoadPPMFile':1,
			'Paint':1, 'GetInfo':1, 'GetBitmapBits':1, 'SaveBitmapFile':1,

			# win32brush.cpp
			'CreateSolidBrush':1, 'GetSafeHandle':1,

			# win32cmd.cpp
			'BeginWaitCursor':1, 'EndWaitCursor':1,
			'HookCommand':1, 'HookCommandUpdate':1,
			'HookOleEvent':1, 'HookNotify':1,
			'RestoreWaitCursor':1,

			# win32cmdui.cpp
			'Enable':1, 'SetCheck':1, 'SetRadio':1, 'SetText':1,
			'ContinueRouting':1,
			'm_nIndex':1, 'm_nID':1,

			# win32control.cpp
			'GetBitmap':1, 'SetBitmap':1, 'GetCheck':1, 'SetCheck':1,
			'GetState':1, 'SetState':1, 'GetButtonStyle':1,
			'SetButtonStyle':1,
			#
			'AddString':1, 'DeleteString':1, 'Dir':1, 'GetCaretIndex':1,
			'GetCount':1, 'GetCurSel':1, 'GetItemData':1, 'GetItemValue':1,
			'GetSel':1, 'GetSelCount':1, 'GetSelItems':1, 'GetSelTextItems':1,
			'GetTopIndex':1, 'GetText':1, 'GetTextLen':1, 
			'InsertString':1, 'ResetContent':1, 'SetCaretIndex':1,
			'SelectString':1, 'SelItemRange':1, 'SetCurSel':1,
			'SetItemData':1, 'SetItemValue':1, 'SelSel':1,
			'SetTabStops':1, 'SetTopIndex':1,
			#
			'GetEditSel':1, 'GetExtendedUI':1, 'GetLBText':1,
			'GetLBTextLen':1, 'LimitText':1, 'SetEditSel':1,
			'SetExtendedUI':1, 'ShowDropDown':1,
			#
			'SetRange':1, 'SetPos':1, 'OffsetPos':1, 'SetStep':1, 'StepIt':1,
			#
			'CreateWindow':1, 'GetLineSize':1, 'SetLineSize':1,
			'GetPageSize':1, 'SetPageSize':1, 'GetRangeMax':1,
			'GetRangeMin':1, 'GetRange':1, 'SetRangeMax':1, 
			'SetRangeMin':1, 'SetRange':1, 'GetSelection':1,
			'SetSelection':1, 'GetChannelRect':1, 'GetThumbRect':1,
			'GetPos':1, 'SetPos':1, 'GetNumTics':1, 'GetTicArray':1,
			'GetTic':1, 'GetTicPos':1, 'SetTic':1, 'SetTicFreq':1,
			'ClearSel':1, 'VerifyPos':1, 'ClearTics':1,
			#
			'GetBorders':1, 'GetParts':1, 'GetTextAttr':1,
			'GetTextLength':1, 'SetMinHeight':1, 'SetParts':1, 'SetText':1,
			#
			'SetRange':1, 'SetRange32':1,

			# win32cltedit.cpp
			'Clear':1, 'Copy':1, 'Cut':1, 'FmtLines':1, 
			'GetFirstVisibleLine':1, 'GetSel':1, 'GetLine':1,
			'GetLineCount':1, 'LimitText':1, 'LineFromChar':1,
			'LineIndex':1, 'LineScroll':1, 'Paste':1, 'ReplaceSel':1,
			'SetReadOnly':1, 'SetSel':1,

			# win32ctrllList.cpp
			'Arrange':1, 'DeleteAllItems':1, 'DeleteItem':1,
			'GetTextColor':1, 'SetTextColor':1, 'GetBkColor':1,
			'SetBkColor':1, 'GetItemRect':1, 'GetItem':1,
			'GetItemCount':1, 'GetEditControl':1, 'EditLabel':1,
			'EnsureVisible':1, 'CreateDragImage':1, 'GetImageList':1,
			'GetNextItem':1, 'InsertColumn':1, 'InsertItem':1,
			'SetImageList':1, 'GetColumn':1, 'GetTextBkColor':1,
			'SetTextBkColor':1, 'GetTopIndex':1, 'GetCountPerPage':1,
			'GetSelectedCount':1, 'SetItem':1, 'SetItemState':1,
			'GetItemState':1, 'SetItemData':1, 'GetItemData':1,
			'SetItemCount':1, 'GetItemCount':1, 'SetItemText':1,
			'GetItemText':1, 'RedrawItems':1, 'Update':1,
			'SetColumn':1, 'DeleteColumn':1, 'GetColumnWidth':1,
			'SetColumnWidth':1, 'GetStringWidth':1, 'HitTest':1,
			'GetItemPosition':1,

			# win32ctrlRichEdit.cpp
			'Clear':1, 'Copy':1, 'Cut':1, 'FindText':1, 'GetCharPos':1,
			'GetDefaultCharFormat':1, 'GetEventMask':1, 
			'GetSelectionCharFormat':1, 'GetFirstVisibleLine':1,
			'GetParaFormat':1, 'GetSel':1, 'GetSelText':1,
			'GetTextLength':1, 'GetLine':1, 'GetModify':1,
			'GetLineCount':1, 'LimitText':1, 'LineFromChar':1,
			'LineIndex':1, 'LineScroll':1, 'Paste':1,
			'ReplaceSel':1, 'SetBackgroundColor':1,
			'SetDefaultCharFormat':1, 'SetEventMask':1,
			'SetSelectionCharFormat':1, 'SetModify':1,
			'SetOptions':1, 'SetParaFormat':1, 'SetReadOnly':1,
			'SetSel':1, 'SetSelAndCharFormat':1, 'SetTargetDevice':1,
			'StreamIn':1, 'StreamOut':1,

			# win32ctrlTree.cpp
			'GetIndent':1, 'SetIndent':1, 'ItemHasChildren':1,
			'GetChildItem':1, 'GetNextSiblingItem':1,
			'GetPrevSiblingItem':1, 'GetParentItem':1,
			'GetFirstVisibleItem':1, 'GetNextVisibleItem':1,
			'GetPrevVisibleItem':1, 'GetSelectedItem':1,
			'GetDropHilightItem':1, 'GetRootItem':1, 'GetItemState':1,
			'SetItemState':1, 'GetItemImage':1, 'SetItemImage':1,
			'SetItemText':1, 'GetItemText':1, 'GetItemData':1,
			'SetItemData':1, 'GetItemRect':1, 'GetEditControl':1,
			'GetVisibleCount':1, 'InsertItem':1, 'DeleteItem':1,
			'Expand':1, 'Select':1, 'SelectItem':1, 'SelectDropTarget':1,
			'SelectSetFirstVisible':1, 'EditLabel':1, 'CreateDragImage':1,
			'SortChildren':1, 'EnsureVisible':1, 'HitTest':1,

			# win32dc.cpp
			'AbortDoc':1, 'Arc':1, 'BeginPath':1, 'BitBlt':1,
			'Chord':1, 'CreateCompatibleDC':1, 'CreatePrinterDC':1,
			'CreatePrinterDC':1, 'DeleteDC':1, 'DPtoLP':1,
			'Draw3dRect':1, 'DrawFocusRect':1, 'DrawFrameControl':1,
			'DrawIcon':1, 'DrawText':1, 'Ellipse':1, 'EndDoc':1,
			'EndPage':1, 'EndPath':1, 'ExtTextOut':1, 'FillPath':1,
			'FillRect':1, 'FillSolidRect':1, 'FrameRect':1, 'GetBrushOrg':1,
			'GetClipBox':1, 'GetCurrentPosition':1, 'GetDeviceCaps':1,
			'GetHandleAttrib':1, 'GetHandleOutput':1, 'GetMapMode':1,
			'GetNearestColor':1, 'GetPixel':1, 'GetSafeHdc':1,
			'GetPixel':1, 'GetSafeHdc':1, 'GetTextExtent':1, 
			'GetTextExtentPoint':1, 'GetTextFace':1, 'GetTextMetrics':1,
			'GetViewportExt':1, 'GetViewportOrg':1, 'GetWindowExt':1,
			'GetWindowOrg':1, 'IntersectClipRect':1, 'IsPrinting':1,
			'LineTo':1, 'LPtoDP':1, 'MoveTo':1, 'OffsetWindowOrg':1,
			'OffsetViewportOrg':1, 'PatBlt':1, 'Pie':1, 'PolyBezier':1,
			'Polygon':1, 'Polyline':1, 'RealizePalette':1, 
			'Rectangle':1, 'RectVisible':1, 'RestoreDC':1, 
			'SaveDC':1, 'ScaleWindowExt':1, 'ScaleViewportExt':1,
			'SelectClipRgn':1, 'SelectObject':1, 'SelectPalette':1,
			'SetBkColor':1, 'SetBkMode':1, 'SetBrushOrg':1, 
			'SetGraphicsMode':1, 'SetMapMode':1, 'SetPixel':1,
			'SetPolyFillMode':1, 'SetROP2':1, 'SetTextAlign':1,
			'SetTextColor':1, 'SetWindowExt':1, 'SetWindowOrg':1,
			'SetViewportExt':1, 'SetViewportOrg':1, 
			'SetWorldTransform':1, 'StartDoc':1, 'StartPage':1,
			'StretchBlt':1, 'StrokeAndFinish':1, 'StrokePath':1, 'TextOut':1,


			# win32dlg.cpp
			'data':1, 'datalist':1,
			'DoModal':1, 'EndDialog':1, 'GotoDlgCtrl':1, 'MapDialogRect':1,
			'OnCancel':1, 'OnOK':1, 'OnInitDialog':1,
			#
			'GetPathName':1, 'GetFileName':1, 'GetFileExt':1,
			'GetFileTitle':1, 'GetPathNames':1, 'GetReadOnlyPref':1,
			'GetOFNTitle':1, 'SetOFNInitialDir':1,
			#
			'GetCurrentFont':1, 'GetCharFormat':1, 'GetColor':1,
			'GetFaceName':1, 'GetStyleName':1, 'GetSize':1,
			'GetWeight':1, 'IsStrikeOut':1, 'IsUnderline':1,
			'IsBold':1, 'IsItalic':1,
			#
			'GetSavedCustomColors':1, 'SetCurrentColor':1,
			'SetCustomColors':1, 'GetCustomColors':1,

			# win32dll.cpp
			'GetFileName':1, 'AttachToMFC':1,

			# win32doc.cpp
			'DeleteContents':1, 'DoSave':1, 'DoFileSave':1, 'GetDocTemplate':1,
			'GetAllViews':1, 'GetFirstView':1, 'GetPathName':1,
			'GetTitle':1, 'IsModified':1, 'OnChangedViewList':1,
			'OnCloseDocument':1, 'OnNewDocument':1, 'OnOpenDocument':1,
			'OnSaveDocument':1, 'SetModifiedFlag':1, 'SaveModified':1,
			'SetPathName':1, 'SetTitle':1, 'UpdateAllViews':1,

			# win32ImageList.cpp
			'Add':1, 'Destroy':1, 'DeleteImageList':1, 'GetBkColor':1,
			'GetSafeHandle':1, 'GetImageCount':1, 'GetImageInfo':1, 
			'SetBkColor':1,

			# win32menu.cpp
			'AppendMenu':1, 'DeleteMenu':1, 'Detach':1, 
			'EnableMenuItem':1, 'GetHandle':1, 'GetMenuItemCount':1,
			'GetMenuItemID':1, 'GetMenuString':1, 'GetSubMenu':1,
			'InsertMenu':1, 'ModifyMenu':1, 'TrackPopupMenu':1,

			# win32prinfo.cpp
			'DocObject':1, 'GetDwFlags':1, 'SetDwFlags':1,
			'GetDocOffsetPage':1, 'SetDocOffsetPage':1,
			'SetPrintDialog':1, 'GetDirect':1, 'SetDirect':1,
			'GetPreview':1, 'SetPreview':1, 'GetContinuePrinting':1,
			'SetContinuePrinting':1, 'GetCurPage':1, 'SetCurPage':1,
			'GetNumPreviewPages':1, 'SetNumPreviewPages':1, 
			'GetUserData':1, 'SetUserData':1, 'GetDraw':1, 'SetDraw':1,
			'GetPageDesc':1, 'SetPageDesc':1, 'GetMinPage':1, 'SetMinPage':1,
			'GetMaxPage':1, 'SetMaxPage':1, 'GetOffsetPage':1, 
			'GetFromPage':1, 'GetToPage':1, 'SetHDC':1, 
			'CreatePrinterDC':1, 'GetCopies':1, 'GetDefaults':1,
			'FreeDefaults':1, 'GetDeviceNames':1, 'GetDriveName':1,
			'GetDlgFromPage':1, 'GetDlgToPage':1, 'GetPortName':1,
			'GetPrinterDC':1, 'PrintAll':1, 'PrintCollate':1,
			'PrintRange':1, 'PrintSelection':1, 'GetHDC':1,
			'GetFlags':1, 'SetFlags':1, 'SetFromPage':1,
			'SetToPage':1, 'GetPRINTDLGMinPage':1,
			'SetPRINTDLGMinPage':1, 'GetPRINTDLGCopies':1,
			'SetPRINTDLGCopies':1,

			# win32prop.cpp
			'AddPage':1, 'EnableStackedTabs':1, 'GetActiveIndex':1,
			'GetActivePage':1, 'GetPage':1, 'GetPageIndex':1,
			'GetPageCount':1, 'GetTabCtrl':1, 'OnInitDialog':1,
			'PressButton':1, 'RemovePage':1, 'SetActivePage':1,
			'SetTitle':1, 'SetFinishText':1, 'SetWizardMode':1,
			'SetWizardButtons':1, 'SetPSHBit':1,
			#
			'CancelToClose':1, 'OnApply':1, 'OnReset':1, 'OnQueryCancel':1,
			'OnWizardBack':1, 'OnWizardNext':1, 'OnWizardFinish':1,
			'OnSetActive':1, 'OnKillActive':1, 'SetModified':1,
			'SetPSPBit':1,

			# win32rgn.cpp
			'CreateRectRgn':1, 'CombineRgn':1, 'CopyRgn':1, 'GetRgnBox':1,
			'DeleteObject':1, 

			# win32RichEdit.cpp
			'GetRichEditCtrl':1, 'SetWordWrap':1, 'WrapChanged':1,
			'SaveTextFile':1, 'SetPathName':1,

			# win32RichEditDocTemplate.cpp
			'DoCreateRichEditDoc':1,

			# win32splitter.cpp
			'GetPane':1, 'CreatePane':1, 'CreateStatic':1,
			'SetColumnInfo':1, 'SetRowInfo':1, 'IdFromRowCol':1,
			'DoKeyboardSplit':1,

			# win32template.cpp
			'CreateNewFrame':1, 'DoCreateDoc':1, 'FindOpenDocument':1,
			'GetDocString':1, 'GetDocumentList':1, 'GetResourceID':1,
			'GetSharedMenu':1, 'InitialUpdateFrame':1,
			'SetContainerInfo':1, 'SetDocStrings':1, 'OpenDocumentFile':1,

			# win32thread.cpp
			'CreateThread':1, 'PumpIdle':1, 'PumpMessages':1, 'Run':1,
			'SetMainFrame':1, 'SetThreadPriority':1,

			# win32toolbar.cpp
			'EndDrag':1, 'StartDrag':1, 'EndResize':1, 'StartResize':1,
			'ToggleDocking':1,
			#
			'dockSite':1, 'dockBar':1, 'dockContext':1, 'dwStyle':1,
			#
			'ptLast':1, 'rectLast':1, 'sizeLast':1, 'bDitherLast':1,
			'rectDragHorz':1, 'rectDragVert':1, 'rectFrameDragHorz':1,
			'rectFrameDragVert':1, 'dwDockStyle':1, 'dwStyle':1,
			'dwOverDockStyle':1, 'bFlip':1, 'bForceFrame':1,
			'bDragging':1, 'nHitTest':1, 'uMRUDockID':1,
			'rectMRUDockPos':1, 'dwMRUFloatStyle':1,
			'dwMRUFLoatPos':1,
			#
			'CalcDynamicLayout':1, 'CalcFixedLayout':1, 'EnableDocking':1,
			'EraseNonClient':1, 'GetBarStyle':1, 'GetCount':1,
			'GetDockingFrame':1, 'IsFloating':1, 'SetBarStyle':1,
			'ShowWindow':1,
			#
			'GetButtonStyle':1, 'GetButtonText':1, 'GetItemID':1,
			'GetToolsTips':1, 'GetToolBarCtrl':1,
			'LoadBitmap':1, 'LoadToolBar':1, 'SetBarStyle':1,
			'SetBitmap':1, 'SetButtonInfo':1, 'SetButtons':1,
			'SetButtonStyle':1, 'SetHeight':1, 'SetSizes':1, 'SetToolTips':1,
			#
			'AddButtons':1, 'AddStrings':1, 'AutoSize':1, 'CheckButton':1,
			'CommandToIndex':1, 'Customize':1, 'DeleteButton':1,
			'EnableButton':1, 'GetBitmapFlags':1, 'GetButton':1,
			'GetButtonCount':1, 'GetItemRect':1, 'GetRows':1,
			'HideButton':1, 'Indeterminate':1, 'InsertButton':1,
			'IsButtonChecked':1, 'IsButtonEnabled':1,
			'IsButtonHidden':1, 'IsButtonIndeterminate':1,
			'IsButtonPressed':1, 'PressButton':1, 'SetBitmapSize':1,
			'SetButtonSize':1, 'SetCmdID':1, 'SetRows':1,
			#
			'SetIndicators':1,

			# win32tooltip.cpp
			'UpdateTipText':1, 'AddTool':1,

			# win32uimodule.cpp
			'GetMethodByType':1,

			# win32util.cpp
			'left':1, 'right':1, 'top':1, 'bottom':1,

			# win32view.cpp
			'CreateWindow':1, 'GetDocument':1, 'OnActivateView':1,
			'OnInitialUpdate':1, 'OnMouseActivate':1,
			'PreCreateWindow':1, 'OnFilePrint':1,
			'OnFilePrintPreview':1, 'DoPreparePrinting':1,
			'OnBeginPrinting':1, 'OnEndPrinting':1,
			#
			'GetDeviceScrollPosition':1, 'GetDC':1,
			'GetScrollPosition':1, 'GetTotalSize':1,
			'OnCommand':1, 'ResizeParentToFit':1,
			'SetScaleToFitSize':1,
			'ScrollToPosition':1, 'SetScrollSizes':1,
			'UpdateBars':1,
			#
			'IsModified':1, 'LoadFile':1, 'SetModifiedFlag':1,
			'GetEditCtrl':1, 'PreCreateWindow':1, 'SaveFile':1,
			'OnCommand':1, 
			#
			'GetListCtrl':1, 'GetTreeCtrl':1,

			# win32win.cpp
			'ActivateFrame':1, 'BringWindowToTop':1,
			'BeginPaint':1, 'CalcWindowRect':1, 'CenterWindow':1,
			'CheckRadioButton':1, 'ChildWindowFromPoint':1,
			'ClientToScreen':1, 'CreateWindow':1,
			'CreateWindowEx':1, 'DefWindowProc':1,
			'DestroyWindow':1, 'DlgDirList':1,
			'DlgDirListComboBox':1, 'DlgDirSelect':1,
			'DlgDirSelectComboBox':1, 'DragAcceptFiles':1,
			'DrawMenuBar':1, 'EnableWindow':1, 'EndModalLoop':1,
			'EndPaint':1, 'GetCheckedRadioButton':1,
			'GetClientRect':1, 'GetDC':1, 'GetDCEx':1,
			'GetDlgCtrlID':1, 'GetDlgItem':1, 'GetDlgItemInt':1,
			'GetDlgItemText':1, 'GetLastActivePopup':1,
			'GetMenu':1, 'GetParent':1, 'GetParentFrame':1, 'GetParentOwner':1,
			'GetSafeHwnd':1, 'GetScrollInfo':1, 'GetScrollPos':1,
			'GetStyle':1, 'GetExStyle':1, 'GetSystemMenu':1,
			'GetTopLevelFrame':1, 'GetTopLevelOwner':1, 'GetTopLevelParent':1,
			'GetTopWindow':1, 'GetWindow':1, 'GetWindowDC':1, 
			'GetWindowPlacement':1, 'GetWindowRect':1, 'GetWindowText':1,
			'HideCaret':1, 'HookAllKeyStrokes':1, 'HookKeyStroke':1,
			'HookMessage':1, 'InvalidateRect':1, 'InvalidateRgn':1,
			'IsChild':1, 'IsDlgButtonChecked':1, 'IsIconic':1,
			'IsZoomed':1, 'IsWindow':1, 'IsWindowVisible':1,
			'IsWindowEnabled':1, 'KillTimer':1, 'LockWindowUpdate':1,
			'MapWindowPoints':1, 'MouseCaptured':1, 'MessageBox':1,
			'ModifyStyle':1, 'ModifyStyleEx':1, 'MoveWindow':1,
			'OnClose':1, 'OnCtlColor':1, 'OnEraseBkgnd':1,
			'OnNcHitTest':1, 'OnPaint':1, 'OnQueryDragIcon':1,
			'OnQueryNewPalette':1, 'OnSetCursor':1, 'OnMouseActivate':1,
			'OnWndMsg':1, 'PreCreateWindow':1, 'PumpWaitingMessages':1,
			'ReadrawWindow':1, 'ReleaseCapture':1, 'ReleaseDC':1,
			'RepositionBars':1, 'RunModalLoop':1, 'PostMessage':1,
			'SendMessageToDescendants':1, 'SendMessage':1, 
			'SetActiveWindow':1, 'SetForegroundWindow':1, 'SetWindowPos':1,
			'SetScreenToClient':1, 'SetCapture':1, 'SetDlgItemText':1,
			'SetFocus':1, 'SetFont':1, 'SetMenu':1, 'SetRedraw':1,
			'SetScrollPos':1, 'SetScrollInfo':1, 'SetTimer':1,
			'SetWindowPlacement':1, 'SetWindowText':1, 'ShowCaret':1,
			'ShowScrollBar':1, 'ShowWindow':1, 'UnlockWindowUpdate':1,
			'UpdateDialogControls':1, 'UpdateWindow':1,
			#
			'BeginModalState':1, 'CreateWindow':1, 'EndModalState':1,
			'DockControlBar':1, 'EnableDocking':1, 'FloatControlBar':1,
			'GetActiveDocument':1, 'GetControlBar':1, 'GetMessageString':1,
			'GetMessageBar':1, 'IsTracking':1, 'InModalState':1,
			'LoadAccelTable':1, 'LoadFrame':1, 'LoadBarState':1,
			'SaveBarState':1, 'ShowControlBar':1, 'RecalcLayout':1,
			'GetActiveView':1, 'OnBarCheck':1, 'OnUpdateControlBarMenu':1,
			'SetActiveView':1,
			#
			'GetMDIClient':1, 'MDIGetActive':1, 'MDIActivate':1,
			'MDINext':1, 'PreTranslateMessage':1,
			'OnCommand':1, 'OnContextHelp':1, 'OnClose':1,
			'GetMDIFrame':1,
		}

	elif modname == 'win32uiole':
		d = {
			# win32oleDlgInsert.cpp
			'GetClassID':1, 'GetSelectionType':1, 'GetPathName':1,

			# win32uiole.cpp
			'CreateInsertDialog':1, 'CreateOleClientItem':1,
			'CreateOleDocument':1, 'DaoGetEngine':1,
			'GetIDispatchForWindow':1, 
			'OleGetUserCtrl':1, 'OleSetUserCtrl':1,

			# win32uioleClientItem.cpp
			'CreateNewItem':1, 'Close':1, 'DoVerb':1, 'Draw':1,
			'GetActiveView':1, 'GetDocument':1, 'GetInPlaceWindow':1,
			'GetItemState':1, 'GetObject':1, 'GetStorage':1,
			'OnActivate':1, 'OnChange':1, 'OnChangeItemPosition':1,
			'OnDeactivateUI':1, 'Run':1, 'SetItemRects':1,

			# win32uioledoc.cpp
			'EnableCompoundFile':1, 'GetStartPosition':1,
			'GetNextItem':1, 'GetInPlaceActiveItem':1,
		}


	if d:
		attrs.update(d)  # merge

	return

#
# Find line number if compiled with -O
# See traceback.tb_lineno() for algorithm
#
def FindLineno(co, lasti, lineno):

	if lineno:
		return lineno  # not -O, SET_LINENO
	
	lineno = co.co_firstlineno
	ltab = co.co_lnotab
	iaddr = 0

	i = 0
	n = len(ltab)
	while i < n:
		iaddr = iaddr + ord(ltab[i])
		if iaddr > lasti:
			break
		lineno = lineno + ord(ltab[i+1])
		i = i + 2

	return lineno

#
# Import and return the named module
#
def do_import(import_name, fromlist=[]):

	try:
		module = __import__(import_name, {}, None, fromlist)
	except ImportError, e:
		# dont report failures for common conditional imports
		if import_name not in \
				['posix','nt','dos','os2','mac','MacOS',
					'ce','riscos','riscosenviron',
					'pre', 'pcre', 'ssl']:
			print 'Warning: %s'%str(e)
		return None

	if not fromlist:  # otherwise module is already the rightmost component
		#
		# import "os.path" really returns m=os
		# We must explicitly drill down to the rightmost component (m=path)
		#
		comps = string.split(import_name,'.')
		i = 0
		while i < len(comps)-1:
			module = getattr(module, comps[i+1])
			i = i + 1

	file = getattr(module,'__file__',None)
	if file:
		#
		# Handle sub-imports within a package by adding the 
		# calling module's dir to sys.path
		#
		if file[-4:] == suffix:  # .pyc or .pyo file
			directory = string.join(string.split(file, os.sep)[:-1], os.sep)
			if not directory in sys.path:
				sys.path.append(directory)

	return module

#
# Return a dict of stored names in the co 
#
def do_collect_names(co, globals, attrs, importLevel):

	local_attrs = {}

	#
	# Walk the code recursively
	#
	code = co.co_code
	n = len(code)
	i = 0
	extended_arg = 0
	last_import_name = None

	while i < n:
		c = code[i]
		op = ord(c)
		i = i + 1

		if op == 84: # IMPORT_STAR  # Python 2.x
			#
			# from foo import *
			#
			# Add the module's dictionary to globals
			#
			module = do_import(last_import_name, [])
			if module:
				#
				# Decrement the nest level so all names are included as attrs
				#
				_collect_attrs_from_file(module, local_attrs, importLevel-1)

			continue

		if op < 90:  # if opcode has no argument
			extended_arg = 0
			continue

		#################### Opcodes with argument #####################

		oparg = ord(code[i]) + (ord(code[i+1]) << 8) + (extended_arg << 16)
		i = i + 2
		extended_arg = 0

		if op == 143:  # EXTENDED_ARG
			extended_arg = oparg
			continue

		#################################################################

		if op == 90: # STORE_NAME
			name = co.co_names[oparg]
			if ((co.co_flags & (CO_OPTIMIZED|CO_NEWLOCALS)) == CO_NEWLOCALS):
					#
					# Class level definition (var or func)
					# (May include defns in a non-optimized function)
					#
					local_attrs[name] = 1  # class C:\n name=1\n def f(self): self.name
			# if main module and module-level code
			if importLevel == 0 and (co.co_flags & CO_NEWLOCALS)==0:
				globals[name] = 1  # fwd ref: def f(): print name\n name=1
			continue


		if op == 95: # STORE_ATTR
			name = co.co_names[oparg]
			if importLevel == 0:  # if main code
				local_attrs[name] = 1
			continue

		if op == 97:  # STORE_GLOBAL
			name = co.co_names[oparg]
			if importLevel == 0:
				globals[name] = 1  # fwd ref: def f(): print name\n name=1
			continue


		if op == 125: # STORE_FAST
			name = co.co_varnames[oparg]
			if ((co.co_flags & (CO_OPTIMIZED|CO_NEWLOCALS)) == CO_NEWLOCALS):
					#
					# Class level definition (var or func)
					# (May include defns in a non-optimized function)
					#
					local_attrs[name] = 1  # class C:\n name=1\n def f(self): self.name
			continue

		if op == 107: # IMPORT_NAME
			name = co.co_names[oparg]

			last_import_name = name  

			if importLevel == 0:  # if main code
				if ord(code[i]) <> 108: # if next opcode is not IMPORT_FROM
					# import win32com.server.register -> .server, .register
					comps = string.split(last_import_name,'.')[1:]
					for c in comps:
						local_attrs[c] = 1
					#
					module = do_import(last_import_name, [])
					if module:
						#
						# Collect names as attributes: import foo; foo.woz
						#
						_collect_attrs_from_file(module, local_attrs, importLevel)
					#
					# Hack: import os.path if import os.
					# Unlike packaged modules, os.path is _implicitly_ loaded!!
					#
					if last_import_name == 'os':
						module = do_import('os.path', [])
						_collect_attrs_from_file(module, local_attrs, importLevel)
			continue

		if op == 108: # IMPORT_FROM  # from xxx import name
			name = co.co_names[oparg]

			if name == '*':  # Python 1.5.2
				#
				# from foo import *
				#
				# Add the module's dictionary to globals
				#
				module = do_import(last_import_name, [])
				if module:
					#
					# Decrement the nest level so all names are included as attrs
					#
					_collect_attrs_from_file(module, local_attrs, importLevel-1)
					continue

			module = do_import(last_import_name, [name])
			if module:
				fromobj = getattr(module, name, None)
				if type(fromobj) is types.ModuleType: # standard import
					if  importLevel == 0: # if main code
						module = fromobj
						# Collect names as attributes: import foo; foo.woz
						_collect_attrs_from_file(module, local_attrs, importLevel)
				else:
					# from xxx import name (any non-module object)
					# Decrement the nest level so all names are included as attrs
					_collect_attrs_from_file(module, local_attrs, importLevel-1)
			continue

		if op == 100: # LOAD_CONST
			obj = co.co_consts[oparg]
			if type(obj) is types.CodeType:
				#
				# Recursively collect attrs in the same module (e.g., def f())
				#
				do_collect_names(obj, globals, local_attrs, importLevel)
			continue

	if importLevel == 1:
		#
		# For first-level imports, include names as attrs
		#
		# Example,
		#	import foo  # declares name woz
		#	foo.woz
		#
		for n in co.co_names:
			local_attrs[n] = 1

	attrs.update(local_attrs)  # merge


#
# Load the file's code and collect stored attributes from it
#
attr_files = {}

def _collect_attrs_from_file(module, attrs, importLevel):

	if not hasattr(module, '__file__'):
		#
		# builtin - collect all names in __dict__
		#
		if importLevel == 0:
			attrs.update(module.__dict__) # merge
		collect_extension_attrs(module.__name__, attrs)
		return

	file = module.__file__
	filekey = file + "_imp_" + str(importLevel)
	if attr_files.has_key(filekey):
		return  # avoid recursive loop
	attr_files[filekey] = 1

	if file[-3:] == '.py':
		try:
			py_compile.compile(file)
		except IOError, e:
			print 'Cannot compile %s: %s'%(file, e[1])
			return

		file = file[:-3] + suffix

	if file[-4:] <> suffix:
		#
		# .pyd or .so - collect all names in __dict__
		#
		if importLevel == 0:
			attrs.update(module.__dict__) # merge
		collect_extension_attrs(module.__name__, attrs)
		return

	import marshal
	f = open(file, 'rb')
	magic = f.read(4)
	if magic <> MAGIC:
		print '%s: file is not a %s module.' % (file,suffix)
		return

	timestamp = f.read(4)  # skip timestamp
	codeobject = marshal.load(f)
	f.close()
	if not (type(codeobject) is types.CodeType):
		raise Exception, '%s: file does not contain code.' % file

	dummy_globals = {}
	do_collect_names(codeobject, dummy_globals, attrs, importLevel+1)


#
# Recursively examine code for typos
#
def examine(co, file, parent_globals, attrs):

	if disasm:
		import dis
		codename = co.co_name
		if codename == '?':
			codename = ''
		print "\n          * CODE BLOCK %s *******************"%codename
		#print "\n          * CODE BLOCK %s,co_nlocals=%d,co_varnames=%s,co_flags=%s,co_argcount=%d" % (codename, co.co_nlocals,co.co_varnames,co.co_flags,co.co_argcount)
		dis.dis(co)

	globals = parent_globals.copy()
	code = co.co_code
	n = len(code)
	i = 0
	lineno = 0
	extended_arg = 0
	last_import_name = None
	last_load_name = None
	last_load_const = None

	while i < n:
		c = code[i]
		op = ord(c)
		name = None
		i = i + 1

		if op == 84: # IMPORT_STAR  Python 2.x
			#
			# from foo import *
			#
			# Add the module's dictionary to globals
			#
			module = do_import(last_import_name, [])
			if module:
				for x in module.__dict__.keys():
					globals[x] = 1

			continue

		if op < 90:  # if opcode has no argument
			extended_arg = 0
			continue

		#################### Opcodes with argument #####################

		oparg = ord(code[i]) + (ord(code[i+1]) << 8) + (extended_arg << 16)
		i = i + 2

		extended_arg = 0

		if op == 143:  # EXTENDED_ARG
			extended_arg = oparg
			continue

		#################################################################

		if op == 127: # SET_LINENO
			lineno = oparg
			continue

		if op == 124: # LOAD_FAST
			name = co.co_varnames[oparg]
			last_load_name = name
			continue

		if op == 125: # STORE_FAST, oparg is index into varnames
			name = co.co_varnames[oparg]
			#attrs[name] = 1  #  Class C:\n cVar=123\n def x(self): self.cVar
			continue

		#
		# All of the following opcodes use oparg to index into 
		# the co_names list.
		#

		if op == 90 or op == 97: # STORE_NAME or STORE_GLOBAL
			name = co.co_names[oparg]
			globals[name] = 1
			#attrs[name] = 1  #  Class C:\n cVar=123\n def x(self): self.cVar
			continue

		if op == 95: # STORE_ATTR
			name = co.co_names[oparg]
			attrs[name] = 1
			continue

		if op == 107: # IMPORT_NAME
			name = co.co_names[oparg]
			last_import_name = name  
			if ord(code[i]) <> 108: # if next opcode is not IMPORT_FROM
				globals[string.split(last_import_name, ".")[0]] = 1
			continue

		if op == 108: # IMPORT_FROM  # from xxx import name
			name = co.co_names[oparg]

			if name == '*': # Python 1.5.2
				#
				# from foo import *
				#
				# Add the module's dictionary to globals
				#
				module = do_import(last_import_name, [])
				if module:
					for x in module.__dict__.keys():
						globals[x] = 1

				continue

			globals[name] = 1
			continue

		#

		if op == 116 or op == 101: # LOAD_GLOBAL or LOAD_NAME
			name = co.co_names[oparg]
			if not disasm and not globals.has_key(name):
				print "%s might be used before set at line %d in %s." \
					% (name, FindLineno(co,i-2,lineno), file)
			last_load_name = name
			continue

		if op == 105: # LOAD_ATTR
			name = co.co_names[oparg]
			if not disasm and not attrs.has_key(name):
				print "%s.%s might be undefined at line %d in %s."\
					% (last_load_name, name, FindLineno(co,i-2,lineno), file)
			last_load_name = name  # alpha.beta.gamma  (beta)
			continue

		if op == 100: # LOAD_CONST
			obj = co.co_consts[oparg]
			last_load_const = obj
			if type(obj) is types.CodeType:
				#
				# Recursively examine code (e.g., def f(): ...)
				#
				if (co.co_flags & CO_NEWLOCALS) <> 0:  # if interior code
					globals = parent_globals # use module-level globals
				examine(obj, file, globals, attrs)
			continue


import imp
MAGIC = imp.get_magic()

def typo(file):
	import marshal
	f = open(file, 'rb')
	magic = f.read(4)
	if magic <> MAGIC:
		print '%s: file is not a %s module.' % (file,suffix)
		return
	timestamp = f.read(4)  # skip timestamp
	codeobject = marshal.load(f)
	f.close()
	if not (type(codeobject) is types.CodeType):
		print '%s: file does not contain code.' % file

	globals = {}
	globals['__builtins__'] = 1
	globals['__doc__'] = 1
	globals['__file__'] = 1
	globals['__name__'] = 1

	if type(__builtins__) is types.DictType:  # bug?
		d = __builtins__  #  when loaded via import typo.  Is this a python bug?
	elif type(__builtins__) is types.ModuleType:
		d = __builtins__.__dict__ #  when loaded via the command line

	#
	# Add all builtin names
	#
	for x in d.keys():
		globals[x] = 1

	global attr_files
	attr_files = {} # reset attr cache

	#
	# Pass 1: Collect STORE_xxx names
	#
	attrs = builtin_attrs.copy()
	if not disasm:
		do_collect_names(codeobject, globals, attrs, 0)
	
	#
	# Pass 2: Examine code for typos
	#
	examine(codeobject, file, globals, attrs)


def main():
	import getopt
	try:
		opts, args = getopt.getopt(sys.argv[1:], 'd')
	except getopt.error, msg:
		print msg
		print "usage: %s [-d] file.py" % sys.argv[0]
		sys.exit(1)

	if len(args) <> 1:
		print "usage: %s [-d] file.py" % sys.argv[0]
		sys.exit(1)

	for opt in opts:
		if opt[0] == '-d':
			global disasm
			disasm = 1

	# Note: because a module once loaded cannot be unloaded, we can 
	# only process one script per run.

	for file in args:
		if file[-3:] == '.py':
			try:
				py_compile.compile(file)
			except IOError, e:
				print 'Cannot compile %s: %s'%(file, e[1])
				sys.exit(1)

			file = file[:-3] + suffix

		if file[-4:] <> suffix:
			print '%s: file is not a python .py or %s file' % (file,suffix)

		typo(file)

if __name__=='__main__':
	sys.path.append('.')  # search cwd for .py files
	main()
