Lots of things added.  README written (mostly).
diff --git a/Tools/freeze/freeze.py b/Tools/freeze/freeze.py
index c423819..7d52ccf 100755
--- a/Tools/freeze/freeze.py
+++ b/Tools/freeze/freeze.py
@@ -1,31 +1,49 @@
 #! /usr/local/bin/python
 
 # "Freeze" a Python script into a binary.
-# Usage: see first function below (before the imports!)
+# Usage: see variable usage_msg below (before the imports!)
 
 # HINTS:
-# - Edit the line at XXX below before running!
+# - Edit the lines marked XXX below to localize.
 # - You must have done "make inclinstall libainstall" in the Python
 #   build directory.
 # - The script should not use dynamically loaded modules
 #   (*.so on most systems).
 
 
-# XXX Change the following line to point to your Demo/freeze directory!
-pack = '/ufs/guido/src/python/Demo/freeze'
+# Usage message
+
+usage_msg = """
+usage: freeze [-p prefix] [-e extension] ... script [module] ...
+
+-p prefix:    This is the prefix used when you ran
+              'Make inclinstall libainstall' in the Python build directory.
+              (If you never ran this, freeze won't work.)
+               The default is /usr/local.
+
+-e extension: A directory containing additional .o files that
+              may be used to resolve modules.  This directory
+              should also have a Setup file describing the .o files.
+              More than one -e option may be given.
+
+script:       The Python script to be executed by the resulting binary.
+
+module ...:   Additional Python modules (referenced by pathname)
+              that will be included in the resulting binary.  These
+              may be .py or .pyc files.
+"""
 
 
-# Print usage message and exit
+# XXX Change the following line to point to your Demo/freeze directory
+PACK = '/ufs/guido/src/python/Demo/freeze'
 
-def usage(msg = None):
-	if msg:
-		sys.stderr.write(str(msg) + '\n')
-	sys.stderr.write('usage: freeze [-p prefix] script [module] ...\n')
-	sys.exit(2)
+# XXX Change the following line to point to your install prefix
+PREFIX = '/usr/local'
 
 
 # Import standard modules
 
+import cmp
 import getopt
 import os
 import string
@@ -38,29 +56,27 @@
 dir = os.path.dirname(sys.argv[0])
 if dir:
 	pack = dir
+else:
+	pack = PACK
 addpack.addpack(pack)
 
 
 # Import the freeze-private modules
 
+import checkextensions
 import findmodules
 import makeconfig
 import makefreeze
 import makemakefile
 import parsesetup
 
-hint = """
-Use the '-p prefix' command line option to specify the prefix used
-when you ran 'Make inclinstall libainstall' in the Python build directory.
-(Please specify an absolute path.)
-"""
-
 
 # Main program
 
 def main():
 	# overridable context
-	prefix = '/usr/local'		# settable with -p option
+	prefix = PREFIX			# settable with -p option
+	extensions = []
 	path = sys.path
 
 	# output files
@@ -71,14 +87,14 @@
 
 	# parse command line
 	try:
-		opts, args = getopt.getopt(sys.argv[1:], 'p:')
-		if not args:
-			raise getopt.error, 'not enough arguments'
+		opts, args = getopt.getopt(sys.argv[1:], 'e:p:')
 	except getopt.error, msg:
 		usage('getopt error: ' + str(msg))
 
 	# proces option arguments
 	for o, a in opts:
+		if o == '-e':
+			extensions.append(a)
 		if o == '-p':
 			prefix = a
 
@@ -89,13 +105,13 @@
 	frozenmain_c = os.path.join(binlib, 'frozenmain.c')
 	makefile_in = os.path.join(binlib, 'Makefile')
 	defines = ['-DHAVE_CONFIG_H', '-DUSE_FROZEN', '-DNO_MAIN',
-		   '-DPTHONPATH=\\"$(PYTHONPATH)\\"']
+		   '-DPYTHONPATH=\\"$(PYTHONPATH)\\"']
 	includes = ['-I' + incldir, '-I' + binlib]
 
