Get rid of freeze (now its own directory).
Added some new demos. Fixed a few others.
diff --git a/Demo/scripts/README b/Demo/scripts/README
index 5b5e88d..e7443da 100644
--- a/Demo/scripts/README
+++ b/Demo/scripts/README
@@ -21,7 +21,6 @@
fixps.py Fix Python scripts' first line (if #!)
fixcid.py Massive identifier substitution on C source files
fixheader.py Add some cpp magic to a C include file
-freeze.py Convert a Python script into a free-standing binary
from.py Summarize mailbox
ftpstats.py Summarize ftp daemon log file
ifdef.py Remove #if(n)def groups from C sources
@@ -31,6 +30,7 @@
markov.py Markov chain simulation of words or characters
mboxconvvert.py Convert MH or MMDF mailboxes to unix mailbox format
methfix.py Fix old method syntax def f(self, (a1, ..., aN)):
+morse.py Produce morse code (audible or on AIFF file)
mkreal.py Turn a symbolic link into a real file or directory
mpzpi.py test mpz -- print digits of pi (compare pi.py)
objgraph.py Print object graph from nm output on a library
@@ -41,7 +41,9 @@
pp.py Emulate some Perl command line options
primes.py Print prime numbers
ptags.py Create vi tags file for Python modules
+script.py Equivalent to BSD script(1) -- by Steen Lumholt
suff.py Sort a list of files by suffix
+sum5.py Print md5 checksums of files
unbirthday.py Print unbirthday count
which.py Find a program in $PATH
xxci.py Wrapper for rcsdiff and ci
diff --git a/Demo/scripts/morse.py b/Demo/scripts/morse.py
new file mode 100755
index 0000000..2cea83e
--- /dev/null
+++ b/Demo/scripts/morse.py
@@ -0,0 +1,149 @@
+# DAH should be three DOTs.
+# Space between DOTs and DAHs should be one DOT.
+# Space between two letters should be one DAH.
+# Space between two words should be DOT DAH DAH.
+
+import sys, math, audiodev
+
+DOT = 30
+DAH = 3 * DOT
+OCTAVE = 2 # 1 == 441 Hz, 2 == 882 Hz, ...
+
+morsetab = {
+ 'A': '.-', 'a': '.-',
+ 'B': '-...', 'b': '-...',
+ 'C': '-.-.', 'c': '-.-.',
+ 'D': '-..', 'd': '-..',
+ 'E': '.', 'e': '.',
+ 'F': '..-.', 'f': '..-.',
+ 'G': '--.', 'g': '--.',
+ 'H': '....', 'h': '....',
+ 'I': '..', 'i': '..',
+ 'J': '.---', 'j': '.---',
+ 'K': '-.-', 'k': '-.-',
+ 'L': '.-..', 'l': '.-..',
+ 'M': '--', 'm': '--',
+ 'N': '-.', 'n': '-.',
+ 'O': '---', 'o': '---',
+ 'P': '.--.', 'p': '.--.',
+ 'Q': '--.-', 'q': '--.-',
+ 'R': '.-.', 'r': '.-.',
+ 'S': '...', 's': '...',
+ 'T': '-', 't': '-',
+ 'U': '..-', 'u': '..-',
+ 'V': '...-', 'v': '...-',
+ 'W': '.--', 'w': '.--',
+ 'X': '-..-', 'x': '-..-',
+ 'Y': '-.--', 'y': '-.--',
+ 'Z': '--..', 'z': '--..',
+ '0': '-----',
+ '1': '.----',
+ '2': '..---',
+ '3': '...--',
+ '4': '....-',
+ '5': '.....',
+ '6': '-....',
+ '7': '--...',
+ '8': '---..',
+ '9': '----.',
+ ',': '--..--',
+ '.': '.-.-.-',
+ '?': '..--..',
+ ';': '-.-.-.',
+ ':': '---...',
+ "'": '.----.',
+ '-': '-....-',
+ '/': '-..-.',
+ '(': '-.--.-',
+ ')': '-.--.-',
+ '_': '..--.-',
+ ' ': ' '
+}
+
+# If we play at 44.1 kHz (which we do), then if we produce one sine
+# wave in 100 samples, we get a tone of 441 Hz. If we produce two
+# sine waves in these 100 samples, we get a tone of 882 Hz. 882 Hz
+# appears to be a nice one for playing morse code.
+def mkwave(octave):
+ global sinewave, nowave
+ sinewave = ''
+ for i in range(100):
+ val = int(math.sin(math.pi * float(i) * octave / 50.0) * 30000)
+ sinewave = sinewave + chr((val >> 8) & 255) + chr(val & 255)
+ nowave = '\0' * 200
+
+mkwave(OCTAVE)
+
+def main():
+ import getopt, string
+ try:
+ opts, args = getopt.getopt(sys.argv[1:], 'o:p:')
+ except getopt.error:
+ sys.stderr.write('Usage ' + sys.argv[0] +
+ ' [ -o outfile ] [ args ] ...\n')
+ sys.exit(1)
+ dev = None
+ for o, a in opts:
+ if o == '-o':
+ import aifc
+ dev = aifc.open(a, 'w')
+ dev.setframerate(44100)
+ dev.setsampwidth(2)
+ dev.setnchannels(1)
+ if o == '-p':
+ mkwave(string.atoi(a))
+ if not dev:
+ import audiodev
+ dev = audiodev.AudioDev()
+ dev.setoutrate(44100)
+ dev.setsampwidth(2)
+ dev.setnchannels(1)
+ dev.close = dev.stop
+ dev.writeframesraw = dev.writeframes
+ if args:
+ line = string.join(args)
+ else:
+ line = sys.stdin.readline()
+ while line:
+ mline = morse(line)
+ play(mline, dev)
+ if hasattr(dev, 'wait'):
+ dev.wait()
+ if not args:
+ line = sys.stdin.readline()
+ else:
+ line = ''
+ dev.close()
+
+# Convert a string to morse code with \001 between the characters in
+# the string.
+def morse(line):
+ res = ''
+ for c in line:
+ try:
+ res = res + morsetab[c] + '\001'
+ except KeyError:
+ pass
+ return res
+
+# Play a line of morse code.
+def play(line, dev):
+ for c in line:
+ if c == '.':
+ sine(dev, DOT)
+ elif c == '-':
+ sine(dev, DAH)
+ else: # space
+ pause(dev, DAH + DOT)
+ pause(dev, DOT)
+
+def sine(dev, length):
+ for i in range(length):
+ dev.writeframesraw(sinewave)
+
+def pause(dev, length):
+ for i in range(length):
+ dev.writeframesraw(nowave)
+
+if __name__ == '__main__' or sys.argv[0] == __name__:
+ main()
diff --git a/Demo/scripts/script.py b/Demo/scripts/script.py
new file mode 100755
index 0000000..04e7ecb
--- /dev/null
+++ b/Demo/scripts/script.py
@@ -0,0 +1,33 @@
+#! /usr/local/bin/python
+# script.py -- Make typescript of terminal session.
+# Usage:
+# -a Append to typescript.
+# -p Use Python as shell.
+# Author: Steen Lumholt.
+
+
+import os, time, sys
+import pty
+
+def read(fd):
+ data = os.read(fd, 1024)
+ file.write(data)
+ return data
+
+shell = 'sh'
+filename = 'typescript'
+mode = 'w'
+if os.environ.has_key('SHELL'):
+ shell = os.environ['SHELL']
+if '-a' in sys.argv:
+ mode = 'a'
+if '-p' in sys.argv:
+ shell = 'python'
+
+file = open(filename, mode)
+
+sys.stdout.write('Script started, file is %s\n' % filename)
+file.write('Script started on %s\n' % time.ctime(time.time()))
+pty.spawn(shell, read)
+file.write('Script done on %s\n' % time.ctime(time.time()))
+sys.stdout.write('Script done, file is %s\n' % filename)
diff --git a/Tools/scripts/fixcid.py b/Tools/scripts/fixcid.py
index ce3f1f3..3b37bb8 100755
--- a/Tools/scripts/fixcid.py
+++ b/Tools/scripts/fixcid.py
@@ -194,7 +194,7 @@
# Tokenizing ANSI C (partly)
-Identifier = '[a-zA-Z_][a-zA-Z0-9_]+'
+Identifier = '\(struct \)?[a-zA-Z_][a-zA-Z0-9_]+'
String = '"\([^\n\\"]\|\\\\.\)*"'
Char = '\'\([^\n\\\']\|\\\\.\)*\''
CommentStart = '/\*'
@@ -246,6 +246,7 @@
if Program is InsideCommentProgram:
if not Docomments:
print 'Found in comment:', found
+ i = i + n
continue
if NotInComment.has_key(found):
## print 'Ignored in comment:',
@@ -290,7 +291,9 @@
i = -1 # Happens to delete trailing \n
words = string.split(line[:i])
if not words: continue
- if len(words) <> 2:
+ if len(words) == 3 and words[0] == 'struct':
+ words[:2] == [words[0] + ' ' + words[1]]
+ elif len(words) <> 2:
err(substfile + ':' + `lineno` +
': warning: bad line: ' + line)
continue
diff --git a/Tools/scripts/h2py.py b/Tools/scripts/h2py.py
index 3d7a851..db0dbd8 100755
--- a/Tools/scripts/h2py.py
+++ b/Tools/scripts/h2py.py
@@ -1,32 +1,43 @@
#! /usr/local/bin/python
-# Read #define's from stdin and translate to Python code on stdout.
-# Very primitive: non-#define's are ignored, as is anything that isn't
-# valid Python as it stands.
+# Read #define's and translate to Python code.
+# Handle #include statements.
+# Handle #define macros with one argument.
+# Anything that isn't recognized or doesn't translate into valid
+# Python is ignored.
+
+# Without filename arguments, acts as a filter.
# If one or more filenames are given, output is written to corresponding
# filenames in the local directory, translated to all uppercase, with
# the extension replaced by ".py".
+
# By passing one or more options of the form "-i regular_expression"
# you can specify additional strings to be ignored. This is useful
# e.g. to ignore casts to u_long: simply specify "-i '(u_long)'".
# XXX To do:
# - 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 #include?
-# - what to do about macros with parameters?
-# - reject definitions with semicolons in them
+# - what to do about macros with multiple parameters?
-import sys, regex, string, getopt, os
+import sys, regex, regsub, string, getopt, os
p_define = regex.compile('^#[\t ]*define[\t ]+\([a-zA-Z0-9_]+\)[\t ]+')
+p_macro = regex.compile(
+ '^#[\t ]*define[\t ]+\([a-zA-Z0-9_]+\)(\([_a-zA-Z][_a-zA-Z0-9]*\))[\t ]+')
+
+p_include = regex.compile('^#[\t ]*include[\t ]+<\([a-zA-Z0-9_/\.]+\)')
+
p_comment = regex.compile('/\*\([^*]+\|\*+[^/]\)*\(\*+/\)?')
ignores = [p_comment]
+p_char = regex.compile("'\(\\\\.[^\\\\]*\|[^\\\\]\)'")
+
+filedict = {}
+
def main():
opts, args = getopt.getopt(sys.argv[1:], 'i:')
for o, a in opts:
@@ -47,40 +58,65 @@
outfile = outfile + '.py'
outfp = open(outfile, 'w')
outfp.write('# Generated by h2py from %s\n' % filename)
+ filedict = {}
+ if filename[:13] == '/usr/include/':
+ filedict[filename[13:]] = None
process(fp, outfp)
outfp.close()
fp.close()
-def process(fp, outfp):
- env = {}
+def process(fp, outfp, env = {}):
lineno = 0
while 1:
line = fp.readline()
if not line: break
lineno = lineno + 1
- # gobble up continuation lines
- while line[-2:] == '\\\n':
- nextline = fp.readline()
- if not nextline: break
- lineno = lineno + 1
- line = line + nextline
n = p_define.match(line)
if n >= 0:
+ # gobble up continuation lines
+ while line[-2:] == '\\\n':
+ nextline = fp.readline()
+ if not nextline: break
+ lineno = lineno + 1
+ line = line + nextline
name = p_define.group(1)
body = line[n:]
# replace ignored patterns by spaces
for p in ignores:
- while p.search(body) >= 0:
- a, b = p.regs[0]
- body = body[:a] + ' ' + body[b:]
+ body = regsub.gsub(p, ' ', body)
+ # replace char literals by ord(...)
+ body = regsub.gsub(p_char, 'ord(\\0)', body)
stmt = '%s = %s\n' % (name, string.strip(body))
ok = 0
try:
exec stmt in env
- ok = 1
except:
sys.stderr.write('Skipping: %s' % stmt)
- if ok:
+ else:
outfp.write(stmt)
-
+ n =p_macro.match(line)
+ if n >= 0:
+ macro, arg = p_macro.group(1, 2)
+ body = line[n:]
+ for p in ignores:
+ body = regsub.gsub(p, ' ', body)
+ body = regsub.gsub(p_char, 'ord(\\0)', body)
+ stmt = 'def %s(%s): return %s\n' % (macro, arg, body)
+ try:
+ exec stmt in env
+ except:
+ sys.stderr.write('Skipping: %s' % stmt)
+ else:
+ outfp.write(stmt)
+ if p_include.match(line) >= 0:
+ regs = p_include.regs
+ a, b = regs[1]
+ filename = line[a:b]
+ if not filedict.has_key(filename):
+ filedict[filename] = None
+ outfp.write(
+ '\n# Included from %s\n' % filename)
+ inclfp = open('/usr/include/' + filename, 'r')
+ process(inclfp, outfp, env)
main()
+
diff --git a/Tools/scripts/sum5.py b/Tools/scripts/sum5.py
new file mode 100755
index 0000000..fdb83fa
--- /dev/null
+++ b/Tools/scripts/sum5.py
@@ -0,0 +1,97 @@
+#! /usr/local/bin/python
+
+# print md5 checksum for files
+
+bufsize = 8096
+fnfilter = None
+rmode = 'r'
+
+usage = """
+usage: sum5 [-b] [-t] [-l] [-s bufsize] [file ...]
+-b : read files in binary mode
+-t : read files in text mode (default)
+-l : print last pathname component only
+-s bufsize: read buffer size (default %d)
+file ... : files to sum; '-' or no files means stdin
+""" % bufsize
+
+import sys
+import string
+import os
+import md5
+import regsub
+
+StringType = type('')
+FileType = type(sys.stdin)
+
+def sum(*files):
+ sts = 0
+ if files and type(files[-1]) == FileType:
+ out, files = files[-1], files[:-1]
+ else:
+ out = sys.stdout
+ if len(files) == 1 and type(files[0]) != StringType:
+ files = files[0]
+ for f in files:
+ if type(f) == StringType:
+ if f == '-':
+ sts = printsumfp(sys.stdin, '<stdin>', out) or sts
+ else:
+ sts = printsum(f, out) or sts
+ else:
+ sts = sum(f, out) or sts
+ return sts
+
+def printsum(file, out = sys.stdout):
+ try:
+ fp = open(file, rmode)
+ except IOError, msg:
+ sys.stderr.write('%s: Can\'t open: %s\n' % (file, msg))
+ return 1
+ if fnfilter:
+ file = fnfilter(file)
+ sts = printsumfp(fp, file, out)
+ fp.close()
+ return sts
+
+def printsumfp(fp, file, out = sys.stdout):
+ m = md5.md5()
+ try:
+ while 1:
+ data = fp.read(bufsize)
+ if not data: break
+ m.update(data)
+ except IOError, msg:
+ sys.stderr.write('%s: I/O error: %s\n' % (file, msg))
+ return 1
+ out.write('%s %s\n' % (hexify(m.digest()), file))
+ return 0
+
+def hexify(s):
+ res = ''
+ for c in s:
+ res = res + '%02x' % ord(c)
+ return res
+
+def main(args = sys.argv[1:], out = sys.stdout):
+ global fnfilter, rmode, bufsize
+ import getopt
+ try:
+ opts, args = getopt.getopt(args, 'blts:')
+ except getopt.error, msg:
+ sys.stderr.write('%s: %s\n%s' % (sys.argv[0], msg, usage))
+ return 2
+ for o, a in opts:
+ if o == '-l':
+ fnfilter = os.path.basename
+ if o == '-b':
+ rmode = 'rb'
+ if o == '-t':
+ rmode = 'r'
+ if o == '-s':
+ bufsize = string.atoi(a)
+ if not args: args = ['-']
+ return sum(args, out)
+
+if __name__ == '__main__' or __name__ == sys.argv[0]:
+ sys.exit(main(sys.argv[1:], sys.stdout))