Mac version of freeze. Uses standard freeze modules where it can,
augmenting them here and there. For now, it works more-or-less similar
to unix/windows freeze, generating a config.c file, but storing
modules in PYC resources. A template project is also copied.

The hooks are in place to freeze by merging shared libraries so you
can freeze without a C compiler/linker, but this does not work yet.
diff --git a/Mac/Tools/macfreeze/directives.py b/Mac/Tools/macfreeze/directives.py
new file mode 100644
index 0000000..e233745
--- /dev/null
+++ b/Mac/Tools/macfreeze/directives.py
@@ -0,0 +1,39 @@
+import re
+import os
+
+# The regular expression for freeze directives. These are comments with the
+# word macfreeze immedeately followed by a colon, followed by a directive,
+# followed by argument(s)
+#
+# The directives supported are
+# include - Include a module or file
+# exclude - Exclude a module
+# path - Add sys.path entries. Relative paths are relative to the source file.
+#
+# See the macfreeze.py main program for a real live example.
+#
+DIRECTIVE_RE=r'^\s*#\s*macfreeze:\s*(\S*)\s*(.*)\s*$'
+REPROG=re.compile(DIRECTIVE_RE)
+
+def findfreezedirectives(program):
+	extra_modules = []
+	exclude_modules = []
+	extra_path = []
+	progdir, filename = os.path.split(program)
+	fp = open(program)
+	for line in fp.readlines():
+		match = REPROG.match(line)
+		if match:
+			directive = match.group(1)
+			argument = match.group(2)
+			if directive == 'include':
+				extra_modules.append(argument)
+			elif directive == 'exclude':
+				exclude_modules.append(argument)
+			elif directive == 'path':
+				argument = os.path.join(progdir, argument)
+				extra_path.append(argument)
+			else:
+				print '** Unknown directive', line
+	return extra_modules, exclude_modules, extra_path
+	
diff --git a/Mac/Tools/macfreeze/macfreeze.py b/Mac/Tools/macfreeze/macfreeze.py
new file mode 100644
index 0000000..60962ee
--- /dev/null
+++ b/Mac/Tools/macfreeze/macfreeze.py
@@ -0,0 +1,72 @@
+"""macfreeze - Main program and GUI
+
+macfreeze allows you to turn Python scripts into fully self-contained
+Mac applications, by including all the Python and C code needed in a single
+executable. Like unix/windows freeze it can produce a config.c allowing you
+to build the application with a development environment (CodeWarrior, to be
+precise), but unlike the standard freeze it is also possible to create frozen
+applications without a development environment, by glueing all the
+shared libraries and extension modules needed together in a single
+executable, using some Code Fragment Manager tricks."""
+
+import macfs
+import sys
+import EasyDialogs
+import string
+
+import macfreezegui
+import macmodulefinder
+
+#
+# Here are the macfreeze directives, used when freezing macfreeze itself
+# (see directives.py for an explanation)
+#
+# macfreeze: path ::::Tools:freeze
+# macfreeze: exclude win32api
+#
+
+def main():
+	if len(sys.argv) < 2:
+		gentype, program, output, debug = macfreezegui.dialog()
+	elif len(sys.argv) == 2:
+		gentype, program, output, debug = macfreezegui.dialog(sys.argv[1])
+	else:
+		EasyDialog.Message(
+		  "Please pass a single script. Additional modules can be specified with directives")
+		sys.exit(0)
+	mustwait = process(gentype, program, output, debug=debug)
+	if mustwait:
+		sys.exit(1)
+		
+def process(gentype, program, output, modules=[], module_files=[], debug=0):
+	try:
+		module_dict = macmodulefinder.process(program, modules, module_files, debug)
+	except macmodulefinder.Missing, arg:
+		arg.sort()
+		print '** Missing modules:', string.join(arg, ' ')
+		sys.exit(1)
+	#
+	# And generate
+	#
+	if gentype == 'info':
+		import macgen_info
+		macgen_info.generate(output, module_dict)
+		return 1		# So the user can inspect it
+	elif gentype == 'source':
+		import macgen_src
+		warnings = macgen_src.generate(output, module_dict, debug)
+		return warnings
+	elif gentype == 'resource':
+		import macgen_rsrc
+		macgen_rsrc.generate(output, module_dict, debug)
+		warnings = macgen_rsrc.warnings(module_dict)
+		return warnings
+	elif gentype == 'applet':
+		import macgen_bin
+		macgen_bin.generate(output, module_dict, debug)
+	else:
+		raise 'unknown gentype', gentype
+			
+if __name__ == '__main__':
+	main()
+		
diff --git a/Mac/Tools/macfreeze/macfreeze.rsrc.hqx b/Mac/Tools/macfreeze/macfreeze.rsrc.hqx
new file mode 100644
index 0000000..303068b
--- /dev/null
+++ b/Mac/Tools/macfreeze/macfreeze.rsrc.hqx
@@ -0,0 +1,21 @@
+(This file must be converted with BinHex 4.0)
+
+:$QeKBfCbC@9kC5jbFh*M!(*cFQ058d9%!3#3"`1-AQF!N!3"!!!!!cS!!!)k!!!
+!8M4lA$"F-M!dA$)`0(YF-&`b-$4F-M!dHe``A$)`0&`b$QeKBfCbC@9kC5jbFh*
+MFfaKH@9bFR0bG(4iG#ia0f`!-(*cFQ058d9%!3!!J!#"!*!5XE4#FJ#3"J0ZA$-
+b-&`c0cGF-&`b06"F-c)`A$-h0e``A$)e-&`c-M"F-cFhA$"F-M8`A$-b-&`c0cG
+F-&`b06"F-c)`A$-h0e``A$)e-&`c-M"F-cFhA$"F-M8`A$-b-&`c0cGF-&`b06"
+F-c)`A$-h0e``A$)e-&`c-M"F-cFhA$"F-M8`A$-b-!!!!"J!2!!U!@)"m3!&!*!
+)!J!!!$!+!!!#'J!6!*!&$`!*!"m!9)J(8f0bDA"d1J#3"Ji!L`!H!@@)"R0MFQP
+`G!#3"3d"F3!K!Ed%#8*bEhGcC5iZ,R)!N!93!!N!BJ&P"L0(C@jPFQ&dC5"bCA0
+[GA*MC5"KEQ3JFfpeFQ0P)'C[FL"$9f`!N!9S!"X!H!#"L!j2GA4`GA3JCQpXC'9
+b1J#3"@J!L`"i!@@)"R0MFQP`G!#3"@F"F3"k!Ed%#8*bEhGcC5iZ,Q%!N!@%!!N
+!PJ&P"Kp(C@jPFQ&dC5"3@8-JFQ9cEh9bBf8JCQPXC5"[EQajG!#3"Cd!'`#Y!(f
+)$%peG("eG#"QD@aP1J#3"Ci!L!#Y!@@)"R0MFQP`G!#3"CX"F!#[!Ed%#8*bEhG
+cC5iZ,Q%!N!@j!!N!bJ&L"L9(C@jPFQ&dC5"KF("XD@0KG'P[EL"QFQpY)(0SBA*
+PC#"XD@*cE!#3"G%!'`$K!(b)$%peG("eG#"QD@aP1J#3"G%!L!$K!@@)"R0MFQP
+`G!#3"Fm"E`$M!Ed%#8*bEhGcC5iZ,T`!N!3""`&[!4X"[33#6dX!N!3""J!,!4S
+!8!3'3f&ZBf9X!*!&+J!*!$X!ISJ04'9LG@FJ)'aPGQ9X1XJ!N!8U!)X!1J$@%!%
+aG!#3"H`!#3$q!@-'%%PZCQpbE@&dD@pZ)'pZE(N!!!%!!!!$1J!!!MS!!!"5"cH
+I$#UD!!!!(!"'!!&%6%p(!!!!%N4*9%`!!!!H!J#3"`FhXI3#!2rr!!!!(!FhY5!
+,6@&TEL"ND@&XEfGZ5!:
diff --git a/Mac/Tools/macfreeze/macfreezegui.py b/Mac/Tools/macfreeze/macfreezegui.py
new file mode 100644
index 0000000..bd70c00
--- /dev/null
+++ b/Mac/Tools/macfreeze/macfreezegui.py
@@ -0,0 +1,158 @@
+"""macfreezegui - The GUI for macfreeze"""
+import Dlg
+import macfs
+import EasyDialogs
+import sys
+import os
+import string
+import Res
+
+ID_MAINDIALOG=512
+
+ITEM_SCRIPTNAME=2
+ITEM_SCRIPTBROWSE=3
+ITEM_GENSOURCE=4
+ITEM_GENSOURCE_ITEMS=(7,)
+ITEM_SOURCEDIRNAME=6
+ITEM_SOURCEDIRBROWSE=7
+ITEM_GENRESOURCE=8
+ITEM_GENRESOURCE_ITEMS=(11,)
+ITEM_RESOURCENAME=10
+ITEM_RESOURCEBROWSE=11
+ITEM_GENAPPLET=12
+ITEM_GENAPPLET_ITEMS=(15,)
+ITEM_APPLETNAME=14
+ITEM_APPLETBROWSE=15
+ITEM_OK=16
+ITEM_CANCEL=17
+ITEM_DEBUG=19
+ITEM_GENINFO=20
+
+RADIO_GROUPING={
+	ITEM_GENSOURCE: ITEM_GENSOURCE_ITEMS,
+	ITEM_GENRESOURCE: ITEM_GENRESOURCE_ITEMS,
+	ITEM_GENAPPLET: ITEM_GENAPPLET_ITEMS,
+	ITEM_GENINFO: ()
+}
+
+def dialog(script=None):
+
+	# Invent the various names
+	if not script:
+		fss, ok = macfs.PromptGetFile("Script?", "TEXT")
+		if not ok:
+			sys.exit(0)
+		script = fss.as_pathname()
+	basename, ext = os.path.splitext(script)
+	if ext:
+		appletname = basename
+		rsrcname = basename + 'modules.rsrc'
+	else:
+		appletname = script + '.applet'
+		rsrcname = script + 'modules.rsrc'
+	dirname, basebase = os.path.split(basename)
+	dirname = os.path.join(dirname, 'build.'+basebase)
+	
+	# Get the dialog, possibly opening the resource file (if needed)
+	try:
+		d = Dlg.GetNewDialog(ID_MAINDIALOG, -1)
+	except Dlg.Error:
+		d = None
+	if d == None:
+		try:
+			Res.OpenResFile('macfreeze.rsrc')
+		except Res.Error:
+			d = None
+		else:
+			d = Dlg.GetNewDialog(ID_MAINDIALOG, -1)
+	if d == None:
+		EasyDialogs.Message("Dialog resource not found or faulty")
+		sys.exit(1)
+	
+	# Fill the dialog
+	d.SetDialogDefaultItem(ITEM_OK)
+	d.SetDialogCancelItem(ITEM_CANCEL)
+	
+	_dialogsetfile(d, ITEM_SCRIPTNAME, script)
+	_dialogsetfile(d, ITEM_SOURCEDIRNAME, dirname)
+	_dialogsetfile(d, ITEM_RESOURCENAME, rsrcname)
+	_dialogsetfile(d, ITEM_APPLETNAME, appletname)
+
+	gentype = ITEM_GENSOURCE
+	_dialogradiogroup(d, ITEM_GENSOURCE)
+
+	# Interact
+	d.GetDialogWindow().SetWTitle("Standalone application creation options")
+	d.GetDialogWindow().ShowWindow()
+	d.DrawDialog()
+	while 1:
+		item = Dlg.ModalDialog(None)
+		if item == ITEM_OK:
+			break
+		elif item == ITEM_CANCEL:
+			sys.exit(0)
+		elif item in RADIO_GROUPING.keys():
+			gentype = item
+			_dialogradiogroup(d, item)
+		elif item == ITEM_SCRIPTBROWSE:
+			fss, ok = macfs.PromptGetFile("Script?")
+			if ok:
+				script = fss.as_pathname()
+				_dialogsetfile(d, ITEM_SCRIPTNAME, script)
+		elif item == ITEM_SOURCEDIRBROWSE:
+			fss, ok = macfs.StandardPutFile("Output folder name", os.path.split(dirname)[1])
+			if ok:
+				dirname = fss.as_pathname()
+				_dialogsetfile(d, ITEM_SOURCEDIRNAME, dirname)
+		elif item == ITEM_RESOURCEBROWSE:
+			fss, ok = macfs.StandardPutFile("Resource output file", os.path.split(rsrcname)[1])
+			if ok:
+				rsrcname = fss.as_pathname()
+				_dialogsetfile(d, ITEM_RESOURCENAME, rsrcname)
+		elif item == ITEM_APPLETBROWSE:
+			fss, ok = macfs.StandardPutFile("Applet output file", os.path.split(appletname)[1])
+			if ok:
+				appletname = fss.as_pathname()
+				_dialogsetfile(d, ITEM_APPLETNAME, appletname)
+		else:
+			pass
+	tp, h, rect = d.GetDialogItem(ITEM_DEBUG)
+	debug = Dlg.GetDialogItemText(h)
+	try:
+		debug = string.atoi(string.strip(debug))
+	except ValueError:
+		EasyDialogs.Message("Illegal debug value %s, set to zero."%`debug`)
+		debug = 0
+	if gentype == ITEM_GENSOURCE:
+		return 'source', script, dirname, debug
+	elif gentype == ITEM_GENRESOURCE:
+		return 'resource', script, rsrcname, debug
+	elif gentype == ITEM_GENAPPLET:
+		return 'applet', script, appletname, debug
+	elif gentype == ITEM_GENINFO:
+		return 'info', script, '', debug
+	raise 'Error in gentype', gentype
+
+def _dialogradiogroup(d, item):
+	for k in RADIO_GROUPING.keys():
+		subitems = RADIO_GROUPING[k]
+		tp, h, rect = d.GetDialogItem(k)
+		if k == item:
+			h.as_Control().SetControlValue(1)
+			for i2 in subitems:
+				d.ShowDialogItem(i2)
+		else:
+			h.as_Control().SetControlValue(0)
+			for i2 in subitems:
+				d.HideDialogItem(i2)
+
+def _dialogsetfile(d, item, file):
+	if len(file) > 32:
+		file = '\311:' + os.path.split(file)[1]
+	tp, h, rect = d.GetDialogItem(item)
+	Dlg.SetDialogItemText(h, file)
+			
+if __name__ == '__main__':
+	type, script, file, debug = dialog()
+	print type, script, file, 'debug=%d'%debug
+	sys.exit(1)
diff --git a/Mac/Tools/macfreeze/macgen_bin.py b/Mac/Tools/macfreeze/macgen_bin.py
new file mode 100644
index 0000000..d524e9b
--- /dev/null
+++ b/Mac/Tools/macfreeze/macgen_bin.py
@@ -0,0 +1,6 @@
+"""macgen_bin - Generate application from shared libraries"""
+import EasyDialogs
+
+def generate(output, module_dict):
+	EasyDialogs.Message('Not yet implemented')
+	
diff --git a/Mac/Tools/macfreeze/macgen_info.py b/Mac/Tools/macfreeze/macgen_info.py
new file mode 100644
index 0000000..9ec6aa0
--- /dev/null
+++ b/Mac/Tools/macfreeze/macgen_info.py
@@ -0,0 +1,8 @@
+"""macgen_info - Generate informational output"""
+
+def generate(output, module_dict):
+	for name in module_dict.keys():
+		print 'Include %-20s\t'%name,
+		module = module_dict[name]
+		print module.gettype(), '\t', `module`
+	return 0
diff --git a/Mac/Tools/macfreeze/macgen_rsrc.py b/Mac/Tools/macfreeze/macgen_rsrc.py
new file mode 100644
index 0000000..107e734
--- /dev/null
+++ b/Mac/Tools/macfreeze/macgen_rsrc.py
@@ -0,0 +1,35 @@
+"""macgen_info - Generate PYC resource file only"""
+import EasyDialogs
+import py_resource
+import Res
+import sys
+
+def generate(output, module_dict, debug=0, preload=1):
+	fsid = py_resource.create(output)
+
+	for name, module in module_dict.items():
+		if module.gettype() != 'module':
+			continue
+		location = module.__file__
+		
+		if location[-4:] == '.pyc':
+			# Attempt corresponding .py
+			location = location[:-1]
+		if location[-3:] != '.py':
+			print '*** skipping', location
+			continue
+			
+		id, name = py_resource.frompyfile(location, name, preload=preload)
+		if debug > 0:
+			print 'PYC resource %5d\t%s\t%s'%(id, name, location)
+
+	Res.CloseResFile(fsid)
+	
+def warnings(module_dict):
+	problems = 0
+	for name, module in module_dict.items():
+		if module.gettype() not in ('builtin', 'module'):
+			problems = problems + 1
+			print 'Warning: %s not included: %s %s'%(name, module.gettype(), module)
+	return problems
+	
diff --git a/Mac/Tools/macfreeze/macgen_src.py b/Mac/Tools/macfreeze/macgen_src.py
new file mode 100644
index 0000000..ad0739e
--- /dev/null
+++ b/Mac/Tools/macfreeze/macgen_src.py
@@ -0,0 +1,109 @@
+"""macgen_info - Generate CodeWarrior project, config source, resource file"""
+import EasyDialogs
+import os
+import sys
+import macfs
+import MacOS
+import macostools
+import macgen_rsrc
+# Note: this depends on being frozen, or on sys.path already being
+# modified by macmodulefinder.
+import makeconfig
+
+TEMPLATEDIR=os.path.join(sys.prefix, ':Mac:mwerks:projects:build.macfreeze')
+PROJECT_TEMPLATE=os.path.join(TEMPLATEDIR, ':frozen.prj')
+CONFIG_TEMPLATE=os.path.join(TEMPLATEDIR, ':templatefrozenconfig.c')
+BUNDLE_TEMPLATE=os.path.join(TEMPLATEDIR, ':frozenbundle.rsrc')
+
+def generate(output, module_dict, debug=0):
+	problems = 0
+	output_created=0
+	if not os.path.exists(output):
+		print 'Creating project folder', output
+		os.mkdir(output)
+		output_created = 1
+	# Resolve aliases, if needed
+	try:
+		fss, dummy1, dummy2 = macfs.ResolveAliasFile(output)
+	except macfs.error:
+		pass
+	else:
+		newname = fss.as_pathname()
+		if newname != output:
+			if debug:
+				print 'Alias', output
+				print 'Resolved to', newname
+			output = newname	
+	# Construct the filenames
+	dummy, outfile = os.path.split(output)
+	build, ext = os.path.splitext(outfile)
+	if build == 'build' and ext[0] == '.':
+		# This is probably a good name for the project
+		projname = ext[1:]
+	else:
+		projname = 'frozenapplet.prj'
+	config_name = os.path.join(output, ':macfrozenconfig.c')
+	project_name = os.path.join(output, ':' + projname + '.prj')
+	resource_name = os.path.join(output, ':frozenmodules.rsrc')
+	bundle_name = os.path.join(output, ':frozenbundle.rsrc')
+
+	# Fill the output folder, if needed.
+	if output_created:
+		# Create the project, if needed
+		if not os.path.exists(project_name):
+			print 'Creating project', project_name
+			if not os.path.exists(PROJECT_TEMPLATE):
+				print '** No template CodeWarrior project found at', PROJECT_TEMPLATE
+				print '   To generate standalone Python applications from source you need'
+				print '   a full source distribution. Check http://www.cwi.nl/~jack/macpython.html'
+				print '   for details.'
+				problems = 1
+			else:		
+				macostools.copy(PROJECT_TEMPLATE, project_name)
+				print 'A template CodeWarrior project has been copied to', project_name
+				print 'It is up to you to make the following changes:'
+				print '- Change the output file name'
+				print '- Change the search path, unless the folder is in the python home'
+				print '- Add sourcefiles/libraries for any extension modules used'
+				print '- Remove unused sources, to speed up the build process'
+				print '- Remove unused resource files (like tcl/tk) for a smaller binary'
+				problems = 1
+				macostools.copy(BUNDLE_TEMPLATE, bundle_name)
+				print 'A template bundle file has also been copied to', bundle_name
+				print 'You may want to adapt signature, size resource, etc'
+
+	
+	# Create the resource file
+	macgen_rsrc.generate(resource_name, module_dict, debug=debug)
+	
+	# Create the config.c file
+	if not os.path.exists(CONFIG_TEMPLATE):
+		print '** No template config.c found at', PROJECT_TEMPLATE
+		print '   To generate standalone Python applications from source you need'
+		print '   a full source distribution. Check http://www.cwi.nl/~jack/macpython.html'
+		print '   for details.'
+		problems = 1
+	else:
+		# Find elegible modules (builtins and dynamically loaded modules)
+		c_modules = []
+		for module in module_dict.keys():
+			if module_dict[module].gettype() in ('builtin', 'dynamic'):
+				c_modules.append(module)
+		ifp = open(CONFIG_TEMPLATE)
+		ofp = open(config_name, 'w')
+		makeconfig.makeconfig(ifp, ofp, c_modules)
+		ifp.close()
+		ofp.close()
+		MacOS.SetCreatorAndType(config_name, 'CWIE', 'TEXT')
+	
+	if warnings(module_dict):
+		problems = 1
+	return problems
+	
+def warnings(module_dict):
+	problems = 0
+	for name, module in module_dict.items():
+		if module.gettype() not in ('builtin', 'module', 'dynamic'):
+			problems = problems + 1
+			print 'Warning: %s not included: %s %s'%(name, module.gettype(), module)
+	return problems
diff --git a/Mac/Tools/macfreeze/macgenerate.py b/Mac/Tools/macfreeze/macgenerate.py
new file mode 100644
index 0000000..6c60605
--- /dev/null
+++ b/Mac/Tools/macfreeze/macgenerate.py
@@ -0,0 +1,8 @@
+"""macgenerate - Generate the out for macfreeze"""
+
+def generate(program, module_dict):
+	for name in module_dict.keys():
+		print 'Include %-20s\t'%name,
+		module = module_dict[name]
+		print module.gettype(), '\t', `module`
+	return 0
diff --git a/Mac/Tools/macfreeze/macmodulefinder.py b/Mac/Tools/macfreeze/macmodulefinder.py
new file mode 100644
index 0000000..d87ca9b
--- /dev/null
+++ b/Mac/Tools/macfreeze/macmodulefinder.py
@@ -0,0 +1,101 @@
+"""macmodulefinder - Find modules used in a script. Only slightly
+mac-specific, really."""
+
+import sys
+import os
+
+import directives
+
+try:
+	# This will work if we are frozen ourselves
+	import modulefinder
+except ImportError:
+	# And this will work otherwise
+	_FREEZEDIR=os.path.join(sys.prefix, ':Tools:freeze')
+	sys.path.insert(0, _FREEZEDIR)
+	import modulefinder
+
+#
+# Modules that must be included, and modules that need not be included
+# (but are if they are found)
+#
+MAC_INCLUDE_MODULES=['site', 'exceptions']
+MAC_MAYMISS_MODULES=['posix', 'os2', 'nt', 'dos', 'dospath', 'nturl2path', 'pwd', 'sitecustomize']
+
+# An exception:
+Missing="macmodulefinder.Missing"
+
+class Module(modulefinder.Module):
+	
+	def gettype(self):
+		"""Return type of module"""
+		if self.__path__:
+			return 'package'
+		if self.__code__:
+			return 'module'
+		if self.__file__:
+			return 'dynamic'
+		return 'builtin'
+
+class ModuleFinder(modulefinder.ModuleFinder):
+
+    def add_module(self, fqname):
+        if self.modules.has_key(fqname):
+            return self.modules[fqname]
+        self.modules[fqname] = m = Module(fqname)
+        return m
+        
+def process(program, modules=[], module_files = [], debug=0):
+	error = []
+	#
+	# Add the standard modules needed for startup
+	#
+	modules = modules + MAC_INCLUDE_MODULES
+	#
+	# search the main source for directives
+	#
+	extra_modules, exclude_modules, extra_path = \
+			directives.findfreezedirectives(program)
+	for m in extra_modules:
+		if os.sep in m:
+			# It is a file
+			module_files.append(m)
+		else:
+			modules.append(m)
+	path = extra_path + sys.path[:]
+	#
+	# Create the module finder and let it do its work
+	#
+	modfinder = ModuleFinder(path, 
+			excludes=exclude_modules, debug=debug)
+	for m in modules:
+		modfinder.import_hook(m)
+	for m in module_files:
+		modfinder.load_file(m)
+	modfinder.run_script(program)
+	module_dict = modfinder.modules
+	#
+	# Tell the user about missing modules
+	#
+	maymiss = exclude_modules + MAC_MAYMISS_MODULES
+	for m in modfinder.badmodules.keys():
+		if not m in maymiss:
+			if debug > 0:
+				print 'Missing', m
+			error.append(m)
+	#
+	# Warn the user about unused builtins
+	#
+	for m in sys.builtin_module_names:
+		if m in ('__main__', '__builtin__'):
+			pass
+		elif not module_dict.has_key(m):
+			if debug > 0:
+				print 'Unused', m
+		elif module_dict[m].gettype() != 'builtin':
+			# XXXX Can this happen?
+			if debug > 0:
+				print 'Conflict', m
+	if error:
+		raise Missing, error
+	return module_dict