-	# sanity check of locations
-	for dir in prefix, binlib, incldir:
+	# sanity check of directories and files
+	for dir in [prefix, binlib, incldir] + extensions:
 		if not os.path.exists(dir):
-			usage('needed directory %s not found' % dir + hint)
+			usage('needed directory %s not found' % dir)
 		if not os.path.isdir(dir):
 			usage('%s: not a directory' % dir)
 	for file in config_c_in, makefile_in, frozenmain_c:
@@ -103,6 +119,16 @@
 			usage('needed file %s not found' % file)
 		if not os.path.isfile(file):
 			usage('%s: not a plain file' % file)
+	for dir in extensions:
+		setup = os.path.join(dir, 'Setup')
+		if not os.path.exists(setup):
+			usage('needed file %s not found' % setup)
+		if not os.path.isfile(setup):
+			usage('%s: not a plain file' % setup)
+
+	# check that enough arguments are passed
+	if not args:
+		usage('at least one filename argument required')
 
 	# check that file arguments exist
 	for arg in args:
@@ -128,30 +154,61 @@
 
 	dict = findmodules.findmodules(scriptfile, modules, path)
 
+	backup = frozen_c + '~'
+	try:
+		os.rename(frozen_c, backup)
+	except os.error:
+		backup = None
+	outfp = open(frozen_c, 'w')
+	try:
+		makefreeze.makefreeze(outfp, dict)
+	finally:
+		outfp.close()
+	if backup:
+		if cmp.cmp(backup, frozen_c):
+			sys.stderr.write('%s not changed, not written\n' %
+					 frozen_c)
+			os.rename(backup, frozen_c)
+
 	builtins = []
+	unknown = []
 	mods = dict.keys()
 	mods.sort()
 	for mod in mods:
 		if dict[mod] == '<builtin>':
 			builtins.append(mod)
 		elif dict[mod] == '<unknown>':
-			sys.stderr.write(
-				'Warning: module %s not found anywhere\n' %
-				mod)
+			unknown.append(mod)
 
-	outfp = open(frozen_c, 'w')
-	try:
-		makefreeze.makefreeze(outfp, dict)
-	finally:
-		outfp.close()
+	addfiles = []
+	if unknown:
+		addfiles, addmods = \
+			  checkextensions.checkextensions(unknown, extensions)
+		for mod in addmods:
+			unknown.remove(mod)
+		builtins = builtins + addmods
+	if unknown:
+		sys.stderr.write('Warning: unknown modules remain: %s\n' %
+				 string.join(unknown))
 
+	builtins.sort()
 	infp = open(config_c_in)
+	backup = config_c + '~'
+	try:
+		os.rename(config_c, backup)
+	except os.error:
+		backup = None
 	outfp = open(config_c, 'w')
 	try:
 		makeconfig.makeconfig(infp, outfp, builtins)
 	finally:
 		outfp.close()
 	infp.close()
+	if backup:
+		if cmp.cmp(backup, config_c):
+			sys.stderr.write('%s not changed, not written\n' %
+					 config_c)
+			os.rename(backup, config_c)
 
 	cflags = defines + includes + ['$(OPT)']
 	libs = []
@@ -166,7 +223,8 @@
 		somevars[key] = makevars[key]
 
 	somevars['CFLAGS'] = string.join(cflags) # override
-	files = ['$(OPT)', config_c, frozenmain_c] + libs + \
+	files = ['$(OPT)', config_c, frozen_c, frozenmain_c] + \
+		addfiles + libs + \
 		['$(MODLIBS)', '$(LIBS)', '$(SYSLIBS)']
 
 	outfp = open(makefile, 'w')
@@ -179,4 +237,14 @@
 
 	print 'Now run make to build the target:', target
 
+
+# Print usage message and exit
+
+def usage(msg = None):
+	if msg:
+		sys.stderr.write(str(msg) + '\n')
+	sys.stderr.write(usage_msg)
+	sys.exit(2)
+
+
 main()