Initial revision
diff --git a/Demo/scripts/wh.py b/Demo/scripts/wh.py
new file mode 100755
index 0000000..b9b09ef
--- /dev/null
+++ b/Demo/scripts/wh.py
@@ -0,0 +1,2 @@
+# This is here so I can use 'wh' instead of 'which' in '~/bin/generic_python'
+import which
diff --git a/Tools/scripts/dutree.doc b/Tools/scripts/dutree.doc
new file mode 100644
index 0000000..2a09426
--- /dev/null
+++ b/Tools/scripts/dutree.doc
@@ -0,0 +1,54 @@
+Path: cwi.nl!sun4nl!mcsun!uunet!cs.utexas.edu!convex!usenet
+From: tchrist@convex.COM (Tom Christiansen)
+Newsgroups: comp.lang.perl
+Subject: Re: The problems of Perl (Re: Question (silly?))
+Message-ID: <1992Jan17.053115.4220@convex.com>
+Date: 17 Jan 92 05:31:15 GMT
+References: <17458@ector.cs.purdue.edu> <1992Jan16.165347.25583@cherokee.uswest.com> <=#Hues+4@cs.psu.edu>
+Sender: usenet@convex.com (news access account)
+Reply-To: tchrist@convex.COM (Tom Christiansen)
+Organization: CONVEX Realtime Development, Colorado Springs, CO
+Lines: 83
+Nntp-Posting-Host: pixel.convex.com
+
+From the keyboard of flee@cs.psu.edu (Felix Lee):
+:And Perl is definitely awkward with data types.  I haven't yet found a
+:pleasant way of shoving non-trivial data types into Perl's grammar.
+
+Yes, it's pretty aweful at that, alright.  Sometimes I write perl programs
+that need them, and sometimes it just takes a little creativity.  But
+sometimes it's not worth it.  I actually wrote a C program the other day
+(gasp) because I didn't want to deal with a game matrix with six links per node.
+
+:Here's a very simple problem that's tricky to express in Perl: process
+:the output of "du" to produce output that's indented to reflect the
+:tree structure, and with each subtree sorted by size.  Something like:
+:    434 /etc
+:      |     344 .
+:      |      50 install
+:      |      35 uucp
+:      |       3 nserve
+:      |       |       2 .
+:      |       |       1 auth.info
+:      |       1 sm
+:      |       1 sm.bak
+
+At first I thought I could just keep one local list around
+at once, but this seems inherently recursive.  Which means 
+I need an real recursive data structure.  Maybe you could
+do it with one of the %assoc arrays Larry uses in the begat
+programs, but I broke down and got dirty.  I think the hardest
+part was matching Felix's desired output exactly.  It's not 
+blazingly fast: I should probably inline the &childof routine,
+but it *was* faster to write than I could have written the 
+equivalent C program.
+
+
+--tom
+
+--
+"GUIs normally make it simple to accomplish simple actions and impossible
+to accomplish complex actions."   --Doug Gwyn  (22/Jun/91 in comp.unix.wizards)
+
+     Tom Christiansen           tchrist@convex.com      convex!tchrist
+
diff --git a/Tools/scripts/dutree.py b/Tools/scripts/dutree.py
new file mode 100755
index 0000000..c309212
--- /dev/null
+++ b/Tools/scripts/dutree.py
@@ -0,0 +1,52 @@
+#! /usr/local/python
+# Format du output in a tree shape
+
+import posix, string, sys, path
+
+def main():
+	p = posix.popen('du ' + string.join(sys.argv[1:]), 'r')
+	total, d = None, {}
+	for line in p.readlines():
+		[num, file] = string.split(line)
+		size = eval(num)
+		comps = string.splitfields(file, '/')
+		if comps[0] == '': comps[0] = '/'
+		if comps[len(comps)-1] == '': del comps[len(comps)-1]
+		total, d = store(size, comps, total, d)
+	display(total, d)
+
+def store(size, comps, total, d):
+	if comps == []:
+		return size, d
+	if not d.has_key(comps[0]):
+		d[comps[0]] = None, {}
+	t1, d1 = d[comps[0]]
+	d[comps[0]] = store(size, comps[1:], t1, d1)
+	return total, d
+
+def display(total, d):
+	show(total, d, '')
+
+def show(total, d, prefix):
+	if not d: return
+	list = []
+	sum = 0
+	for key in d.keys():
+		tsub, dsub = d[key]
+		list.append((tsub, key))
+		if tsub is not None: sum = sum + tsub
+	if sum < total:
+		list.append((total - sum, '.'))
+	list.sort()
+	list.reverse()
+	width = len(`list[0][0]`)
+	for tsub, key in list:
+		if tsub is None:
+			psub = prefix
+		else:
+			print prefix + string.rjust(`tsub`, width) + ' ' + key
+			psub = prefix + ' '*(width-1) + '|' + ' '*(len(key)+1)
+		if d.has_key(key):
+			show(tsub, d[key][1], psub)
+
+main()
diff --git a/Tools/scripts/h2py.py b/Tools/scripts/h2py.py
new file mode 100755
index 0000000..ff2afc2
--- /dev/null
+++ b/Tools/scripts/h2py.py
@@ -0,0 +1,50 @@
+#! /ufs/guido/bin/sgi/python
+#! /usr/local/python
+
+# Read #define's from stdin and translate to Python code on stdout.
+# Very primitive: non-#define's are ignored, no check for valid Python
+# syntax is made -- you will have to edit the output in most cases.
+
+# XXX To do:
+# - accept filename arguments
+# - turn trailing C comments into Python comments
+# - turn C string quotes into Python comments
+# - turn C Boolean operators "&& || !" into Python "and or not"
+# - what to do about #if(def)?
+# - what to do about macros with parameters?
+# - reject definitions with semicolons in them
+
+import sys, regex, string
+
+p_define = regex.compile('^#[\t ]*define[\t ]+\([a-zA-Z0-9_]+\)[\t ]+')
+
+p_comment = regex.compile('/\*\([^*]+\|\*+[^/]\)*\*+/')
+
+def main():
+	process(sys.stdin)
+
+def process(fp):
+	lineno = 0
+	while 1:
+		line = fp.readline()
+		if not line: break
+		lineno = lineno + 1
+		if p_define.match(line) >= 0:
+			# gobble up continuation lines
+			while line[-2:] == '\\\n':
+				nextline = fp.readline()
+				if not nextline: break
+				lineno = lineno + 1
+				line = line + nextline
+			regs = p_define.regs
+			a, b = regs[1] # where the macro name is
+			name = line[a:b]
+			a, b = regs[0] # the whole match
+			body = line[b:]
+			# replace comments by spaces
+			while p_comment.search(body) >= 0:
+				a, b = p_comment.regs[0]
+				body = body[:a] + ' ' + body[b:]
+			print name, '=', string.strip(body)
+
+main()
diff --git a/Tools/scripts/linktree.py b/Tools/scripts/linktree.py
new file mode 100755
index 0000000..5a66507
--- /dev/null
+++ b/Tools/scripts/linktree.py
@@ -0,0 +1,76 @@
+#! /usr/local/python
+
+# linktree
+#
+# Make a copy of a directory tree with symbolic links to all files in the
+# original tree.
+# All symbolic links go to a special symbolic link at the top, so you
+# can easily fix things if the original source tree moves.
+# See also "mkreal".
+#
+# usage: mklinks oldtree newtree
+
+import sys, posix, path
+
+LINK = '.LINK' # Name of special symlink at the top.
+
+debug = 0
+
+def main():
+	if not 3 <= len(sys.argv) <= 4:
+		print 'usage:', sys.argv[0], 'oldtree newtree [linkto]'
+		return 2
+	oldtree, newtree = sys.argv[1], sys.argv[2]
+	if len(sys.argv) > 3:
+		link = sys.argv[3]
+		link_may_fail = 1
+	else:
+		link = LINK
+		link_may_fail = 0
+	if not path.isdir(oldtree):
+		print oldtree + ': not a directory'
+		return 1
+	try:
+		posix.mkdir(newtree, 0777)
+	except posix.error, msg:
+		print newtree + ': cannot mkdir:', msg
+		return 1
+	linkname = path.cat(newtree, link)
+	try:
+		posix.symlink(path.cat('..', oldtree), linkname)
+	except posix.error, msg:
+		if not link_may_fail:
+			print linkname + ': cannot symlink:', msg
+			return 1
+		else:
+			print linkname + ': warning: cannot symlink:', msg
+	linknames(oldtree, newtree, link)
+	return 0
+
+def linknames(old, new, link):
+	if debug: print 'linknames', (old, new, link)
+	try:
+		names = posix.listdir(old)
+	except posix.error, msg:
+		print old + ': warning: cannot listdir:', msg
+		return
+	for name in names:
+	    if name not in ('.', '..'):
+		oldname = path.cat(old, name)
+		linkname = path.cat(link, name)
+		newname = path.cat(new, name)
+		if debug > 1: print oldname, newname, linkname
+		if path.isdir(oldname) and not path.islink(oldname):
+			try:
+				posix.mkdir(newname, 0777)
+				ok = 1
+			except:
+				print newname + ': warning: cannot mkdir:', msg
+				ok = 0
+			if ok:
+				linkname = path.cat('..', linkname)
+				linknames(oldname, newname, linkname)
+		else:
+			posix.symlink(linkname, newname)
+
+sys.exit(main())
diff --git a/Tools/scripts/lll.py b/Tools/scripts/lll.py
new file mode 100755
index 0000000..509936d
--- /dev/null
+++ b/Tools/scripts/lll.py
@@ -0,0 +1,25 @@
+#! /usr/local/python
+
+# Find symbolic links and show where they point to.
+# Arguments are directories to search; default is current directory.
+# No recursion.
+# (This is a totally different program from "findsymlinks.py"!)
+
+import sys, posix, path
+
+def lll(dirname):
+	for name in posix.listdir(dirname):
+		if name not in ['.', '..']:
+			full = path.join(dirname, name)
+			if path.islink(full):
+				print name, '->', posix.readlink(full)
+
+args = sys.argv[1:]
+if not args: args = ['.']
+first = 1
+for arg in args:
+	if len(args) > 1:
+		if not first: print
+		first = 0
+		print arg + ':'
+	lll(arg)