aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSkip Montanaro <[email protected]>2021-02-16 14:40:46 -0600
committerSkip Montanaro <[email protected]>2021-02-16 14:40:46 -0600
commita19a216bc60160c162e616145ef091dd18ce4e61 (patch)
treefa4bdff21f9b04a125c84a2bfab8a1c738359e15
downloadpython-0.9.1-patched-QoL-a19a216bc60160c162e616145ef091dd18ce4e61.tar.xz
python-0.9.1-patched-QoL-a19a216bc60160c162e616145ef091dd18ce4e61.zip
Python 0.9.1 as posted in alt.sources
-rw-r--r--README71
-rw-r--r--demo/README22
-rwxr-xr-xdemo/scripts/findlinksto.py29
-rwxr-xr-xdemo/scripts/mkreal.py65
-rwxr-xr-xdemo/scripts/ptags.py66
-rwxr-xr-xdemo/scripts/suff.py29
-rwxr-xr-xdemo/scripts/xxci.py77
-rw-r--r--demo/sgi/README15
-rw-r--r--demo/sgi/audio/README5
-rwxr-xr-xdemo/sgi/audio/play.py75
-rw-r--r--demo/sgi/audio_stdwin/README16
-rwxr-xr-xdemo/sgi/audio_stdwin/jukebox.py321
-rwxr-xr-xdemo/sgi/audio_stdwin/rec.py271
-rwxr-xr-xdemo/sgi/audio_stdwin/vumeter.py35
-rw-r--r--demo/sgi/gl/README22
-rwxr-xr-xdemo/sgi/gl/backface.py140
-rwxr-xr-xdemo/sgi/gl/kites.py194
-rw-r--r--demo/sgi/gl/mclock.doc60
-rwxr-xr-xdemo/sgi/gl/mclock.py729
-rwxr-xr-xdemo/sgi/gl/mixing.py116
-rwxr-xr-xdemo/sgi/gl/nurbs.py171
-rwxr-xr-xdemo/sgi/gl/zrgb.py169
-rw-r--r--demo/sgi/gl_panel/README23
-rwxr-xr-xdemo/sgi/gl_panel/apanel/apanel.py63
-rw-r--r--demo/sgi/gl_panel/apanel/apanel.s76
-rw-r--r--demo/sgi/gl_panel/flying/data.py42
-rwxr-xr-xdemo/sgi/gl_panel/flying/flying.py375
-rw-r--r--demo/sgi/gl_panel/flying/flying.s140
-rw-r--r--demo/sgi/gl_panel/flying/freeze.s31
-rw-r--r--demo/sgi/gl_panel/flying/light.py46
-rw-r--r--demo/sgi/gl_panel/flying/light.s94
-rw-r--r--demo/sgi/gl_panel/flying/material.py26
-rw-r--r--demo/sgi/gl_panel/flying/materials.s161
-rw-r--r--demo/sgi/gl_panel/flying/objdict.py41
-rw-r--r--demo/sgi/gl_panel/flying/objectdef.py147
-rw-r--r--demo/sgi/gl_panel/flying/panel.s76
-rwxr-xr-xdemo/sgi/gl_panel/nurbs/nurbs.py196
-rw-r--r--demo/sgi/gl_panel/nurbs/nurbs.s81
-rw-r--r--demo/sgi/gl_panel/nurbs/nurbsdata.py82
-rw-r--r--demo/sgi/gl_panel/twoview/block.py73
-rw-r--r--demo/sgi/gl_panel/twoview/camera.s55
-rw-r--r--demo/sgi/gl_panel/twoview/observer.s98
-rw-r--r--demo/sgi/gl_panel/twoview/topview.s47
-rwxr-xr-xdemo/sgi/gl_panel/twoview/twoview.py395
-rwxr-xr-xdemo/stdwin/wdiff.py480
-rw-r--r--doc/Makefile47
-rw-r--r--doc/README24
-rw-r--r--doc/SetClass.py17
-rw-r--r--doc/fibo.py15
-rw-r--r--doc/mod.tex62
-rw-r--r--doc/mod1.tex521
-rw-r--r--doc/mod2.tex1083
-rw-r--r--doc/mod3.tex484
-rw-r--r--doc/myformat.sty34
-rwxr-xr-xdoc/pytry20
-rw-r--r--doc/tut.tex1550
-rw-r--r--lib/Abstract.py61
-rw-r--r--lib/Buttons.py399
-rw-r--r--lib/CSplit.py70
-rw-r--r--lib/DEVICE.py423
-rw-r--r--lib/GL.py365
-rw-r--r--lib/HVSplit.py56
-rw-r--r--lib/Histogram.py36
-rw-r--r--lib/Sliders.py175
-rw-r--r--lib/Soundogram.py36
-rw-r--r--lib/Split.py116
-rw-r--r--lib/StripChart.py68
-rw-r--r--lib/Tcl.py421
-rw-r--r--lib/TclShell.py255
-rw-r--r--lib/TclUtil.py377
-rw-r--r--lib/TestCSplit.py26
-rw-r--r--lib/TransParent.py96
-rw-r--r--lib/VUMeter.py47
-rw-r--r--lib/WindowParent.py101
-rw-r--r--lib/adv.py366
-rw-r--r--lib/anywin.py14
-rw-r--r--lib/auds.py106
-rw-r--r--lib/calendar.py213
-rw-r--r--lib/clock.py202
-rw-r--r--lib/cmp.py61
-rw-r--r--lib/cmpcache.py68
-rw-r--r--lib/commands.py77
-rw-r--r--lib/dircache.py36
-rw-r--r--lib/dircmp.py205
-rw-r--r--lib/dirwin.py29
-rw-r--r--lib/dis.py176
-rw-r--r--lib/dump.py63
-rw-r--r--lib/fact.py37
-rw-r--r--lib/filewin.py18
-rw-r--r--lib/fnmatch.py35
-rw-r--r--lib/getopt.py47
-rw-r--r--lib/glob.py44
-rw-r--r--lib/grep.py32
-rw-r--r--lib/gwin.py122
-rw-r--r--lib/lambda.py151
-rw-r--r--lib/listwin.py47
-rw-r--r--lib/localtime.py53
-rw-r--r--lib/maccache.py61
-rw-r--r--lib/macglob.py46
-rw-r--r--lib/macpath.py108
-rw-r--r--lib/macshell.py399
-rw-r--r--lib/minmax.py6
-rw-r--r--lib/packmail.py48
-rw-r--r--lib/panel.py281
-rw-r--r--lib/panelparser.py128
-rw-r--r--lib/path.py125
-rw-r--r--lib/poly.py55
-rw-r--r--lib/rand.py12
-rw-r--r--lib/rect.py88
-rw-r--r--lib/selection.py72
-rw-r--r--lib/shutil.py70
-rw-r--r--lib/stat.py57
-rw-r--r--lib/statcache.py86
-rw-r--r--lib/stdwinevents.py46
-rw-r--r--lib/stdwinsupport.py34
-rw-r--r--lib/string.py129
-rw-r--r--lib/sunaudio.py54
-rw-r--r--lib/tablewin.py237
-rw-r--r--lib/tb.py220
-rw-r--r--lib/testall.py416
-rw-r--r--lib/textwin.py119
-rw-r--r--lib/util.py30
-rw-r--r--lib/whrandom.py74
-rw-r--r--lib/zmod.py94
-rw-r--r--python.man79
-rw-r--r--shar/python-0.9.1-01-21.shar1952
-rw-r--r--shar/python-0.9.1-01.patch163
-rw-r--r--shar/python-0.9.1-03-21.shar2944
-rw-r--r--shar/python-0.9.1-04-21.shar2755
-rw-r--r--shar/python-0.9.1-05-21.shar2528
-rw-r--r--shar/python-0.9.1-06-21.shar2510
-rw-r--r--shar/python-0.9.1-07-21.shar2518
-rw-r--r--shar/python-0.9.1-08-21.shar2349
-rw-r--r--shar/python-0.9.1-09-21.shar2688
-rw-r--r--shar/python-0.9.1-10-21.shar2508
-rw-r--r--shar/python-0.9.1-11-21.shar2618
-rw-r--r--shar/python-0.9.1-12-21.shar2833
-rw-r--r--shar/python-0.9.1-13-21.shar2811
-rw-r--r--shar/python-0.9.1-14-21.shar2720
-rw-r--r--shar/python-0.9.1-15-21.shar2539
-rw-r--r--shar/python-0.9.1-16-21.shar2495
-rw-r--r--shar/python-0.9.1-17-21.shar2464
-rw-r--r--shar/python-0.9.1-18-21.shar2268
-rw-r--r--shar/python-0.9.1-19-21.shar1997
-rw-r--r--shar/python-0.9.1-20-21.shar1941
-rw-r--r--shar/python-0.9.1-21-21.shar1675
-rw-r--r--src/Grammar72
-rw-r--r--src/Makefile508
-rw-r--r--src/PROTO.h79
-rw-r--r--src/README11
-rw-r--r--src/To.do11
-rw-r--r--src/acceler.c136
-rw-r--r--src/allobjects.h50
-rw-r--r--src/amoebamodule.c774
-rw-r--r--src/asa.c494
-rw-r--r--src/asa.h33
-rw-r--r--src/assert.h25
-rw-r--r--src/audiomodule.c615
-rw-r--r--src/bitset.c99
-rw-r--r--src/bitset.h46
-rw-r--r--src/bltinmodule.c559
-rw-r--r--src/bltinmodule.h27
-rw-r--r--src/ceval.c1436
-rw-r--r--src/ceval.h33
-rw-r--r--src/cgen458
-rw-r--r--src/cgensupport.c393
-rw-r--r--src/cgensupport.h39
-rw-r--r--src/classobject.c298
-rw-r--r--src/classobject.h44
-rw-r--r--src/compile.c1772
-rw-r--r--src/compile.h47
-rw-r--r--src/config.c180
-rw-r--r--src/configmac.c109
-rw-r--r--src/cstubs999
-rw-r--r--src/dictobject.c605
-rw-r--r--src/dictobject.h44
-rw-r--r--src/errcode.h36
-rw-r--r--src/errors.c196
-rw-r--r--src/errors.h58
-rw-r--r--src/fgetsintr.c94
-rw-r--r--src/fgetsintr.h25
-rw-r--r--src/fileobject.c293
-rw-r--r--src/fileobject.h33
-rw-r--r--src/firstsets.c133
-rw-r--r--src/floatobject.c271
-rw-r--r--src/floatobject.h44
-rw-r--r--src/fmod.c51
-rw-r--r--src/frameobject.c156
-rw-r--r--src/frameobject.h80
-rw-r--r--src/funcobject.c113
-rw-r--r--src/funcobject.h33
-rw-r--r--src/getcwd.c102
-rw-r--r--src/graminit.c1094
-rw-r--r--src/graminit.h66
-rw-r--r--src/grammar.c233
-rw-r--r--src/grammar.h105
-rw-r--r--src/grammar1.c75
-rw-r--r--src/import.c259
-rw-r--r--src/import.h31
-rw-r--r--src/intobject.c307
-rw-r--r--src/intobject.h72
-rw-r--r--src/intrcheck.c144
-rw-r--r--src/listnode.c93
-rw-r--r--src/listobject.c519
-rw-r--r--src/listobject.h59
-rw-r--r--src/macmodule.c246
-rw-r--r--src/malloc.h63
-rw-r--r--src/mathmodule.c180
-rw-r--r--src/metagrammar.c176
-rw-r--r--src/metagrammar.h30
-rw-r--r--src/methodobject.c147
-rw-r--r--src/methodobject.h42
-rw-r--r--src/modsupport.c381
-rw-r--r--src/modsupport.h27
-rw-r--r--src/moduleobject.c154
-rw-r--r--src/moduleobject.h33
-rw-r--r--src/node.c100
-rw-r--r--src/node.h58
-rw-r--r--src/object.c290
-rw-r--r--src/object.h324
-rw-r--r--src/objimpl.h50
-rw-r--r--src/opcode.h109
-rw-r--r--src/panelmodule.c1090
-rw-r--r--src/parser.c423
-rw-r--r--src/parser.h50
-rw-r--r--src/parsetok.c158
-rw-r--r--src/parsetok.h29
-rw-r--r--src/patchlevel.h1
-rw-r--r--src/pgen.c751
-rw-r--r--src/pgen.h30
-rw-r--r--src/pgenheaders.h50
-rw-r--r--src/pgenmain.c148
-rw-r--r--src/posixmodule.c427
-rw-r--r--src/printgrammar.c149
-rw-r--r--src/profmain.c133
-rw-r--r--src/pythonmain.c440
-rw-r--r--src/pythonrun.h47
-rw-r--r--src/regexp.c1394
-rw-r--r--src/regexp.h51
-rw-r--r--src/regexpmodule.c191
-rw-r--r--src/regmagic.h29
-rw-r--r--src/regsub.c115
-rw-r--r--src/rltokenizer.c26
-rw-r--r--src/sc_errors.c145
-rw-r--r--src/sc_errors.h41
-rw-r--r--src/sc_global.h137
-rw-r--r--src/sc_interpr.c1352
-rw-r--r--src/scdbg.c152
-rw-r--r--src/sigtype.h51
-rw-r--r--src/stdwinmodule.c1697
-rw-r--r--src/stdwinobject.h31
-rw-r--r--src/strdup.c39
-rw-r--r--src/strerror.c47
-rw-r--r--src/stringobject.c347
-rw-r--r--src/stringobject.h63
-rw-r--r--src/strtol.c122
-rw-r--r--src/structmember.c158
-rw-r--r--src/structmember.h64
-rw-r--r--src/stubcode.h28
-rw-r--r--src/sysmodule.c214
-rw-r--r--src/sysmodule.h30
-rw-r--r--src/timemodule.c229
-rw-r--r--src/token.h69
-rw-r--r--src/tokenizer.c523
-rw-r--r--src/tokenizer.h53
-rw-r--r--src/traceback.c217
-rw-r--r--src/traceback.h30
-rw-r--r--src/tupleobject.c287
-rw-r--r--src/tupleobject.h56
-rw-r--r--src/typeobject.c61
-rw-r--r--src/xxobject.c131
271 files changed, 96470 insertions, 0 deletions
diff --git a/README b/README
new file mode 100644
index 0000000..5fe1ff7
--- /dev/null
+++ b/README
@@ -0,0 +1,71 @@
+This is Python, an extensible interpreted programming language that
+combines remarkable power with very clear syntax.
+
+This is version 0.9 (the first beta release), patchlevel 1.
+
+Python can be used instead of shell, Awk or Perl scripts, to write
+prototypes of real applications, or as an extension language of large
+systems, you name it. There are built-in modules that interface to
+the operating system and to various window systems: X11, the Mac
+window system (you need STDWIN for these two), and Silicon Graphics'
+GL library. It runs on most modern versions of UNIX, on the Mac, and
+I wouldn't be surprised if it ran on MS-DOS unchanged. I developed it
+mostly on an SGI IRIS workstation (using IRIX 3.1 and 3.2) and on the
+Mac, but have tested it also on SunOS (4.1) and BSD 4.3 (tahoe).
+
+Building and installing Python is easy (but do read the Makefile).
+A UNIX style manual page and extensive documentation (in LaTeX format)
+are provided. (In the beta release, the documentation is still under
+development.)
+
+Please try it out and send me your comments (on anything -- the
+language design, implementation, portability, installation,
+documentation) and the modules you wrote for it, to make the first
+real release better. If you needed to hack the source to get it to
+compile and run on a particular machine, send me the fixes -- I'll try
+to incorporate them into the next patch. If you can't get it to work
+at all, send me a *detailed* description of the problem and I may look
+into it.
+
+If you want to profit of the X11 or Mac window interface, you'll need
+STDWIN. This is a portable window system interface by the same
+author. The versions of STDWIN floating around on some archives are
+not sufficiently up-to-date for use with Python. I will distribute
+the latest and greatest STDWIN version at about the same time as Python.
+
+I am the author of Python:
+
+ Guido van Rossum
+ CWI, dept. CST
+ Kruislaan 413
+ 1098 SJ Amsterdam
+ The Netherlands
+
+
+The Python source is copyrighted, but you can freely use and copy it
+as long as you don't change or remove the copyright:
+
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
diff --git a/demo/README b/demo/README
new file mode 100644
index 0000000..a9ff224
--- /dev/null
+++ b/demo/README
@@ -0,0 +1,22 @@
+This directory contains various demonstrations of what you can do with
+Python. The demos are grouped sub(sub*)directories according to
+required optional built-in modules.
+
+scripts Some useful Python scripts that I put in my bin
+ directory. No optional built-in modules meeded.
+
+sgi Demos that only run on Silicon Graphics machines.
+ Require the built-in modules 'audio' and/or 'gl'.
+
+stdwin Demos that use the STDWIN library. Require the 'stdwin'
+ built-in module.
+
+WARNING: some scripts are executable and have a first line saying
+
+ #! /ufs/guido/bin/sgi/python
+
+This is unlikely to give good results anywhere else except in my
+office. Edit the first line before installing such scripts; to try
+them out, you can just say "python file.py". (The .py suffix is not
+necessary in this case, but makes it possible to debug the modules
+interactively by importing them.)
diff --git a/demo/scripts/findlinksto.py b/demo/scripts/findlinksto.py
new file mode 100755
index 0000000..210441e
--- /dev/null
+++ b/demo/scripts/findlinksto.py
@@ -0,0 +1,29 @@
+#! /ufs/guido/bin/sgi/python
+
+# findlinksto
+#
+# find symbolic links to a given path
+
+import posix, path, sys
+
+def visit(pattern, dirname, names):
+ if path.islink(dirname):
+ names[:] = []
+ return
+ if path.ismount(dirname):
+ print 'descend into', dirname
+ n = len(pattern)
+ for name in names:
+ name = path.cat(dirname, name)
+ try:
+ linkto = posix.readlink(name)
+ if linkto[:n] = pattern:
+ print name, '->', linkto
+ except posix.error:
+ pass
+
+def main(pattern, args):
+ for dirname in args:
+ path.walk(dirname, visit, pattern)
+
+main(sys.argv[1], sys.argv[2:])
diff --git a/demo/scripts/mkreal.py b/demo/scripts/mkreal.py
new file mode 100755
index 0000000..19fef28
--- /dev/null
+++ b/demo/scripts/mkreal.py
@@ -0,0 +1,65 @@
+#! /ufs/guido/bin/sgi/python
+
+# mkreal
+#
+# turn a symlink to a directory into a real directory
+
+import sys
+import posix
+import path
+from stat import *
+
+cat = path.cat
+
+error = 'mkreal error'
+
+BUFSIZE = 32*1024
+
+def mkrealfile(name):
+ st = posix.stat(name) # Get the mode
+ mode = S_IMODE(st[ST_MODE])
+ linkto = posix.readlink(name) # Make sure again it's a symlink
+ f_in = open(name, 'r') # This ensures it's a file
+ posix.unlink(name)
+ f_out = open(name, 'w')
+ while 1:
+ buf = f_in.read(BUFSIZE)
+ if not buf: break
+ f_out.write(buf)
+ del f_out # Flush data to disk before changing mode
+ posix.chmod(name, mode)
+
+def mkrealdir(name):
+ st = posix.stat(name) # Get the mode
+ mode = S_IMODE(st[ST_MODE])
+ linkto = posix.readlink(name)
+ files = posix.listdir(name)
+ posix.unlink(name)
+ posix.mkdir(name, mode)
+ posix.chmod(name, mode)
+ linkto = cat('..', linkto)
+ #
+ for file in files:
+ if file not in ('.', '..'):
+ posix.symlink(cat(linkto, file), cat(name, file))
+
+def main():
+ sys.stdout = sys.stderr
+ progname = path.basename(sys.argv[0])
+ args = sys.argv[1:]
+ if not args:
+ print 'usage:', progname, 'path ...'
+ sys.exit(2)
+ status = 0
+ for name in args:
+ if not path.islink(name):
+ print progname+':', name+':', 'not a symlink'
+ status = 1
+ else:
+ if path.isdir(name):
+ mkrealdir(name)
+ else:
+ mkrealfile(name)
+ sys.exit(status)
+
+main()
diff --git a/demo/scripts/ptags.py b/demo/scripts/ptags.py
new file mode 100755
index 0000000..0f99650
--- /dev/null
+++ b/demo/scripts/ptags.py
@@ -0,0 +1,66 @@
+#! /ufs/guido/bin/sgi/python
+
+# ptags
+#
+Create a tags file for Python programs
+# Tagged are:
+# - functions (even inside other defs or classes)
+# - classes
+# - filenames
+# Warns about files it cannot open.
+# No warnings about duplicate tags.
+
+import sys
+import posix
+import path
+import string
+
+keywords = ['def', 'class'] # If you add keywords, update starts!!!
+starts = 'dc' # Starting characters of keywords
+
+whitespace = string.whitespace
+identchars = string.letters + string.digits + '_'
+
+tags = [] # Modified!
+
+def main():
+ args = sys.argv[1:]
+ for file in args: treat_file(file)
+ if tags:
+ fp = open('tags', 'w')
+ tags.sort()
+ for s in tags: fp.write(s)
+
+def treat_file(file):
+ try:
+ fp = open(file, 'r')
+ except:
+ print 'Cannot open', file
+ return
+ base = path.basename(file)
+ if base[-3:] = '.py': base = base[:-3]
+ s = base + '\t' + file + '\t' + '1\n'
+ tags.append(s)
+ while 1:
+ line = fp.readline()
+ if not line: break
+ maketag(line, file)
+
+def maketag(line, file):
+ i = 0
+ while line[i:i+1] in whitespace: i = i+1
+ if line[i:i+1] not in starts: return
+ n = len(line)
+ j = i
+ while i < n and line[i] not in whitespace: i = i+1
+ if line[j:i] not in keywords: return
+ while i < n and line[i] in whitespace: i = i+1
+ j = i
+ while i < n and line[i] in identchars: i = i+1
+ name = line[j:i]
+ while i < n and line[i] in whitespace: i = i+1
+ if i < n and line[i] = '(': i = i+1
+ s = name + '\t' + file + '\t' + '/^' + line[:i] + '/\n'
+ tags.append(s)
+
+main()
diff --git a/demo/scripts/suff.py b/demo/scripts/suff.py
new file mode 100755
index 0000000..f6bd6bf
--- /dev/null
+++ b/demo/scripts/suff.py
@@ -0,0 +1,29 @@
+#! /ufs/guido/bin/sgi/python
+
+# suff
+#
+# show different suffixes amongst arguments
+
+import sys
+
+def main():
+ files = sys.argv[1:]
+ suffixes = {}
+ for file in files:
+ suff = getsuffix(file)
+ if not suffixes.has_key(suff):
+ suffixes[suff] = []
+ suffixes[suff].append(file)
+ keys = suffixes.keys()
+ keys.sort()
+ for suff in keys:
+ print `suff`, len(suffixes[suff])
+
+def getsuffix(file):
+ suff = ''
+ for i in range(len(file)):
+ if file[i] = '.':
+ suff = file[i:]
+ return suff
+
+main()
diff --git a/demo/scripts/xxci.py b/demo/scripts/xxci.py
new file mode 100755
index 0000000..43ea316
--- /dev/null
+++ b/demo/scripts/xxci.py
@@ -0,0 +1,77 @@
+#! /ufs/guido/bin/sgi/python
+
+# xxci
+#
+# check in files for which rcsdiff returns nonzero exit status
+
+import sys
+import posix
+import stat
+import path
+import commands
+
+MAXSIZE = 200*1024 # Files this big must be binaries and are skipped.
+
+def getargs():
+ args = sys.argv[1:]
+ if args:
+ return args
+ print 'No arguments, checking almost *'
+ for file in posix.listdir('.'):
+ if not skipfile(file):
+ args.append(file)
+ if not args:
+ print 'Nothing to do -- exit 1'
+ sys.exit(1)
+ args.sort()
+ return args
+
+badnames = ['tags', 'xyzzy']
+badprefixes = ['.', ',', '@', '#', 'o.']
+badsuffixes = \
+ ['~', '.a', '.o', '.old', '.bak', '.orig', '.new', '.prev', '.not']
+# XXX Should generalize even more to use fnmatch!
+
+def skipfile(file):
+ if file in badnames or \
+ badprefix(file) or badsuffix(file) or \
+ path.islink(file) or path.isdir(file):
+ return 1
+ # Skip huge files -- probably binaries.
+ try:
+ st = posix.stat(file)
+ except posix.error:
+ return 1 # Doesn't exist -- skip it
+ return st[stat.ST_SIZE] >= MAXSIZE
+
+def badprefix(file):
+ for bad in badprefixes:
+ if file[:len(bad)] = bad: return 1
+ return 0
+
+def badsuffix(file):
+ for bad in badsuffixes:
+ if file[-len(bad):] = bad: return 1
+ return 0
+
+def go(args):
+ for file in args:
+ print file + ':'
+ if run('rcsdiff -c', file):
+ if askyesno('Check in ' + file + ' ? '):
+ sts = run('rcs -l', file) # ignored
+ # can't use run() here because it's interactive
+ sts = posix.system('ci -l ' + file)
+
+def run(cmd, file):
+ sts, output = commands.getstatusoutput(cmd + commands.mkarg(file))
+ if sts:
+ print output
+ print 'Exit status', sts
+ return sts
+
+def askyesno(prompt):
+ s = raw_input(prompt)
+ return s in ['y', 'yes']
+
+go(getargs())
diff --git a/demo/sgi/README b/demo/sgi/README
new file mode 100644
index 0000000..5740c22
--- /dev/null
+++ b/demo/sgi/README
@@ -0,0 +1,15 @@
+Demonstrations of Python that use various features of the Silicon
+Graphics IRIS machines.
+
+audio Demonstrations of the audio capabilities of the 4D/25.
+ Require the built-in module 'audio'.
+
+audio_stdwin Window-based demonstrations the audio capabilities of
+ the 4D/25. Require the built-in modules 'stdwin' and
+ 'audio'.
+
+gl Demonstrations of the Graphics Library (GL).
+ Require the built-in module 'gl'.
+
+gl_panel Demonstrations of the Panel Library by NASA Ames.
+ Require the built-in modules 'gl' and 'pnl'.
diff --git a/demo/sgi/audio/README b/demo/sgi/audio/README
new file mode 100644
index 0000000..17dc9b2
--- /dev/null
+++ b/demo/sgi/audio/README
@@ -0,0 +1,5 @@
+Programs that demonstrate the use of the audio device on the SGI 4D/25.
+These require the built-in module 'audio'.
+
+play Read a sound sample from a file and play it through the
+ speaker. Options to set volume, sampling rate etc.
diff --git a/demo/sgi/audio/play.py b/demo/sgi/audio/play.py
new file mode 100755
index 0000000..8f6a802
--- /dev/null
+++ b/demo/sgi/audio/play.py
@@ -0,0 +1,75 @@
+#!/ufs/guido/bin/sgi/python
+
+import sys
+import audio
+
+import string
+import getopt
+import auds
+
+debug = []
+
+DEF_RATE = 3
+
+def main():
+ #
+ gain = 100
+ rate = 0
+ starter = audio.write
+ stopper = 0
+ #
+ optlist, args = getopt.getopt(sys.argv[1:], 'adg:r:')
+ #
+ for optname, optarg in optlist:
+ if 0:
+ pass
+ elif optname = '-d':
+ debug.append(1)
+ elif optname = '-g':
+ gain = string.atoi(optarg)
+ if not (0 < gain < 256):
+ raise optarg.error, '-g gain out of range'
+ elif optname = '-r':
+ rate = string.atoi(optarg)
+ if not (1 <= rate <= 3):
+ raise optarg.error, '-r rate out of range'
+ elif optname = '-a':
+ starter = audio.start_playing
+ stopper = audio.wait_playing
+ #
+ audio.setoutgain(gain)
+ audio.setrate(rate)
+ #
+ if not args:
+ play(starter, rate, auds.loadfp(sys.stdin))
+ else:
+ real_stopper = 0
+ for file in args:
+ if real_stopper:
+ real_stopper()
+ play(starter, rate, auds.load(file))
+ real_stopper = stopper
+
+def play(starter, rate, data):
+ magic = data[:4]
+ if magic = '0008':
+ mrate = 3
+ elif magic = '0016':
+ mrate = 2
+ elif magic = '0032':
+ mrate = 1
+ else:
+ mrate = 0
+ if mrate:
+ data = data[4:]
+ else:
+ mrate = DEF_RATE
+ if not rate: rate = mrate
+ audio.setrate(rate)
+ starter(data)
+
+try:
+ main()
+finally:
+ audio.setoutgain(0)
+ audio.done()
diff --git a/demo/sgi/audio_stdwin/README b/demo/sgi/audio_stdwin/README
new file mode 100644
index 0000000..3074715
--- /dev/null
+++ b/demo/sgi/audio_stdwin/README
@@ -0,0 +1,16 @@
+Three programs that provide a user interface based upon STDWIN to the
+audio device of the SGI 4D/25. These scripts also demonstrate the power
+of a set of window interface classes implemented in Python that simplify
+the construction of all sorts of buttons, etc.
+
+jukebox Browses a directory full of sound samples and lets you
+ play selected ones. (Probably not fully functional, it
+ requires a conversion program.)
+
+rec A tape recorder that lets you record a sound sample,
+ play it back, and save it to a file. Various options to
+ set sampling rate, volume etc. When idle it doubles
+ as a VU meter.
+
+vumeter A VU meter that displays a history of the volume of
+ sound recently sampled from the microphone.
diff --git a/demo/sgi/audio_stdwin/jukebox.py b/demo/sgi/audio_stdwin/jukebox.py
new file mode 100755
index 0000000..5267d73
--- /dev/null
+++ b/demo/sgi/audio_stdwin/jukebox.py
@@ -0,0 +1,321 @@
+#! /ufs/guido/bin/sgi/python
+
+# JUKEBOX: browse directories full of sampled sound files.
+#
+# One or more "list windows" display the files and subdirectories of
+# the arguments. Double-clicking on a subdirectory opens a new window
+# displaying its contents (and so on recursively). Double clicking
+# on a file plays it as a sound file (assuming it is one).
+#
+# Playing is asynchronous: the application keeps listening to events
+# while the sample is playing, so you can change the volume (gain)
+# during playing, cancel playing or start a new sample right away.
+#
+# The control window displays the current output gain and a primitive
+# "stop button" to cancel the current play request.
+#
+# Sound files must currently be in Dik Winter's compressed Mac format.
+# Since decompression is costly, decompressed samples are saved in
+# /usr/tmp/@j* until the application is left. The files are read
+# afresh each time, though.
+
+import audio
+import sunaudio
+import commands
+import getopt
+import path
+import posix
+import rand
+import stdwin
+from stdwinevents import *
+import string
+import sys
+
+from WindowParent import WindowParent
+from HVSplit import VSplit
+from Buttons import PushButton
+from Sliders import ComplexSlider
+
+# Pathnames
+
+HOME_BIN_SGI = '/ufs/guido/bin/sgi/' # Directory where macsound2sgi lives
+DEF_DB = '/ufs/dik/sounds/Mac/HCOM' # Default directory of sounds
+
+
+# Global variables
+
+class struct(): pass # Class to define featureless structures
+
+G = struct() # Holds writable global variables
+
+
+# Main program
+
+def main():
+ G.synchronous = 0 # If set, use synchronous audio.write()
+ G.debug = 0 # If set, print debug messages
+ G.gain = 75 # Output gain
+ G.rate = 3 # Sampling rate
+ G.busy = 0 # Set while asynchronous playing is active
+ G.windows = [] # List of open windows (except control)
+ G.mode = 'mac' # Macintosh mode
+ G.tempprefix = '/usr/tmp/@j' + `rand.rand()` + '-'
+ #
+ optlist, args = getopt.getopt(sys.argv[1:], 'dg:r:sSa')
+ for optname, optarg in optlist:
+ if optname = '-d':
+ G.debug = 1
+ elif optname = '-g':
+ G.gain = string.atoi(optarg)
+ if not (0 < G.gain < 256):
+ raise optarg.error, '-g gain out of range'
+ elif optname = '-r':
+ G.rate = string.atoi(optarg)
+ if not (1 <= G.rate <= 3):
+ raise optarg.error, '-r rate out of range'
+ elif optname = '-s':
+ G.synchronous = 1
+ elif optname = '-S':
+ G.mode = 'sgi'
+ elif optname = '-a':
+ G.mode = 'sun'
+ #
+ if not args:
+ args = [DEF_DB]
+ #
+ G.cw = opencontrolwindow()
+ for dirname in args:
+ G.windows.append(openlistwindow(dirname))
+ #
+ #
+ savegain = audio.getoutgain()
+ try:
+ # Initialize stdaudio
+ audio.setoutgain(0)
+ audio.start_playing('')
+ dummy = audio.wait_playing()
+ audio.setoutgain(0)
+ maineventloop()
+ finally:
+ audio.setoutgain(savegain)
+ audio.done()
+ clearcache()
+
+def maineventloop():
+ mouse_events = WE_MOUSE_DOWN, WE_MOUSE_MOVE, WE_MOUSE_UP
+ while G.windows:
+ type, w, detail = event = stdwin.getevent()
+ if w = G.cw.win:
+ if type = WE_CLOSE:
+ return
+ G.cw.dispatch(event)
+ else:
+ if type = WE_DRAW:
+ w.drawproc(w, detail)
+ elif type in mouse_events:
+ w.mouse(w, type, detail)
+ elif type = WE_CLOSE:
+ w.close(w)
+ del w, event
+ else:
+ if G.debug: print type, w, detail
+
+# Control window -- to set gain and cancel play operations in progress
+
+def opencontrolwindow():
+ cw = WindowParent().create('Jukebox', (0, 0))
+ v = VSplit().create(cw)
+ #
+ gain = ComplexSlider().define(v)
+ gain.setminvalmax(0, G.gain, 255)
+ gain.settexts(' ', ' ')
+ gain.sethook(gain_setval_hook)
+ #
+ stop = PushButton().definetext(v, 'Stop')
+ stop.hook = stop_hook
+ #
+ cw.realize()
+ return cw
+
+def gain_setval_hook(self):
+ G.gain = self.val
+ if G.busy: audio.setoutgain(G.gain)
+
+def stop_hook(self):
+ if G.busy:
+ audio.setoutgain(0)
+ dummy = audio.stop_playing()
+ G.busy = 0
+
+
+# List windows -- to display list of files and subdirectories
+
+def openlistwindow(dirname):
+ list = posix.listdir(dirname)
+ list.sort()
+ i = 0
+ while i < len(list):
+ if list[i] = '.' or list[i] = '..':
+ del list[i]
+ else:
+ i = i+1
+ for i in range(len(list)):
+ name = list[i]
+ if path.isdir(path.cat(dirname, name)):
+ list[i] = list[i] + '/'
+ width = maxwidth(list)
+ width = width + stdwin.textwidth(' ') # XXX X11 stdwin bug workaround
+ height = len(list) * stdwin.lineheight()
+ stdwin.setdefwinsize(width, min(height, 500))
+ w = stdwin.open(dirname)
+ stdwin.setdefwinsize(0, 0)
+ w.setdocsize(width, height)
+ w.drawproc = drawlistwindow
+ w.mouse = mouselistwindow
+ w.close = closelistwindow
+ w.dirname = dirname
+ w.list = list
+ w.selected = -1
+ return w
+
+def maxwidth(list):
+ width = 1
+ for name in list:
+ w = stdwin.textwidth(name)
+ if w > width: width = w
+ return width
+
+def drawlistwindow(w, area):
+ d = w.begindrawing()
+ d.erase((0, 0), (1000, 10000))
+ lh = d.lineheight()
+ h, v = 0, 0
+ for name in w.list:
+ d.text((h, v), name)
+ v = v + lh
+ showselection(w, d)
+
+def hideselection(w, d):
+ if w.selected >= 0:
+ invertselection(w, d)
+
+def showselection(w, d):
+ if w.selected >= 0:
+ invertselection(w, d)
+
+def invertselection(w, d):
+ lh = d.lineheight()
+ h1, v1 = p1 = 0, w.selected*lh
+ h2, v2 = p2 = 1000, v1 + lh
+ d.invert(p1, p2)
+
+def mouselistwindow(w, type, detail):
+ (h, v), clicks, button = detail[:3]
+ d = w.begindrawing()
+ lh = d.lineheight()
+ if 0 <= v < lh*len(w.list):
+ i = v / lh
+ else:
+ i = -1
+ if w.selected <> i:
+ hideselection(w, d)
+ w.selected = i
+ showselection(w, d)
+ if type = WE_MOUSE_DOWN and clicks >= 2 and i >= 0:
+ name = path.cat(w.dirname, w.list[i])
+ if name[-1:] = '/':
+ if clicks = 2:
+ G.windows.append(openlistwindow(name[:-1]))
+ else:
+ playfile(name)
+
+def closelistwindow(w):
+ remove(G.windows, w)
+
+def remove(list, item):
+ for i in range(len(list)):
+ if list[i] = item:
+ del list[i]
+ break
+
+
+# Playing tools
+
+cache = {}
+
+def clearcache():
+ for x in cache.keys():
+ try:
+ sts = posix.system('rm -f ' + cache[x])
+ if sts:
+ print cmd
+ print 'Exit status', sts
+ except:
+ print cmd
+ print 'Exception?!'
+ del cache[x]
+
+def playfile(name):
+ if G.mode <> 'mac':
+ tempname = name
+ elif cache.has_key(name):
+ tempname = cache[name]
+ else:
+ tempname = G.tempprefix + `rand.rand()`
+ cmd = HOME_BIN_SGI + 'macsound2sgi'
+ cmd = cmd + ' ' + commands.mkarg(name)
+ cmd = cmd + ' >' + tempname
+ if G.debug: print cmd
+ sts = posix.system(cmd)
+ if sts:
+ print cmd
+ print 'Exit status', sts
+ stdwin.fleep()
+ return
+ cache[name] = tempname
+ fp = open(tempname, 'r')
+ try:
+ hdr = sunaudio.gethdr(fp)
+ except sunaudio.error, msg:
+ hdr = ()
+ if hdr:
+ data_size = hdr[0]
+ data = fp.read(data_size)
+ # XXX this doesn't work yet, need to convert from uLAW!!!
+ del fp
+ else:
+ del fp
+ data = readfile(tempname)
+ if G.debug: print len(data), 'bytes read from', tempname
+ if G.busy:
+ G.busy = 0
+ dummy = audio.stop_playing()
+ #
+ # Completely reset the audio device
+ audio.setrate(G.rate)
+ audio.setduration(0)
+ audio.setoutgain(G.gain)
+ #
+ if G.synchronous:
+ audio.write(data)
+ audio.setoutgain(0)
+ else:
+ try:
+ audio.start_playing(data)
+ G.busy = 1
+ except:
+ stdwin.fleep()
+ del data
+
+def readfile(filename):
+ return readfp(open(filename, 'r'))
+
+def readfp(fp):
+ data = ''
+ while 1:
+ buf = fp.read(102400) # Reads most samples in one fell swoop
+ if not buf:
+ return data
+ data = data + buf
+
+main()
diff --git a/demo/sgi/audio_stdwin/rec.py b/demo/sgi/audio_stdwin/rec.py
new file mode 100755
index 0000000..3ab3aea
--- /dev/null
+++ b/demo/sgi/audio_stdwin/rec.py
@@ -0,0 +1,271 @@
+#! /ufs/guido/bin/sgi/python
+
+import sys
+import audio
+import stdwin
+
+import string
+import getopt
+
+from stdwinevents import *
+from Buttons import *
+from Sliders import *
+#from Soundogram import Soundogram
+from VUMeter import VUMeter
+from WindowParent import WindowParent
+from HVSplit import HSplit, VSplit
+
+class TimeOutToggleButton() = ToggleButton():
+ def define(self, parent):
+ self = ToggleButton.define(self, parent)
+ self.parent.need_timer(self)
+ self.timer_hook = 0
+ return self
+ def timer(self):
+ if self.timer_hook:
+ self.timer_hook(self)
+
+K = 1024
+BUFSIZE = 30*8*K
+Rates = [0, 32*K, 16*K, 8*K]
+Magics = ['', '0032', '0016', '0008']
+
+class Struct(): pass
+G = Struct()
+
+def main():
+ #
+ # Set default state
+ #
+ G.gain = 60
+ G.rate = 3
+ G.nomuting = 0
+ G.savefile = '@rec'
+ #
+ # Set default values
+ #
+ G.data = ''
+ G.playing = 0
+ G.recording = 0
+ G.sogram = 0
+ #
+ # Parse options
+ #
+ optlist, args = getopt.getopt(sys.argv[1:], 'mdg:r:')
+ #
+ for optname, optarg in optlist:
+ if 0: # (So all cases start with elif)
+ pass
+ elif optname = '-d':
+ G.debug = 1
+ elif optname = '-g':
+ G.gain = string.atoi(optarg)
+ if not (0 < G.gain < 256):
+ raise optarg.error, '-g gain out of range'
+ elif optname = '-m':
+ G.nomuting = (not G.nomuting)
+ elif optname = '-r':
+ G.rate = string.atoi(optarg)
+ if not (1 <= G.rate <= 3):
+ raise optarg.error, '-r rate out of range'
+ #
+ if args:
+ G.savefile = args[0]
+ #
+ # Initialize the sound package
+ #
+ audio.setoutgain(G.nomuting * G.gain) # Silence the speaker
+ audio.setrate(G.rate)
+ #
+ # Create the WindowParent and VSplit
+ #
+ G.window = WindowParent().create('Recorder', (0, 0))
+ w = G.vsplit = VSplit().create(G.window)
+ #
+ # VU-meter
+ #
+ G.vubtn = VUMeter().define(w)
+ #
+ # Radiobuttons for rates
+ #
+ r1btn = RadioButton().definetext(w, '32 K/sec')
+ r1btn.on_hook = rate_hook
+ r1btn.rate = 1
+ #
+ r2btn = RadioButton().definetext(w, '16 K/sec')
+ r2btn.on_hook = rate_hook
+ r2btn.rate = 2
+ #
+ r3btn = RadioButton().definetext(w, '8 K/sec')
+ r3btn.on_hook = rate_hook
+ r3btn.rate = 3
+ #
+ radios = [r1btn, r2btn, r3btn]
+ r1btn.group = r2btn.group = r3btn.group = radios
+ for r in radios:
+ if r.rate = G.rate: r.select(1)
+ #
+ # Other controls
+ #
+ G.recbtn = TimeOutToggleButton().definetext(w, 'Record')
+ G.recbtn.on_hook = record_on_hook
+ G.recbtn.timer_hook = record_timer_hook
+ G.recbtn.off_hook = record_off_hook
+ #
+ G.mutebtn = CheckButton().definetext(w, 'Mute')
+ G.mutebtn.select(not G.nomuting)
+ G.mutebtn.hook = mute_hook
+ #
+ G.playbtn = TimeOutToggleButton().definetext(w, 'Playback')
+ G.playbtn.on_hook = play_on_hook
+ G.playbtn.timer_hook = play_timer_hook
+ G.playbtn.off_hook = play_off_hook
+ #
+ G.gainbtn = ComplexSlider().define(w)
+ G.gainbtn.settexts(' Volume: ', ' ')
+ G.gainbtn.setminvalmax(0, G.gain, 255)
+ G.gainbtn.sethook(gain_hook)
+ #
+ G.sizebtn = Label().definetext(w, `len(G.data)` + ' bytes')
+ #
+ #G.showbtn = PushButton().definetext(w, 'Sound-o-gram...')
+ #G.showbtn.hook = show_hook
+ #
+ G.savebtn = PushButton().definetext(w, 'Save...')
+ G.savebtn.hook = save_hook
+ #
+ G.quitbtn = PushButton().definetext(w, 'Quit')
+ G.quitbtn.hook = quit_hook
+ G.playbtn.enable(0)
+ G.savebtn.enable(0)
+ #G.showbtn.enable(0)
+ start_vu()
+ G.window.realize()
+ #
+ # Event loop
+ #
+ while 1:
+ e = stdwin.getevent()
+ G.window.dispatch(e)
+
+# XXX Disabled...
+def show_hook(self):
+ savetext = self.text
+ self.settext('Be patient...')
+ close_sogram()
+ stdwin.setdefwinsize(400, 300)
+ win = stdwin.open('Sound-o-gram')
+ G.sogram = Soundogram().define(win, G.data)
+ win.buttons = [G.sogram]
+ self.settext(savetext)
+
+def close_sogram():
+ if G.sogram:
+ # Break circular references
+ G.sogram.win.buttons[:] = []
+ del G.sogram.win
+ G.sogram = 0
+
+def mute_hook(self):
+ G.nomuting = (not self.selected)
+ audio.setoutgain(G.nomuting * G.gain)
+
+def rate_hook(self):
+ G.rate = self.rate
+ audio.setrate(G.rate)
+
+def record_on_hook(self):
+ stop_vu()
+ close_sogram()
+ audio.setrate(G.rate)
+ audio.setoutgain(G.nomuting * G.gain)
+ audio.start_recording(BUFSIZE)
+ G.recording = 1
+ G.playbtn.enable(0)
+ G.window.settimer(10 * BUFSIZE / Rates[G.rate])
+
+def record_timer_hook(self):
+ if G.recording:
+ if audio.poll_recording():
+ self.hilite(0)
+ record_off_hook(self)
+ else:
+ self.parent.settimer(5)
+
+def record_off_hook(self):
+ if not G.recording:
+ return
+ G.data = audio.stop_recording()
+ G.recording = 0
+ G.sizebtn.settext(`len(G.data)` + ' bytes')
+ audio.setoutgain(G.nomuting * G.gain)
+ G.playbtn.enable((len(G.data) > 0))
+ G.savebtn.enable((len(G.data) > 0))
+ #G.showbtn.enable((len(G.data) > 0))
+ G.window.settimer(0)
+ start_vu()
+
+def play_on_hook(self):
+ stop_vu()
+ audio.setrate(G.rate)
+ audio.setoutgain(G.gain)
+ audio.start_playing(G.data)
+ G.playing = 1
+ G.recbtn.enable(0)
+ G.window.settimer(max(10 * len(G.data) / Rates[G.rate], 1))
+
+def play_timer_hook(self):
+ if G.playing:
+ if audio.poll_playing():
+ self.hilite(0)
+ play_off_hook(self)
+ else:
+ self.parent.settimer(5)
+
+def play_off_hook(self):
+ if not G.playing:
+ return
+ x = audio.stop_playing()
+ G.playing = 0
+ audio.setoutgain(G.nomuting * G.gain)
+ G.recbtn.enable(1)
+ G.window.settimer(0)
+ start_vu()
+
+def gain_hook(self):
+ G.gain = self.val
+ if G.playing or G.nomuting: audio.setoutgain(G.gain)
+
+def save_hook(self):
+ if not G.data:
+ stdwin.fleep()
+ else:
+ prompt = 'Store sampled data on file: '
+ try:
+ G.savefile = stdwin.askfile(prompt, G.savefile, 1)
+ except KeyboardInterrupt:
+ return
+ try:
+ fp = open(G.savefile, 'w')
+ fp.write(Magics[G.rate] + G.data)
+ except:
+ stdwin.message('Cannot create ' + file)
+
+def stop_vu():
+ G.vubtn.stop()
+
+def start_vu():
+ G.vubtn.start()
+
+Exit = 'exit' # exception
+
+def quit_hook(self):
+ raise Exit, 0
+
+try:
+ try:
+ main()
+ finally:
+ audio.setoutgain(0)
+except Exit, sts:
+ sys.exit(sts)
diff --git a/demo/sgi/audio_stdwin/vumeter.py b/demo/sgi/audio_stdwin/vumeter.py
new file mode 100755
index 0000000..1685ba2
--- /dev/null
+++ b/demo/sgi/audio_stdwin/vumeter.py
@@ -0,0 +1,35 @@
+#! /ufs/guido/bin/sgi/python
+
+import audio
+import stdwin
+
+from VUMeter import VUMeter
+from WindowParent import WindowParent
+import MainLoop
+
+NBUFS=20
+BUFSIZE = NBUFS*48
+SCALE=128
+
+class MyVUMeter() = VUMeter():
+ def init_reactivity(self):
+ self.parent.need_mouse(self)
+ def mouse_down(self, detail):
+ if self.enabled:
+ self.stop()
+ else:
+ self.start()
+ def mouse_move(self, detail): pass
+ def mouse_up(self, detail): pass
+
+def main():
+ audio.setrate(3)
+ audio.setoutgain(0)
+ w = WindowParent().create('VU Meter', (200, 100))
+ v = MyVUMeter().define(w)
+ v.start()
+ w.realize()
+ while 1:
+ w.dispatch(stdwin.getevent())
+
+main()
diff --git a/demo/sgi/gl/README b/demo/sgi/gl/README
new file mode 100644
index 0000000..f191cf5
--- /dev/null
+++ b/demo/sgi/gl/README
@@ -0,0 +1,22 @@
+These demos run only on SGI machines and require the 'gl' built-in module.
+The demonstrate the abilities of SGI's GL library as well as the ease of
+GL programming in Python. Most demos require the Z-buffer (aka
+24-bitplane) option.
+
+backface Demonstrates the 'backface' GL function.
+
+kites Show 3 flying kites. Demonstrates the rendering speed
+ obtainable by Python programs.
+
+mclock A colorful clock with more options than you can
+ remember. Works on 8-bit machines (but allows more
+ colors on 24-bit machines).
+
+mixing Demonstrates the effect of color mixing: through
+ frequent color switching it gives the effect of white
+ light.
+
+nurbs A simple demonstration of the 'nurbs' GL functions.
+
+zrgb Displays a 3-D Gouraud-shaded figure which can be moved
+ around with the mouse.
diff --git a/demo/sgi/gl/backface.py b/demo/sgi/gl/backface.py
new file mode 100755
index 0000000..5936f75
--- /dev/null
+++ b/demo/sgi/gl/backface.py
@@ -0,0 +1,140 @@
+#! /ufs/guido/bin/sgi/python
+
+# backface
+#
+# draw a cube that can run with backface() turned on or off.
+# cube is moved when LEFTMOUSE is pressed and mouse itself is moved.
+
+from gl import *
+from DEVICE import *
+from GL import *
+
+CUBE_SIZE = 200.0
+CUBE_OBJ = 1
+
+def main () :
+ #
+ x = 0
+ y = 0
+ moveit = 0
+ #
+ initialize()
+ #
+ while (1) :
+ #
+ while (qtest()) :
+ dev, val = qread()
+ #
+ if dev = ESCKEY :
+ backface(0)
+ return
+ #
+ elif dev = REDRAW :
+ reshapeviewport()
+ drawcube(x,y)
+ #
+ elif dev = LEFTMOUSE :
+ #
+ # LEFTMOUSE down
+ moveit = val
+ #
+ elif dev = BKEY :
+ backface(1)
+ drawcube(x,y)
+ #
+ elif dev = FKEY :
+ backface(0)
+ drawcube(x,y)
+ #
+ if moveit :
+ x = getvaluator(MOUSEX)
+ y = getvaluator(MOUSEY)
+ drawcube(x,y)
+
+
+def initialize () :
+ foreground ()
+ keepaspect (1, 1)
+ gid = winopen('backface')
+ winset(gid)
+ winconstraints()
+ #
+ doublebuffer()
+ gconfig()
+ shademodel(FLAT)
+ #
+ ortho(-1024.0, 1024.0, -1024.0, 1024.0, -1024.0, 1024.0)
+ #
+ qdevice(ESCKEY)
+ qdevice(REDRAW)
+ qdevice(LEFTMOUSE)
+ qdevice(BKEY)
+ qdevice(FKEY)
+ qenter(REDRAW,gid)
+ #
+ backface(1)
+
+#
+# define a cube
+def cube () :
+ #
+ # front face
+ pushmatrix()
+ translate(0.0,0.0,CUBE_SIZE)
+ color(RED)
+ rectf(-CUBE_SIZE,-CUBE_SIZE,CUBE_SIZE,CUBE_SIZE)
+ popmatrix()
+ #
+ # right face
+ pushmatrix()
+ translate(CUBE_SIZE, 0.0, 0.0)
+ rotate(900, 'y')
+ color(GREEN)
+ rectf(-CUBE_SIZE,-CUBE_SIZE,CUBE_SIZE,CUBE_SIZE)
+ popmatrix()
+ #
+ # back face
+ pushmatrix()
+ translate(0.0, 0.0, -CUBE_SIZE)
+ rotate(1800, 'y')
+ color(BLUE)
+ rectf(-CUBE_SIZE,-CUBE_SIZE,CUBE_SIZE,CUBE_SIZE)
+ popmatrix()
+ #
+ # left face
+ pushmatrix()
+ translate(-CUBE_SIZE, 0.0, 0.0)
+ rotate(-900, 'y')
+ color(CYAN)
+ rectf(-CUBE_SIZE,-CUBE_SIZE,CUBE_SIZE,CUBE_SIZE)
+ popmatrix()
+ #
+ # top face
+ pushmatrix()
+ translate(0.0, CUBE_SIZE, 0.0)
+ rotate(-900, 'x')
+ color(MAGENTA)
+ rectf(-CUBE_SIZE,-CUBE_SIZE,CUBE_SIZE,CUBE_SIZE)
+ popmatrix()
+ #
+ # bottom face
+ pushmatrix()
+ translate(0.0, -CUBE_SIZE, 0.0)
+ rotate(900, 'x')
+ color(YELLOW)
+ rectf(-CUBE_SIZE,-CUBE_SIZE,CUBE_SIZE,CUBE_SIZE)
+ popmatrix()
+
+def drawcube(x,y) :
+ #
+ pushmatrix()
+ rotate(2*x, 'x')
+ rotate(2*y, 'y')
+ color(BLACK)
+ clear()
+ cube()
+ popmatrix()
+ swapbuffers()
+
+
+main ()
diff --git a/demo/sgi/gl/kites.py b/demo/sgi/gl/kites.py
new file mode 100755
index 0000000..764ad2c
--- /dev/null
+++ b/demo/sgi/gl/kites.py
@@ -0,0 +1,194 @@
+#! /ufs/guido/bin/sgi/python
+
+# *** This only works correctly on a 24 bit-plane machine. ***
+#
+# A simple Python program that tests the some parts of the
+# GL library. It shows the speed that can be obtained when
+# doing simple graphics.
+#
+# The bottleneck in this program is NOT Python but the graphics
+# engine; i.e Python can feed the graphics pipeline fast enough
+# on the 4D/25G.
+#
+# This program show 3 kites flying around the screen. It uses
+#
+# * bgnpolygon, endpolygon
+# * v3, n3
+# * lmdef, lmbind
+#
+# Usage :
+#
+# ESC -> exit program
+# MOUSE3 -> freeze toggle
+# MOUSE2 -> one step (use this in freeze state)
+
+from GL import *
+from gl import *
+import DEVICE
+from math import *
+
+#
+# viewobj : sets the rotation, translation and scaling
+# set appropiate material, call drawobject()
+#
+def viewobj (r, s, t, mat) :
+ pushmatrix()
+ rot (r * 10.0, 'X')
+ rot (r * 10.0, 'Y')
+ rot (r * 10.0, 'Z')
+ scale (s[0], s[1], s[2])
+ translate (t[0], t[1], t[2])
+ lmbind(MATERIAL, mat)
+ drawobject()
+ popmatrix()
+
+#
+# makeobj : the contructor of the object
+#
+def mkobj () :
+ v0 = (-5.0 ,0.0, 0.0)
+ v1 = (0.0 ,5.0, 0.0)
+ v2 = (5.0 ,0.0, 0.0)
+ v3 = (0.0 ,2.0, 0.0)
+ n0 = (sqrt(2.0)/2.0, sqrt(2.0)/2.0, 0.0)
+ vn = ((v0, n0), (v1, n0), (v2, n0), (v3, n0))
+ #
+ return vn
+
+#
+# the object itself as an array of vertices and normals
+#
+kite = mkobj ()
+
+#
+# drawobject : draw a triangle. with bgnpolygon
+#
+def drawobject () :
+ #
+ bgnpolygon()
+ vnarray (kite)
+ endpolygon()
+
+#
+# identity matrix
+#
+idmat=[1.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,1.0]
+
+#
+# the rgb-value of light-blue
+#
+LightBlue = (43,169,255)
+
+#
+# the different materials.
+#
+m1=[SPECULAR,0.0,0.0,0.6,DIFFUSE,0.0,0.0,0.8,SHININESS,20.0,LMNULL]
+m2=[SPECULAR,0.8,0.0,0.1,DIFFUSE,0.8,0.0,0.3,SHININESS,120.0,LMNULL]
+m3=[SPECULAR,0.0,1.0,0.0,DIFFUSE,0.0,0.6,0.0,SHININESS,120.0,LMNULL]
+
+#
+# lightsources
+#
+light1 = [LCOLOR,1.0,1.0,1.0,POSITION,15.0,15.0,0.0,1.0,LMNULL]
+light2 = [LCOLOR,1.0,1.0,1.0,POSITION,-15.0,15.0,0.0,1.0,LMNULL]
+
+#
+# the lightmodel
+#
+model = [AMBIENT,0.2,0.2,0.2,LMNULL]
+
+#
+# initgl : opens the window, configures the pipeline to 2buf and zbuf,
+# sets the viewing, defines and binds the materials
+#
+def initgl () :
+ #
+ # open window
+ #
+ foreground ()
+ keepaspect (1, 1)
+ prefposition (100, 500, 100, 500)
+ w = winopen ('PYTHON lights')
+ keepaspect (1, 1)
+ winconstraints()
+ #
+ # configure pipeline (zbuf, 2buf, GOURAUD and RGBmode)
+ #
+ zbuffer (1)
+ doublebuffer ()
+ shademodel (GOURAUD)
+ RGBmode ()
+ gconfig ()
+ #
+ # define and bind materials (set perspective BEFORE loadmat !)
+ #
+ mmode(MVIEWING)
+ perspective (900, 1.0, 1.0, 20.0)
+ loadmatrix(idmat)
+ lmdef(DEFMATERIAL, 1, m1)
+ lmdef(DEFMATERIAL, 2, m2)
+ lmdef(DEFMATERIAL, 3, m3)
+ lmdef(DEFLIGHT, 1, light1)
+ lmdef(DEFLIGHT, 2, light2)
+ lmdef(DEFLMODEL, 1, model)
+ lmbind(LIGHT0,1)
+ lmbind(LIGHT1,2)
+ lmbind(LMODEL,1)
+ #
+ # set viewing
+ #
+ lookat (0.0, 0.0, 10.0, 0.0, 0.0, 0.0, 0)
+ #
+ # ask for the REDRAW and ESCKEY events
+ #
+ qdevice(DEVICE.MOUSE3)
+ qdevice(DEVICE.MOUSE2)
+ qdevice(DEVICE.REDRAW)
+ qdevice(DEVICE.ESCKEY)
+
+#
+# GoForIT : use 2buf to redraw the object 2n times. index i is used as
+# the (smoothly changing) rotation angle
+#
+def GoForIt(i) :
+ freeze = 1
+ while 1 :
+ if freeze <> 0 :
+ i = i + 1
+ #
+ # clear z-buffer and clear background to light-blue
+ #
+ zclear()
+ c3i (LightBlue)
+ clear()
+ #
+ # draw the 3 traiangles scaled above each other.
+ #
+ viewobj(float(i),[1.0,1.0,1.0],[1.0,1.0,1.0],1)
+ viewobj(float(i),[0.75,0.75,0.75],[0.0,2.0,2.0],2)
+ viewobj(float(i),[0.5,0.5,0.5],[0.0,4.0,4.0],3)
+ #
+ swapbuffers()
+ #
+ if qtest() <> 0 :
+ dev, val = qread()
+ if dev = DEVICE.ESCKEY :
+ break
+ elif dev = DEVICE.REDRAW :
+ reshapeviewport ()
+ elif dev = DEVICE.MOUSE3 and val <> 0 :
+ freeze = 1 - freeze
+ elif dev = DEVICE.MOUSE2 and val <> 0 :
+ i = i + 1
+
+
+# the main program
+#
+def main () :
+ initgl ()
+ GoForIt (0)
+
+#
+# exec main
+#
+main ()
diff --git a/demo/sgi/gl/mclock.doc b/demo/sgi/gl/mclock.doc
new file mode 100644
index 0000000..610e9ab
--- /dev/null
+++ b/demo/sgi/gl/mclock.doc
@@ -0,0 +1,60 @@
+Newsgroups: cwi.sgi
+Subject: Re: new clock
+Distribution: cwi.sgi
+References: <[email protected]>
+
+Last week I wrote:
+
+>For your enjoyment I have implemented a colorful clock.
+
+The clock has now been extended with some new facilities: a menu, an
+alarm and a gong. These may require some explanation beyond what's in
+the usage message.
+
+Menu
+----
+The right mouse button now pops up a menu that allows you to turn the
+seconds hand on or off and to switch the alarm off.
+
+Alarm
+-----
+
+The left and middle buttons set the alarm. When it is on, the alarm
+time is displayed as a time on a 24 hour clock in the bottom left
+corner. It is also indicated by two red triangles, corresponding to the
+little (hours) and big (minutes) hand. These hands can be moved around:
+the left mouse button moves the minutes hand, the middle button moves
+the hourds hand. Watch out for differences of twelve hours (always
+check the digital display); these can be corrected by dragging the hours
+hand once around the dial.
+
+When the alarm goes off, two things happen: a shell command specified on
+the command line with the -a option is executed (in the background), and
+the clock's colors change every two seconds, for five minutes. You can
+also turn the alarm off by using the menu accessible through the right
+mouse button.
+
+There is no default command for the -a option; if it is not specified,
+only the changing of the colors happens. If you have an 8 ohm speaker
+connected to the audio output of your Personal Iris, a suitable command
+would be:
+
+ mclock -a '/ufs/guido/bin/sgi/play /ufs/guido/lib/sounds/alarm'
+
+Gong
+----
+
+Some people like a clock that makes noises every hour, or even more
+often. This is supported by the -g and -G options. With -g you specify
+a shell command to be executed to sound the gong; with -G you can
+specify the interval between gong calls, in seconds (default is one hour).
+The shell command is executed in the background. It is given two
+arguments: the hours (on a 24 hour clock!) and the minutes. The
+executable Python script /ufs/guido/bin/sgi/chime is a suitable example.
+Again, this only works if you have installed a speaker (I bet 8 ohm
+speakers are going to be in demand!)
+
+--
+Guido van Rossum, Centre for Mathematics and Computer Science (CWI), Amsterdam
[email protected] or ..!hp4nl!cwi.nl!guido or guido%[email protected]
+"A thing of beauty is a joy till sunrise"
diff --git a/demo/sgi/gl/mclock.py b/demo/sgi/gl/mclock.py
new file mode 100755
index 0000000..806511c
--- /dev/null
+++ b/demo/sgi/gl/mclock.py
@@ -0,0 +1,729 @@
+#! /ufs/guido/bin/sgi/python
+
+#############################################################################
+# NOTA BENE: Before installing, fix TZDIFF to reflect your local time zone! #
+#############################################################################
+
+# "M Clock"
+#
+# An implementation in software of an original design by Rob Juda.
+# Clock implementation: Guido van Rossum.
+# Alarm and Gong features: Sape Mullender.
+#
+# XXX TO DO:
+# find out local time zone difference automatically
+# add a date indicator
+# allow multiple alarms
+# allow the menu to change more parameters
+
+import sys
+
+from gl import *
+from GL import *
+from DEVICE import *
+import time
+import getopt
+import string
+import path
+from math import pi
+import math
+import posix
+
+FULLC = 3600 # Full circle in 1/10-ths of a degree
+MIDN = 900 # Angle of the 12 o'clock position
+R, G, B = 0, 1, 2 # Indices of colors in RGB list
+
+HOUR = 3600 # Number of seconds per hour
+MINUTE = 60 # Number of seconds per minute
+
+class struct(): pass # Class to define featureless structures
+Gl = struct() # Object to hold writable global variables
+
+# Default constants (used in multiple places)
+
+SCREENBG = 127, 156, 191
+NPARTS = 9
+TITLE = 'M Clock'
+TZDIFF = -1*HOUR # <--- change this to reflect your local time zone
+
+# Default parameters
+
+Gl.foreground = 0 # If set, run in the foreground
+Gl.fullscreen = 0 # If set, run on full screen
+Gl.tzdiff = TZDIFF # Seconds west of Greenwich (winter time)
+Gl.nparts = NPARTS # Number of parts each circle is divided in (>= 2)
+Gl.debug = 0 # If set, print debug output
+Gl.doublebuffer = 1 # If set, use double buffering
+Gl.update = 0 # Update interval; seconds hand is suppressed if > 1
+Gl.colorsubset = 0 # If set, display only a subset of the colors
+Gl.cyan = 0 # If set, display cyan overlay (big hand)
+Gl.magenta = 0 # If set, display magenta overlay (little hand)
+Gl.yellow = 0 # If set, display yellow overlay (fixed background)
+Gl.black = 0 # If set, display black overlay (hands)
+Gl.colormap = 0 # If set, use colormap mode instead of RGB mode
+Gl.warnings = 0 # If set, print warnings
+Gl.title = '- - ' # Window title (default set later)
+Gl.border = 1 # If set, use a window border (and title)
+Gl.bg = 0, 0, 0 # Background color R, G, B value
+Gl.iconic = 0 # Set in iconic state
+Gl.fg = 255, 0, 0 # Alarm background RGB (either normal or alarm)
+Gl.ox,Gl.oy = 0,0 # Window origin
+Gl.cx,Gl.cy = 0,0 # Window size
+Gl.alarm_set = 0 # Alarm on or off
+Gl.alarm_on = 0 # Alarm is ringing
+Gl.alarm_time = 0 # Alarm time in seconds after midnight
+Gl.alarm_hours = 0 # Alarm hour setting, 24 hour clock
+Gl.alarm_minutes = 0 # Alarm minutes setting
+Gl.alarm_rgb = 0,0,0 # Alarm display RGB colors
+Gl.alarm_cmd = '' # Command to execute when alarm goes off
+Gl.mouse2down = 0 # Mouse button state
+Gl.mouse3down = 0 # Mouse button state
+Gl.gong_cmd = '' # Command to execute when chimes go off
+Gl.gong_int = 3600 # Gong interval
+Gl.indices = R, G, B # Colors (permuted when alarm is on)
+
+def main():
+ #
+ sys.stdout = sys.stderr # All output is errors/warnings etc.
+ #
+ try:
+ args = getoptions()
+ except string.atoi_error, value:
+ usage(string.atoi_error, value)
+ except getopt.error, msg:
+ usage(getopt.error, msg)
+ #
+ if args:
+ realtime = 0
+ hours = string.atoi(args[0])
+ minutes = seconds = 0
+ if args[1:]: minutes = string.atoi(args[1])
+ if args[2:]: seconds = string.atoi(args[2])
+ localtime = ((hours*60)+minutes)*60+seconds
+ else:
+ realtime = 1
+ #
+ if Gl.title = '- - ':
+ if realtime:
+ Gl.title = TITLE
+ else:
+ title = ''
+ for arg in args: title = title + ' ' + arg
+ Gl.title = title[1:]
+ del title
+ #
+ wid = makewindow()
+ Gl.ox,Gl.oy = getorigin()
+ Gl.cx,Gl.cy = getsize()
+ initmenu()
+ clearall()
+ #
+ if not Gl.update:
+ Gl.update = 60
+ #
+ if Gl.update <= 1:
+ Gl.timernoise = 6
+ else:
+ Gl.timernoise = 60
+ noise(TIMER0, Gl.timernoise)
+ #
+ qdevice(WINSHUT)
+ qdevice(WINQUIT)
+ qdevice(ESCKEY)
+ if realtime:
+ qdevice(TIMER0)
+ qdevice(REDRAW)
+ qdevice(WINFREEZE)
+ qdevice(WINTHAW)
+ qdevice(MENUBUTTON) # MOUSE1
+ qdevice(MOUSE3) # Left button
+ qdevice(MOUSE2) # Middle button
+ unqdevice(INPUTCHANGE)
+ #
+ lasttime = 0
+ Gl.change = 1
+ while 1:
+ if realtime:
+ localtime = time.time() - Gl.tzdiff
+ if Gl.alarm_set:
+ if localtime%(24*HOUR) = Gl.alarm_time:
+ # Ring the alarm!
+ if Gl.debug:
+ print 'Rrrringg!'
+ Gl.alarm_on = 1
+ if Gl.alarm_cmd <> '':
+ d = posix.system(Gl.alarm_cmd+' '+`Gl.alarm_time/3600`+' '+`(Gl.alarm_time/60)%60` + ' &')
+ Gl.change = 1
+ clearall()
+ if Gl.alarm_on:
+ if (localtime - Gl.alarm_time) % (24*HOUR) > 300:
+ # More than 5 minutes away from alarm
+ Gl.alarm_on = 0
+ if Gl.debug:
+ print 'Alarm turned off'
+ Gl.change = 1
+ clearall()
+ Gl.indices = R, G, B
+ else:
+ if localtime % 2 = 0:
+ # Permute color indices
+ Gl.indices = Gl.indices[2:] + Gl.indices[:2]
+ Gl.change = 1
+ if Gl.gong_cmd <> '' and localtime%Gl.gong_int = 0:
+ d = posix.system(Gl.gong_cmd+' '+`(localtime/3600)%24`+' '+`(localtime/60)%60` + ' &')
+ if localtime/Gl.update <> lasttime/Gl.update:
+ if Gl.debug: print 'new time'
+ Gl.change = 1
+ if Gl.change:
+ if Gl.debug: print 'drawing'
+ doit(localtime)
+ lasttime = localtime
+ Gl.change = 0
+ dev, data = qread()
+ if Gl.debug and dev <> TIMER0:
+ print dev, data
+ if dev = TIMER0:
+ if Gl.debug > 1:
+ print dev, data
+ elif dev = MOUSE3:
+ mousex = getvaluator(MOUSEX)
+ mousey = getvaluator(MOUSEY)
+ if mouseclick(3, data, mousex, mousey):
+ Gl.change = 1
+ elif dev = MOUSE2:
+ mousex = getvaluator(MOUSEX)
+ mousey = getvaluator(MOUSEY)
+ if mouseclick(2, data, mousex, mousey):
+ Gl.change = 1
+ elif dev = MOUSEX:
+ mousex = data
+ if Gl.mouse2down:
+ mouse2track(mousex, mousey)
+ if Gl.mouse3down:
+ mouse3track(mousex, mousey)
+ elif dev = MOUSEY:
+ mousey = data
+ if Gl.mouse2down:
+ mouse2track(mousex, mousey)
+ if Gl.mouse3down:
+ mouse3track(mousex, mousey)
+ elif dev = REDRAW or dev = REDRAWICONIC:
+ if Gl.debug:
+ if dev = REDRAW: print 'REDRAW'
+ else: print 'REDRAWICONIC'
+ reshapeviewport()
+ Gl.ox,Gl.oy = getorigin()
+ Gl.cx,Gl.cy = getsize()
+ Gl.change = 1
+ clearall()
+ elif dev = MENUBUTTON:
+ if Gl.debug: print 'MENUBUTTON'
+ handlemenu()
+ elif dev = WINFREEZE:
+ if Gl.debug: print 'WINFREEZE'
+ Gl.iconic = 1
+ noise(TIMER0, 60*60) # Redraw every 60 seconds only
+ elif dev = WINTHAW:
+ if Gl.debug: print 'WINTHAW'
+ Gl.iconic = 0
+ noise(TIMER0, Gl.timernoise)
+ Gl.change = 1
+ elif dev = ESCKEY or dev = WINSHUT or dev = WINQUIT:
+ if Gl.debug: print 'Exit'
+ sys.exit(0)
+
+def getoptions():
+ optlist, args = getopt.getopt(sys.argv[1:], 'A:a:B:bc:dFfG:g:n:sT:t:u:wCMYK')
+ for optname, optarg in optlist:
+ if optname = '-A':
+ Gl.fg = eval(optarg) # Should be (r,g,b)
+ elif optname = '-a':
+ Gl.alarm_cmd = optarg
+ elif optname = '-B':
+ Gl.bg = eval(optarg) # Should be (r,g,b)
+ elif optname = '-b':
+ Gl.border = 0
+ elif optname = '-c':
+ Gl.colormap = string.atoi(optarg)
+ elif optname = '-d':
+ Gl.debug = Gl.debug + 1
+ Gl.warnings = 1
+ elif optname = '-F':
+ Gl.foreground = 1
+ elif optname = '-f':
+ Gl.fullscreen = 1
+ elif optname = '-G':
+ Gl.gong_int = 60*string.atoi(optarg)
+ elif optname = '-g':
+ Gl.gong_cmd = optarg
+ elif optname = '-n':
+ Gl.nparts = string.atoi(optarg)
+ elif optname = '-s':
+ Gl.doublebuffer = 0
+ elif optname = '-T':
+ Gl.title = optarg
+ elif optname = '-t':
+ Gl.tzdiff = string.atoi(optarg)
+ elif optname = '-u':
+ Gl.update = string.atoi(optarg)
+ elif optname = '-w':
+ Gl.warnings = 1
+ elif optname = '-C':
+ Gl.cyan = Gl.colorsubset = 1
+ elif optname = '-M':
+ Gl.magenta = Gl.colorsubset = 1
+ elif optname = '-Y':
+ Gl.yellow = Gl.colorsubset = 1
+ elif optname = '-K':
+ Gl.black = Gl.colorsubset = 1
+ else:
+ print 'Unsupported option', optname
+ return args
+
+def usage(exc, msg):
+ if sys.argv:
+ progname = path.basename(sys.argv[0])
+ else:
+ progname = 'mclock'
+ #
+ print progname + ':',
+ if exc = string.atoi_error:
+ print 'non-numeric argument:',
+ print msg
+ #
+ print 'usage:', progname, '[options] [hh [mm [ss]]]'
+ #
+ print '-A r,g,b : alarm background red,green,blue [255,0,0]'
+ print '-a cmd : shell command executed when alarm goes off'
+ print '-B r,g,b : background red,green,blue [0,0,0]'
+ print ' (-B SCREENBG uses the default screen background)'
+ print '-b : suppress window border and title'
+ print '-c cmapid : select explicit colormap'
+ print '-d : more debug output (implies -F, -w)'
+ print '-F : run in foreground'
+ print '-f : use full screen'
+ print '-G intrvl : interval between chimes in minutes [60]'
+ print '-g cmd : shell command executed when chimes go off'
+ print '-s : single buffer mode'
+ print '-w : print various warnings'
+ print '-n nparts : number of parts [' + `NPARTS` + ']'
+ print '-T title : alternate window title [\'' + TITLE + '\']'
+ print '-t tzdiff : time zone difference [' + `TZDIFF` + ']'
+ print '-u update : update interval [60]'
+ print '-CMYK : Cyan, Magenta, Yellow or blacK overlay only'
+ print 'if hh [mm [ss]] is specified, display that time statically'
+ print 'on machines with < 12 bitplanes, -c and -s are forced on'
+ #
+ sys.exit(2)
+
+def doit(localtime):
+ hands = makehands(localtime)
+ list = makelist(hands)
+ render(list, hands)
+
+def makehands(localtime):
+ localtime = localtime % (12*HOUR)
+ seconds_hand = MIDN + FULLC - (localtime*60) % FULLC
+ big_hand = (MIDN + FULLC - (localtime%HOUR)) % FULLC
+ little_hand = (MIDN + FULLC - ((localtime/12) % HOUR)) % FULLC
+ return little_hand, big_hand, seconds_hand
+
+def makelist(little_hand, big_hand, seconds_hand):
+ total = []
+ if Gl.cyan or not Gl.colorsubset:
+ total = total + makesublist(big_hand, Gl.indices[0])
+ if Gl.magenta or not Gl.colorsubset:
+ total = total + makesublist(little_hand, Gl.indices[1])
+ if Gl.yellow or not Gl.colorsubset:
+ total = total + makesublist(MIDN, Gl.indices[2])
+ total.sort()
+ return total
+
+def makesublist(first, icolor):
+ list = []
+ alpha = FULLC/Gl.nparts
+ a = first - alpha/2
+ for i in range(Gl.nparts):
+ angle = (a + i*alpha + FULLC) % FULLC
+ value = 255*(Gl.nparts-1-i)/(Gl.nparts-1)
+ list.append(angle, icolor, value)
+ list.sort()
+ a, icolor, value = list[0]
+ if a <> 0:
+ a, icolor, value = list[len(list)-1]
+ t = 0, icolor, value
+ list.insert(0, t)
+ return list
+
+def rgb_fg():
+ return Gl.fg
+ # Obsolete code:
+ if Gl.alarm_on:
+ return Gl.bg
+ else:
+ return Gl.fg
+
+def rgb_bg():
+ return Gl.bg
+ # Obsolete code:
+ if Gl.alarm_on:
+ return Gl.fg
+ else:
+ return Gl.bg
+
+def clearall():
+ Gl.c3i(rgb_bg())
+ clear()
+ if Gl.doublebuffer:
+ swapbuffers()
+ clear()
+
+def draw_alarm(color):
+ frontbuffer(TRUE)
+ Gl.c3i(color)
+ pushmatrix()
+ rotate(-((Gl.alarm_time/12)%3600), 'z')
+ bgnpolygon()
+ v2f( 0.00,1.00)
+ v2f( 0.04,1.05)
+ v2f(-0.04,1.05)
+ endpolygon()
+ popmatrix()
+ #
+ pushmatrix()
+ rotate(-((Gl.alarm_time)%3600), 'z')
+ bgnpolygon()
+ v2f( 0.00,1.05)
+ v2f( 0.07,1.10)
+ v2f(-0.07,1.10)
+ endpolygon()
+ popmatrix()
+ #
+ cmov2(-1.06, -1.06)
+ charstr(string.rjust(`Gl.alarm_time/3600`,2))
+ charstr(':')
+ charstr(string.zfill((Gl.alarm_time/60)%60,2))
+ frontbuffer(FALSE)
+
+def render(list, (little_hand, big_hand, seconds_hand)):
+ #
+ if Gl.colormap:
+ resetindex()
+ #
+ if not list:
+ Gl.c3i(255, 255, 255) # White
+ circf(0.0, 0.0, 1.0)
+ else:
+ list.append(3600, 0, 255) # Sentinel
+ #
+ rgb = [255, 255, 255]
+ a_prev = 0
+ for a, icolor, value in list:
+ if a <> a_prev:
+ [r, g, b] = rgb
+ if Gl.debug > 1:
+ print rgb, a_prev, a
+ Gl.c3i(r, g, b)
+ arcf(0.0, 0.0, 1.0, a_prev, a)
+ rgb[icolor] = value
+ a_prev = a
+ #
+ if Gl.black or not Gl.colorsubset:
+ #
+ # Draw the hands -- in black
+ #
+ Gl.c3i(0, 0, 0)
+ #
+ if Gl.update = 1 and not Gl.iconic:
+ # Seconds hand is only drawn if we update every second
+ pushmatrix()
+ rotate(seconds_hand, 'z')
+ bgnline()
+ v2f(0.0, 0.0)
+ v2f(1.0, 0.0)
+ endline()
+ popmatrix()
+ #
+ pushmatrix()
+ rotate(big_hand, 'z')
+ rectf(0.0, -0.01, 0.97, 0.01)
+ circf(0.0, 0.0, 0.01)
+ circf(0.97, 0.0, 0.01)
+ popmatrix()
+ #
+ pushmatrix()
+ rotate(little_hand, 'z')
+ rectf(0.04, -0.02, 0.63, 0.02)
+ circf(0.04, 0.0, 0.02)
+ circf(0.63, 0.0, 0.02)
+ popmatrix()
+ #
+ # Draw the alarm time, if set or being set
+ #
+ if Gl.alarm_set:
+ draw_alarm(rgb_fg())
+ #
+ if Gl.doublebuffer: swapbuffers()
+
+def makewindow():
+ #
+ if Gl.debug or Gl.foreground:
+ foreground()
+ #
+ if Gl.fullscreen:
+ # XXX Should find out true screen size using getgdesc()
+ prefposition(0, 1279, 0, 1023)
+ else:
+ keepaspect(1, 1)
+ minsize(64, 64)
+ #
+ if not Gl.border:
+ noborder()
+ wid = winopen(Gl.title)
+ #
+ if not Gl.fullscreen:
+ keepaspect(1, 1)
+ minsize(10, 10)
+ maxsize(2000, 2000)
+ iconsize(66, 66)
+ winconstraints()
+ #
+ nplanes = getplanes()
+ nmaps = getgdesc(GD_NMMAPS)
+ if Gl.warnings:
+ print nplanes, 'color planes,', nmaps, 'color maps'
+ #
+ if nplanes < 12 or Gl.colormap:
+ if not Gl.colormap:
+ Gl.colormap = nmaps - 1
+ if Gl.warnings:
+ print 'not enough color planes available',
+ print 'for RGB mode; forcing colormap mode'
+ print 'using color map number', Gl.colormap
+ if not Gl.colorsubset:
+ needed = 3
+ else:
+ needed = Gl.cyan + Gl.magenta + Gl.yellow
+ needed = needed*Gl.nparts
+ if Gl.bg <> (0, 0, 0):
+ needed = needed+1
+ if Gl.fg <> (0, 0, 0):
+ needed = needed+1
+ if Gl.doublebuffer:
+ if needed > available(nplanes/2):
+ Gl.doublebuffer = 0
+ if Gl.warnings:
+ print 'not enough colors available',
+ print 'for double buffer mode;',
+ print 'forcing single buffer mode'
+ else:
+ nplanes = nplanes/2
+ if needed > available(nplanes):
+ # Do this warning always
+ print 'still not enough colors available;',
+ print 'parts will be left white'
+ print '(needed', needed, 'but have only',
+ print available(nplanes), 'colors available)'
+ #
+ if Gl.doublebuffer:
+ doublebuffer()
+ gconfig()
+ #
+ if Gl.colormap:
+ Gl.c3i = pseudo_c3i
+ fixcolormap()
+ else:
+ Gl.c3i = c3i
+ RGBmode()
+ gconfig()
+ #
+ if Gl.fullscreen:
+ # XXX Should find out true screen size using getgdesc()
+ ortho2(-1.1*1.280, 1.1*1.280, -1.1*1.024, 1.1*1.024)
+ else:
+ ortho2(-1.1, 1.1, -1.1, 1.1)
+ #
+ return wid
+
+def available(nplanes):
+ return pow(2, nplanes) - 1 # Reserve one pixel for black
+
+def fixcolormap():
+ multimap()
+ gconfig()
+ nplanes = getplanes()
+ if Gl.warnings:
+ print 'multimap mode has', nplanes, 'color planes'
+ imap = Gl.colormap
+ Gl.startindex = pow(2, nplanes) - 1
+ Gl.stopindex = 1
+ setmap(imap)
+ mapcolor(0, 0, 0, 0) # Fixed entry for black
+ if Gl.bg <> (0, 0, 0):
+ r, g, b = Gl.bg
+ mapcolor(1, r, g, b) # Fixed entry for Gl.bg
+ Gl.stopindex = 2
+ if Gl.fg <> (0, 0, 0):
+ r, g, b = Gl.fg
+ mapcolor(2, r, g, b) # Fixed entry for Gl.fg
+ Gl.stopindex = 3
+ Gl.overflow_seen = 0
+ resetindex()
+
+def resetindex():
+ Gl.index = Gl.startindex
+
+r0g0b0 = (0, 0, 0)
+
+def pseudo_c3i(rgb):
+ if rgb = r0g0b0:
+ index = 0
+ elif rgb = Gl.bg:
+ index = 1
+ elif rgb = Gl.fg:
+ index = 2
+ else:
+ index = definecolor(rgb)
+ color(index)
+
+def definecolor(rgb):
+ index = Gl.index
+ if index < Gl.stopindex:
+ if Gl.debug: print 'definecolor hard case', rgb
+ # First see if we already have this one...
+ for index in range(Gl.stopindex, Gl.startindex+1):
+ if rgb = getmcolor(index):
+ if Gl.debug: print 'return', index
+ return index
+ # Don't clobber reserverd colormap entries
+ if not Gl.overflow_seen:
+ # Shouldn't happen any more, hence no Gl.warnings test
+ print 'mclock: out of colormap entries'
+ Gl.overflow_seen = 1
+ return Gl.stopindex
+ r, g, b = rgb
+ if Gl.debug > 1: print 'mapcolor', (index, r, g, b)
+ mapcolor(index, r, g, b)
+ Gl.index = index - 1
+ return index
+
+# Compute n**i
+def pow(n, i):
+ x = 1
+ for j in range(i): x = x*n
+ return x
+
+def mouseclick(mouse, updown, x, y):
+ if updown = 1:
+ # mouse button came down, start tracking
+ if Gl.debug:
+ print 'mouse', mouse, 'down at', x, y
+ if mouse = 2:
+ Gl.mouse2down = 1
+ mouse2track(x, y)
+ elif mouse = 3:
+ Gl.mouse3down = 1
+ mouse3track(x, y)
+ else:
+ print 'fatal error'
+ qdevice(MOUSEX)
+ qdevice(MOUSEY)
+ return 0
+ else:
+ # mouse button came up, stop tracking
+ if Gl.debug:
+ print 'mouse', mouse, 'up at', x, y
+ unqdevice(MOUSEX)
+ unqdevice(MOUSEY)
+ if mouse = 2:
+ mouse2track(x, y)
+ Gl.mouse2down = 0
+ elif mouse = 3:
+ mouse3track(x, y)
+ Gl.mouse3down = 0
+ else:
+ print 'fatal error'
+ Gl.alarm_set = 1
+ return 1
+
+def mouse3track(x, y):
+ # first compute polar coordinates from x and y
+ cx, cy = Gl.ox + Gl.cx/2, Gl.oy + Gl.cy/2
+ x, y = x - cx, y - cy
+ if (x, y) = (0, 0): return # would cause an exception
+ minutes = int(30.5 + 30.0*math.atan2(float(-x), float(-y))/pi)
+ if minutes = 60: minutes = 0
+ a,b = Gl.alarm_minutes/15, minutes/15
+ if (a,b) = (0,3):
+ # Moved backward through 12 o'clock:
+ Gl.alarm_hours = Gl.alarm_hours - 1
+ if Gl.alarm_hours < 0: Gl.alarm_hours = Gl.alarm_hours + 24
+ if (a,b) = (3,0):
+ # Moved forward through 12 o'clock:
+ Gl.alarm_hours = Gl.alarm_hours + 1
+ if Gl.alarm_hours >= 24: Gl.alarm_hours = Gl.alarm_hours - 24
+ Gl.alarm_minutes = minutes
+ seconds = Gl.alarm_hours * HOUR + Gl.alarm_minutes * MINUTE
+ if seconds <> Gl.alarm_time:
+ draw_alarm(rgb_bg())
+ Gl.alarm_time = seconds
+ draw_alarm(rgb_fg())
+
+def mouse2track(x, y):
+ # first compute polar coordinates from x and y
+ cx, cy = Gl.ox + Gl.cx/2, Gl.oy + Gl.cy/2
+ x, y = x - cx, y - cy
+ if (x, y) = (0, 0): return # would cause an exception
+ hours = int(6.5 - float(Gl.alarm_minutes)/60.0 + 6.0*math.atan2(float(-x), float(-y))/pi)
+ if hours = 12: hours = 0
+ if (Gl.alarm_hours,hours) = (0,11):
+ # Moved backward through midnight:
+ Gl.alarm_hours = 23
+ elif (Gl.alarm_hours,hours) = (12,11):
+ # Moved backward through noon:
+ Gl.alarm_hours = 11
+ elif (Gl.alarm_hours,hours) = (11,0):
+ # Moved forward through noon:
+ Gl.alarm_hours = 12
+ elif (Gl.alarm_hours,hours) = (23,0):
+ # Moved forward through midnight:
+ Gl.alarm_hours = 0
+ elif Gl.alarm_hours < 12:
+ Gl.alarm_hours = hours
+ else:
+ Gl.alarm_hours = hours + 12
+ seconds = Gl.alarm_hours * HOUR + Gl.alarm_minutes * MINUTE
+ if seconds <> Gl.alarm_time:
+ draw_alarm(rgb_bg())
+ Gl.alarm_time = seconds
+ draw_alarm(rgb_fg())
+
+def initmenu():
+ Gl.pup = pup = newpup()
+ addtopup(pup, 'M Clock%t|Alarm On/Off|Seconds Hand On/Off|Quit', 0)
+
+def handlemenu():
+ item = dopup(Gl.pup)
+ if item = 1:
+ # Toggle alarm
+ if Gl.alarm_set:
+ Gl.alarm_set = 0
+ Gl.alarm_on = 0
+ else:
+ Gl.alarm_set = 1
+ Gl.change = 1
+ clearall()
+ elif item = 2:
+ # Toggle Seconds Hand
+ if Gl.update = 1:
+ Gl.update = 60
+ Gl.timernoise = 60
+ else:
+ Gl.update = 1
+ Gl.timernoise = 6
+ Gl.change = 1
+ elif item = 3:
+ if Gl.debug: print 'Exit'
+ sys.exit(0)
+
+main()
diff --git a/demo/sgi/gl/mixing.py b/demo/sgi/gl/mixing.py
new file mode 100755
index 0000000..294e65f
--- /dev/null
+++ b/demo/sgi/gl/mixing.py
@@ -0,0 +1,116 @@
+#! /ufs/guido/bin/sgi/python
+
+# Use Gouraud shading to mix colors. Requires Z-buffer.
+# It changes the color assignments so fast that you see white.
+# Left button pauses, middle rotates the square. ESC to quit.
+# Experiment with a larger window (too slow) or smaller window (really white).
+
+from GL import *
+from gl import *
+import DEVICE
+from math import *
+
+#
+# tekenvlak : draw a square. with bgnpolygon
+#
+def tekenvlak (vc) :
+ bgnpolygon()
+ #vcarray (vc)
+ for i in vc :
+ c3f (i[1])
+ v3f (i[0])
+ endpolygon()
+
+#
+# tekendoos : draw a box
+#
+def tekendoos (col) :
+ v = [(-5.0,0.0,0.0),(0.0,5.0,0.0),(5.0,0.0,0.0),(0.0,-5.0,0.0)]
+ vc = [(v[0],col[0]),(v[1],col[1]),(v[2],col[2]),(v[3],col[1])]
+ tekenvlak (vc)
+
+#
+# initialize gl
+#
+def initgl () :
+ #
+ # open window
+ #
+ foreground ()
+ keepaspect (1, 1)
+ prefposition (100, 500, 100, 500)
+ w = winopen ('PYTHON RGB')
+ keepaspect (1, 1)
+ winconstraints()
+ #
+ # configure pipeline (2buf, GOURAUD and RGBmode)
+ #
+ doublebuffer ()
+ zbuffer (1)
+ shademodel (GOURAUD)
+ RGBmode ()
+ gconfig ()
+ #
+ # set viewing
+ #
+ perspective (900, 1, 1.0, 10.0)
+ polarview (10.0, 0, 0, 0)
+ #
+ # ask for the REDRAW and ESCKEY events
+ #
+ qdevice(DEVICE.MOUSE2)
+ qdevice(DEVICE.MOUSE3)
+ qdevice(DEVICE.REDRAW)
+ qdevice(DEVICE.ESCKEY)
+
+
+#
+# the color black
+#
+black = 0
+#
+# GoForIT : use 2buf to redraw the object 2n times. index i is used as
+# the (smoothly changing) rotation angle
+#
+def GoForIt(i) :
+ col = [(255.0,0.0,0.0), (0.0,255.0,0.0), (0.0,0.0,255.0)]
+ twist = 0
+ freeze = 1
+ while 1 :
+ if freeze <> 0 :
+ col[0],col[1],col[2] = col[1],col[2],col[0]
+ #
+ # clear z-buffer and clear background to light-blue
+ #
+ zclear()
+ cpack (black)
+ clear()
+ #
+ tekendoos (col)
+ #
+ swapbuffers()
+ #
+ if qtest() <> 0 :
+ dev, val = qread()
+ if dev = DEVICE.ESCKEY :
+ break
+ elif dev = DEVICE.REDRAW :
+ reshapeviewport ()
+ elif dev = DEVICE.MOUSE2 and val <> 0 :
+ twist = twist + 30
+ perspective (900, 1, 1.0, 10.0)
+ polarview (10.0, 0, 0, twist)
+ elif dev = DEVICE.MOUSE3 and val <> 0 :
+ freeze = 1 - freeze
+
+
+# the main program
+#
+def main () :
+ initgl ()
+ GoForIt (0)
+
+#
+# exec main
+#
+main ()
diff --git a/demo/sgi/gl/nurbs.py b/demo/sgi/gl/nurbs.py
new file mode 100755
index 0000000..ee48e23
--- /dev/null
+++ b/demo/sgi/gl/nurbs.py
@@ -0,0 +1,171 @@
+#! /ufs/guido/bin/sgi/python
+
+# Rotate a 3D surface created using NURBS.
+#
+# Press left mouse button to toggle surface trimming.
+# Press ESC to quit.
+#
+# See the GL manual for an explanation of NURBS.
+
+from gl import *
+from GL import *
+from DEVICE import *
+
+TRUE = 1
+FALSE = 0
+ORDER = 4
+
+idmat = [1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1]
+
+surfknots = [-1, -1, -1, -1, 1, 1, 1, 1]
+
+def make_ctlpoints():
+ c = []
+ #
+ ci = []
+ ci.append(-2.5, -3.7, 1.0)
+ ci.append(-1.5, -3.7, 3.0)
+ ci.append(1.5, -3.7, -2.5)
+ ci.append(2.5, -3.7, -0.75)
+ c.append(ci)
+ #
+ ci = []
+ ci.append(-2.5, -2.0, 3.0)
+ ci.append(-1.5, -2.0, 4.0)
+ ci.append(1.5, -2.0, -3.0)
+ ci.append(2.5, -2.0, 0.0)
+ c.append(ci)
+ #
+ ci = []
+ ci.append(-2.5, 2.0, 1.0)
+ ci.append(-1.5, 2.0, 0.0)
+ ci.append(1.5, 2.0, -1.0)
+ ci.append(2.5, 2.0, 2.0)
+ c.append(ci)
+ #
+ ci = []
+ ci.append(-2.5, 2.7, 1.25)
+ ci.append(-1.5, 2.7, 0.1)
+ ci.append(1.5, 2.7, -0.6)
+ ci.append(2.5, 2.7, 0.2)
+ c.append(ci)
+ #
+ return c
+
+ctlpoints = make_ctlpoints()
+
+trimknots = [0., 0., 0., 1., 1., 2., 2., 3., 3., 4., 4., 4.]
+
+def make_trimpoints():
+ c = []
+ c.append(1.0, 0.0, 1.0)
+ c.append(1.0, 1.0, 1.0)
+ c.append(0.0, 2.0, 2.0)
+ c.append(-1.0, 1.0, 1.0)
+ c.append(-1.0, 0.0, 1.0)
+ c.append(-1.0, -1.0, 1.0)
+ c.append(0.0, -2.0, 2.0)
+ c.append(1.0, -1.0, 1.0)
+ c.append(1.0, 0.0, 1.0)
+ return c
+
+trimpoints = make_trimpoints()
+
+def main():
+ init_windows()
+ setup_queue()
+ make_lights()
+ init_view()
+ #
+ set_scene()
+ setnurbsproperty( N_ERRORCHECKING, 1.0 )
+ setnurbsproperty( N_PIXEL_TOLERANCE, 50.0 )
+ trim_flag = 0
+ draw_trim_surface(trim_flag)
+ #
+ while 1:
+ while qtest():
+ dev, val = qread()
+ if dev = ESCKEY:
+ return
+ elif dev = WINQUIT:
+ dglclose(-1) # this for DGL only
+ return
+ elif dev = REDRAW:
+ reshapeviewport()
+ set_scene()
+ draw_trim_surface(trim_flag)
+ elif dev = LEFTMOUSE:
+ if val:
+ trim_flag = (not trim_flag)
+ set_scene()
+ draw_trim_surface(trim_flag)
+
+def init_windows():
+ foreground()
+ #prefposition(0, 500, 0, 500)
+ wid = winopen('nurbs')
+ wintitle('NURBS Surface')
+ doublebuffer()
+ RGBmode()
+ gconfig()
+ lsetdepth(0x000, 0x7fffff)
+ zbuffer( TRUE )
+
+def setup_queue():
+ qdevice(ESCKEY)
+ qdevice(REDRAW)
+ qdevice(RIGHTMOUSE)
+ qdevice(WINQUIT)
+ qdevice(LEFTMOUSE) #trimming
+
+def init_view():
+ mmode(MPROJECTION)
+ ortho( -4., 4., -4., 4., -4., 4. )
+ #
+ mmode(MVIEWING)
+ loadmatrix(idmat)
+ #
+ lmbind(MATERIAL, 1)
+
+def set_scene():
+ lmbind(MATERIAL, 0)
+ RGBcolor(150,150,150)
+ lmbind(MATERIAL, 1)
+ clear()
+ zclear()
+ #
+ rotate( 100, 'y' )
+ rotate( 100, 'z' )
+
+def draw_trim_surface(trim_flag):
+ bgnsurface()
+ nurbssurface(surfknots, surfknots, ctlpoints, ORDER, ORDER, N_XYZ)
+ if trim_flag:
+ bgntrim()
+ nurbscurve(trimknots, trimpoints, ORDER-1, N_STW)
+ endtrim()
+ endsurface()
+ swapbuffers()
+
+def make_lights():
+ lmdef(DEFLMODEL,1,[])
+ lmdef(DEFLIGHT,1,[])
+ #
+ # define material #1
+ #
+ a = []
+ a = a + [EMISSION, 0.0, 0.0, 0.0]
+ a = a + [AMBIENT, 0.1, 0.1, 0.1]
+ a = a + [DIFFUSE, 0.6, 0.3, 0.3]
+ a = a + [SPECULAR, 0.0, 0.6, 0.0]
+ a = a + [SHININESS, 2.0]
+ a = a + [LMNULL]
+ lmdef(DEFMATERIAL, 1, a)
+ #
+ # turn on lighting
+ #
+ lmbind(LIGHT0, 1)
+ lmbind(LMODEL, 1)
+
+main()
diff --git a/demo/sgi/gl/zrgb.py b/demo/sgi/gl/zrgb.py
new file mode 100755
index 0000000..c3f934a
--- /dev/null
+++ b/demo/sgi/gl/zrgb.py
@@ -0,0 +1,169 @@
+#! /ufs/guido/bin/sgi/python
+
+# zrgb (Requires Z buffer.)
+#
+# This program demostrates zbuffering 3 intersecting RGB polygons while
+# in doublebuffer mode where, movement of the mouse with the LEFTMOUSE
+# button depressed will, rotate the 3 polygons. This is done by compound
+# rotations allowing continuous screen-oriented rotations.
+#
+# Press the "Esc" key to exit.
+
+from gl import *
+from GL import *
+from DEVICE import *
+
+
+objmat=[1.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,1.0]
+
+idmat=[1.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,1.0]
+
+def main() :
+ #
+ # old and new mouse position
+ #
+ #
+ mode = 0
+ omx = 0
+ mx = 0
+ omy = 0
+ my = 0
+ #
+ initialize ()
+ #
+ draw_scene (objmat)
+ #
+ while (1) :
+ #
+ dev, val = qread()
+ #
+ if dev = ESCKEY :
+ if val :
+ break
+ # exit when key is going up, not down
+ # this avoids the scenario where a window
+ # underneath this program's window
+ # would otherwise "eat up" the up-
+ # event of the Esc key being released
+ return
+ #
+ elif dev = REDRAW :
+ reshapeviewport()
+ draw_scene(objmat)
+ #
+ elif dev = LEFTMOUSE:
+ omx = mx
+ omy = my
+ if val :
+ mode = 1
+ else :
+ mode = 0
+ elif dev = MOUSEX :
+ omx = mx
+ mx = val
+ #print omx, mx
+ objmat = update_scene(objmat,mx,my,omx,omy,mode)
+ #
+ elif dev = MOUSEY :
+ omy = my
+ my = val
+ #print omy, my
+ objmat = update_scene(objmat,mx,my,omx,omy,mode)
+ #
+
+
+def initialize () :
+ #
+ foreground ()
+ keepaspect(5, 4)
+ w = winopen('Zbuffered RGB')
+ #
+ doublebuffer()
+ RGBmode()
+ gconfig()
+ zbuffer(1)
+ lsetdepth(0x0, 0x7FFFFF)
+ #
+ qdevice(ESCKEY)
+ qdevice(LEFTMOUSE)
+ qdevice(MOUSEX)
+ qdevice(MOUSEY)
+
+def update_scene (mat, mx, my, omx, omy, mode) :
+ #
+ if mode = 1 :
+ mat = orient(mat, mx, my, omx, omy)
+ draw_scene(mat)
+ return mat
+
+def orient (mat, mx, my, omx, omy) :
+ #
+ #
+ pushmatrix()
+ loadmatrix(idmat)
+ #
+ if mx - omx : rot (float (mx - omx), 'y')
+ if omy - my : rot (float (omy - my), 'x')
+ #
+ multmatrix(mat)
+ mat = getmatrix()
+ #
+ #
+ popmatrix()
+ #
+ return mat
+
+def draw_scene (mat) :
+ RGBcolor(40, 100, 200)
+ clear()
+ zclear()
+ #
+ perspective(400, 1.25, 30.0, 60.0)
+ translate(0.0, 0.0, -40.0)
+ multmatrix(mat)
+ #
+ # skews original view to show all polygons
+ #
+ rotate(-580, 'y')
+ draw_polys()
+ #
+ swapbuffers()
+
+polygon1 = [(-10.0,-10.0,0.0),(10.0,-10.0,0.0),(-10.0,10.0,0.0)]
+
+polygon2 = [(0.0,-10.0,-10.0),(0.0,-10.0,10.0),(0.0,5.0,-10.0)]
+
+polygon3 = [(-10.0,6.0,4.0),(-10.0,3.0,4.0),(4.0,-9.0,-10.0),(4.0,-6.0,-10.0)]
+
+def draw_polys():
+ bgnpolygon()
+ cpack(0x0)
+ v3f(polygon1[0])
+ cpack(0x007F7F7F)
+ v3f(polygon1[1])
+ cpack(0x00FFFFFF)
+ v3f(polygon1[2])
+ endpolygon()
+ #
+ bgnpolygon()
+ cpack(0x0000FFFF)
+ v3f(polygon2[0])
+ cpack(0x007FFF00)
+ v3f(polygon2[1])
+ cpack(0x00FF0000)
+ v3f(polygon2[2])
+ endpolygon()
+ #
+ bgnpolygon()
+ cpack(0x0000FFFF)
+ v3f(polygon3[0])
+ cpack(0x00FF00FF)
+ v3f(polygon3[1])
+ cpack(0x00FF0000)
+ v3f(polygon3[2])
+ cpack(0x00FF00FF)
+ v3f(polygon3[3])
+ endpolygon()
+
+
+main ()
diff --git a/demo/sgi/gl_panel/README b/demo/sgi/gl_panel/README
new file mode 100644
index 0000000..889a2cf
--- /dev/null
+++ b/demo/sgi/gl_panel/README
@@ -0,0 +1,23 @@
+This directory contains demos that use the Panel Library by NASA Ames.
+They only run on SGI machines and require the 'pnl' and 'gl' built-in
+modules. Each subdirectory contains one demo.
+
+apanel A trivial user interface to the audio capabilities of
+ the 4D/25 (Personal IRIS). Lets you record a sample and
+ play it back at different volumes. Requires the 'audio'
+ built-in module.
+
+flying A large demonstration that can display several
+ differently shaped objects through space. Control
+ panels let you manipulate light sources, material
+ properties and drawing modes.
+
+nurbs A demo of the capabilities of the GL 'nurbs' functions
+ that can display the control points. (It was intended
+ to let you move these as well, but there was a problem
+ with the mapping of mouse movements in a 3-D world.)
+
+twoview A demo of GL's transformation primitives. Two views on
+ a scene are given, and the position and orientation of a
+ viewer in one of the views can be changed through
+ various buttons and dials in a control panel.
diff --git a/demo/sgi/gl_panel/apanel/apanel.py b/demo/sgi/gl_panel/apanel/apanel.py
new file mode 100755
index 0000000..de9a710
--- /dev/null
+++ b/demo/sgi/gl_panel/apanel/apanel.py
@@ -0,0 +1,63 @@
+#! /ufs/guido/bin/sgi/python
+
+# A (too) trivial control panel to record a sound sample and play it back.
+# Requires the audio built-in module.
+# Requires the NASA AMES Panel Library.
+
+import sys
+
+import gl
+import panel
+
+panel.block(1)
+
+import audio
+
+def main():
+ gl.foreground()
+ gl.noport()
+ #gl.prefposition(700, 850, 950, 970)
+ wid = gl.winopen('audio demo')
+ #
+ panels = panel.defpanellist('apanel.s') # XXX
+ p = panels[0]
+ p.playbackbutton.back = p
+ p.recordbutton.back = p
+ p.sample = ''
+ #
+ def quit(a):
+ sys.exit(0)
+ #
+ p.quitbutton.downfunc = quit
+ #
+ def playback(a):
+ p = a.back
+ gain = int(255.0*p.outputgain.val)
+ a.val = 1.0
+ a.fixact()
+ panel.drawpanel()
+ audio.setoutgain(gain)
+ audio.write(p.sample)
+ audio.setoutgain(0)
+ a.val = 0.0
+ a.fixact()
+ #
+ p.playbackbutton.downfunc = playback
+ #
+ def record(a):
+ p = a.back
+ size = int(10.0 * 8192.0 * p.recordsize.val)
+ a.val = 1.0
+ a.fixact()
+ panel.drawpanel()
+ audio.setoutgain(0)
+ p.sample = audio.read(size)
+ a.val = 0.0
+ a.fixact()
+ #
+ p.recordbutton.downfunc = record
+ #
+ while 1:
+ act = panel.dopanel()
+
+main()
diff --git a/demo/sgi/gl_panel/apanel/apanel.s b/demo/sgi/gl_panel/apanel/apanel.s
new file mode 100644
index 0000000..7c94da2
--- /dev/null
+++ b/demo/sgi/gl_panel/apanel/apanel.s
@@ -0,0 +1,76 @@
+;;; This file was automatically generated by the panel editor.
+;;; If you read it into gnu emacs, it will automagically format itself.
+
+(panel (prop help creator:user-panel-help)
+(prop user-panel #t)
+(label "Audio Control Panel")
+(x 395)
+(y 69)
+(al (pnl_filled_vslider (name "outputgain")
+(prop help creator:user-act-help)
+(label "output gain")
+(x 6.5)
+(y 0.75)
+(w 0.4)
+(h 4.35)
+(val 0.329)
+(labeltype 13)
+(downfunc move-then-resize)
+)
+(pnl_frame (prop help creator:user-frame-help)
+(x 0.25)
+(y 2.75)
+(w 5.1)
+(h 2.3)
+(downfunc move-then-resize)
+(al (pnl_filled_hslider (name "recordsize")
+(prop help creator:user-act-help)
+(label "recording length")
+(x -0.75)
+(w 3.3)
+(h 0.4)
+(val 0.1)
+(labeltype 11)
+(downfunc move-then-resize)
+)
+(pnl_label (prop help creator:user-act-help)
+(label "(max 10 seconds)")
+(x -0.75)
+(y -0.75)
+(downfunc move-then-resize)
+)
+(pnl_wide_button (name "recordbutton")
+(prop help creator:user-act-help)
+(label "record from microphone...")
+(x -0.75)
+(y 0.75)
+(w 4.7)
+(downfunc move-then-resize)
+)
+)
+)
+(pnl_wide_button (name "playbackbutton")
+(prop help creator:user-act-help)
+(label "playback to speaker")
+(x 0.25)
+(y 2)
+(w 5.15)
+(downfunc move-then-resize)
+)
+(pnl_wide_button (name "quitbutton")
+(prop help creator:user-act-help)
+(label "quit")
+(x 0.25)
+(y 0.25)
+(w 1.75)
+(downfunc move-then-resize)
+)
+)
+)
+;;; Local Variables:
+;;; mode: scheme
+;;; eval: (save-excursion (goto-char (point-min)) (kill-line 3))
+;;; eval: (save-excursion (goto-char (point-min)) (replace-regexp "[ \n]*)" ")"))
+;;; eval: (indent-region (point-min) (point-max) nil)
+;;; eval: (progn (kill-line -3) (delete-backward-char 1) (save-buffer))
+;;; End:
diff --git a/demo/sgi/gl_panel/flying/data.py b/demo/sgi/gl_panel/flying/data.py
new file mode 100644
index 0000000..bfc934a
--- /dev/null
+++ b/demo/sgi/gl_panel/flying/data.py
@@ -0,0 +1,42 @@
+
+# two string constants
+ARROW = '-> '
+NULL = ''
+ZERO = 0
+ONE = 1
+
+#
+# the color light-blue
+#
+lightblue = (43,169,255)
+
+
+#
+# a couple of rotation, translation, scaling vectors
+#
+rts1 = [[3.0,3.1,2.0],[2.2, 1.2, 2.0], [0.8,0.8,0.8]]
+rts2 = [[3.2,2.6,1.8],[-1.9, 1.2, 1.6], [0.3,0.3,1.0]]
+rts3 = [[2.2,3.3,1.4], [-1.0, 1.2,-1.5], [0.6,0.6, 0.6]]
+rts4 = [[4.2,2.1,3.2],[1.2, 1.3, 1.0],[0.5,0.5,0.8]]
+rts5 = [[1.2,3.3,2.4], [-2.0, 1.4,-2.1], [0.8, 0.8, 0.2]]
+rts6 = [[3.2,3.6,2.4], [1.1, 1.6, 2.5], [0.8,0.3,0.1]]
+rts7 = [[2.3,2.7,3.3], [1.1, 2.3, 1.7], [0.6,0.6,0.5]]
+rts8 = [[4.2,2.1,3.2], [1.2, 1.3, 0.0], [0.5,0.5,0.5]]
+#
+rts90 = [[4.2,2.1,3.2], [2.0, 0.0, 0.9], [0.3,0.3,1.0]]
+rts91 = [[4.2,2.1,3.2], [-2.0, 0.0, 0.9], [0.3,0.3,1.0]]
+rts92 = [[4.2,2.1,3.2], [0.0, 2.0, 0.9], [0.3,0.3,1.0]]
+rts93 = [[4.2,2.1,3.2], [0.0, -2.0, 0.9], [0.3,0.3,1.0]]
+rts10 = [[4.2,2.1,3.2], [0.0, 0.0, 0.0], [2.2,2.2,0.2]]
+
+#
+# (composite) object definitions
+#
+o1 = [['sphere',rts1, 1]]
+o2 = [['cylinder', rts2, 4]]
+o3 = [['cube', rts3, 3]]
+o4 = [['cone', rts4, 2], ['sphere', rts8, 9]]
+o5 = [['sphere', rts5, 5]]
+o6 = [['cube', rts6, 6]]
+o7 = [['pyramid', rts7, 8]]
+o8 = [['cube', rts10, 9], ['cylinder', rts90, 2], ['cylinder', rts91, 2], ['cylinder', rts92, 2], ['cylinder', rts93, 2]]
diff --git a/demo/sgi/gl_panel/flying/flying.py b/demo/sgi/gl_panel/flying/flying.py
new file mode 100755
index 0000000..e6fd823
--- /dev/null
+++ b/demo/sgi/gl_panel/flying/flying.py
@@ -0,0 +1,375 @@
+#! /ufs/guido/bin/sgi/python
+
+from gl import *
+from objdict import *
+from GL import *
+import DEVICE, time
+import objectdef, light, panel, material
+
+def fixmatact (p) :
+ p.diffR.fixact ()
+ p.diffG.fixact ()
+ p.diffB.fixact ()
+ p.specR.fixact ()
+ p.specG.fixact ()
+ p.specB.fixact ()
+ p.shine.fixact ()
+
+def fixlichtact (p) :
+ p.R.fixact ()
+ p.G.fixact ()
+ p.B.fixact ()
+ p.X.fixact ()
+ p.Y.fixact ()
+ p.Z.fixact ()
+ p.local.fixact ()
+
+def cbsetlight (a) :
+ p = a.back
+ setlight (p, a.label)
+
+def cbsetmaterial (a) :
+ p = a.back
+ setmaterial (p, a.label)
+
+mater = [0]
+licht = [0]
+
+def setmaterial (p, mname) :
+ #
+ mater [0:1] = [material.materdict [mname]]
+ #
+ p.diffR.val = mater [0][1]
+ p.diffG.val = mater [0][2]
+ p.diffB.val = mater [0][3]
+ #
+ p.specR.val = mater [0][5]
+ p.specG.val = mater [0][6]
+ p.specB.val = mater [0][7]
+ #
+ p.shine.val = mater [0][9] / 128.0
+ fixmatact (p)
+
+def setlight (p, mname) :
+ #
+ licht [0:1] = [material.lichtdict [mname]]
+ #
+ p.R.val = licht [0][1]
+ p.G.val = licht [0][2]
+ p.B.val = licht [0][3]
+ #
+ p.X.val = (licht [0][5] + 10.0) / 20.0
+ p.Y.val = (licht [0][6] + 10.0) / 20.0
+ p.Z.val = (licht [0][7] + 10.0) / 20.0
+ #
+ p.local.val = licht [0][8]
+ #
+ fixlichtact (p)
+
+def cbmaterial (a) :
+ #
+ if mater[0] = 0 : return
+ #
+ p = a.back
+ mater [0][5:8] = [p.diffR.val, p.diffG.val, p.diffB.val]
+ mater [0][1:4] = [p.specR.val, p.specG.val, p.specB.val]
+ mater [0][9:10] = [128.0 * p.shine.val]
+ light.bindlight (0)
+
+def cblight (a) :
+ #
+ if licht[0] = 0 : return
+ #
+ p = a.back
+ licht [0][1:4] = [p.R.val, p.G.val, p.B.val]
+ licht [0][5:8] = [20.0 * p.X.val - 10.0, 20.0 * p.Y.val - 10.0, 20.0 * p.Z.val - 10.0]
+ if p.local.val = 0.0 :
+ licht [0][8:9] = [0.0]
+ else:
+ licht [0][8:9] = [1.0]
+ #
+ light.bindlight (0)
+
+#
+# initgl : initialize window, pipeline, light, viewing
+#
+def initgl () :
+ #
+ # init window
+ #
+ foreground ()
+ keepaspect (1, 1)
+ prefposition (100, 500, 100, 500)
+ w = winopen ('flying objects')
+ keepaspect (1, 1)
+ winconstraints ()
+ #
+ # configure pipline
+ #
+ doublebuffer ()
+ shademodel (GOURAUD)
+ zbuffer (1)
+ RGBmode ()
+ gconfig ()
+ #
+ # init lighting
+ #
+ light.bindlight (1)
+ #
+ # set viewing
+ #
+ lookat (0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0)
+ #
+
+#
+# drawit : draws the object with the given attributes.
+#
+# rfac : the rotation factor.
+# mat : the material identification
+# attr : a list of attributes :
+#
+# [[rotate vector ], [tranlate vector], [scale vector]]
+# i.e :
+# [[rX, rY, rZ], [tX, tY, tZ], [sX, sY, sZ]]
+#
+def drawit(object, rfac, attr, mat) :
+ pushmatrix()
+ rot (attr[0][0] * float (rfac), 'X')
+ rot (attr[0][1] * float (rfac), 'Y')
+ rot (attr[0][2] * float (rfac), 'Z')
+ translate(attr[1][0], attr[1][1], attr[1][2])
+ scale(attr[2][0], attr[2][1], attr[2][2])
+ lmbind(MATERIAL, mat)
+ objectdef.drawobject(object)
+ popmatrix()
+
+def callbacksphere (a) :
+ putDict (objects, 'sphere', int (a.val))
+
+def callbackcylinder (a) :
+ putDict (objects, 'cylinder', int (a.val))
+
+def callbackcube (a) :
+ putDict (objects, 'cube', int (a.val))
+
+def callbackicecream (a) :
+ putDict (objects, 'icecream', int (a.val))
+
+def callbackdisk (a) :
+ putDict (objects, 'disk', int (a.val))
+
+def callbackdiamond (a) :
+ putDict (objects, 'diamond', int (a.val))
+
+def callbackglass (a) :
+ putDict (objects, 'glass', int (a.val))
+
+def callbackpyramid (a) :
+ putDict (objects, 'pyramid', int (a.val))
+
+def callbacktable (a) :
+ putDict (objects, 'table', int (a.val))
+
+def callbackflat (a) :
+ shademodel(FLAT)
+
+def callbackgouraud (a) :
+ shademodel(GOURAUD)
+
+def callbackwire (a) :
+ objectdef.putFunc ([bgnclosedline, endclosedline])
+
+def callbackfilled (a) :
+ objectdef.putFunc ([bgnpolygon, endpolygon])
+
+def callbackquit (a) :
+ import sys
+ sys.exit (-1)
+
+def allObjects(p, val) :
+ p.sphere.val = val
+ p.sphere.fixact ()
+ p.cube.val = val
+ p.cube.fixact ()
+ p.cylinder.val = val
+ p.cylinder.fixact ()
+ p.pyramid.val = val
+ p.pyramid.fixact ()
+ p.disk.val = val
+ p.disk.fixact ()
+ p.diamond.val = val
+ p.diamond.fixact ()
+ p.icecream.val = val
+ p.icecream.fixact ()
+ p.table.val = val
+ p.table.fixact ()
+ p.fixpanel()
+
+
+def callbackshowall (a) :
+ #print objects
+ for key in objects.keys () :
+ #print key
+ putDict (objects, key, 1)
+ allObjects (a.back, 1.0)
+
+def callbackshownone (a) :
+ for key in objects.keys () :
+ putDict (objects, key, 0)
+ allObjects (a.back, 0.0)
+
+#
+# main : makeobjects, initialze graphics, and loop continuously.
+#
+def main () :
+ #
+ # iter keeps track of the iterations. It is used as the
+ # (x, y, z) rotation increments to which the objects rotate.
+ iter = 0
+ #
+ # make the objects. the objects are put in the odict dictionary
+ #
+ od = objectdef.makeobjects ()
+ #
+ # initialize gl
+ #
+ initgl ()
+ #
+ # initialize time and iterations per second
+ #
+ time0 = time.time () # epoch-time of previous second
+ fps = 0 # frames per second
+ #
+ # initialize panels
+ #
+ panel.needredraw()
+ panels = panel.defpanellist('flying.s') #XXX
+ p = panels[0]
+ p.sphere.upfunc = callbacksphere
+ p.cylinder.upfunc = callbackcylinder
+ p.cube.upfunc = callbackcube
+ p.icecream.upfunc = callbackicecream
+ p.disk.upfunc = callbackdisk
+ p.diamond.upfunc = callbackdiamond
+ # NOT YET IMPLEMENTED p.glass.upfunc = callbackglass
+ p.pyramid.upfunc = callbackpyramid
+ p.table.upfunc = callbacktable
+ p.wire.upfunc = callbackwire
+ p.filled.upfunc = callbackfilled
+ p.flat.upfunc = callbackflat
+ p.gouraud.upfunc = callbackgouraud
+ p.quit.upfunc = callbackquit
+ p.showall.upfunc = callbackshowall
+ p.shownone.upfunc = callbackshownone
+ p.showall.back = p
+ p.shownone.back = p
+ #
+ qanels = panel.defpanellist('freeze.s') #XXX
+ q = qanels[0]
+ #
+ ranels = panel.defpanellist('materials.s') #XXX
+ r = ranels[0]
+ r.m9.upfunc = cbsetmaterial
+ r.m8.upfunc = cbsetmaterial
+ r.m7.upfunc = cbsetmaterial
+ r.m6.upfunc = cbsetmaterial
+ r.m5.upfunc = cbsetmaterial
+ r.m4.upfunc = cbsetmaterial
+ r.m3.upfunc = cbsetmaterial
+ r.m2.upfunc = cbsetmaterial
+ r.m1.upfunc = cbsetmaterial
+ r.specR.activefunc = cbmaterial
+ r.specG.activefunc = cbmaterial
+ r.specB.activefunc = cbmaterial
+ r.diffR.activefunc = cbmaterial
+ r.diffG.activefunc = cbmaterial
+ r.diffB.activefunc = cbmaterial
+ r.shine.activefunc = cbmaterial
+ r.m9.back = r
+ r.m8.back = r
+ r.m7.back = r
+ r.m6.back = r
+ r.m5.back = r
+ r.m4.back = r
+ r.m3.back = r
+ r.m2.back = r
+ r.m1.back = r
+ r.diffR.back = r
+ r.diffG.back = r
+ r.diffB.back = r
+ r.specR.back = r
+ r.specG.back = r
+ r.specB.back = r
+ r.shine.back = r
+ #
+ sanels = panel.defpanellist('light.s') #XXX
+ s = sanels[0]
+ s.X.back = s
+ s.Y.back = s
+ s.Z.back = s
+ s.R.back = s
+ s.G.back = s
+ s.B.back = s
+ s.light1.back = s
+ s.light2.back = s
+ s.local.back = s
+ s.light1.upfunc = cbsetlight
+ s.light2.upfunc = cbsetlight
+ s.R.activefunc = cblight
+ s.G.activefunc = cblight
+ s.B.activefunc = cblight
+ s.X.activefunc = cblight
+ s.Y.activefunc = cblight
+ s.Z.activefunc = cblight
+ #
+ while 1 :
+ #
+ act = panel.dopanel()
+ #
+ wid = panel.userredraw ()
+ if wid :
+ winset (wid)
+ reshapeviewport()
+ #
+ # increment iter
+ #
+ if int (q.freeze.val) = 0 :
+ iter = iter + 1
+ fps = fps + 1
+ if time.time() - time0 >= 1 :
+ f = float(fps)/float(time.time()-time0)
+ q.mystrip.val = f
+ q.mystrip.fixact ()
+ q.fixpanel()
+ time0 = time.time()
+ fps = 0
+ #
+ # clear the zbuffer and make the background light blue
+ #
+ zclear()
+ c3i (LightBlue)
+ clear()
+ #
+ # for each object in the objects dictionary
+ #
+ for key in objects.keys() :
+ #
+ # if the object should be displayed
+ #
+ if getDict (objects, key, 0) = ONE :
+ loo = getDict (objects, key, 1)
+ for o in loo :
+ #
+ # get attributes and materail
+ #
+ attr = o [1]
+ mat = o [2]
+ #
+ # display the object
+ #
+ drawit(od[o[0]],iter,attr,mat)
+ #
+ swapbuffers()
+ #
+
+main()
diff --git a/demo/sgi/gl_panel/flying/flying.s b/demo/sgi/gl_panel/flying/flying.s
new file mode 100644
index 0000000..a39fdaa
--- /dev/null
+++ b/demo/sgi/gl_panel/flying/flying.s
@@ -0,0 +1,140 @@
+;;; This file was automatically generated by the panel editor.
+;;; If you read it into gnu emacs, it will automagically format itself.
+
+(panel (prop help creator:user-panel-help)
+(prop user-panel #t)
+(label "flying objects")
+(al (pnl_toggle_button (name "table")
+(prop help creator:user-act-help)
+(label "table")
+(x 4.75)
+(y 0.25)
+(downfunc move-then-resize)
+)
+(pnl_toggle_button (name "pyramid")
+(prop help creator:user-act-help)
+(label "pyramid")
+(x 4.75)
+(y 0.75)
+(downfunc move-then-resize)
+)
+(pnl_toggle_button (name "glass")
+(prop help creator:user-act-help)
+(label "glass")
+(x 4.75)
+(y 1.25)
+(downfunc move-then-resize)
+)
+(pnl_toggle_button (name "diamond")
+(prop help creator:user-act-help)
+(label "diamond")
+(x 4.75)
+(y 1.75)
+(downfunc move-then-resize)
+)
+(pnl_toggle_button (name "disk")
+(prop help creator:user-act-help)
+(label "disk")
+(x 4.75)
+(y 2.25)
+(downfunc move-then-resize)
+)
+(pnl_toggle_button (name "icecream")
+(prop help creator:user-act-help)
+(label "ice cream")
+(x 4.75)
+(y 2.75)
+(downfunc move-then-resize)
+)
+(pnl_toggle_button (name "cube")
+(prop help creator:user-act-help)
+(label "cube")
+(x 4.75)
+(y 3.25)
+(val 1)
+(downfunc move-then-resize)
+)
+(pnl_toggle_button (name "cylinder")
+(prop help creator:user-act-help)
+(label "cylinder")
+(x 4.75)
+(y 3.75)
+(downfunc move-then-resize)
+)
+(pnl_toggle_button (name "sphere")
+(prop help creator:user-act-help)
+(label "sphere")
+(x 4.75)
+(y 4.25)
+(downfunc move-then-resize)
+)
+(pnl_button (name "quit")
+(prop help creator:user-act-help)
+(label "quit")
+(x 0.25)
+(y 2.25)
+(w 1.3)
+(h 0.65)
+(labeltype 16)
+(downfunc move-then-resize)
+)
+(pnl_button (name "showall")
+(prop help creator:user-act-help)
+(label "show all")
+(x 3.75)
+(y 3.75)
+(labeltype 8)
+(downfunc move-then-resize)
+)
+(pnl_button (name "shownone")
+(prop help creator:user-act-help)
+(label "show none")
+(x 3.75)
+(y 3.25)
+(labeltype 8)
+(downfunc move-then-resize)
+)
+(pnl_radio_button (name "wire")
+(prop end-of-group #t)
+(prop help creator:user-act-help)
+(label "wire frame")
+(x 0.25)
+(y 4.5)
+(h 0.36)
+(downfunc move-then-resize)
+)
+(pnl_radio_button (name "filled")
+(prop help creator:user-act-help)
+(label "filled")
+(x 0.25)
+(y 4)
+(h 0.36)
+(val 1)
+(downfunc move-then-resize)
+)
+(pnl_radio_button (name "flat")
+(prop end-of-group #t)
+(prop help creator:user-act-help)
+(label "flat shaded")
+(x 0.25)
+(y 0.5)
+(h 0.36)
+(downfunc move-then-resize)
+)
+(pnl_radio_button (name "gouraud")
+(prop help creator:user-act-help)
+(label "gouraud shaded")
+(x 0.25)
+(h 0.36)
+(val 1)
+(downfunc move-then-resize)
+)
+)
+)
+;;; Local Variables:
+;;; mode: scheme
+;;; eval: (save-excursion (goto-char (point-min)) (kill-line 3))
+;;; eval: (save-excursion (goto-char (point-min)) (replace-regexp "[ \n]*)" ")"))
+;;; eval: (indent-region (point-min) (point-max) nil)
+;;; eval: (progn (kill-line -3) (delete-backward-char 1) (save-buffer))
+;;; End:
diff --git a/demo/sgi/gl_panel/flying/freeze.s b/demo/sgi/gl_panel/flying/freeze.s
new file mode 100644
index 0000000..4bfa88c
--- /dev/null
+++ b/demo/sgi/gl_panel/flying/freeze.s
@@ -0,0 +1,31 @@
+;;; This file was automatically generated by the panel editor.
+;;; If you read it into gnu emacs, it will automagically format itself.
+
+(panel (prop help creator:user-panel-help)
+(prop user-panel #t)
+(label "frames per second")
+(al (pnl_toggle_button (name "freeze")
+(prop help creator:user-act-help)
+(label "freeze")
+(x 0.25)
+(y 4.3)
+(w 1.45)
+(h 0.6)
+(labeltype 16)
+(downfunc move-then-resize)
+)
+(pnl_scale_chart (name "mystrip")
+(prop help creator:user-act-help)
+(x 0.25)
+(y 0.25)
+(downfunc move-then-resize)
+)
+)
+)
+;;; Local Variables:
+;;; mode: scheme
+;;; eval: (save-excursion (goto-char (point-min)) (kill-line 3))
+;;; eval: (save-excursion (goto-char (point-min)) (replace-regexp "[ \n]*)" ")"))
+;;; eval: (indent-region (point-min) (point-max) nil)
+;;; eval: (progn (kill-line -3) (delete-backward-char 1) (save-buffer))
+;;; End:
diff --git a/demo/sgi/gl_panel/flying/light.py b/demo/sgi/gl_panel/flying/light.py
new file mode 100644
index 0000000..f6bf379
--- /dev/null
+++ b/demo/sgi/gl_panel/flying/light.py
@@ -0,0 +1,46 @@
+from GL import *
+from gl import *
+
+# identity matrix
+idmat=[1.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,1.0]
+
+# the different materials.
+m1=[SPECULAR,0.8,0.0,0.0,DIFFUSE,0.4,0.0,0.0,SHININESS,40.0,LMNULL]
+m2=[SPECULAR,1.0,0.4,0.0,DIFFUSE,1.0,0.4,0.0,SHININESS,80.0,LMNULL]
+m3=[SPECULAR,0.0,0.0,0.6,DIFFUSE,0.0,0.0,0.8,SHININESS,60.0,LMNULL]
+m4=[SPECULAR,0.0,1.0,0.0,DIFFUSE,0.0,0.6,0.0,SHININESS,120.0,LMNULL]
+m5=[SPECULAR,1.0,1.0,0.0,DIFFUSE,0.6,0.6,0.0,SHININESS,100.0,LMNULL]
+m6=[SPECULAR,1.0,0.0,1.0,DIFFUSE,0.6,0.0,0.6,SHININESS,120.0,LMNULL]
+m7=[SPECULAR,0.9,0.9,0.9,DIFFUSE,0.6,0.6,0.6,SHININESS,120.0,LMNULL]
+m8=[SPECULAR,0.4,0.7,0.4,DIFFUSE,0.5,1.0,0.5,SHININESS,50.0,LMNULL]
+m9=[SPECULAR,0.2,0.0,0.1,DIFFUSE,0.8,0.0,0.3,SHININESS,10.0,LMNULL]
+
+#the lightsources.
+light1 = [LCOLOR,1.0,1.0,1.0,POSITION,10.0,10.0,5.0,0.0,LMNULL]
+light2 = [LCOLOR,1.0,1.0,1.0,POSITION,-10.0,10.0,5.0,0.0,LMNULL]
+
+# the lightmodel.
+model = [AMBIENT,0.4,0.4,0.4,LMNULL]
+
+def bindlight (bool) :
+ # Initializes all settings for a window.
+ if bool <> 0 :
+ mmode(MVIEWING)
+ perspective (900, 1.0, 1.0, 35.0)
+ loadmatrix(idmat)
+ # define materials and lights
+ lmdef(DEFMATERIAL, 1, m1)
+ lmdef(DEFMATERIAL, 2, m2)
+ lmdef(DEFMATERIAL, 3, m3)
+ lmdef(DEFMATERIAL, 4, m4)
+ lmdef(DEFMATERIAL, 5, m5)
+ lmdef(DEFMATERIAL, 6, m6)
+ lmdef(DEFMATERIAL, 7, m7)
+ lmdef(DEFMATERIAL, 8, m8)
+ lmdef(DEFMATERIAL, 9, m9)
+ lmdef(DEFLIGHT, 1, light1)
+ lmdef(DEFLIGHT, 2, light2)
+ lmdef(DEFLMODEL, 1, model)
+ lmbind(LIGHT0,1)
+ lmbind(LIGHT1,2)
+ lmbind(LMODEL,1)
diff --git a/demo/sgi/gl_panel/flying/light.s b/demo/sgi/gl_panel/flying/light.s
new file mode 100644
index 0000000..ad56861
--- /dev/null
+++ b/demo/sgi/gl_panel/flying/light.s
@@ -0,0 +1,94 @@
+;;; This file was automatically generated by the panel editor.
+;;; If you read it into gnu emacs, it will automagically format itself.
+
+(panel (prop help creator:user-panel-help)
+(prop user-panel #t)
+(label "Light Sources")
+(al (pnl_hslider (name "X")
+(prop help creator:user-act-help)
+(label "x")
+(y 4)
+(w 3.3)
+(h 0.4)
+(val 0.50)
+(labeltype 0)
+(downfunc move-then-resize)
+)
+(pnl_hslider (name "Y")
+(prop help creator:user-act-help)
+(label "y")
+(y 3.5)
+(w 3.3)
+(h 0.4)
+(val 0.50)
+(labeltype 0)
+(downfunc move-then-resize)
+)
+(pnl_hslider (name "Z")
+(prop help creator:user-act-help)
+(label "z")
+(y 3)
+(w 3.3)
+(h 0.4)
+(val 0.50)
+(labeltype 0)
+(downfunc move-then-resize)
+)
+(pnl_radio_button (name "light2")
+(prop help creator:user-act-help)
+(label "light 2")
+(x 5)
+(y 4)
+(h 0.36)
+(downfunc move-then-resize)
+)
+(pnl_radio_button (name "light1")
+(prop help creator:user-act-help)
+(label "light 1")
+(x 5)
+(y 4.5)
+(h 0.36)
+(downfunc move-then-resize)
+)
+(pnl_toggle_button (name "local")
+(prop help creator:user-act-help)
+(label "local")
+(x 5)
+(y 2.75)
+(downfunc move-then-resize)
+)
+(pnl_filled_hslider (name "B")
+(prop help creator:user-act-help)
+(label "B")
+(w 3.3)
+(h 0.4)
+(labeltype 0)
+(downfunc move-then-resize)
+)
+(pnl_filled_hslider (name "G")
+(prop help creator:user-act-help)
+(label "G")
+(y 0.5)
+(w 3.3)
+(h 0.4)
+(labeltype 0)
+(downfunc move-then-resize)
+)
+(pnl_filled_hslider (name "R")
+(prop help creator:user-act-help)
+(label "R")
+(y 1)
+(w 3.3)
+(h 0.4)
+(labeltype 0)
+(downfunc move-then-resize)
+)
+)
+)
+;;; Local Variables:
+;;; mode: scheme
+;;; eval: (save-excursion (goto-char (point-min)) (kill-line 3))
+;;; eval: (save-excursion (goto-char (point-min)) (replace-regexp "[ \n]*)" ")"))
+;;; eval: (indent-region (point-min) (point-max) nil)
+;;; eval: (progn (kill-line -3) (delete-backward-char 1) (save-buffer))
+;;; End:
diff --git a/demo/sgi/gl_panel/flying/material.py b/demo/sgi/gl_panel/flying/material.py
new file mode 100644
index 0000000..f9137ea
--- /dev/null
+++ b/demo/sgi/gl_panel/flying/material.py
@@ -0,0 +1,26 @@
+import light
+
+def mkmatdict () :
+ m = {}
+ m['material 1'] = light.m1
+ m['material 2'] = light.m2
+ m['material 3'] = light.m3
+ m['material 4'] = light.m4
+ m['material 5'] = light.m5
+ m['material 6'] = light.m6
+ m['material 7'] = light.m7
+ m['material 8'] = light.m8
+ m['material 9'] = light.m9
+ #
+ return m
+
+materdict = mkmatdict ()
+
+def mklichtdict () :
+ m = {}
+ m['light 1'] = light.light1
+ m['light 2'] = light.light2
+ #
+ return m
+
+lichtdict = mklichtdict ()
diff --git a/demo/sgi/gl_panel/flying/materials.s b/demo/sgi/gl_panel/flying/materials.s
new file mode 100644
index 0000000..ae45ca9
--- /dev/null
+++ b/demo/sgi/gl_panel/flying/materials.s
@@ -0,0 +1,161 @@
+;;; This file was automatically generated by the panel editor.
+;;; If you read it into gnu emacs, it will automagically format itself.
+
+(panel (prop help creator:user-panel-help)
+(prop user-panel #t)
+(label "Materials")
+(al (pnl_label (prop help creator:user-act-help)
+(label "specular")
+(x 4)
+(y 0.5)
+(downfunc move-then-resize)
+)
+(pnl_label (prop help creator:user-act-help)
+(label "diffuse")
+(x 4)
+(y 4)
+(downfunc move-then-resize)
+)
+(pnl_radio_button (name "m7")
+(prop help creator:user-act-help)
+(label "material 7")
+(x 6.5)
+(y 1.5)
+(h 0.36)
+(downfunc move-then-resize)
+)
+(pnl_radio_button (name "m9")
+(prop help creator:user-act-help)
+(label "material 9")
+(x 6.5)
+(y 0.5)
+(h 0.36)
+(downfunc move-then-resize)
+)
+(pnl_radio_button (name "m8")
+(prop help creator:user-act-help)
+(label "material 8")
+(x 6.5)
+(y 1)
+(h 0.36)
+(downfunc move-then-resize)
+)
+(pnl_radio_button (name "m6")
+(prop help creator:user-act-help)
+(label "material 6")
+(x 6.5)
+(y 2)
+(h 0.36)
+(downfunc move-then-resize)
+)
+(pnl_radio_button (name "m5")
+(prop help creator:user-act-help)
+(label "material 5")
+(x 6.5)
+(y 2.5)
+(h 0.36)
+(downfunc move-then-resize)
+)
+(pnl_radio_button (name "m4")
+(prop help creator:user-act-help)
+(label "material 4")
+(x 6.5)
+(y 3)
+(h 0.36)
+(downfunc move-then-resize)
+)
+(pnl_radio_button (name "m3")
+(prop help creator:user-act-help)
+(label "material 3")
+(x 6.5)
+(y 3.5)
+(h 0.36)
+(downfunc move-then-resize)
+)
+(pnl_radio_button (name "m2")
+(prop help creator:user-act-help)
+(label "material 2")
+(x 6.5)
+(y 4)
+(h 0.36)
+(downfunc move-then-resize)
+)
+(pnl_radio_button (name "m1")
+(prop help creator:user-act-help)
+(label "material 1")
+(x 6.5)
+(y 4.5)
+(h 0.36)
+(downfunc move-then-resize)
+)
+(pnl_filled_hslider (name "diffB")
+(prop help creator:user-act-help)
+(label "B")
+(y 3.5)
+(w 3.3)
+(h 0.4)
+(labeltype 0)
+(downfunc move-then-resize)
+)
+(pnl_filled_hslider (name "diffG")
+(prop help creator:user-act-help)
+(label "G")
+(y 4)
+(w 3.3)
+(h 0.4)
+(labeltype 0)
+(downfunc move-then-resize)
+)
+(pnl_filled_hslider (name "diffR")
+(prop help creator:user-act-help)
+(label "R")
+(y 4.5)
+(w 3.3)
+(h 0.4)
+(labeltype 0)
+(downfunc move-then-resize)
+)
+(pnl_filled_hslider (name "specB")
+(prop help creator:user-act-help)
+(label "B")
+(w 3.3)
+(h 0.4)
+(labeltype 0)
+(downfunc move-then-resize)
+)
+(pnl_filled_hslider (name "specG")
+(prop help creator:user-act-help)
+(label "G")
+(y 0.5)
+(w 3.3)
+(h 0.4)
+(labeltype 0)
+(downfunc move-then-resize)
+)
+(pnl_filled_hslider (name "specR")
+(prop help creator:user-act-help)
+(label "R")
+(y 1)
+(w 3.3)
+(h 0.4)
+(labeltype 0)
+(downfunc move-then-resize)
+)
+(pnl_filled_hslider (name "shine")
+(prop help creator:user-act-help)
+(label "shininess")
+(y 2.25)
+(w 3.3)
+(h 0.4)
+(labeltype 0)
+(downfunc move-then-resize)
+)
+)
+)
+;;; Local Variables:
+;;; mode: scheme
+;;; eval: (save-excursion (goto-char (point-min)) (kill-line 3))
+;;; eval: (save-excursion (goto-char (point-min)) (replace-regexp "[ \n]*)" ")"))
+;;; eval: (indent-region (point-min) (point-max) nil)
+;;; eval: (progn (kill-line -3) (delete-backward-char 1) (save-buffer))
+;;; End:
diff --git a/demo/sgi/gl_panel/flying/objdict.py b/demo/sgi/gl_panel/flying/objdict.py
new file mode 100644
index 0000000..a5d5371
--- /dev/null
+++ b/demo/sgi/gl_panel/flying/objdict.py
@@ -0,0 +1,41 @@
+
+from data import *
+
+#
+#the color light-blue
+#
+LightBlue = lightblue
+
+# the 'object' dictionary contains the strings of the menu items
+# that denote the objects
+objects = {}
+
+# object dictionary initialization
+objects['sphere'] = [ZERO, o1]
+objects['cylinder'] = [ZERO, o2]
+objects['cube'] = [ONE, o3]
+objects['icecream'] = [ZERO, o4]
+objects['disk'] = [ZERO, o5]
+objects['diamond'] = [ZERO, o6]
+#objects['glass'] = [ZERO]
+objects['pyramid'] = [ZERO, o7]
+objects['table'] = [ZERO, o8]
+
+# 'putDict' sets the value of entry 'key' of dictionary 'dict'
+def putDict(dict, key, val) :
+ dict[key][0] = val
+
+#
+# 'getDict' get the contents of entry i of key 'key'
+# of dictionary 'dict'
+#
+def getDict(dict, key, i) :
+ return dict[key][i]
+
+# the 'options' dictionary contains the strings of the menu items
+# that denote the options
+options = {}
+
+# option dictionary initialization
+options['wire'] = [ZERO]
+options['filled'] = [ONE]
diff --git a/demo/sgi/gl_panel/flying/objectdef.py b/demo/sgi/gl_panel/flying/objectdef.py
new file mode 100644
index 0000000..3e96113
--- /dev/null
+++ b/demo/sgi/gl_panel/flying/objectdef.py
@@ -0,0 +1,147 @@
+from math import *
+from objdict import *
+from gl import *
+
+FUZZY = 0.00001
+
+# first try - brute force method (ala M.Overmars...)
+
+def makespinobject (smooth,rot,n,x1,z1,nx1,nz1,x2,z2,nx2,nz2) :
+ object = []
+ dth = 2.0 * pi / float (rot)
+ for i in range (0, n) :
+ for j in range (0, rot) :
+ th = dth * float (j)
+ #
+ if smooth = 1:
+ a1 = th
+ a2 =th+dth
+ else :
+ a1 = th + dth / 2.0
+ a2 = th + dth / 2.0
+ #
+ v0 = (x1[i]*sin(th),x1[i]*cos(th),z1[i])
+ n0 = (nx1[i]*sin(a1),nx1[i]*cos(a1),nz1[i])
+ #
+ v1 = (x1[i]*sin(th+dth),x1[i]*cos(th+dth),z1[i])
+ n1 = (nx1[i]*sin(a2), nx1[i]*cos(a2), nz1[i])
+ #
+ v2 = (x2[i]*sin(th+dth),x2[i]*cos(th+dth),z2[i])
+ n2 = (nx2[i]*sin(a2), nx2[i]*cos(a2), nz2[i])
+ #
+ v3 = (x2[i]*sin(th), x2[i]*cos(th), z2[i])
+ n3 = (nx2[i]*sin(a1), nx2[i]*cos(a1), nz2[i])
+ #
+ patch = ((v0,n0), (v1,n1), (v2,n2), (v3,n3))
+ #patch = ((n0,v0), (n1,v1), (n2,v2), (n3,v3))
+ #
+ if x1[i] < FUZZY :
+ patch = patch[1:]
+ #
+ object.append (patch)
+ #
+ return object
+
+def makesphere (n):
+ asin = []
+ acos = []
+ for i in range (0, n-1):
+ asin.append (sin((pi/float (n))*(1.0+float (i))))
+ acos.append(cos((pi/float (n))*(1.0+float (i))))
+ #
+ x1 = [0.0] + asin
+ z1 = [1.0] + acos
+ nx1 = [0.0] + asin
+ nz1 = [1.0] + acos
+ #
+ x2 = asin + [0.0]
+ z2 = acos + [-1.0]
+ nx2 = asin + [0.0]
+ nz2 = acos + [-1.0]
+ #
+ return makespinobject (1,2*n,n,x1,z1,nx1,nz1,x2,z2,nx2,nz2)
+
+def makecylinder(n) :
+ x1 = [0.0, 1.0, 1.0]
+ nx1 = [0.0, 1.0, 0.0]
+ z1 = [1.0, 1.0, -1.0]
+ nz1 = [1.0, 0.0, -1.0]
+ #
+ z2 = [1.0, -1.0, -1.0]
+ nz2 = [1.0, 0.0, -1.0]
+ x2 = [1.0, 1.0, 0.0]
+ nx2 = [0.0, 1.0, 0.0]
+ #
+ return makespinobject(1,2*n,3,x1,z1,nx1,nz1,x2,z2,nx2,nz2)
+
+def makecone(n) :
+ x1 = [0.0, 1.0, 1.0]
+ nx1 = [2.0/sqrt(5.0), 0.0, 0.0]
+ z1 = [1.0, -1.0, -1.0]
+ nz1 = [1.0/sqrt(5.0), -1.0, -1.0]
+ #
+ x2 = [1.0, 0.0, 0.0]
+ nx2 = [2.0/sqrt(5.0), 0.0, 0.0]
+ nz2 = [1.0/sqrt(5.0), -1.0, -1.0]
+ z2 = [-1.0, -1.0, -1.0]
+ #
+ return makespinobject(1,2*n,2,x1,z1,nx1,nz1,x2,z2,nx2,nz2)
+
+def makecube() :
+ x1 = [0.0, sqrt(2.0), sqrt (2.0)]
+ nx1 = [0.0, 1.0, 0.0]
+ z1 = [1.0, 1.0, -1.0]
+ nz1 = [1.0, 0.0, -1.0]
+ #
+ x2 = [sqrt(2.0), sqrt(2.0), 0.0]
+ nx2 = [0.0, 1.0, 0.0]
+ z2 = [1.0, -1.0, -1.0]
+ nz2 = [1.0, 0.0, -1.0]
+ #
+ return makespinobject(0,4,3,x1,z1,nx1,nz1,x2,z2,nx2,nz2)
+
+
+def makepyramid() :
+ x1 = [0.0, sqrt(2.0), 0.0]
+ nx1 = [2.0 / sqrt(5.0), 0.0, 0.0]
+ z1 = [1.0, -1.0, 0.0]
+ nz1 = [1.0 / sqrt(5.0), -1.0, 0.0]
+ #
+ x2 = [sqrt(2.0), 0.0, 0.0]
+ nx2 = [2.0 / sqrt(5.0), 0.0, 0.0]
+ z2 = [-1.0, -1.0, -1.0]
+ nz2 = [1.0/sqrt(5.0), -1.0, 0.0]
+ #
+ return makespinobject(0,4,3,x1,z1,nx1,nz1,x2,z2,nx2,nz2)
+
+def makeobjects () :
+ cube = makecube()
+ sphere = makesphere (6)
+ cylinder = makecylinder (6)
+ cone = makecone (6)
+ pyramid = makepyramid ()
+ #
+ odict = {}
+ odict ['cube'] = cube
+ odict ['pyramid'] = pyramid
+ odict ['sphere'] = sphere
+ odict ['cylinder'] = cylinder
+ odict ['cone'] = cone
+ odict ['diamond'] = cube
+ odict ['disk'] = sphere
+ #
+ return odict
+
+
+renderfuncs = [bgnpolygon, endpolygon]
+
+def putFunc (funcs) :
+ renderfuncs [:] = funcs
+
+def drawobject (obj) :
+ #
+ for patch in obj :
+ renderfuncs[0] ()
+ vnarray (patch)
+ renderfuncs[1] ()
+
diff --git a/demo/sgi/gl_panel/flying/panel.s b/demo/sgi/gl_panel/flying/panel.s
new file mode 100644
index 0000000..2365a76
--- /dev/null
+++ b/demo/sgi/gl_panel/flying/panel.s
@@ -0,0 +1,76 @@
+;;; This file was automatically generated by the panel editor.
+;;; If you read it into gnu emacs, it will automagically format itself.
+
+(panel (prop help creator:user-panel-help)
+(prop user-panel #t)
+(label "Panel Control")
+(x 394)
+(y 622)
+(al (pnl_radio_button (name "button4")
+(prop help creator:user-act-help)
+(y 2.5)
+(h 0.36)
+(downfunc move-then-resize)
+)
+(pnl_radio_button (name "button3")
+(prop help creator:user-act-help)
+(y 3)
+(h 0.36)
+(downfunc move-then-resize)
+)
+(pnl_radio_button (name "button2")
+(prop help creator:user-act-help)
+(y 3.5)
+(h 0.36)
+(downfunc move-then-resize)
+)
+(pnl_radio_button (name "button1")
+(prop help creator:user-act-help)
+(y 4)
+(h 0.36)
+(downfunc move-then-resize)
+)
+(pnl_wide_button (name "title1")
+(prop help creator:user-act-help)
+(x 0.75)
+(y 4.75)
+(w 2.44)
+(downfunc move-then-resize)
+)
+(pnl_wide_button (name "title2")
+(prop help creator:user-act-help)
+(x 3.5)
+(y 4.75)
+(w 2.44)
+(downfunc move-then-resize)
+)
+(pnl_wide_button (name "title3")
+(prop help creator:user-act-help)
+(x 6.25)
+(y 4.75)
+(w 2.44)
+(downfunc move-then-resize)
+)
+(pnl_wide_button (name "title4")
+(prop help creator:user-act-help)
+(x 9)
+(y 4.75)
+(w 2.44)
+(downfunc move-then-resize)
+)
+(pnl_button (name "root")
+(prop help creator:user-act-help)
+(label "R")
+(y 4.75)
+(labeltype 16)
+(downfunc move-then-resize)
+)
+)
+)
+;;; Local Variables:
+;;; mode: scheme
+;;; eval: (save-excursion (goto-char (point-min)) (kill-line 3))
+;;; eval: (save-excursion (goto-char (point-min)) (replace-regexp "[ \n]*)" ")"))
+;;; eval: (indent-region (point-min) (point-max) nil)
+;;; eval: (progn (kill-line -3) (delete-backward-char 1) (save-buffer))
+;;; End:
diff --git a/demo/sgi/gl_panel/nurbs/nurbs.py b/demo/sgi/gl_panel/nurbs/nurbs.py
new file mode 100755
index 0000000..686c3bd
--- /dev/null
+++ b/demo/sgi/gl_panel/nurbs/nurbs.py
@@ -0,0 +1,196 @@
+#! /ufs/guido/bin/sgi/python
+
+# Fancy NURBS demo. Require Z buffer and Panel Library.
+
+from gl import *
+from GL import *
+from DEVICE import *
+from nurbsdata import *
+import panel
+
+#
+# flags = trim_f, invis_f, cpvis_f, tpvis_f, axvis_f, freeze_f
+#
+TRIM = 0
+VIS = 1
+CPVIS = 2
+TPVIS = 3
+AXVIS = 4
+FREEZE = 5
+flags = [0, 1, 0, 0, 0, 0]
+
+def draw_axis () :
+ cpack (0x0)
+ zero = (0.0, 0.0, 0.0)
+ #
+ one = (1.0, 0.0, 0.0)
+ smallline (zero, one)
+ cmov (1.0, 0.0, 0.0)
+ charstr ('x')
+ #
+ one = (0.0, 1.0, 0.0)
+ smallline (zero, one)
+ cmov (0.0, 1.0, 0.0)
+ charstr ('y')
+ #
+ one = (0.0, 0.0, 1.0)
+ smallline (zero, one)
+ cmov (0.0, 0.0, 1.0)
+ charstr ('z')
+
+DELTA = 0.1
+
+def cross (p) :
+ p0 = [p[0], p[1], p[2]]
+ p1 = [p[0], p[1], p[2]]
+ for i in range (0, 3) :
+ p0[i] = p0[i] + DELTA
+ p1[i] = p1[i] - DELTA
+ smallline (p0, p1)
+ p0[i] = p0[i] - DELTA
+ p1[i] = p1[i] + DELTA
+
+def smallline (p0, p1) :
+ bgnline ()
+ v3f (p0)
+ v3f (p1)
+ endline ()
+
+def draw_pts (pnts, color) :
+ linewidth (2)
+ cpack (color)
+ for i in pnts :
+ cross (i)
+
+def init_windows():
+ foreground()
+ wid = winopen('nurbs')
+ wintitle('NURBS Surface')
+ doublebuffer()
+ RGBmode()
+ gconfig()
+ lsetdepth(0x000, 0x7fffff)
+ zbuffer( TRUE )
+
+def init_view():
+ mmode(MPROJECTION)
+ ortho( -5., 5., -5., 5., -5., 5. )
+ #
+ mmode(MVIEWING)
+ loadmatrix(idmat)
+ #
+ lmbind(MATERIAL, 1)
+
+def set_scene(flags):
+ #
+ lmbind(MATERIAL, 0)
+ RGBcolor(150,150,150)
+ lmbind(MATERIAL, 1)
+ clear()
+ zclear()
+ #
+ if not flags[FREEZE] :
+ rotate( 100, 'y' )
+ rotate( 100, 'z' )
+
+def draw_trim_surface(flags):
+ pnts = ctlpoints
+ if flags[VIS] :
+ bgnsurface()
+ nurbssurface(surfknots,surfknots,pnts,ORDER,ORDER,N_XYZ)
+ if flags[TRIM]:
+ bgntrim()
+ nurbscurve(trimknots,trimpoints,ORDER-1,N_STW)
+ endtrim()
+ endsurface()
+ #
+ if flags[CPVIS] :
+ for i in pnts :
+ draw_pts (i, RED)
+ #
+ if flags[TPVIS] :
+ tpts = trimpoints
+ draw_pts (tpts, YELLOW)
+ #
+ if flags[AXVIS] :
+ draw_axis ()
+ #
+ swapbuffers()
+
+def make_lights():
+ lmdef(DEFLMODEL,1,[])
+ lmdef(DEFLIGHT,1,[])
+ #
+ # define material #1
+ #
+ a = []
+ a = a + [EMISSION, 0.0, 0.0, 0.0]
+ a = a + [AMBIENT, 0.1, 0.1, 0.1]
+ a = a + [DIFFUSE, 0.6, 0.3, 0.3]
+ a = a + [SPECULAR, 0.0, 0.6, 0.0]
+ a = a + [SHININESS, 2.0]
+ a = a + [LMNULL]
+ lmdef(DEFMATERIAL, 1, a)
+ #
+ # turn on lighting
+ #
+ lmbind(LIGHT0, 1)
+ lmbind(LMODEL, 1)
+
+def main():
+ init_windows()
+ make_lights()
+ init_view()
+ #
+ panel.needredraw()
+ panels = panel.defpanellist('nurbs.s')
+ p = panels[0]
+ #
+ def cbtrim (a) :
+ flags[TRIM:TRIM+1] = [int (a.val)]
+ p.trim.upfunc = cbtrim
+ #
+ def cbquit (a) :
+ import sys
+ sys.exit (1)
+ p.quit.upfunc = cbquit
+ #
+ def cbmotion (a) :
+ flags[FREEZE:FREEZE+1] = [int (a.val)]
+ p.motion.upfunc = cbmotion
+ #
+ def cbxyzaxis (a) :
+ flags[AXVIS:AXVIS+1] = [int (a.val)]
+ p.xyzaxis.upfunc = cbxyzaxis
+ #
+ def cbtrimpnts (a) :
+ flags[TPVIS:TPVIS+1] = [int (a.val)]
+ p.trimpnts.upfunc = cbtrimpnts
+ #
+ def cbcntlpnts (a) :
+ flags[CPVIS:CPVIS+1] = [int (a.val)]
+ p.cntlpnts.upfunc = cbcntlpnts
+ #
+ def cbnurb (a) :
+ flags[VIS:VIS+1] = [int (a.val)]
+ p.nurb.upfunc = cbnurb
+ #
+ set_scene(flags)
+ setnurbsproperty( N_ERRORCHECKING, 1.0 )
+ setnurbsproperty( N_PIXEL_TOLERANCE, 50.0 )
+ draw_trim_surface(flags)
+ #
+ while 1:
+ act = panel.dopanel()
+ #
+ wid = panel.userredraw ()
+ if wid :
+ winset (wid)
+ reshapeviewport()
+ set_scene(flags)
+ draw_trim_surface(flags)
+ #
+ set_scene(flags)
+ draw_trim_surface(flags)
+
+main()
diff --git a/demo/sgi/gl_panel/nurbs/nurbs.s b/demo/sgi/gl_panel/nurbs/nurbs.s
new file mode 100644
index 0000000..05fb514
--- /dev/null
+++ b/demo/sgi/gl_panel/nurbs/nurbs.s
@@ -0,0 +1,81 @@
+;;; This file was automatically generated by the panel editor.
+;;; If you read it into gnu emacs, it will automagically format itself.
+
+(panel (prop help creator:user-panel-help)
+(prop user-panel #t)
+(label "NURB controls")
+(x 815)
+(y 22)
+(al (pnl_toggle_button (name "trim")
+(prop help creator:user-act-help)
+(label "trim on/off")
+(x 4)
+(y 4.5)
+(w 0.45)
+(h 0.4)
+(downfunc move-then-resize)
+)
+(pnl_toggle_button (name "motion")
+(prop help creator:user-act-help)
+(label "motion on/off")
+(y 1)
+(downfunc move-then-resize)
+)
+(pnl_toggle_button (name "xyzaxis")
+(prop help creator:user-act-help)
+(label "xyz-axis")
+(y 3)
+(downfunc move-then-resize)
+)
+(pnl_toggle_button (name "trimpnts")
+(prop help creator:user-act-help)
+(label "trimming pnts")
+(y 3.5)
+(downfunc move-then-resize)
+)
+(pnl_toggle_button (name "cntlpnts")
+(prop help creator:user-act-help)
+(label "control pnts")
+(y 4)
+(downfunc move-then-resize)
+)
+(pnl_toggle_button (name "nurb")
+(prop help creator:user-act-help)
+(label "nurb")
+(y 4.5)
+(val 1)
+(downfunc move-then-resize)
+)
+(pnl_button (name "quit")
+(prop help creator:user-act-help)
+(label "quit")
+(x 4)
+(y 1)
+(labeltype 1)
+(downfunc move-then-resize)
+)
+(pnl_label (prop help creator:user-act-help)
+(label "TRIMMING")
+(x 4)
+(y 5)
+(downfunc move-then-resize)
+)
+(pnl_label (prop help creator:user-act-help)
+(label "MOTION")
+(y 1.5)
+(downfunc move-then-resize)
+)
+(pnl_label (prop help creator:user-act-help)
+(label "VISIBILITY")
+(y 5)
+(downfunc move-then-resize)
+)
+)
+)
+;;; Local Variables:
+;;; mode: scheme
+;;; eval: (save-excursion (goto-char (point-min)) (kill-line 3))
+;;; eval: (save-excursion (goto-char (point-min)) (replace-regexp "[ \n]*)" ")"))
+;;; eval: (indent-region (point-min) (point-max) nil)
+;;; eval: (progn (kill-line -3) (delete-backward-char 1) (save-buffer))
+;;; End:
diff --git a/demo/sgi/gl_panel/nurbs/nurbsdata.py b/demo/sgi/gl_panel/nurbs/nurbsdata.py
new file mode 100644
index 0000000..ed7e705
--- /dev/null
+++ b/demo/sgi/gl_panel/nurbs/nurbsdata.py
@@ -0,0 +1,82 @@
+# Data used by fancy nurbs demo.
+
+TRUE = 1
+FALSE = 0
+
+RED = 0xff
+YELLOW = 0xffff
+
+#
+# nurb order
+#
+ORDER = 4
+
+#
+# identity matrix
+#
+idmat = [1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1]
+
+#
+# s and t knots
+#
+surfknots = [-1, -1, -1, -1, 1, 1, 1, 1]
+
+#
+# list of list of control points
+#
+def make_ctlpoints():
+ c = []
+ #
+ ci = []
+ ci.append(-2.5, -3.7, 1.0)
+ ci.append(-1.5, -3.7, 3.0)
+ ci.append(1.5, -3.7, -2.5)
+ ci.append(2.5, -3.7, -0.75)
+ c.append(ci)
+ #
+ ci = []
+ ci.append(-2.5, -2.0, 3.0)
+ ci.append(-1.5, -2.0, 4.0)
+ ci.append(1.5, -2.0, -3.0)
+ ci.append(2.5, -2.0, 0.0)
+ c.append(ci)
+ #
+ ci = []
+ ci.append(-2.5, 2.0, 1.0)
+ ci.append(-1.5, 2.0, 0.0)
+ ci.append(1.5, 2.0, -1.0)
+ ci.append(2.5, 2.0, 2.0)
+ c.append(ci)
+ #
+ ci = []
+ ci.append(-2.5, 2.7, 1.25)
+ ci.append(-1.5, 2.7, 0.1)
+ ci.append(1.5, 2.7, -0.6)
+ ci.append(2.5, 2.7, 0.2)
+ c.append(ci)
+ #
+ return c
+
+ctlpoints = make_ctlpoints ()
+
+#
+# trim knots
+#
+trimknots = [0., 0., 0., 1., 1., 2., 2., 3., 3., 4., 4., 4.]
+
+def make_trimpoints():
+ c = []
+ #
+ c.append(1.0, 0.0, 1.0)
+ c.append(1.0, 1.0, 1.0)
+ c.append(0.0, 2.0, 2.0)
+ c.append(-1.0, 1.0, 1.0)
+ c.append(-1.0, 0.0, 1.0)
+ c.append(-1.0, -1.0, 1.0)
+ c.append(0.0, -2.0, 2.0)
+ c.append(1.0, -1.0, 1.0)
+ c.append(1.0, 0.0, 1.0)
+ #
+ return c
+
+trimpoints = make_trimpoints()
diff --git a/demo/sgi/gl_panel/twoview/block.py b/demo/sgi/gl_panel/twoview/block.py
new file mode 100644
index 0000000..9ac518d
--- /dev/null
+++ b/demo/sgi/gl_panel/twoview/block.py
@@ -0,0 +1,73 @@
+# module 'block' imported by twoview demo.
+
+from gl import n3f, bgnpolygon, varray, endpolygon, lmbind
+from GL import MATERIAL
+
+# Draw a single 2x2x2 block with its center at (0, 0, 0)
+# Arguments are the material indices (0 = don't call lmbind)
+#
+def block(m_front, m_back, m_left, m_right, m_top, m_bottom):
+ #
+ # Distances defining the sides
+ #
+ x_left = -1.0
+ x_right = 1.0
+ y_top = 1.0
+ y_bottom = -1.0
+ z_front = 1.0
+ z_back = -1.0
+ #
+ # Top surface points: A, B, C, D
+ #
+ A = x_right, y_top, z_front
+ B = x_right, y_top, z_back
+ C = x_left, y_top, z_back
+ D = x_left, y_top, z_front
+ #
+ # Bottom surface points: E, F, G, H
+ #
+ E = x_right, y_bottom, z_front
+ F = x_right, y_bottom, z_back
+ G = x_left, y_bottom, z_back
+ H = x_left, y_bottom, z_front
+ #
+ # Draw front face
+ #
+ if m_front: lmbind(MATERIAL, m_front)
+ n3f(0.0, 0.0, 1.0)
+ face(H, E, A, D)
+ #
+ # Draw back face
+ #
+ if m_back: lmbind(MATERIAL, m_back)
+ n3f(0.0, 0.0, -1.0)
+ face(G, F, B, C)
+ #
+ # Draw left face
+ #
+ if m_left: lmbind(MATERIAL, m_left)
+ n3f(-1.0, 0.0, 0.0)
+ face(G, H, D, C)
+ #
+ # Draw right face
+ #
+ if m_right: lmbind(MATERIAL, m_right)
+ n3f(1.0, 0.0, 0.0)
+ face(F, E, A, B)
+ #
+ # Draw top face
+ #
+ if m_top: lmbind(MATERIAL, m_top)
+ n3f(0.0, 1.0, 0.0)
+ face(A, B, C, D)
+ #
+ # Draw bottom face
+ #
+ if m_bottom: lmbind(MATERIAL, m_bottom)
+ n3f(0.0, -1.0, 0.0)
+ face(E, F, G, H)
+
+def face(points):
+ bgnpolygon()
+ varray(points)
+ endpolygon()
diff --git a/demo/sgi/gl_panel/twoview/camera.s b/demo/sgi/gl_panel/twoview/camera.s
new file mode 100644
index 0000000..f61a58e
--- /dev/null
+++ b/demo/sgi/gl_panel/twoview/camera.s
@@ -0,0 +1,55 @@
+;;; This file was automatically generated by the panel editor.
+;;; If you read it into gnu emacs, it will automagically format itself.
+
+(panel (prop help creator:user-panel-help)
+(prop user-panel #t)
+(label "Camera Control")
+(x 1010)
+(y 589)
+(al (pnl_wide_button (name "quitbutton")
+(prop help creator:user-act-help)
+(label "quit")
+(x 3.5)
+(y 1)
+(w 0.94)
+(downfunc move-then-resize)
+)
+(pnl_filled_hslider (name "farclip")
+(prop help creator:user-act-help)
+(label "far clipping plane")
+(x 1.25)
+(y 3.5)
+(w 3.3)
+(h 0.4)
+(val 0.752)
+(downfunc move-then-resize)
+)
+(pnl_filled_hslider (name "nearclip")
+(prop help creator:user-act-help)
+(label "near clipping plane")
+(x 1.25)
+(y 4.5)
+(w 3.3)
+(h 0.4)
+(val 0.17)
+(downfunc move-then-resize)
+)
+(pnl_filled_vslider (name "zoom")
+(prop help creator:user-act-help)
+(label "zoom")
+(x 0.2)
+(y 1.25)
+(w 0.4)
+(h 3.9)
+(val 0.344)
+(downfunc move-then-resize)
+)
+)
+)
+;;; Local Variables:
+;;; mode: scheme
+;;; eval: (save-excursion (goto-char (point-min)) (kill-line 3))
+;;; eval: (save-excursion (goto-char (point-min)) (replace-regexp "[ \n]*)" ")"))
+;;; eval: (indent-region (point-min) (point-max) nil)
+;;; eval: (progn (kill-line -3) (delete-backward-char 1) (save-buffer))
+;;; End:
diff --git a/demo/sgi/gl_panel/twoview/observer.s b/demo/sgi/gl_panel/twoview/observer.s
new file mode 100644
index 0000000..ddcfe7a
--- /dev/null
+++ b/demo/sgi/gl_panel/twoview/observer.s
@@ -0,0 +1,98 @@
+;;; This file was automatically generated by the panel editor.
+;;; If you read it into gnu emacs, it will automagically format itself.
+
+(panel (prop help creator:user-panel-help)
+(prop user-panel #t)
+(label "Observer Control")
+(x 876)
+(y 10)
+(al (pnl_right_arrow_button (name "right")
+(prop help creator:user-act-help)
+(x 3.2)
+(y 2.09)
+(downfunc move-then-resize)
+)
+(pnl_up_double_arrow_button (name "fast_forward")
+(prop help creator:user-act-help)
+(label "step forward")
+(x 2.66)
+(y 3.13)
+(h 0.45)
+(labeltype 4)
+(downfunc move-then-resize)
+)
+(pnl_up_arrow_button (name "forward")
+(prop help creator:user-act-help)
+(x 2.66)
+(y 2.64)
+(downfunc move-then-resize)
+)
+(pnl_down_arrow_button (name "reverse")
+(prop help creator:user-act-help)
+(x 2.66)
+(y 1.49)
+(h 0.45)
+(labeltype 12)
+(downfunc move-then-resize)
+)
+(pnl_down_double_arrow_button (name "fast_reverse")
+(prop help creator:user-act-help)
+(label "step back")
+(x 2.66)
+(y 1)
+(labeltype 12)
+(downfunc move-then-resize)
+)
+(pnl_left_arrow_button (name "left")
+(prop help creator:user-act-help)
+(x 2.11)
+(y 2.09)
+(downfunc move-then-resize)
+)
+(pnl_right_double_arrow_button (name "fast_right")
+(prop help creator:user-act-help)
+(label "turn right")
+(x 3.75)
+(y 2.09)
+(downfunc move-then-resize)
+)
+(pnl_left_double_arrow_button (name "fast_left")
+(prop help creator:user-act-help)
+(label "turn left")
+(x 1.57)
+(y 2.09)
+(labeltype 8)
+(downfunc move-then-resize)
+)
+(pnl_vslider (name "ypos")
+(prop help creator:user-act-help)
+(x 6.25)
+(y 1)
+(w 0.4)
+(h 2.9)
+(val 0.0758)
+(downfunc move-then-resize)
+)
+(pnl_down_arrow_button (name "down")
+(prop help creator:user-act-help)
+(label "eye height")
+(x 6.25)
+(y 0.5)
+(labeltype 12)
+(downfunc move-then-resize)
+)
+(pnl_up_arrow_button (name "up")
+(prop help creator:user-act-help)
+(x 6.25)
+(y 4)
+(downfunc move-then-resize)
+)
+)
+)
+;;; Local Variables:
+;;; mode: scheme
+;;; eval: (save-excursion (goto-char (point-min)) (kill-line 3))
+;;; eval: (save-excursion (goto-char (point-min)) (replace-regexp "[ \n]*)" ")"))
+;;; eval: (indent-region (point-min) (point-max) nil)
+;;; eval: (progn (kill-line -3) (delete-backward-char 1) (save-buffer))
+;;; End:
diff --git a/demo/sgi/gl_panel/twoview/topview.s b/demo/sgi/gl_panel/twoview/topview.s
new file mode 100644
index 0000000..0e380cc
--- /dev/null
+++ b/demo/sgi/gl_panel/twoview/topview.s
@@ -0,0 +1,47 @@
+;;; This file was automatically generated by the panel editor.
+;;; If you read it into gnu emacs, it will automagically format itself.
+
+(panel (prop help creator:user-panel-help)
+(prop user-panel #t)
+(label "Top View Control")
+(x 1020)
+(y 287)
+(al (pnl_hslider (name "xpos")
+(prop help creator:user-act-help)
+(label "X")
+(x 2)
+(y 0.5)
+(w 3.85)
+(h 0.4)
+(val 0.5)
+(downfunc move-then-resize)
+)
+(pnl_vslider (name "zpos")
+(prop help creator:user-act-help)
+(label "Z")
+(x 1.25)
+(y 1.3)
+(w 0.4)
+(h 3.6)
+(val 0.5)
+(downfunc move-then-resize)
+)
+(pnl_dial (name "direction")
+(prop help creator:user-act-help)
+(label "looking direction")
+(x 2.15)
+(y 1.4)
+(w 3.5)
+(h 3.45)
+(val 0.5)
+(downfunc move-then-resize)
+)
+)
+)
+;;; Local Variables:
+;;; mode: scheme
+;;; eval: (save-excursion (goto-char (point-min)) (kill-line 3))
+;;; eval: (save-excursion (goto-char (point-min)) (replace-regexp "[ \n]*)" ")"))
+;;; eval: (indent-region (point-min) (point-max) nil)
+;;; eval: (progn (kill-line -3) (delete-backward-char 1) (save-buffer))
+;;; End:
diff --git a/demo/sgi/gl_panel/twoview/twoview.py b/demo/sgi/gl_panel/twoview/twoview.py
new file mode 100755
index 0000000..eea7c75
--- /dev/null
+++ b/demo/sgi/gl_panel/twoview/twoview.py
@@ -0,0 +1,395 @@
+#! /ufs/guido/bin/sgi/python
+
+# A demo of GL's viewing transformations, showing two views on one scene.
+# Requires the NASA AMES Panel Library. Requires Z buffer.
+
+from gl import *
+from GL import *
+import panel
+from math import sin, cos, pi
+
+inf = 1000000.0
+far = 1000.0
+near = 100.0
+
+def main():
+ foreground()
+ #
+ keepaspect(1, 1)
+ prefposition(10, 610, 10, 610)
+ obswid = winopen('Observer View')
+ doublebuffer()
+ RGBmode()
+ gconfig()
+ #
+ keepaspect(1, 1)
+ prefposition(10, 310, 650, 950)
+ topwid = winopen('Top View')
+ doublebuffer()
+ RGBmode()
+ gconfig()
+ #
+ panels = panel.defpanellist('observer.s')
+ panels = panels + panel.defpanellist('camera.s')
+ panels = panels + panel.defpanellist('topview.s')
+ #
+ p = panels[0]
+ q = panels[1]
+ r = panels[2]
+ #
+ p.farclip = q.farclip
+ p.nearclip = q.nearclip
+ p.zoom = q.zoom
+ p.quitbutton = q.quitbutton
+ #
+ p.xpos = r.xpos
+ p.zpos = r.zpos
+ p.direction = r.direction
+ #
+ p.direction.winds = 1.0 # allow full rotation
+ #
+ def quit(act):
+ import sys
+ sys.exit(0)
+ p.quitbutton.downfunc = quit
+ #
+ p.left.back = p
+ p.fast_left.back = p
+ p.right.back = p
+ p.fast_right.back = p
+ p.forward.back = p
+ p.fast_forward.back = p
+ p.reverse.back = p
+ p.fast_reverse.back = p
+ p.up.back = p
+ p.down.back = p
+ #
+ p.left.activefunc = left
+ p.fast_left.activefunc = fast_left
+ p.right.activefunc = right
+ p.fast_right.activefunc = fast_right
+ p.forward.activefunc = forward
+ p.fast_forward.activefunc = fast_forward
+ p.reverse.activefunc = reverse
+ p.fast_reverse.activefunc = fast_reverse
+ p.up.activefunc = up
+ p.down.activefunc = down
+ #
+ makeobjects()
+ #
+ drawall(p, obswid, topwid)
+ panel.needredraw()
+ while 1:
+ act = panel.dopanel()
+ if panel.userredraw() or act:
+ drawall(p, obswid, topwid)
+
+def left(a):
+ doturn(a.back, 0.01)
+
+def fast_left(a):
+ doturn(a.back, 0.1)
+
+def right(a):
+ doturn(a.back, -0.01)
+
+def fast_right(a):
+ doturn(a.back, -0.1)
+
+def doturn(p, angle):
+ alpha = lookangle(p) + angle
+ # Reverse the following assignment:
+ # alpha = pi*1.5 - p.direction.val*2.0*pi
+ val = (pi*1.5 - alpha) / 2.0 / pi
+ while val < 0.0: val = val + 1.0
+ while val > 1.0: val = val - 1.0
+ p.direction.val = val
+ p.direction.fixact()
+
+def forward(a):
+ dostep(a.back, 1.0)
+
+def fast_forward(a):
+ dostep(a.back, 10.0)
+
+def reverse(a):
+ dostep(a.back, -1.0)
+
+def fast_reverse(a):
+ dostep(a.back, -10.0)
+
+def dostep(p, step):
+ x, y, z = observerpos(p)
+ alpha = lookangle(p)
+ x = x + step*cos(alpha)
+ z = z - step*sin(alpha)
+ # Reverse the following assignments:
+ # x = 2.0 * p.xpos.val * near - near
+ # z = near - 2.0 * p.zpos.val * near
+ p.xpos.val = (x + near) / 2.0 / near
+ p.zpos.val = - (z - near) / 2.0 / near
+ p.xpos.fixact()
+ p.zpos.fixact()
+
+def up(a):
+ doup(a.back, 0.2)
+
+def down(a):
+ doup(a.back, -0.2)
+
+def doup(p, step):
+ x, y, z = observerpos(p)
+ y = y + step
+ # Reverse:
+ # y = p.ypos.val * near
+ p.ypos.val = y/near
+ p.ypos.fixact()
+
+def drawall(p, obswid, topwid):
+ #
+ winset(obswid)
+ obsview(p)
+ drawscene()
+ swapbuffers()
+ #
+ winset(topwid)
+ topview(p)
+ drawscene()
+ drawobserver(p)
+ swapbuffers()
+
+def drawobserver(p):
+ x, y, z = observerpos(p)
+ alpha = lookangle(p)
+ fov = 2.0 + 1798.0 * p.zoom.val
+ beta = fov*pi/3600.0 # Half fov, expressed in radians
+ #
+ c3i(0, 255, 0)
+ #
+ move(x, y, z)
+ x1 = x + inf*cos(alpha+beta)
+ y1 = y
+ z1 = z - inf*sin(alpha+beta)
+ draw(x1, y1, z1)
+ #
+ move(x, y, z)
+ x1 = x + inf*cos(alpha-beta)
+ y1 = y
+ z1 = z - inf*sin(alpha-beta)
+ draw(x1, y1, z1)
+
+def observerlookat(p):
+ x, y, z = observerpos(p)
+ alpha = lookangle(p)
+ return x, y, z, x+near*cos(alpha), y, z-near*sin(alpha), 0
+
+def observerpos(p):
+ x = 2.0 * p.xpos.val * near - near
+ y = p.ypos.val * near
+ z = near - 2.0 * p.zpos.val * near
+ return x, y, z
+
+def lookangle(p):
+ return pi*1.5 - p.direction.val*2.0*pi
+
+idmat = 1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1
+
+def topview(p):
+ mmode(MVIEWING)
+ ortho(-far, far, -far, far, far, -far)
+ loadmatrix(idmat)
+ rotate(900, 'x')
+
+def obsview(p):
+ fov = 2.0 + 1798.0 * p.zoom.val
+ nearclip = p.nearclip.val * 10.0
+ farclip = p.farclip.val * 10.0*far
+ aspectratio = 1.0
+ mmode(MVIEWING)
+ perspective(int(fov), aspectratio, nearclip, farclip)
+ loadmatrix(idmat)
+ lookat(observerlookat(p))
+
+def drawscene():
+ #
+ # clear window
+ #
+ c3i(0, 0, 0)
+ clear()
+ #
+ # turn on z buffering and clear it
+ #
+ zbuffer(TRUE)
+ zclear()
+ #
+ # dark blue sky (depending on your gamma value!)
+ #
+ c3i(0, 0, 150)
+ callobj(41)
+ #
+ # bright red near and far units circle
+ # (use rotate since circ() always draws in x-y plane)
+ #
+ c3i(255, 0, 0)
+ pushmatrix()
+ rotate(900, 'x')
+ circ(0.0, 0.0, near)
+ circ(0.0, 0.0, far)
+ popmatrix()
+ #
+ # bright white striping
+ #
+ c3i(255, 255, 200)
+ callobj(42)
+ #
+ # building (does its own colors)
+ #
+ building()
+ #
+ # some other objects
+ #
+ dice()
+
+def makeobjects():
+ #
+ # sky object
+ #
+ makeobj(41)
+ pmv(-inf, 0.0, -far)
+ pdr(inf, 0.0, -far)
+ pdr(inf, inf, -far)
+ pdr(-inf, inf, -far)
+ pclos()
+ closeobj()
+ #
+ # road stripes object
+ #
+ makeobj(42)
+ stripes()
+ closeobj()
+ #
+ # lighting model definitions
+ #
+ deflight()
+
+def stripes():
+ #
+ # left line
+ #
+ botrect(-11, -10, far, -far)
+ #
+ # right line
+ #
+ botrect(10, 11, far, -far)
+ #
+ # center lines
+ #
+ z = far
+ while z > -far:
+ botrect(-0.5, 0.5, z, z - 4.0)
+ z = z - 10.0
+
+def dice():
+ from block import block
+ uselight()
+ pushmatrix()
+ translate(0.0, 1.0, -20.0)
+ rotate(200, 'y')
+ block(1, 0, 0, 0, 0, 0)
+ translate(1.0, 0.0, 3.0)
+ rotate(500, 'y')
+ block(2, 0, 0, 0, 0, 0)
+ popmatrix()
+
+def deflight():
+ # Material for first die (red)
+ lmdef(DEFMATERIAL, 1, (DIFFUSE, 1.0, 0.0, 0.0))
+ # Material for second die (green)
+ lmdef(DEFMATERIAL, 2, (DIFFUSE, 0.0, 1.0, 0.0))
+ # First light source (default: white, from front)
+ lmdef(DEFLIGHT, 1, ())
+ # Second light source (red, from back)
+ lmdef(DEFLIGHT, 2, (POSITION, 0.0, 1.0, -1.0, 0.0))
+ lmdef(DEFLIGHT, 2, (LCOLOR, 1.0, 0.0, 0.0))
+ # Lighting model
+ lmdef(DEFLMODEL, 1, (AMBIENT, 0.0, 0.0, 1.0))
+
+def uselight():
+ lmbind(LIGHT0, 1)
+ lmbind(LIGHT1, 2)
+ lmbind(LMODEL, 1)
+ # (materials are bound later)
+
+def building():
+ #
+ c3i(0, 255, 255)
+ #
+ # house bounding coordinates
+ #
+ x1 = 20.0
+ x1a = 25.0
+ x2 = 30.0
+ y1 = 0.0
+ y2 = 15.0
+ y2a = 20.0
+ z1 = -40.0
+ z2 = -55.0
+ #
+ # door y and z coordinates
+ #
+ dy1 = 0.0
+ dy2 = 4.0
+ dz1 = -45.0
+ dz2 = -47.0
+ #
+ # front side (seen from origin)
+ #
+ A1 = (x1, y1, z1)
+ B1 = (x2, y1, z1)
+ C1 = (x2, y2, z1)
+ D1 = (x1a, y2a, z1)
+ E1 = (x1, y2, z1)
+ #
+ # back size
+ #
+ A2 = (x1, y1, z2)
+ B2 = (x2, y1, z2)
+ C2 = (x2, y2, z2)
+ D2 = (x1a, y2a, z2)
+ E2 = (x1, y2, z2)
+ #
+ # door in the left side
+ #
+ P = x1, dy1, dz2
+ Q = x1, dy2, dz2
+ R = x1, dy2, dz1
+ S = x1, dy1, dz1
+ #
+ # draw it
+ #
+ concave(TRUE)
+ c3i(255, 0, 0)
+ face(A1, B1, C1, D1, E1)
+ c3i(127, 127, 0)
+ face(A1, E1, E2, A2, P, Q, R, S)
+ c3i(0, 255, 0)
+ face(E1, D1, D2, E2)
+ c3i(0, 127, 127)
+ face(D1, C1, C2, D2)
+ c3i(0, 0, 255)
+ face(C1, B1, B2, C2)
+ c3i(127, 0, 127)
+ face(E2, D2, C2, B2, A2)
+ concave(FALSE)
+
+def face(points):
+ bgnpolygon()
+ varray(points)
+ endpolygon()
+
+# draw a rectangle at y=0.0
+#
+def botrect(x1, x2, z1, z2):
+ polf(x1, 0.0, z1, x2, 0.0, z1, x2, 0.0, z2, x1, 0.0, z2)
+
+main()
diff --git a/demo/stdwin/wdiff.py b/demo/stdwin/wdiff.py
new file mode 100755
index 0000000..bc005f8
--- /dev/null
+++ b/demo/stdwin/wdiff.py
@@ -0,0 +1,480 @@
+#! /ufs/guido/bin/sgi/python
+
+# A window-oriented recursive diff utility.
+# NB: This uses undocumented window classing modules.
+
+# TO DO:
+# - faster update after moving/copying one file
+# - diff flags (-b, etc.) should be global or maintained per window
+# - use a few fixed windows instead of creating new ones all the time
+# - ways to specify patterns to skip
+# (best by pointing at a file and clicking a special menu entry!)
+# - add rcsdiff menu commands
+# - add a way to view status of selected files without opening them
+# - add a way to diff two files with different names
+# - add a way to rename files
+# - keep backups of overwritten/deleted files
+# - a way to mark specified files as uninteresting for dircmp
+
+import sys
+import posix
+import path
+import rand
+import commands
+import dircache
+import statcache
+import cmp
+import cmpcache
+import stdwin
+import gwin
+import textwin
+import filewin
+import tablewin
+import anywin
+
+mkarg = commands.mkarg
+mk2arg = commands.mk2arg
+
+# List of names to ignore in dircmp()
+# (Should be done with function, so we can specify patterns as well)
+#
+skiplist = ['RCS', '.Amake', 'tags', '.', '..']
+
+
+def anydiff(a, b, flags): # Display differences between any two objects
+ print 'diff', flags, a, b
+ if path.isdir(a) and path.isdir(b):
+ w = dirdiff(a, b, flags)
+ else:
+ w = filediff(a, b, flags)
+ addstatmenu(w, [a, b])
+ w.original_close = w.close
+ w.close = close_dirwin
+ return w
+
+def close_dirwin(w):
+ close_subwindows(w, (), 0)
+ w.original_close(w)
+
+def filediff(a, b, flags): # Display differences between two text files
+ diffcmd = 'diff'
+ if flags: diffcmd = diffcmd + mkarg(flags)
+ diffcmd = diffcmd + mkarg(a) + mkarg(b)
+ difftext = commands.getoutput(diffcmd)
+ return textwin.open_readonly(mktitle(a, b), difftext)
+
+def dirdiff(a, b, flags): # Display differences between two directories
+ data = diffdata(a, b, flags)
+ w = tablewin.open(mktitle(a, b), data)
+ w.flags = flags
+ w.a = a
+ w.b = b
+ addviewmenu(w)
+ addactionmenu(w)
+ return w
+
+def diffdata(a, b, flags): # Compute directory differences.
+ #
+ a_only = [('A only:', header_action), ('', header_action)]
+ b_only = [('B only:', header_action), ('', header_action)]
+ ab_diff = [('A <> B:', header_action), ('', header_action)]
+ ab_same = [('A == B:', header_action), ('', header_action)]
+ data = [a_only, b_only, ab_diff, ab_same]
+ #
+ a_list = dircache.listdir(a)[:]
+ b_list = dircache.listdir(b)[:]
+ dircache.annotate(a, a_list)
+ dircache.annotate(b, b_list)
+ a_list.sort()
+ b_list.sort()
+ #
+ for x in a_list:
+ if x in ['./', '../']:
+ pass
+ elif x not in b_list:
+ a_only.append(x, a_only_action)
+ else:
+ ax = path.cat(a, x)
+ bx = path.cat(b, x)
+ if path.isdir(ax) and path.isdir(bx):
+ if flags = '-r':
+ same = dircmp(ax, bx)
+ else:
+ same = 0
+ else:
+ try:
+ same = cmp.cmp(ax, bx)
+ except posix.error:
+ same = 0
+ if same:
+ ab_same.append(x, ab_same_action)
+ else:
+ ab_diff.append(x, ab_diff_action)
+ #
+ for x in b_list:
+ if x in ['./', '../']:
+ pass
+ elif x not in a_list:
+ b_only.append(x, b_only_action)
+ #
+ return data
+
+# Re-read the directory.
+# Attempt to find the selected item back.
+
+def update(w):
+ setbusy(w)
+ icol, irow = w.selection
+ if 0 <= icol < len(w.data) and 2 <= irow < len(w.data[icol]):
+ selname = w.data[icol][irow][0]
+ else:
+ selname = ''
+ statcache.forget_dir(w.a)
+ statcache.forget_dir(w.b)
+ tablewin.select(w, (-1, -1))
+ tablewin.update(w, diffdata(w.a, w.b, w.flags))
+ if selname:
+ for icol in range(len(w.data)):
+ for irow in range(2, len(w.data[icol])):
+ if w.data[icol][irow][0] = selname:
+ tablewin.select(w, (icol, irow))
+ break
+
+# Action functions for table items in directory diff windows
+
+def header_action(w, string, (icol, irow), (pos, clicks, button, mask)):
+ tablewin.select(w, (-1, -1))
+
+def a_only_action(w, string, (icol, irow), (pos, clicks, button, mask)):
+ tablewin.select(w, (icol, irow))
+ if clicks = 2:
+ w2 = anyopen(path.cat(w.a, string))
+ if w2:
+ w2.parent = w
+
+def b_only_action(w, string, (icol, irow), (pos, clicks, button, mask)):
+ tablewin.select(w, (icol, irow))
+ if clicks = 2:
+ w2 = anyopen(path.cat(w.b, string))
+ if w2:
+ w2.parent = w
+
+def ab_diff_action(w, string, (icol, irow), (pos, clicks, button, mask)):
+ tablewin.select(w, (icol, irow))
+ if clicks = 2:
+ w2 = anydiff(path.cat(w.a, string), path.cat(w.b, string), '')
+ w2.parent = w
+
+def ab_same_action(w, string, sel, detail):
+ ax = path.cat(w.a, string)
+ if path.isdir(ax):
+ ab_diff_action(w, string, sel, detail)
+ else:
+ a_only_action(w, string, sel, detail)
+
+def anyopen(name): # Open any kind of document, ignore errors
+ try:
+ w = anywin.open(name)
+ except (RuntimeError, posix.error):
+ stdwin.message('Can\'t open ' + name)
+ return 0
+ addstatmenu(w, [name])
+ return w
+
+def dircmp(a, b): # Compare whether two directories are the same
+ # To make this as fast as possible, it uses the statcache
+ print ' dircmp', a, b
+ a_list = dircache.listdir(a)
+ b_list = dircache.listdir(b)
+ for x in a_list:
+ if x in skiplist:
+ pass
+ elif x not in b_list:
+ return 0
+ else:
+ ax = path.cat(a, x)
+ bx = path.cat(b, x)
+ if statcache.isdir(ax) and statcache.isdir(bx):
+ if not dircmp(ax, bx): return 0
+ else:
+ try:
+ if not cmpcache.cmp(ax, bx): return 0
+ except posix.error:
+ return 0
+ for x in b_list:
+ if x in skiplist:
+ pass
+ elif x not in a_list:
+ return 0
+ return 1
+
+
+# View menu (for dir diff windows only)
+
+def addviewmenu(w):
+ w.viewmenu = m = w.menucreate('View')
+ m.action = []
+ add(m, 'diff -r A B', diffr_ab)
+ add(m, 'diff A B', diff_ab)
+ add(m, 'diff -b A B', diffb_ab)
+ add(m, 'diff -c A B', diffc_ab)
+ add(m, 'gdiff A B', gdiff_ab)
+ add(m, ('Open A ', 'A'), open_a)
+ add(m, ('Open B ', 'B'), open_b)
+ add(m, 'Rescan', rescan)
+ add(m, 'Rescan -r', rescan_r)
+
+# Action menu (for dir diff windows only)
+
+def addactionmenu(w):
+ w.actionmenu = m = w.menucreate('Action')
+ m.action = []
+ add(m, 'cp A B', cp_ab)
+ add(m, 'rm B', rm_b)
+ add(m, '', nop)
+ add(m, 'cp B A', cp_ba)
+ add(m, 'rm A', rm_a)
+
+# Main menu (global):
+
+def mainmenu():
+ m = stdwin.menucreate('Wdiff')
+ m.action = []
+ add(m, ('Quit wdiff', 'Q'), quit_wdiff)
+ add(m, 'Close subwindows', close_subwindows)
+ return m
+
+def add(m, text, action):
+ m.additem(text)
+ m.action.append(action)
+
+def quit_wdiff(w, m, item):
+ if askyesno('Really quit wdiff altogether?', 1):
+ sys.exit(0)
+
+def close_subwindows(w, m, item):
+ while 1:
+ for w2 in gwin.windows:
+ if w2.parent = w:
+ close_subwindows(w2, m, item)
+ w2.close(w2)
+ break # inner loop, continue outer loop
+ else:
+ break # outer loop
+
+def diffr_ab(w, m, item):
+ dodiff(w, '-r')
+
+def diff_ab(w, m, item):
+ dodiff(w, '')
+
+def diffb_ab(w, m, item):
+ dodiff(w, '-b')
+
+def diffc_ab(w, m, item):
+ dodiff(w, '-c')
+
+def gdiff_ab(w, m, item): # Call SGI's gdiff utility
+ x = getselection(w)
+ if x:
+ a, b = path.cat(w.a, x), path.cat(w.b, x)
+ if path.isdir(a) or path.isdir(b):
+ stdwin.fleep() # This is for files only
+ else:
+ diffcmd = 'gdiff'
+ diffcmd = diffcmd + mkarg(a) + mkarg(b) + ' &'
+ print diffcmd
+ sts = posix.system(diffcmd)
+ if sts: print 'Exit status', sts
+
+def dodiff(w, flags):
+ x = getselection(w)
+ if x:
+ w2 = anydiff(path.cat(w.a, x), path.cat(w.b, x), flags)
+ w2.parent = w
+
+def open_a(w, m, item):
+ x = getselection(w)
+ if x:
+ w2 = anyopen(path.cat(w.a, x))
+ if w2:
+ w2.parent = w
+
+def open_b(w, m, item):
+ x = getselection(w)
+ if x:
+ w2 = anyopen(path.cat(w.b, x))
+ if w2:
+ w2.parent = w
+
+def rescan(w, m, item):
+ w.flags = ''
+ update(w)
+
+def rescan_r(w, m, item):
+ w.flags = '-r'
+ update(w)
+
+def rm_a(w, m, item):
+ x = getselection(w)
+ if x:
+ if x[-1:] = '/': x = x[:-1]
+ x = path.cat(w.a, x)
+ if path.isdir(x):
+ if askyesno('Recursively remove A directory ' + x, 1):
+ runcmd('rm -rf' + mkarg(x))
+ else:
+ runcmd('rm -f' + mkarg(x))
+ update(w)
+
+def rm_b(w, m, item):
+ x = getselection(w)
+ if x:
+ if x[-1:] = '/': x = x[:-1]
+ x = path.cat(w.b, x)
+ if path.isdir(x):
+ if askyesno('Recursively remove B directory ' + x, 1):
+ runcmd('rm -rf' + mkarg(x))
+ else:
+ runcmd('rm -f' + mkarg(x))
+ update(w)
+
+def cp_ab(w, m, item):
+ x = getselection(w)
+ if x:
+ if x[-1:] = '/': x = x[:-1]
+ ax = path.cat(w.a, x)
+ bx = path.cat(w.b, x)
+ if path.isdir(ax):
+ if path.exists(bx):
+ m = 'Can\'t copy directory to existing target'
+ stdwin.message(m)
+ return
+ runcmd('cp -r' + mkarg(ax) + mkarg(w.b))
+ else:
+ runcmd('cp' + mkarg(ax) + mk2arg(w.b, x))
+ update(w)
+
+def cp_ba(w, m, item):
+ x = getselection(w)
+ if x:
+ if x[-1:] = '/': x = x[:-1]
+ ax = path.cat(w.a, x)
+ bx = path.cat(w.b, x)
+ if path.isdir(bx):
+ if path.exists(ax):
+ m = 'Can\'t copy directory to existing target'
+ stdwin.message(m)
+ return
+ runcmd('cp -r' + mkarg(bx) + mkarg(w.a))
+ else:
+ runcmd('cp' + mk2arg(w.b, x) + mkarg(ax))
+ update(w)
+
+def nop(args):
+ pass
+
+def getselection(w):
+ icol, irow = w.selection
+ if 0 <= icol < len(w.data):
+ if 0 <= irow < len(w.data[icol]):
+ return w.data[icol][irow][0]
+ stdwin.message('no selection')
+ return ''
+
+def runcmd(cmd):
+ print cmd
+ sts, output = commands.getstatusoutput(cmd)
+ if sts or output:
+ if not output:
+ output = 'Exit status ' + `sts`
+ stdwin.message(output)
+
+
+# Status menu (for all kinds of windows)
+
+def addstatmenu(w, files):
+ w.statmenu = m = w.menucreate('Stat')
+ m.files = files
+ m.action = []
+ for file in files:
+ m.additem(commands.getstatus(file))
+ m.action.append(stataction)
+
+def stataction(w, m, item): # Menu item action for stat menu
+ file = m.files[item]
+ try:
+ m.setitem(item, commands.getstatus(file))
+ except posix.error:
+ stdwin.message('Can\'t get status for ' + file)
+
+
+# Compute a suitable window title from two paths
+
+def mktitle(a, b):
+ if a = b: return a
+ i = 1
+ while a[-i:] = b[-i:]: i = i+1
+ i = i-1
+ if not i:
+ return a + ' ' + b
+ else:
+ return '{' + a[:-i] + ',' + b[:-i] + '}' + a[-i:]
+
+
+# Ask a confirmation question
+
+def askyesno(prompt, default):
+ try:
+ return stdwin.askync(prompt, default)
+ except KeyboardInterrupt:
+ return 0
+
+
+# Display a message "busy" in a window, and mark it for updating
+
+def setbusy(w):
+ left, top = w.getorigin()
+ width, height = w.getwinsize()
+ right, bottom = left + width, top + height
+ d = w.begindrawing()
+ d.erase((0, 0), (10000, 10000))
+ text = 'Busy...'
+ textwidth = d.textwidth(text)
+ textheight = d.lineheight()
+ h, v = left + (width-textwidth)/2, top + (height-textheight)/2
+ d.text((h, v), text)
+ del d
+ w.change((0, 0), (10000, 10000))
+
+
+# Main function
+
+def main():
+ print 'wdiff: warning: this version does NOT yet make backups'
+ argv = sys.argv
+ flags = ''
+ if len(argv) >= 2 and argv[1][:1] = '-':
+ flags = argv[1]
+ del argv[1]
+ m = mainmenu() # Create menu earlier than windows
+ if len(argv) = 2: # 1 argument
+ w = anyopen(argv[1])
+ if not w: return
+ elif len(argv) = 3: # 2 arguments
+ w = anydiff(argv[1], argv[2], flags)
+ w.parent = ()
+ else:
+ sys.stdout = sys.stderr
+ print 'usage:', argv[0], '[diff-flags] dir-1 [dir-2]'
+ sys.exit(2)
+ del w # It's preserved in gwin.windows
+ while 1:
+ try:
+ gwin.mainloop()
+ break
+ except KeyboardInterrupt:
+ pass # Just continue...
+
+# Start the main function (this is a script)
+main()
diff --git a/doc/Makefile b/doc/Makefile
new file mode 100644
index 0000000..f2a83bf
--- /dev/null
+++ b/doc/Makefile
@@ -0,0 +1,47 @@
+# Makefile for Python documentation.
+
+LATEX= latex
+DVIPS= dvips
+TEXPREVIEW= xdvi
+
+PRINT= lpr
+
+tut: tut.dvi
+ $(TEXPREVIEW) tut
+
+tut.dvi tut.ps: tut.toc tut.tex myformat.sty
+
+mod: mod.dvi
+ $(TEXPREVIEW) mod
+
+mod.dvi mod.ps: mod.toc mod.tex mod1.tex mod2.tex mod3.tex myformat.sty
+
+ALL= tut.ps mod.ps
+
+all: $(ALL)
+
+print: $(ALL)
+ $(PRINT) $(ALL)
+
+clean:
+ rm -f *.dvi *.aux *.toc *.log *.ps core [#@,]* *~
+
+.SUFFIXES: # Remove default suffixes
+
+.SUFFIXES: .tex .aux .toc .dvi .ps
+
+.tex.aux:
+ $(LATEX) $*
+
+.tex.toc:
+ $(LATEX) $*
+
+.tex.dvi:
+ $(LATEX) $*
+
+.dvi.ps:
+ $(DVIPS) $* >$*.ps
+
+.tex.ps:
+ $(LATEX) $*
+ $(DVIPS) $* >$*.ps
diff --git a/doc/README b/doc/README
new file mode 100644
index 0000000..14c3de9
--- /dev/null
+++ b/doc/README
@@ -0,0 +1,24 @@
+This directory contains the LaTeX source to the Python documentation.
+The documentation is not all finished, but good enough to get you
+started.
+
+The following are the important latex source files:
+
+ tut.tex A tutorial
+ mod.tex The library reference
+
+They both read the style option file "myformat.sty".
+
+You can use the Makefile to format, preview and print the documents.
+Type "make tut" or "make mod" to preview either document with xdvi.
+Type "make print" to print them both (this only works if your print
+spooler is set up just like mine...), or "make all" to create postscript
+files that you can you can print using your local printing commands.
+Type "make clean" to get rid of all the intermediate files produced by
+the latex process, and other junk files.
+
+You can just as well ignore the Makefile; all you really need is:
+ latex tut
+ latex tut
+ dvips tut | lpr
+and similar for the "mod" document.
diff --git a/doc/SetClass.py b/doc/SetClass.py
new file mode 100644
index 0000000..8a5fb9e
--- /dev/null
+++ b/doc/SetClass.py
@@ -0,0 +1,17 @@
+class Set():
+ def new(self):
+ self.elements = []
+ return self
+ def add(self, e):
+ if e not in self.elements:
+ self.elements.append(e)
+ def remove(self, e):
+ if e in self.elements:
+ for i in range(len(self.elements)):
+ if self.elements[i] = e:
+ del self.elements[i]
+ break
+ def is_element(self, e):
+ return e in self.elements
+ def size(self):
+ return len(self.elements)
diff --git a/doc/fibo.py b/doc/fibo.py
new file mode 100644
index 0000000..e8cafa8
--- /dev/null
+++ b/doc/fibo.py
@@ -0,0 +1,15 @@
+# Fibonacci numbers demo
+
+def fib(n): # write Fibonacci series up to n
+ a, b = 0, 1
+ while b <= n:
+ print b,
+ a, b = b, a+b
+
+def fib2(n): # return Fibonacci series up to n
+ ret = []
+ a, b = 0, 1
+ while b <= n:
+ ret.append(b)
+ a, b = b, a+b
+ return ret
diff --git a/doc/mod.tex b/doc/mod.tex
new file mode 100644
index 0000000..c2d2355
--- /dev/null
+++ b/doc/mod.tex
@@ -0,0 +1,62 @@
+% Format this file with latex.
+
+%\documentstyle[garamond,11pt,myformat]{article}
+\documentstyle[11pt,myformat]{article}
+
+% A command to force the text after an item to start on a new line
+\newcommand{\itembreak}{
+ \mbox{}\\*[0mm]
+}
+
+% A command to define a function item
+\newcommand{\funcitem}[2]{\item[#1(#2)]}
+
+% A command to define an exception item
+\newcommand{\excitem}[2]{
+\item[#1 = {\tt '#2'}]
+\itembreak
+}
+
+\title{\bf
+ Python Library Reference \\
+ (DRAFT)
+}
+
+\author{
+ Guido van Rossum \\
+ Dept. CST, CWI, Kruislaan 413 \\
+ 1098 SJ Amsterdam, The Netherlands \\
+ E-mail: {\tt [email protected]}
+}
+
+\begin{document}
+
+\pagenumbering{roman}
+
+\maketitle
+
+\begin{abstract}
+
+\noindent
+This document describes the built-in types, exceptions and functions and
+the standard modules that come with the {\Python} system.
+It assumes basic knowledge about the {\Python} language.
+For an informal introduction to the language, see the Tutorial document.
+The Language Reference document (XXX not yet existing)
+gives a more formal reference to the language.
+
+\end{abstract}
+
+\pagebreak
+
+\tableofcontents
+
+\pagebreak
+
+\pagenumbering{arabic}
+
+\input{mod1.tex}
+\input{mod2.tex}
+\input{mod3.tex}
+
+\end{document}
diff --git a/doc/mod1.tex b/doc/mod1.tex
new file mode 100644
index 0000000..2dac554
--- /dev/null
+++ b/doc/mod1.tex
@@ -0,0 +1,521 @@
+\section{Introduction}
+
+The {\Python} library consists of three parts, with different levels of
+integration with the interpreter.
+Closest to the interpreter are built-in types, exceptions and functions.
+Next are built-in modules, which are written in C and linked statically
+with the interpreter.
+Finally there are standard modules that are implemented entirely in
+{\Python}, but are always available.
+For efficiency, some standard modules may become built-in modules in
+future versions of the interpreter.
+
+\section{Built-in Types, Exceptions and Functions}
+
+Names for built-in exceptions and functions are found in a separate
+read-only symbol table which cannot be modified.
+This table is searched last, so local and global user-defined names can
+override built-in names.
+Built-in types have no names but are created by syntactic constructs
+(such as constants) or built-in functions.
+They are described together here for easy reference.%
+\footnote{
+The descriptions sorely lack explanations of the exceptions that
+may be raised---this will be fixed in a future version of this
+document.
+}
+
+\subsection{Built-in Types}
+
+The following sections describe the standard types that are built into the
+interpreter.
+\subsubsection{Numeric Types}
+
+There are two numeric types: integers and floating point numbers.
+Integers are implemented using {\tt long} in C, so they have at least 32
+bits of precision.
+Floating point numbers are implemented using {\tt double} in C.
+All bets on precision are off.
+Numbers are created by numeric constants or as the result of built-in
+functions and operators.
+
+Numeric types support the following operations:
+
+\begin{center}
+\begin{tabular}{|c|l|c|}
+\hline
+Operation & Result & Notes \\
+\hline
+{\tt abs}({\em x}) & absolute value of {\em x} & \\
+{\tt int}({\em x}) & {\em x} converted to integer & (1) \\
+{\tt float}({\em x}) & {\em x} converted to floating point & \\
+{\tt -}{\em x} & {\em x} negated & \\
+{\tt +}{\em x} & {\em x} unchanged & \\
+{\em x}{\tt +}{\em y} & sum of {\em x} and {\em y} & \\
+{\em x}{\tt -}{\em y} & difference of {\em x} and {\em y} & \\
+{\em x}{\tt *}{\em y} & product of {\em x} and {\em y} & \\
+{\em x}{\tt /}{\em y} & quotient of {\em x} and {\em y} & (2) \\
+{\em x}{\tt \%}{\em y} & remainder of {\em x}{\tt /}{\em y} & (3) \\
+\hline
+\end{tabular}
+\end{center}
+
+\noindent
+Notes:
+\begin{description}
+\item[(1)]
+This may round or truncate as in C; see functions {\tt floor} and
+{\tt ceil} in module {\tt math}.
+\item[(2)]
+Integer division is defined as in C: the result is an integer; with
+positive operands, it truncates towards zero; with a negative operand,
+the result is unspecified.
+\item[(3)]
+Only defined for integers.
+\end{description}
+
+Mixed arithmetic is not supported; both operands must have the same type.
+Mixed comparisons return the wrong result (floats always compare smaller
+than integers).%
+\footnote{
+These restrictions are bugs in the language definitions and will be
+fixed in the future.
+}
+\subsubsection{Sequence Types}
+
+There are three sequence types: strings, lists and tuples.
+Strings constants are written in single quotes: {\tt 'xyzzy'}.
+Lists are constructed with square brackets: {\tt [a,~b,~c]}.
+Tuples are constructed by the comma operator or with an empty set of
+parentheses: {\tt a,~b,~c} or {\tt ()}.
+
+Sequence types support the following operations ({\em s} and {\em t} are
+sequences of the same type; {\em n}, {\em i} and {\em j} are integers):
+
+\begin{center}
+\begin{tabular}{|c|l|c|}
+\hline
+Operation & Result & Notes \\
+\hline
+{\tt len}({\em s}) & length of {\em s} & \\
+{\tt min}({\em s}) & smallest item of {\em s} & \\
+{\tt max}({\em s}) & largest item of {\em s} & \\
+{\em x} {\tt in} {\em s} &
+ true if an item of {\em s} is equal to {\em x} & \\
+{\em x} {\tt not} {\tt in} {\em s} &
+ false if an item of {\em s} is equal to {\em x} & \\
+{\em s}{\tt +}{\em t} & the concatenation of {\em s} and {\em t} & \\
+{\em s}{\tt *}{\em n}, {\em n}*{\em s} &
+ {\em n} copies of {\em s} concatenated & (1) \\
+{\em s}[{\em i}] & {\em i}'th item of {\em s} & \\
+{\em s}[{\em i}:{\em j}] &
+ slice of {\em s} from {\em i} to {\em j} & (2) \\
+\hline
+\end{tabular}
+\end{center}
+
+\noindent
+Notes:
+\begin{description}
+\item[(1)]
+Sequence repetition is only supported for strings.
+\item[(2)]
+The slice of $s$ from $i$ to $j$ is defined as the sequence
+of items with index $k$ such that $i \leq k < j$.
+Special rules apply for negative and omitted indices; see the Tutorial
+or the Reference Manual.
+\end{description}
+
+\paragraph{Mutable Sequence Types.}
+
+List objects support additional operations that allow in-place
+modification of the object.
+These operations would be supported by other mutable sequence types
+(when added to the language) as well.
+Strings and tuples are immutable sequence types and such objects cannot
+be modified once created.
+The following operations are defined on mutable sequence types (where
+{\em x} is an arbitrary object):
+
+\begin{center}
+\begin{tabular}{|c|l|}
+\hline
+Operation & Result \\
+\hline
+{\em s}[{\em i}] = {\em x} &
+ item {\em i} of {\em s} is replaced by {\em x} \\
+{\em s}[{\em i}:{\em j}] = {\em t} &
+ slice of {\em s} from {\em i} to {\em j} is replaced by {\em t} \\
+{\tt del} {\em s}[{\em i}:{\em j}] &
+ same as {\em s}[{\em i}:{\em j}] = [] \\
+{\em s}.{\tt append}({\em x}) &
+ same as {\em s}[{\tt len}({\em x}):{\tt len}({\em x})] = [{\em x}] \\
+{\em s}.{\tt insert}({\em i}, {\em x}) &
+ same as {\em s}[{\em i}:{\em i}] = [{\em x}] \\
+{\em s}.{\tt sort}() &
+ the items of {\em s} are permuted to satisfy \\
+ &
+ $s[i] \leq s[j]$ for $i < j$\\
+\hline
+\end{tabular}
+\end{center}
+
+\subsubsection{Mapping Types}
+
+A
+{\em mapping}
+object maps values of one type (the key type) to arbitrary objects.
+Mappings are mutable objects.
+There is currently only one mapping type, the
+{\em dictionary}.
+A dictionary's keys are strings.
+An empty dictionary is created by the expression \verb"{}".
+An extension of this notation is used to display dictionaries when
+written (see the example below).
+
+The following operations are defined on mappings (where {\em a} is a
+mapping, {\em k} is a key and {\em x} is an arbitrary object):
+
+\begin{center}
+\begin{tabular}{|c|l|c|}
+\hline
+Operation & Result & Notes\\
+\hline
+{\tt len}({\em a}) & the number of elements in {\em a} & \\
+{\em a}[{\em k}] & the item of {\em a} with key {\em k} & \\
+{\em a}[{\em k}] = {\em x} & set {\em a}[{\em k}] to {\em x} & \\
+{\tt del} {\em a}[{\em k}] & remove {\em a}[{\em k}] from {\em a} & \\
+{\em a}.{\tt keys}() & a copy of {\em a}'s list of keys & (1) \\
+{\em a}.{\tt has\_key}({\em k}) & true if {\em a} has a key {\em k} & \\
+\hline
+\end{tabular}
+\end{center}
+
+\noindent
+Notes:
+\begin{description}
+\item[(1)]
+Keys are listed in random order.
+\end{description}
+
+A small example using a dictionary:
+\bcode\begin{verbatim}
+>>> tel = {}
+>>> tel['jack'] = 4098
+>>> tel['sape'] = 4139
+>>> tel['guido'] = 4127
+>>> tel['jack']
+4098
+>>> tel
+{'sape': 4139; 'guido': 4127; 'jack': 4098}
+>>> del tel['sape']
+>>> tel['irv'] = 4127
+>>> tel
+{'guido': 4127; 'irv': 4127; 'jack': 4098}
+>>> tel.keys()
+['guido', 'irv', 'jack']
+>>> tel.has_key('guido')
+1
+>>>
+\end{verbatim}\ecode
+\subsubsection{Other Built-in Types}
+
+The interpreter supports several other kinds of objects.
+Most of these support only one or two operations.
+
+\paragraph{Modules.}
+
+The only operation on a module is member acces: {\em m}{\tt .}{\em name},
+where {\em m} is a module and {\em name} accesses a name defined in
+{\em m}'s symbol table.
+Module members can be assigned to.
+
+\paragraph{Classes and Class Objects.}
+
+XXX Classes will be explained at length in a later version of this
+document.
+
+\paragraph{Functions.}
+
+Function objects are created by function definitions.
+The only operation on a function object is to call it:
+{\em func}({\em optional-arguments}).
+
+Built-in functions have a different type than user-defined functions,
+but they support the same operation.
+
+\paragraph{Methods.}
+
+Methods are functions that are called using the member acces notation.
+There are two flavors: built-in methods (such as {\tt append()} on
+lists) and class member methods.
+Built-in methods are described with the types that support them.
+XXX Class member methods will be described in a later version of this
+document.
+
+\paragraph{Type Objects.}
+
+Type objects represent the various object types.
+An object's type is accessed by the built-in function
+{\tt type()}.
+There are no operations on type objects.
+
+\paragraph{The Null Object.}
+
+This object is returned by functions that don't explicitly return a
+value.
+It supports no operations.
+There is exactly one null object, named {\tt None}
+(a built-in name).
+
+\paragraph{File Objects.}
+
+File objects are implemented using C's
+{\em stdio}
+package and can be created with the built-in function
+{\tt open()}.
+They have the following methods:
+\begin{description}
+\funcitem{close}{}
+Closes the file.
+A closed file cannot be read or written anymore.
+\funcitem{read}{size}
+Reads at most
+{\tt size}
+bytes from the file (less if the read hits EOF).
+The bytes are returned as a string object.
+An empty string is returned when EOF is hit immediately.
+(For certain files, like ttys, it makes sense to continue reading after
+an EOF is hit.)
+\funcitem{readline}{size}
+Reads a line of at most
+{\tt size}
+bytes from the file.
+A trailing newline character, if present, is kept in the string.
+The size is optional and defaults to a large number (but not infinity).
+EOF is reported as by
+{\tt read().}
+\funcitem{write}{str}
+Writes a string to the file.
+Returns no value.
+\end{description}
+
+\subsection{Built-in Exceptions}
+
+The following exceptions can be generated by the interpreter or
+built-in functions.
+Except where mentioned, they have a string argument (also known as the
+`associated value' of an exception) indicating the detailed cause of the
+error.
+The strings listed with the exception names are their values when used
+in an expression or printed.
+\begin{description}
+\excitem{EOFError}{end-of-file read}
+(No argument.)
+Raised when a built-in function ({\tt input()} or {\tt raw\_input()})
+hits an end-of-file condition (EOF) without reading any data.
+(N.B.: the {\tt read()} and {\tt readline()} methods of file objects
+return an empty string when they hit EOF.)
+\excitem{KeyboardInterrupt}{end-of-file read}
+(No argument.)
+Raised when the user hits the interrupt key (normally Control-C or DEL).
+During execution, a check for interrupts is made regularly.
+Interrupts typed when a built-in function ({\tt input()} or
+{\tt raw\_input()}) is waiting for input also raise this exception.
+\excitem{MemoryError}{out of memory}
+%.br
+Raised when an operation runs out of memory but the situation
+may still be rescued (by deleting some objects).
+\excitem{NameError}{undefined name}
+%.br
+Raised when a name is not found.
+This applies to unqualified names, module names (on {\tt import}),
+module members and object methods.
+The string argument is the name that could not be found.
+\excitem{RuntimeError}{run-time error}
+%.br
+Raised for a variety of reasons, e.g., division by zero or index out of
+range.
+\excitem{SystemError}{system error}
+%.br
+Raised when the interpreter finds an internal error, but the situation
+does not look so serious to cause it to abandon all hope.
+\excitem{TypeError}{type error}
+%.br
+Raised when an operation or built-in function is applied to an object of
+inappropriate type.
+\end{description}
+
+\subsection{Built-in Functions}
+
+The {\Python} interpreter has a small number of functions built into it that
+are always available.
+They are listed here in alphabetical order.
+\begin{description}
+\funcitem{abs}{x}
+Returns the absolute value of a number.
+The argument may be an integer or floating point number.
+\funcitem{chr}{i}
+Returns a string of one character
+whose ASCII code is the integer {\tt i},
+e.g., {\tt chr(97)} returns the string {\tt 'a'}.
+This is the inverse of {\tt ord()}.
+\funcitem{dir}{}
+Without arguments, this function returns the list of names in the
+current local symbol table, sorted alphabetically.
+With a module object as argument, it returns the sorted list of names in
+that module's global symbol table.
+For example:
+\bcode\begin{verbatim}
+>>> import sys
+>>> dir()
+['sys']
+>>> dir(sys)
+['argv', 'exit', 'modules', 'path', 'stderr', 'stdin', 'stdout']
+>>>
+\end{verbatim}\ecode
+\funcitem{divmod}{a, b}
+%.br
+Takes two integers as arguments and returns a pair of integers
+consisting of their quotient and remainder.
+For
+\bcode\begin{verbatim}
+q, r = divmod(a, b)
+\end{verbatim}\ecode
+the invariants are:
+\bcode\begin{verbatim}
+a = q*b + r
+abs(r) < abs(b)
+r has the same sign as b
+\end{verbatim}\ecode
+For example:
+\bcode\begin{verbatim}
+>>> divmod(100, 7)
+(14, 2)
+>>> divmod(-100, 7)
+(-15, 5)
+>>> divmod(100, -7)
+(-15, -5)
+>>> divmod(-100, -7)
+(14, -2)
+>>>
+\end{verbatim}\ecode
+\funcitem{eval}{s}
+Takes a string as argument and parses and evaluates it as a {\Python}
+expression.
+The expression is executed using the current local and global symbol
+tables.
+Syntax errors are reported as exceptions.
+For example:
+\bcode\begin{verbatim}
+>>> x = 1
+>>> eval('x+1')
+2
+>>>
+\end{verbatim}\ecode
+\funcitem{exec}{s}
+Takes a string as argument and parses and evaluates it as a sequence of
+{\Python} statements.
+The string should end with a newline (\verb"'\n'").
+The statement is executed using the current local and global symbol
+tables.
+Syntax errors are reported as exceptions.
+For example:
+\bcode\begin{verbatim}
+>>> x = 1
+>>> exec('x = x+1\n')
+>>> x
+2
+>>>
+\end{verbatim}\ecode
+\funcitem{float}{x}
+Converts a number to floating point.
+The argument may be an integer or floating point number.
+\funcitem{input}{s}
+Equivalent to
+{\tt eval(raw\_input(s))}.
+As for
+{\tt raw\_input()},
+the argument is optional.
+\funcitem{int}{x}
+Converts a number to integer.
+The argument may be an integer or floating point number.
+\funcitem{len}{s}
+Returns the length (the number of items) of an object.
+The argument may be a sequence (string, tuple or list) or a mapping
+(dictionary).
+\funcitem{max}{s}
+Returns the largest item of a non-empty sequence (string, tuple or list).
+\funcitem{min}{s}
+Returns the smallest item of a non-empty sequence (string, tuple or list).
+\funcitem{open}{name, mode}
+%.br
+Returns a file object (described earlier under Built-in Types).
+The string arguments are the same as for stdio's
+{\tt fopen()}:
+{\tt 'r'}
+opens the file for reading,
+{\tt 'w'}
+opens it for writing (truncating an existing file),
+{\tt 'a'}
+opens it for appending.%
+\footnote{
+This function should go into a built-in module
+{\tt io}.
+}
+\funcitem{ord}{c}
+Takes a string of one character and returns its
+ASCII value, e.g., {\tt ord('a')} returns the integer {\tt 97}.
+This is the inverse of {\tt chr()}.
+\funcitem{range}{}
+This is a versatile function to create lists containing arithmetic
+progressions of integers.
+With two integer arguments, it returns the ascending sequence of
+integers starting at the first and ending one before the second
+argument.
+A single argument is used as the end point of the sequence, with 0 used
+as the starting point.
+A third argument specifies the step size; negative steps are allowed and
+work as expected, but don't specify a zero step.
+The resulting list may be empty.
+For example:
+\bcode\begin{verbatim}
+>>> range(10)
+[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+>>> range(1, 1+10)
+[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
+>>> range(0, 30, 5)
+[0, 5, 10, 15, 20, 25]
+>>> range(0, 10, 3)
+[0, 3, 6, 9]
+>>> range(0, -10, -1)
+[0, -1, -2, -3, -4, -5, -6, -7, -8, -9]
+>>> range(0)
+[]
+>>> range(1, 0)
+[]
+>>>
+\end{verbatim}\ecode
+\funcitem{raw\_input}{s}
+%.br
+The argument is optional; if present, it is written to standard output
+without a trailing newline.
+The function then reads a line from input, converts it to a string
+(stripping a trailing newline), and returns that.
+EOF is reported as an exception.
+For example:
+\bcode\begin{verbatim}
+>>> raw_input('Type anything: ')
+Type anything: Mutant Teenage Ninja Turtles
+'Mutant Teenage Ninja Turtles'
+>>>
+\end{verbatim}\ecode
+\funcitem{reload}{module}
+Causes an already imported module to be re-parsed and re-initialized.
+This is useful if you have edited the module source file and want to
+try out the new version without leaving {\Python}.
+\funcitem{type}{x}
+Returns the type of an object.
+Types are objects themselves:
+the type of a type object is its own type.
+\end{description}
diff --git a/doc/mod2.tex b/doc/mod2.tex
new file mode 100644
index 0000000..46f6d62
--- /dev/null
+++ b/doc/mod2.tex
@@ -0,0 +1,1083 @@
+\section{Built-in Modules}
+
+The modules described in this section are built into the interpreter.
+They must be imported using
+{\tt import}.
+Some modules are not always available; it is a configuration option to
+provide them.
+Details are listed with the descriptions, but the best way to see if
+a module exists in a particular implementation is to attempt to import
+it.
+
+\subsection{Built-in Module {\tt sys}}
+
+This module provides access to some variables used or maintained by the
+interpreter and to functions that interact strongly with the interpreter.
+It is always available.
+\begin{description}
+\funcitem{argv}
+The list of command line arguments passed to a {\Python} script.
+{\tt sys.argv[0]}
+is the script name.
+If no script name was passed to the {\Python} interpreter,
+{\tt sys.argv}
+is empty.
+\funcitem{exit}{n}
+Exits from {\Python} with numeric exit status
+{\tt n}.
+This closes all open files and performs other cleanup-actions required by
+the interpreter (but
+{\em finally clauses}
+of
+{\tt try}
+statements are not executed!).
+\funcitem{modules}
+Gives the list of modules that have already been loaded.
+This can be manipulated to force reloading of modules and other tricks.
+\funcitem{path}
+A list of strings that specifies the search path for modules.
+Initialized from the environment variable {\tt PYTHONPATH}, or an
+installation-dependent default.
+\funcitem{ps1,~ps2}
+Strings specifying the primary and secondary prompt of the interpreter.
+These are only defined if the interpreter is in interactive mode.
+Their initial values in this case are
+{\tt '>>> '}
+and
+{\tt '... '}.
+\funcitem{stdin, stdout, stderr}
+%.br
+File objects corresponding to the interpreter's standard input, output
+and error streams.
+{\tt sys.stdin}
+is used for all interpreter input except for scripts but including calls
+to
+{\tt input()}
+and
+{\tt raw\_input()}.
+{\tt sys.stdout}
+is used for the output of
+{\tt print} and expression statements
+and for the prompts of
+{\tt input()}
+and
+{\tt raw\_input()}.
+The interpreter's own prompts and its error messages are written to
+stderr.
+Assigning to
+{\tt sys.stderr}
+has no effect on the interpreter; it can be used to write error messages
+to stderr using
+{\tt print}.
+\end{description}
+
+\subsection{Built-in Module {\tt math}}
+
+This module is always available.
+It provides access to the mathematical functions defined by the C
+standard.
+They are:
+{\tt acos(x)},
+{\tt asin(x)},
+{\tt atan(x)},
+{\tt atan2(x,y)},
+{\tt ceil(x)},
+{\tt cos(x)},
+{\tt cosh(x)},
+{\tt exp(x)},
+{\tt fabs(x)},
+{\tt floor(x)},
+%{\tt fmod(...)} XXX not yet
+%{\tt frexp(...)} XXX not yet
+%{\tt ldexp(...)} XXX not yet
+{\tt log(x)},
+{\tt log10(x)},
+%{\tt modf(...)} XXX not yet
+{\tt pow(x,y)},
+{\tt sin(x)},
+{\tt sinh(x)},
+{\tt sqrt(x)},
+{\tt tan(x)},
+{\tt tanh(x)}.
+
+It also defines two mathematical constants:
+{\tt pi}
+and
+{\tt e}.
+
+\subsection{Built-in Module {\tt time}}
+
+This module provides various time-related functions.
+It is always available.
+Functions are:
+\begin{description}
+\funcitem{sleep}{secs}
+Suspends execution for the given number of seconds.
+\funcitem{time}{}
+Returns the time in seconds since the Epoch (Thursday January 1,
+00:00:00, 1970 UCT on \UNIX\ machines).
+\end{description}
+
+\noindent
+In some versions (Amoeba, Mac) the following functions also exist:
+\begin{description}
+\funcitem{millisleep}{msecs}
+Suspends execution for the given number of milliseconds.
+\funcitem{millitimer}{}
+Returns the number of milliseconds of real time elapsed since some point
+in the past that is fixed per execution of the python interpreter (but
+may change in each following run).
+\end{description}
+
+\noindent
+The granularity of the milliseconds functions may be more than a
+millisecond (100 msecs on Amoeba, 1/60 sec on the Mac).
+
+\subsection{Built-in Module {\tt regexp}}
+
+This module provides a regular expression matching operation.
+It is always available.
+
+The module defines a function and an exception:
+
+\begin{description}
+
+\funcitem{compile}{pattern}
+
+Compile a regular expression given as a string into a regular
+expression object.
+The string must be an egrep-style regular expression;
+this means that the characters
+{\tt '(' ')' '*' '+' '?'\ '|' }\verb='^' '$'=
+are special.
+(It is implemented using Henry Spencer's regular expression matching
+functions.)
+
+excitem{error}{regexp.error}
+
+Exception raised when a string passed to {\tt compile()} is not a
+valid regular expression (e.g., unmatched parentheses) or when some other
+error occurs during compilation or matching
+(``no match found'' is not an error).
+
+\end{description}
+
+Compiled regular expression objects support a single method:
+
+\begin{description}
+
+\funcitem{exec}{str}
+
+Find the first occurrence of the compiled regular expression in the
+string {\tt str}.
+The return value is a tuple of pairs specifying where a match was
+found and where matches were found for subpatterns specified with
+{\tt '('} and {\tt ')'} in the pattern.
+If no match is found, an empty tuple is returned; otherwise the first
+item of the tuple is a pair of slice indices into the search string
+giving the match found.
+If there were any subpatterns in the pattern, the returned tuple has an
+additional item for each subpattern, giving the slice indices into the
+search string where that subpattern was found.
+
+\end{description}
+
+For example:
+\bcode\begin{verbatim}
+>>> import regexp
+>>> r = regexp.compile('--(.*)--')
+>>> s = 'a--b--c'
+>>> r.exec(s)
+((1, 6), (3, 4))
+>>> s[1:6] # The entire match
+'--b--'
+>>> s[3:4] # The subpattern
+'b'
+>>>
+\end{verbatim}\ecode
+
+\subsection{Built-in Module {\tt posix}}
+
+This module provides access to operating system functionality that is
+standardized by the C Standard and the POSIX standard (a thinly diguised
+{\UNIX} interface).
+It is available in all {\Python} versions except on the Macintosh.
+Errors are reported exceptions.
+It defines the following items:
+\begin{description}
+\funcitem{chdir}{path}
+Changes the current directory to
+{\tt path}.
+\funcitem{chmod}{path, mode}
+Change the mode of
+{\tt path}
+to the numeric
+{\tt mode}.
+\funcitem{environ}
+A dictionary representing the string environment at the time
+the interpreter was started.
+(Modifying this dictionary does not affect the string environment of the
+interpreter.)
+For example,
+{\tt posix.environ['HOME']}
+is the pathname of your home directory, equivalent to
+{\tt getenv("HOME")}
+in C.
+\excitem{error}{posix.error}
+%.br
+The exception raised when an POSIX function returns an error.
+The value accompanying this exception is a pair containing the numeric
+error code from
+{\tt errno}
+and the corresponding string, as would be printed by the C function
+{\tt perror()}.
+\funcitem{getcwd}{}
+Returns a string representing the current working directory.
+\funcitem{link}{src, dst}
+Creates a hard link pointing to
+{\tt src}
+named
+{\tt dst}.
+\funcitem{listdir}{path}
+Returns a list containing the names of the entries in the
+directory.
+The list is in arbitrary order.
+It includes the special entries
+{\tt '.'}
+and
+{\tt '..'}
+if they are present in the directory.
+\funcitem{mkdir}{path, mode}
+Creates a directory named
+{\tt path}
+with numeric mode
+{\tt mode}.
+\funcitem{rename}{src, dst}
+Renames the file or directory
+{\tt src}
+to
+{\tt dst}.
+\funcitem{rmdir}{path}
+Removes the directory
+{\tt path}.
+\funcitem{stat}{path}
+Performs a
+{\em stat}
+system call on the given path.
+The return value is a tuple of at least 10 integers giving the most
+important (and portable) members of the
+{\em stat}
+structure, in the order
+{\tt st\_mode},
+{\tt st\_ino},
+{\tt st\_dev},
+{\tt st\_nlink},
+{\tt st\_uid},
+{\tt st\_gid},
+{\tt st\_size},
+{\tt st\_atime},
+{\tt st\_mtime},
+{\tt st\_ctime}.
+More items may be added at the end by some implementations.
+\funcitem{system}{command}
+Executes the command (a string) in a subshell.
+This is implemented by calling the Standard C function
+{\tt system()},
+and has the same limitations.
+Changes to
+{\tt posix.environ},
+{\tt sys.stdin}
+etc. are not reflected in the environment of the executed command.
+The return value is the exit status of the process as returned by
+Standard C
+{\tt system()}.
+\funcitem{umask}{mask}
+Sets the current numeric umask and returns the previous umask.
+\funcitem{unlink}{path}
+Unlinks the file
+{\tt path}.
+\funcitem{utimes(path, }{atime, mtime)}
+%.br
+Sets the access and modified time of the file to the given values.
+(The second argument is a tuple of two items.)
+\end{description}
+
+The following functions are only available on systems that support
+symbolic links:
+\begin{description}
+\funcitem{lstat}{path}
+Like
+{\tt stat()},
+but does not follow symbolic links.
+\funcitem{readlink}{path}
+Returns a string representing the path to which the symbolic link
+points.
+\funcitem{symlink}{src, dst}
+Creates a symbolic link pointing to
+{\tt src}
+named
+{\tt dst}.
+\end{description}
+
+\subsection{Built-in Module {\tt stdwin}}
+
+This module defines several new object types and functions that
+provide access to the functionality of the Standard Window System
+Interface, STDWIN [CWI report CR-R8817].
+It is available on systems to which STDWIN has been ported (which is
+most systems).
+It is only available if the {\tt DISPLAY} environment variable is set
+or an explicit `{\tt -display \it displayname}' argument is passed to
+the interpreter.
+
+Functions have names that usually resemble their C STDWIN counterparts
+with the initial `w' dropped.
+Points are represented by pairs of integers; rectangles
+by pairs of points.
+For a complete description of STDWIN please refer to the documentation
+of STDWIN for C programmers (aforementioned CWI report).
+\subsubsection{Functions Defined in Module {\tt stdwin}}
+
+The following functions are defined in the {\tt stdwin} module:
+\begin{description}
+\funcitem{open}{title}
+%.br
+Opens a new window whose initial title is given by the string argument.
+Returns a window object; window object methods are described below.%
+\footnote{
+The {\Python} version of STDWIN does not support draw procedures; all
+drawing requests are reported as draw events.
+}
+\funcitem{getevent}{}
+%.br
+Waits for and returns the next event.
+An event is returned as a triple: the first element is the event
+type, a small integer; the second element is the window object to which
+the event applies, or
+{\tt None}
+if it applies to no window in particular;
+the third element is type-dependent.
+Names for event types and command codes are defined in the standard
+module
+{\tt stdwinevent}.
+\funcitem{setdefwinpos}{h, v}
+%.br
+Sets the default window position.
+\funcitem{setdefwinsize}{width, height}
+%.br
+Sets the default window size.
+\funcitem{menucreate}{title}
+%.br
+Creates a menu object referring to a global menu (a menu that appears in
+all windows).
+Methods of menu objects are described below.
+\funcitem{fleep}{}
+%.br
+Causes a beep or bell (or perhaps a `visual bell' or flash, hence the
+name).
+\funcitem{message}{string}
+%.br
+Displays a dialog box containing the string.
+The user must click OK before the function returns.
+\funcitem{askync}{prompt, default}
+%.br
+Displays a dialog that prompts the user to answer a question with yes or
+no.
+The function returns 0 for no, 1 for yes.
+If the user hits the Return key, the default (which must be 0 or 1) is
+returned.
+If the user cancels the dialog, the
+{\tt KeyboardInterrupt}
+exception is raised.
+\funcitem{askstr}{prompt, default}
+%.br
+Displays a dialog that prompts the user for a string.
+If the user hits the Return key, the default string is returned.
+If the user cancels the dialog, the
+{\tt KeyboardInterrupt}
+exception is raised.
+\funcitem{askfile}{prompt, default, new}
+%.br
+Asks the user to specify a filename.
+If
+{\tt new}
+is zero it must be an existing file; otherwise, it must be a new file.
+If the user cancels the dialog, the
+{\tt KeyboardInterrupt}
+exception is raised.
+\funcitem{setcutbuffer}{i, string}
+%.br
+Stores the string in the system's cut buffer number
+{\tt i},
+where it can be found (for pasting) by other applications.
+On X11, there are 8 cut buffers (numbered 0..7).
+Cut buffer number 0 is the `clipboard' on the Macintosh.
+\funcitem{getcutbuffer}{i}
+%.br
+Returns the contents of the system's cut buffer number
+{\tt i}.
+\funcitem{rotatebutbuffers}{n}
+%.br
+On X11, this rotates the 8 cut buffers by
+{\tt n}.
+Ignored on the Macintosh.
+\funcitem{getselection}{i}
+%.br
+Returns X11 selection number
+{\tt i.}
+Selections are not cut buffers.
+Selection numbers are defined in module
+{\tt stdwinevents}.
+Selection {\tt WS\_PRIMARY} is the
+{\em primary}
+selection (used by
+xterm,
+for instance);
+selection {\tt WS\_SECONDARY} is the
+{\em secondary}
+selection; selection {\tt WS\_CLIPBOARD} is the
+{\em clipboard}
+selection (used by
+xclipboard).
+On the Macintosh, this always returns an empty string.
+\funcitem{resetselection}{i}
+%.br
+Resets selection number
+{\tt i},
+if this process owns it.
+(See window method
+{\tt setselection()}).
+\funcitem{baseline}{}
+%.br
+Return the baseline of the current font (defined by STDWIN as the
+vertical distance between the baseline and the top of the
+characters).%
+\footnote{
+There is no way yet to set the current font.
+This will change in a future version.
+}
+\funcitem{lineheight}{}
+%.br
+Return the total line height of the current font.
+\funcitem{textbreak}{str, width}
+%.br
+Return the number of characters of the string that fit into a space of
+{\tt width}
+bits wide when drawn in the curent font.
+\funcitem{textwidth}{str}
+%.br
+Return the width in bits of the string when drawn in the current font.
+\end{description}
+
+\subsubsection{Window Object Methods}
+
+Window objects are created by
+{\tt stdwin.open()}.
+There is no explicit function to close a window; windows are closed when
+they are garbage-collected.
+Window objects have the following methods:
+\begin{description}
+\funcitem{begindrawing}{}
+Returns a drawing object, whose methods (described below) allow drawing
+in the window.
+\funcitem{change}{rect}
+Invalidates the given rectangle; this may cause a draw event.
+\funcitem{gettitle}{}
+Returns the window's title string.
+\funcitem{getdocsize}{}
+\begin{sloppypar}
+Returns a pair of integers giving the size of the document as set by
+{\tt setdocsize()}.
+\end{sloppypar}
+\funcitem{getorigin}{}
+Returns a pair of integers giving the origin of the window with respect
+to the document.
+\funcitem{getwinsize}{}
+Returns a pair of integers giving the size of the window.
+\funcitem{menucreate}{title}
+Creates a menu object referring to a local menu (a menu that appears
+only in this window).
+Methods menu objects are described below.
+\funcitem{scroll}{rect,~point}
+Scrolls the given rectangle by the vector given by the point.
+\funcitem{setwincursor}{name}
+\begin{sloppypar}
+Sets the window cursor to a cursor of the given name.
+It raises the
+{\tt Runtime\-Error}
+exception if no cursor of the given name exists.
+Suitable names are
+{\tt 'ibeam'},
+{\tt 'arrow'},
+{\tt 'cross'},
+{\tt 'watch'}
+and
+{\tt 'plus'}.
+On X11, there are many more (see
+{\tt <X11/cursorfont.h>}).
+\end{sloppypar}
+\funcitem{setdocsize}{point}
+Sets the size of the drawing document.
+\funcitem{setorigin}{point}
+Moves the origin of the window to the given point in the document.
+\funcitem{setselection}{i, str}
+Attempts to set X11 selection number
+{\tt i}
+to the string
+{\tt str}.
+(See stdwin method
+{\tt getselection()}
+for the meaning of
+{\tt i}.)
+Returns true if it succeeds.
+If it succeeds, the window ``owns'' the selection until
+(a) another applications takes ownership of the selection; or
+(b) the window is deleted; or
+(c) the application clears ownership by calling
+{\tt stdwin.resetselection(i)}.
+When another application takes ownership of the selection, a
+{\tt WE\_LOST\_SEL}
+event is received for no particular window and with the selection number
+as detail.
+Ignored on the Macintosh.
+\funcitem{settitle}{title}
+Sets the window's title string.
+\funcitem{settimer}{dsecs}
+Schedules a timer event for the window in
+{\tt dsecs/10}
+seconds.
+\funcitem{show}{rect}
+Tries to ensure that the given rectangle of the document is visible in
+the window.
+\funcitem{textcreate}{rect}
+Creates a text-edit object in the document at the given rectangle.
+Methods of text-edit objects are described below.
+\end{description}
+
+\subsubsection{Drawing Object Methods}
+
+Drawing objects are created exclusively by the window method
+{\tt begindrawing()}.
+Only one drawing object can exist at any given time; the drawing object
+must be deleted to finish drawing.
+No drawing object may exist when
+{\tt stdwin.getevent()}
+is called.
+Drawing objects have the following methods:
+\begin{description}
+\funcitem{box}{rect}
+Draws a box around a rectangle.
+\funcitem{circle}{center, radius}
+%.br
+Draws a circle with given center point and radius.
+\funcitem{elarc(center, (rh, rv), }{a1, a2)}
+%.br
+Draws an elliptical arc with given center point.
+{\tt (rh, rv)}
+gives the half sizes of the horizontal and vertical radii.
+{\tt (a1, a2)}
+gives the angles (in degrees) of the begin and end points.
+0 degrees is at 3 o'clock, 90 degrees is at 12 o'clock.
+\funcitem{erase}{rect}
+Erases a rectangle.
+\funcitem{invert}{rect}
+Inverts a rectangle.
+\funcitem{line}{p1, p2}
+Draws a line from point
+{\tt p1}
+to
+{\tt p2}.
+\funcitem{paint}{rect}
+Fills a rectangle.
+\funcitem{text}{p, str}
+Draws a string starting at point p (the point specifies the
+top left coordinate of the string).
+\funcitem{shade}{rect, percent}
+%.br
+Fills a rectangle with a shading pattern that is about
+{\tt percent}
+percent filled.
+\funcitem{xorline}{p1, p2}
+Draws a line in XOR mode.
+\funcitem{baseline(), lineheight(), textbreak(), textwidth}{}
+%.br
+These functions are similar to the corresponding functions described
+above for the
+{\tt stdwin}
+module, but use the current font of the window instead of the (global)
+default font.
+\end{description}
+
+\subsubsection{Menu Object Methods}
+
+A menu object represents a menu.
+The menu is destroyed when the menu object is deleted.
+The following methods are defined:
+\begin{description}
+\funcitem{additem}{text, shortcut}
+%.br
+Adds a menu item with given text.
+The shortcut must be a string of length 1, or omitted (to specify no
+shortcut).
+\funcitem{setitem}{i, text}
+Sets the text of item number
+{\tt i}.
+\funcitem{enable}{i, flag}
+Enables or disables item
+{\tt i}.
+\funcitem{check}{i, flag}
+Sets or clears the
+{\em check mark}
+for item
+{\tt i}.
+\end{description}
+
+\subsubsection{Text-edit Object Methods}
+
+A text-edit object represents a text-edit block.
+For semantics, see the STDWIN documentation for C programmers.
+The following methods exist:
+\begin{description}
+\funcitem{arrow}{code}
+Passes an arrow event to the text-edit block.
+The
+{\tt code}
+must be one of
+{\tt WC\_LEFT},
+{\tt WC\_RIGHT},
+{\tt WC\_UP}
+or
+{\tt WC\_DOWN}
+(see module
+{\tt stdwinevents}).
+\funcitem{draw}{rect}
+Passes a draw event to the text-edit block.
+The rectangle specifies the redraw area.
+\funcitem{event}{type, window, detail}
+%.br
+Passes an event gotten from
+{\tt stdwin.getevent()}
+to the text-edit block.
+Returns true if the event was handled.
+\funcitem{getfocus}{}
+Returns 2 integers representing the start and end positions of the
+focus, usable as slice indices on the string returned by
+{\tt getfocustext()}.
+\funcitem{getfocustext}{}
+Returns the text in the focus.
+\funcitem{getrect}{}
+Returns a rectangle giving the actual position of the text-edit block.
+(The bottom coordinate may differ from the initial position because
+the block automatically shrinks or grows to fit.)
+\funcitem{gettext}{}
+Returns the entire text buffer.
+\funcitem{move}{rect}
+Specifies a new position for the text-edit block in the document.
+\funcitem{replace}{str}
+Replaces the focus by the given string.
+The new focus is an insert point at the end of the string.
+\funcitem{setfocus}{i,~j}
+Specifies the new focus.
+Out-of-bounds values are silently clipped.
+\end{description}
+
+\subsubsection{Example}
+
+Here is a simple example of using STDWIN in Python.
+It creates a window and draws the string ``Hello world'' in the top
+left corner of the window.
+The window will be correctly redrawn when covered and re-exposed.
+The program quits when the close icon or menu item is requested.
+\bcode\begin{verbatim}
+import stdwin
+from stdwinevents import *
+
+def main():
+ mywin = stdwin.open('Hello')
+ #
+ while 1:
+ (type, win, detail) = stdwin.getevent()
+ if type = WE_DRAW:
+ draw = win.begindrawing()
+ draw.text((0, 0), 'Hello, world')
+ del draw
+ elif type = WE_CLOSE:
+ break
+
+main()
+\end{verbatim}\ecode
+
+\subsection{Built-in Module {\tt amoeba}}
+
+This module provides some object types and operations useful for
+Amoeba applications.
+It is only available on systems that support Amoeba operations.
+RPC errors and other Amoeba errors are reported as the exception
+{\tt amoeba.error = 'amoeba.error'}.
+The module
+{\tt amoeba}
+defines the following items:
+\begin{description}
+\funcitem{name\_append}{path,~cap}
+%.br
+Stores a capability in the Amoeba directory tree.
+Arguments are the pathname (a string) and the capability (a capability
+object as returned by
+{\tt name\_lookup()}).
+\funcitem{name\_delete}{path}
+%.br
+Deletes a capability from the Amoeba directory tree.
+Argument is the pathname.
+\funcitem{name\_lookup}{path}
+%.br
+Looks up a capability.
+Argument is the pathname.
+Returns a
+{\em capability}
+object, to which various interesting operations apply, described below.
+\funcitem{name\_replace}{path,~cap}
+%.br
+Replaces a capability in the Amoeba directory tree.
+Arguments are the pathname and the new capability.
+(This differs from
+{\tt name\_append()}
+in the behavior when the pathname already exists:
+{\tt name\_append()}
+finds this an error while
+{\tt name\_replace()}
+allows it, as its name suggests.)
+\funcitem{capv}
+A table representing the capability environment at the time the
+interpreter was started.
+(Alas, modifying this table does not affect the capability environment
+of the interpreter.)
+For example,
+{\tt amoeba.capv['ROOT']}
+is the capability of your root directory, similar to
+{\tt getcap("ROOT")}
+in C.
+\excitem{error}{amoeba.error}
+%.br
+The exception raised when an Amoeba function returns an error.
+The value accompanying this exception is a pair containing the numeric
+error code and the corresponding string, as returned by the C function
+{\tt err\_why()}.
+\funcitem{timeout}{msecs}
+%.br
+Sets the transaction timeout, in milliseconds.
+Returns the previous timeout.
+Initially, the timeout is set to 2 seconds by the {\Python} interpreter.
+\end{description}
+
+\subsubsection{Capability Operations}
+
+Capabilities are written in a convenient ASCII format, also used by the
+Amoeba utilities
+{\em c2a}(U)
+and
+{\em a2c}(U).
+For example:
+\bcode\begin{verbatim}
+>>> amoeba.name_lookup('/profile/cap')
+aa:1c:95:52:6a:fa/14(ff)/8e:ba:5b:8:11:1a
+>>>
+\end{verbatim}\ecode
+The following methods are defined for capability objects.
+\begin{description}
+\funcitem{dir\_list}{}
+Returns a list of the names of the entries in an Amoeba directory.
+\funcitem{b\_read}{offset, maxsize}
+%.br
+Reads (at most)
+{\tt maxsize}
+bytes from a bullet file at offset
+{\tt offset.}
+The data is returned as a string.
+EOF is reported as an empty string.
+\funcitem{b\_size}{}
+Returns the size of a bullet file.
+\funcitem{dir\_append(), dir\_delete(), dir\_lookup(), dir\_replace}{}
+%.br
+\itembreak
+Like the corresponding
+{\tt name\_*}
+functions, but with a path relative to the capability.
+(For paths beginning with a slash the capability is ignored, since this
+is the defined semantics for Amoeba.)
+\funcitem{std\_info}{}
+Returns the standard info string of the object.
+\funcitem{tod\_gettime}{}
+Returns the time (in seconds since the Epoch, in UCT, as for POSIX) from
+a time server.
+\funcitem{tod\_settime}{t}
+Sets the time kept by a time server.
+\end{description}
+
+\subsection{Built-in Module {\tt audio}}
+
+This module provides rudimentary access to the audio I/O device
+{\tt /dev/audio}
+on the Silicon Graphics Personal IRIS; see audio(7).
+It supports the following operations:
+\begin{description}
+\funcitem{setoutgain}{n}
+Sets the output gain (0-255).
+\funcitem{getoutgain}{}
+Returns the output gain.
+\funcitem{setrate}{n}
+Sets the sampling rate: 1=32K/sec, 2=16K/sec, 3=8K/sec.
+\funcitem{setduration}{n}
+Sets the `sound duration' in units of 1/100 seconds.
+\funcitem{read}{n}
+Reads a chunk of
+{\tt n}
+sampled bytes from the audio input (line in or microphone).
+The chunk is returned as a string of length n.
+Each byte encodes one sample as a signed 8-bit quantity using linear
+encoding.
+This string can be converted to numbers using {\tt chr2num()} described
+below.
+\funcitem{write}{buf}
+Writes a chunk of samples to the audio output (speaker).
+\end{description}
+
+These operations support asynchronous audio I/O:
+\begin{description}
+\funcitem{start\_recording}{n}
+%.br
+Starts a second thread (a process with shared memory) that begins reading
+{\tt n}
+bytes from the audio device.
+The main thread immediately continues.
+\funcitem{wait\_recording}{}
+%.br
+Waits for the second thread to finish and returns the data read.
+\funcitem{stop\_recording}{}
+%.br
+Makes the second thread stop reading as soon as possible.
+Returns the data read so far.
+\funcitem{poll\_recording}{}
+%.br
+Returns true if the second thread has finished reading (so
+{\tt wait\_recording()} would return the data without delay).
+\item[{\tt start\_playing(chunk)}, {\tt wait\_playing()},
+{\tt stop\_playing()}, {\tt poll\_playing()}]
+%.br
+\begin{sloppypar}
+Similar but for output.
+{\tt stop\_playing()}
+returns a lower bound for the number of bytes actually played (not very
+accurate).
+\end{sloppypar}
+\end{description}
+
+The following operations do not affect the audio device but are
+implemented in C for efficiency:
+\begin{description}
+\funcitem{amplify}{buf, f1, f2}
+%.br
+Amplifies a chunk of samples by a variable factor changing from
+{\tt f1}/256 to {\tt f2}/256.
+Negative factors are allowed.
+Resulting values that are to large to fit in a byte are clipped.
+\funcitem{reverse}{buf}
+%.br
+Returns a chunk of samples backwards.
+\funcitem{add}{buf1, buf2}
+%.br
+Bytewise adds two chunks of samples.
+Bytes that exceed the range are clipped.
+If one buffer shorter, it is assumed to be padded with zeros.
+\funcitem{chr2num}{buf}
+%.br
+Converts a string of sampled bytes as returned by {\tt read()} into
+a list containing the numeric values of the samples.
+\funcitem{num2chr}{list}
+%.br
+\begin{sloppypar}
+Converts a list as returned by
+{\tt chr2num()}
+back to a buffer acceptable by
+{\tt write()}.
+\end{sloppypar}
+\end{description}
+
+\subsection{Built-in Module {\tt gl}}
+
+This module provides access to the Silicon Graphics
+{\em Graphics Library}.
+It is available only on Silicon Graphics machines.
+
+{\bf Warning:}
+Some illegal calls to the GL library cause the {\Python} interpreter to dump
+core.
+In particular, the use of most GL calls is unsafe before the first
+window is opened.
+
+The module is too large to document here in its entirety, but the
+following should help you to get started.
+The parameter conventions for the C functions are translated to {\Python} as
+follows:
+
+\begin{itemize}
+\item
+All (short, long, unsigned) int values are represented by {\Python}
+integers.
+\item
+All float and double values are represented by {\Python} floating point
+numbers.
+In most cases, {\Python} integers are also allowed.
+\item
+All arrays are represented by one-dimensional {\Python} lists.
+In most cases, tuples are also allowed.
+\item
+\begin{sloppypar}
+All string and character arguments are represented by {\Python} strings,
+for instance,
+{\tt winopen('Hi~There!')}
+and
+{\tt rotate(900,~'z')}.
+\end{sloppypar}
+\item
+All (short, long, unsigned) integer arguments or return values that are
+only used to specify the length of an array argument are omitted.
+For example, the C call
+\bcode\begin{verbatim}
+lmdef(deftype, index, np, props)
+\end{verbatim}\ecode
+is translated to {\Python} as
+\bcode\begin{verbatim}
+lmdef(deftype, index, props)
+\end{verbatim}\ecode
+\item
+Output arguments are omitted from the argument list; they are
+transmitted as function return values instead.
+If more than one value must be returned, the return value is a tuple.
+If the C function has both a regular return value (that is not omitted
+because of the previous rule) and an output argument, the return value
+comes first in the tuple.
+Examples: the C call
+\bcode\begin{verbatim}
+getmcolor(i, &red, &green, &blue)
+\end{verbatim}\ecode
+is translated to {\Python} as
+\bcode\begin{verbatim}
+red, green, blue = getmcolor(i)
+\end{verbatim}\ecode
+\end{itemize}
+
+The following functions are non-standard or have special argument
+conventions:
+\begin{description}
+\funcitem{varray}{}
+Equivalent to but faster than a number of
+{\tt v3d()}
+calls.
+The argument is a list (or tuple) of points.
+Each point must be a tuple of coordinates (x, y, z) or (x, y).
+The points may be 2- or 3-dimensional but must all have the
+same dimension.
+Float and int values may be mixed however.
+The points are always converted to 3D double precision points
+by assuming z=0.0 if necessary (as indicated in the man page),
+and for each point
+{\tt v3d()}
+is called.
+\funcitem{nvarray}{}
+Equivalent to but faster than a number of
+{\tt n3f}
+and
+{\tt v3f}
+calls.
+The argument is an array (list or tuple) of pairs of normals and points.
+Each pair is a tuple of a point and a normal for that point.
+Each point or normal must be a tuple of coordinates (x, y, z).
+Three coordinates must be given.
+Float and int values may be mixed.
+For each pair,
+{\tt n3f()}
+is called for the normal, and then
+{\tt v3f()}
+is called for the point.
+\funcitem{vnarray}{}
+Similar to
+{\tt nvarray()}
+but the pairs have the point first and the normal second.
+\funcitem{nurbssurface}{s\_k[], t\_k[], ctl[][], s\_ord, t\_ord, type}
+%.br
+\itembreak
+Defines a nurbs surface.
+The dimensions of
+{\tt ctl[][]}
+are computed as follows:
+{\tt [len(s\_k)~-~s\_ord]},
+{\tt [len(t\_k)~-~t\_ord]}.
+\funcitem{nurbscurve}{knots, ctlpoints, order, type}
+%.br
+Defines a nurbs curve.
+The length of ctlpoints is
+{\tt len(knots)~-~order}.
+\funcitem{pwlcurve}{points, type}
+%.br
+Defines a piecewise-linear curve.
+{\tt points}
+is a list of points.
+{\tt type}
+must be
+{\tt N\_ST}.
+\funcitem{pick(n), select}{n}
+%.br
+The only argument to these functions specifies the desired size of the
+pick or select buffer.
+\funcitem{endpick(), endselect}{}
+%.br
+These functions have no arguments.
+They return a list of integers representing the used part of the
+pick/select buffer.
+No method is provided to detect buffer overrun.
+\end{description}
+
+Here is a tiny but complete example GL program in {\Python}:
+\bcode\begin{verbatim}
+import gl, GL, time
+
+def main():
+ gl.foreground()
+ gl.prefposition(500, 900, 500, 900)
+ w = gl.winopen('CrissCross')
+ gl.ortho2(0.0, 400.0, 0.0, 400.0)
+ gl.color(GL.WHITE)
+ gl.clear()
+ gl.color(GL.RED)
+ gl.bgnline()
+ gl.v2f(0.0, 0.0)
+ gl.v2f(400.0, 400.0)
+ gl.endline()
+ gl.bgnline()
+ gl.v2f(400.0, 0.0)
+ gl.v2f(0.0, 400.0)
+ gl.endline()
+ time.sleep(5)
+
+main()
+\end{verbatim}\ecode
+
+\subsection{Built-in Module {\tt pnl}}
+
+This module provides access to the
+{\em Panel Library}
+built by NASA Ames (to get it, send e-mail to
+All access to it should be done through the standard module
+{\tt panel},
+which transparantly exports most functions from
+{\tt pnl}
+but redefines
+{\tt pnl.dopanel()}.
+
+{\bf Warning:}
+the {\Python} interpreter will dump core if you don't create a GL window
+before calling
+{\tt pnl.mkpanel()}.
+
+The module is too large to document here in its entirety.
diff --git a/doc/mod3.tex b/doc/mod3.tex
new file mode 100644
index 0000000..d1a99b1
--- /dev/null
+++ b/doc/mod3.tex
@@ -0,0 +1,484 @@
+\section{Standard Modules}
+
+The following standard modules are defined.
+They are available in one of the directories in the default module
+search path (try printing
+{\tt sys.path}
+to find out the default search path.)
+
+\subsection{Standard Module {\tt string}}
+
+This module defines some constants useful for checking character
+classes, some exceptions, and some useful string functions.
+The constants are:
+\begin{description}
+\funcitem{digits}
+The string
+{\tt '0123456789'}.
+\funcitem{hexdigits}
+The string
+{\tt '0123456789abcdefABCDEF'}.
+\funcitem{letters}
+The concatenation of the strings
+{\tt lowercase}
+and
+{\tt uppercase}
+described below.
+\funcitem{lowercase}
+The string
+{\tt 'abcdefghijklmnopqrstuvwxyz'}.
+\funcitem{octdigits}
+The string
+{\tt '01234567'}.
+\funcitem{uppercase}
+The string
+{\tt 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'}.
+\funcitem{whitespace}
+A string containing all characters that are considered whitespace,
+i.e.,
+space, tab and newline.
+This definition is used by
+{\tt split()}
+and
+{\tt strip()}.
+\end{description}
+
+The exceptions are:
+\begin{description}
+\excitem{atoi\_error}{non-numeric argument to string.atoi}
+%.br
+Exception raised by
+{\tt atoi}
+when a non-numeric string argument is detected.
+The exception argument is the offending string.
+\excitem{index\_error}{substring not found in string.index}
+%.br
+Exception raised by
+{\tt index}
+when
+{\tt sub}
+is not found.
+The argument are the offending arguments to index: {\tt (s, sub)}.
+\end{description}
+
+The functions are:
+\begin{description}
+\funcitem{atoi}{s}
+Converts a string to a number.
+The string must consist of one or more digits, optionally preceded by a
+sign ({\tt '+'} or {\tt '-'}).
+\funcitem{index}{s, sub}
+Returns the lowest index in
+{\tt s}
+where the substring
+{\tt sub}
+is found.
+\funcitem{lower}{s}
+Convert letters to lower case.
+\funcitem{split}{s}
+Returns a list of the whitespace-delimited words of the string
+{\tt s}.
+\funcitem{splitfields}{s, sep}
+%.br
+Returns a list containing the fields of the string
+{\tt s},
+using the string
+{\tt sep}
+as a separator.
+The list will have one more items than the number of non-overlapping
+occurrences of the separator in the string.
+Thus,
+{\tt string.splitfields(s, ' ')}
+is not the same as
+{\tt string.split(s)},
+as the latter only returns non-empty words.
+\funcitem{strip}{s}
+Removes leading and trailing whitespace from the string
+{\tt s}.
+\funcitem{swapcase}{s}
+Converts lower case letters to upper case and vice versa.
+\funcitem{upper}{s}
+Convert letters to upper case.
+\funcitem{ljust(s, width), rjust(s, width), center}{s, width}
+%.br
+These functions respectively left-justify, right-justify and center a
+string in a field of given width.
+They return a string that is at least
+{\tt width}
+characters wide, created by padding the string
+{\tt s}
+with spaces until the given width on the right, left or both sides.
+The string is never truncated.
+\end{description}
+
+\subsection{Standard Module {\tt path}}
+
+This module implements some useful functions on POSIX pathnames.
+\begin{description}
+\funcitem{basename}{p}
+Returns the base name of pathname
+{\tt p}.
+This is the second half of the pair returned by
+{\tt path.split(p)}.
+\funcitem{cat}{p, q}
+Performs intelligent pathname concatenation on paths
+{\tt p}
+and
+{\tt q}:
+If
+{\tt q}
+is an absolute path, the return value is
+{\tt q}.
+Otherwise, the concatenation of
+{\tt p}
+and
+{\tt q}
+is returned, with a slash ({\tt '/'}) inserted unless
+{\tt p}
+is empty or ends in a slash.
+\funcitem{commonprefix}{list}
+%.br
+Returns the longest string that is a prefix of all strings in
+{\tt list}.
+If
+{\tt list}
+is empty, the empty string ({\tt ''}) is returned.
+\funcitem{exists}{p}
+Returns true if
+{\tt p}
+refers to an existing path.
+\funcitem{isdir}{p}
+Returns true if
+{\tt p}
+refers to an existing directory.
+\funcitem{islink}{p}
+Returns true if
+{\tt p}
+refers to a directory entry that is a symbolic link.
+Always false if symbolic links are not supported.
+\funcitem{ismount}{p}
+Returns true if
+{\tt p}
+is an absolute path that occurs in the mount table as output by the
+{\tt /etc/mount}
+utility.
+This output is read once when the function is used for the first
+time.%
+\footnote{
+Is there a better way to check for mount points?
+}
+\funcitem{split}{p}
+Returns a pair
+{\tt (head,~tail)}
+such that
+{\tt tail}
+contains no slashes and
+{\tt path.cat(head, tail)}
+is equal to
+{\tt p}.
+\funcitem{walk}{p, visit, arg}
+%.br
+Calls the function
+{\tt visit}
+with arguments
+{\tt (arg, dirname, names)}
+for each directory in the directory tree rooted at
+{\tt p}
+(including
+{\tt p}
+itself, if it is a directory).
+The argument
+{\tt dirname}
+specifies the visited directory, the argument
+{\tt names}
+lists the files in the directory (gotten from
+{\tt posix.listdir(dirname)}).
+The
+{\tt visit}
+function may modify
+{\tt names}
+to influence the set of directories visited below
+{\tt dirname},
+e.g.,
+to avoid visiting certain parts of the tree.
+(The object referred to by
+{\tt names}
+must be modified in place, using
+{\tt del}
+or slice assignment.)
+\end{description}
+
+\subsection{Standard Module {\tt getopt}}
+
+This module helps scripts to parse the command line arguments in
+{\tt sys.argv}.
+It uses the same conventions as the {\UNIX}
+{\tt getopt()}
+function.
+It defines the function
+{\tt getopt.getopt(args, options)}
+and the exception
+{\tt getopt.error}.
+
+The first argument to
+{\tt getopt()}
+is the argument list passed to the script with its first element
+chopped off (i.e.,
+{\tt sys.argv[1:]}).
+The second argument is the string of option letters that the
+script wants to recognize, with options that require an argument
+followed by a colon (i.e., the same format that {\UNIX}
+{\tt getopt()}
+uses).
+The return value consists of two elements: the first is a list of
+option-and-value pairs; the second is the list of program arguments
+left after the option list was stripped (this is a trailing slice of the
+first argument).
+Each option-and-value pair returned has the option as its first element,
+prefixed with a hyphen (e.g.,
+{\tt '-x'}),
+and the option argument as its second element, or an empty string if the
+option has no argument.
+The options occur in the list in the same order in which they were
+found, thus allowing multiple occurrences.
+Example:
+\bcode\begin{verbatim}
+>>> import getopt, string
+>>> args = string.split('-a -b -cfoo -d bar a1 a2')
+>>> args
+['-a', '-b', '-cfoo', '-d', 'bar', 'a1', 'a2']
+>>> optlist, args = getopt.getopt(args, 'abc:d:')
+>>> optlist
+[('-a', ''), ('-b', ''), ('-c', 'foo'), ('-d', 'bar')]
+>>> args
+['a1', 'a2']
+>>>
+\end{verbatim}\ecode
+The exception
+{\tt getopt.error = 'getopt error'}
+is raised when an unrecognized option is found in the argument list or
+when an option requiring an argument is given none.
+The argument to the exception is a string indicating the cause of the
+error.
+
+\subsection{Standard Module {\tt rand}}
+
+This module implements a pseudo-random number generator similar to
+{\tt rand()}
+in C.
+It defines the following functions:
+\begin{description}
+\funcitem{rand}{}
+Returns an integer random number in the range [0 ... 32768).
+\funcitem{choice}{s}
+Returns a random element from the sequence (string, tuple or list)
+{\tt s.}
+\funcitem{srand}{seed}
+Initializes the random number generator with the given integral seed.
+When the module is first imported, the random number is initialized with
+the current time.
+\end{description}
+
+\subsection{Standard Module {\tt whrandom}}
+
+This module implements a Wichmann-Hill pseudo-random number generator.
+It defines the following functions:
+\begin{description}
+\funcitem{random}{}
+Returns the next random floating point number in the range [0.0 ... 1.0).
+\funcitem{seed}{x, y, z}
+Initializes the random number generator from the integers
+{\tt x},
+{\tt y}
+and
+{\tt z}.
+When the module is first imported, the random number is initialized
+using values derived from the current time.
+\end{description}
+
+\subsection{Standard Module {\tt stdwinevents}}
+
+This module defines constants used by STDWIN for event types
+({\tt WE\_ACTIVATE} etc.), command codes ({\tt WC\_LEFT} etc.)
+and selection types ({\tt WS\_PRIMARY} etc.).
+Read the file for details.
+Suggested usage is
+\bcode\begin{verbatim}
+>>> from stdwinevents import *
+>>>
+\end{verbatim}\ecode
+
+\subsection{Standard Module {\tt rect}}
+
+This module contains useful operations on rectangles.
+A rectangle is defined as in module
+{\tt stdwin}:
+a pair of points, where a point is a pair of integers.
+For example, the rectangle
+\bcode\begin{verbatim}
+(10, 20), (90, 80)
+\end{verbatim}\ecode
+is a rectangle whose left, top, right and bottom edges are 10, 20, 90
+and 80, respectively.
+Note that the positive vertical axis points down (as in
+{\tt stdwin}).
+
+The module defines the following objects:
+\begin{description}
+\excitem{error}{rect.error}
+%.br
+The exception raised by functions in this module when they detect an
+error.
+The exception argument is a string describing the problem in more
+detail.
+\funcitem{empty}
+%.br
+The rectangle returned when some operations return an empty result.
+This makes it possible to quickly check whether a result is empty:
+\bcode\begin{verbatim}
+>>> import rect
+>>> r1 = (10, 20), (90, 80)
+>>> r2 = (0, 0), (10, 20)
+>>> r3 = rect.intersect(r1, r2)
+>>> if r3 is rect.empty: print 'Empty intersection'
+Empty intersection
+>>>
+\end{verbatim}\ecode
+\funcitem{is\_empty}{r}
+%.br
+Returns true if the given rectangle is empty.
+A rectangle
+{\em (left,~top), (right,~bottom)}
+is empty if
+{\em left~$\geq$~right}
+or
+{\em top~$\leq$~bottom}.
+\funcitem{intersect}{list}
+%.br
+Returns the intersection of all rectangles in the list argument.
+It may also be called with a tuple argument or with two or more
+rectangles as arguments.
+Raises
+{\tt rect.error}
+if the list is empty.
+Returns
+{\tt rect.empty}
+if the intersection of the rectangles is empty.
+\funcitem{union}{list}
+%.br
+Returns the smallest rectangle that contains all non-empty rectangles in
+the list argument.
+It may also be called with a tuple argument or with two or more
+rectangles as arguments.
+Returns
+{\tt rect.empty}
+if the list is empty or all its rectangles are empty.
+\funcitem{pointinrect}{point, rect}
+%.br
+Returns true if the point is inside the rectangle.
+By definition, a point
+{\em (h,~v)}
+is inside a rectangle
+{\em (left,~top),}
+{\em (right,~bottom)}
+if
+{\em left~$\leq$~h~$<$~right}
+and
+{\em top~$\leq$~v~$<$~bottom}.
+\funcitem{inset(rect, }{dh, dv)}
+%.br
+Returns a rectangle that lies inside the
+{\tt rect}
+argument by
+{\tt dh}
+pixels horizontally
+and
+{\tt dv}
+pixels
+vertically.
+If
+{\tt dh}
+or
+{\tt dv}
+is negative, the result lies outside
+{\tt rect}.
+\funcitem{rect2geom}{rect}
+%.br
+Converts a rectangle to geometry representation:
+{\em (left,~top),}
+{\em (width,~height)}.
+\funcitem{geom2rect}{geom}
+%.br
+Converts a rectangle given in geometry representation back to the
+standard rectangle representation
+{\em (left,~top),}
+{\em (right,~bottom)}.
+\end{description}
+
+\subsection{Standard Modules {\tt GL} and {\tt DEVICE}}
+
+These modules define the constants used by the Silicon Graphics
+{\em Graphics Library}
+that C programmers find in the header files
+{\tt <gl/gl.h>}
+and
+{\tt <gl/device.h>}.
+Read the module files for details.
+
+\subsection{Standard Module {\tt panel}}
+
+This module should be used instead of the built-in module
+{\tt pnl}
+to interface with the
+{\em Panel Library}.
+
+The module is too large to document here in its entirety.
+One interesting function:
+\begin{description}
+\funcitem{defpanellist}{filename}
+%.br
+Parses a panel description file containing S-expressions written by the
+{\em Panel Editor}
+that accompanies the Panel Library and creates the described panels.
+It returns a list of panel objects.
+\end{description}
+
+{\bf Warning:}
+the {\Python} interpreter will dump core if you don't create a GL window
+before calling
+{\tt panel.mkpanel()}
+or
+{\tt panel.defpanellist()}.
+
+\subsection{Standard Module {\tt panelparser}}
+
+This module defines a self-contained parser for S-expressions as output
+by the Panel Editor (which is written in Scheme so it can't help writing
+S-expressions).
+The relevant function is
+{\tt panelparser.parse\_file(file)}
+which has a file object (not a filename!) as argument and returns a list
+of parsed S-expressions.
+Each S-expression is converted into a {\Python} list, with atoms converted
+to {\Python} strings and sub-expressions (recursively) to {\Python} lists.
+For more details, read the module file.
+
+\section{P.M.}
+
+\begin{verse}
+
+commands
+
+cmp?
+
+*cache?
+
+localtime?
+
+calendar?
+
+\_\_dict?
+
+mac?
+
+\end{verse}
diff --git a/doc/myformat.sty b/doc/myformat.sty
new file mode 100644
index 0000000..be70239
--- /dev/null
+++ b/doc/myformat.sty
@@ -0,0 +1,34 @@
+% Style parameters and macros used by all documents here
+
+% Page lay-out parameters
+\textwidth = 160mm
+\textheight = 240mm
+\topmargin = -11mm
+\oddsidemargin = 0mm
+\evensidemargin = 0mm
+%\parindent = 0mm
+
+% Frequently used system names
+\newcommand{\Python}{Python} % Sometimes I want this italicized
+\newcommand{\UNIX}{U{\sc nix}}
+
+% Variable used by begin code command
+\newlength{\codewidth}
+
+\newcommand{\bcode}{
+ % Calculate the text width for the minipage:
+ \setlength{\codewidth}{\linewidth}
+ \addtolength{\codewidth}{-\parindent}
+ %
+ \vspace{3mm}
+ \par
+ \indent
+ \begin{minipage}[t]{\codewidth}
+}
+
+\newcommand{\ecode}{
+ \end{minipage}
+ \vspace{3mm}
+ \par
+ \noindent
+}
diff --git a/doc/pytry b/doc/pytry
new file mode 100755
index 0000000..dcc3f84
--- /dev/null
+++ b/doc/pytry
@@ -0,0 +1,20 @@
+TMP=/usr/tmp/pytry$$
+trap 'rm -f $TMP; exit 1' 1 2 3 13 14 15
+
+cat $* >$TMP
+
+(
+ cat $TMP
+
+ sed '
+ s/^>>> //
+ s/^>>>$//
+ s/^\.\.\. //
+ s/^\.\.\.$//
+ ' $TMP |
+ python
+
+ echo '>>> '
+) 2>&1
+
+rm $TMP
diff --git a/doc/tut.tex b/doc/tut.tex
new file mode 100644
index 0000000..ad5f56c
--- /dev/null
+++ b/doc/tut.tex
@@ -0,0 +1,1550 @@
+% Format this file with latex.
+
+%\documentstyle[garamond,11pt,myformat]{article}
+\documentstyle[11pt,myformat]{article}
+
+\title{\bf
+ Python Tutorial \\
+ (DRAFT)
+}
+
+\author{
+ Guido van Rossum \\
+ Dept. CST, CWI, Kruislaan 413 \\
+ 1098 SJ Amsterdam, The Netherlands \\
+ E-mail: {\tt [email protected]}
+}
+
+\begin{document}
+
+\pagenumbering{roman}
+
+\maketitle
+
+\begin{abstract}
+
+\noindent
+\Python\ is a simple, yet powerful programming language that bridges the
+gap between C and shell programming, and is thus ideally suited for rapid
+prototyping.
+Its syntax is put together from constructs borrowed from a variety of other
+languages; most prominent are influences from ABC, C, Modula-3 and Icon.
+
+The \Python\ interpreter is easily extended with new functions and data
+types implemented in C.
+\Python\ is also suitable as an extension language for highly
+customizable C applications such as editors or window managers.
+
+\Python\ is available for various operating systems, amongst which
+several flavors of \UNIX, Amoeba, and the Apple Macintosh O.S.
+
+This tutorial introduces the reader informally to the basic concepts and
+features of the \Python\ language and system.
+It helps to have a \Python\ interpreter handy for hands-on experience,
+but as the examples are self-contained, the tutorial can be read
+off-line as well.
+
+For a description of standard objects and modules, see the Library
+Reference document.
+The Language Reference document (XXX not yet existing)
+gives a more formal reference to the language.
+
+\end{abstract}
+
+\pagebreak
+
+\tableofcontents
+
+\pagebreak
+
+\pagenumbering{arabic}
+
+\section{Whetting Your Appetite}
+
+If you ever wrote a large shell script, you probably know this feeling:
+you'd love to add yet another feature, but it's already so slow, and so
+big, and so complicated; or the feature involves a system call or other
+funcion that is only accessible from C \ldots
+Usually the problem at hand isn't serious enough to warrant rewriting
+the script in C; perhaps because the problem requires variable-length
+strings or other data types (like sorted lists of file names) that
+are easy in the shell but lots of work to implement in C; or perhaps
+just because you're not sufficiently familiar with C.
+
+In all such cases, \Python\ is just the language for you.
+\Python\ is simple to use, but it is a real programming language, offering
+much more structure and support for large programs than the shell has.
+On the other hand, it also offers much more error checking than C, and,
+being a
+{\em very-high-level language},
+it has high-level data types built in, such as flexible arrays and
+dictionaries that would cost you days to implement efficiently in C.
+Because of its more general data types \Python\ is applicable to a
+much larger problem domain than
+{\em Awk}
+or even
+{\em Perl},
+yet most simple things are at least as easy in \Python\ as in those
+languages.
+
+\Python\ allows you to split up your program in modules that can be reused
+in other \Python\ programs.
+It comes with a large collection of standard modules that you can use as
+the basis for your programs --- or as examples to start learning to
+program in \Python.
+There are also built-in modules that provide things like file I/O,
+system calls, and even a generic interface to window systems (STDWIN).
+
+\Python\ is an interpreted language, which saves you considerable time
+during program development because no compilation and linking is
+necessary.
+The interpreter can be used interactively, which makes it easy to
+experiment with features of the language, to write throw-away programs,
+or to test functions during bottom-up program development.
+It is also a handy desk calculator.
+
+\Python\ allows writing very compact and readable programs.
+Programs written in \Python\ are typically much shorter than equivalent C
+programs:
+No declarations are necessary (all type checking is
+dynamic); statement grouping is done by indentation instead of begin/end
+brackets; and the high-level data types allow you to express complex
+operations in a single statement.
+
+\Python\ is
+{\em extensible}:
+if you know how to program in C it is easy to add a new built-in module
+to the interpreter, either to perform critical operations at maximum
+speed, or to link \Python\ programs to libraries that may be only available
+in binary form (such as a vendor-specific graphics library).
+Once you are really hooked, you can link the \Python\ interpreter into an
+application written in C and use it as an extension or command language.
+
+\subsection{Where From Here}
+
+Now that you are all excited about \Python, you'll want to examine it in
+some more detail.
+Since the best introduction to a language is using it, you are invited
+here to do so.
+
+In the next section, the mechanics of using the interpreter are
+explained.
+This is rather mundane information, but essential for trying out the
+examples shown later.
+The rest of the tutorial introduces various features of the \Python\
+language and system though examples, beginning with simple expressions,
+statements and data types, through functions and modules, and finally
+touching upon advanced concepts like exceptions and classes.
+
+\section{Using the Python Interpreter}
+
+The \Python\ interpreter is usually installed as
+{\tt /usr/local/python}
+on those machines where it is available; putting
+{\tt /usr/local}
+in your \UNIX\ shell's search path makes it possible to start it by
+typing the command
+\bcode\begin{verbatim}
+python
+\end{verbatim}\ecode
+to the shell.
+Since the choice of the directory where the interpreter lives is an
+installation option, other places instead of
+{\tt /usr/local}
+are possible; check with your local \Python\ guru or system
+administrator.%
+\footnote{
+ At CWI, at the time of writing, the interpreter can be found in
+ the following places:
+ On the Amoeba Ultrix machines, use the standard path,
+ {\tt /usr/local/python}.
+ On the Sun file servers, use
+ {\tt /ufs/guido/bin/}{\em arch}{\tt /python},
+ where {\em arch} can be {\tt sgi} or {\tt sun4}.
+ On piring, use {\tt /userfs3/amoeba/bin/python}.
+ (If you can't find a binary advertised here, get in touch with me.)
+}
+
+The interpreter operates somewhat like the \UNIX\ shell: when called with
+standard input connected to a tty device, it reads and executes commands
+interactively; when called with a file name argument or with a file as
+standard input, it reads and executes a
+{\em script}
+from that file.%
+\footnote{
+ There is a difference between ``{\tt python file}'' and
+ ``{\tt python $<$file}''. In the latter case {\tt input()} and
+ {\tt raw\_input()} are satisfied from {\em file}, which has
+ already been read until the end by the parser, so they will read
+ EOF immediately. In the former case (which is usually what
+ you want) they are satisfied from whatever file or device is
+ connected to standard input of the \Python\ interpreter.
+}
+If available, the script name and additional arguments thereafter are
+passed to the script in the variable
+{\tt sys.argv},
+which is a list of strings.
+
+When standard input is a tty, the interpreter is said to be in
+{\em interactive\ mode}.
+In this mode it prompts for the next command with the
+{\em primary\ prompt},
+usually three greater-than signs ({\tt >>>}); for continuation lines
+it prompts with the
+{\em secondary\ prompt},
+by default three dots ({\tt ...}).
+Typing an EOF (Control-D) at the primary prompt causes the interpreter
+to exit with a zero exit status.
+
+When an error occurs in interactive mode, the interpreter prints a
+message and a stack trace and returns to the primary prompt; with input
+from a file, it exits with a nonzero exit status.
+(Exceptions handled by an
+{\tt except}
+clause in a
+{\tt try}
+statement are not errors in this context.)
+Some errors are unconditionally fatal and cause an exit with a nonzero
+exit; this applies to internal inconsistencies and some cases of running
+out of memory.
+All error messages are written to the standard error stream; normal
+output from the executed commands is written to standard output.
+
+Typing an interrupt (normally Control-C or DEL) to the primary or
+secondary prompt cancels the input and returns to the primary prompt.
+Typing an interrupt while a command is being executed raises the
+{\tt KeyboardInterrupt}
+exception, which may be handled by a
+{\tt try}
+statement.
+
+When a module named
+{\tt foo}
+is imported, the interpreter searches for a file named
+{\tt foo.py}
+in a list of directories specified by the environment variable
+{\tt PYTHONPATH}.
+It has the same syntax as the \UNIX\ shell variable
+{\tt PATH},
+i.e., a list of colon-separated directory names.
+When
+{\tt PYTHONPATH}
+is not set, an installation-dependent default path is used, usually
+{\tt .:/usr/local/lib/python}.%
+\footnote{
+ Modules are really searched in the list of directories given by
+ the variable {\tt sys.path} which is initialized from
+ {\tt PYTHONPATH} or from the installation-dependent default.
+ See the section on Standard Modules later.
+}
+
+On BSD'ish \UNIX\ systems, \Python\ scripts can be made directly executable,
+like shell scripts, by putting the line
+\bcode\begin{verbatim}
+#! /usr/local/python
+\end{verbatim}\ecode
+(assuming that's the name of the interpreter) at the beginning of the
+script and giving the file an executable mode.
+(The
+{\tt \#!}
+must be the first two characters of the file.)
+
+\subsection{Interactive Input Editing and History Substitution}
+
+Some versions of the \Python\ interpreter support editing of the current
+input line and history substitution, similar to facilities found in the
+Korn shell and the GNU Bash shell.
+This is implemented using the
+{\em GNU\ Readline}
+library, which supports Emacs-style and vi-style editing.
+This library has its own documentation which I won't duplicate here;
+however, the basics are easily explained.
+
+If supported,%
+\footnote{
+ Perhaps the quickest check to see whether command line editing
+ is supported is typing Control-P to the first \Python\ prompt
+ you get. If it beeps, you have command line editing.
+ If not, you can skip the rest of this section.
+}
+input line editing is active whenever the interpreter prints a primary
+or secondary prompt.
+The current line can be edited using the conventional Emacs control
+characters.
+The most important of these are:
+C-A (Control-A) moves the cursor to the beginning of the line, C-E to
+the end, C-B moves it one position to the left, C-F to the right.
+Backspace erases the character to the left of the cursor, C-D the
+character to its right.
+C-K kills (erases) the rest of the line to the right of the cursor, C-Y
+yanks back the last killed string.
+C-underscore undoes the last change you made; it can be repeated for
+cumulative effect.
+
+History substitution works as follows.
+All non-empty input lines issued are saved in a history buffer,
+and when a new prompt is given you are positioned on a new line at the
+bottom of this buffer.
+C-P moves one line up (back) in the history buffer, C-N moves one down.
+Any line in the history buffer can be edited; an asterisk appears in
+front of the prompt to mark a line as modified.
+Pressing the Return key passes the current line to the interpreter.
+C-R starts an incremental reverse search; C-S starts a forward search.
+
+The key bindings and some other parameters of the Readline library can
+be customized by placing commands in an initialization file called
+{\tt \$HOME/.initrc}.
+Key bindings have the form
+\bcode\begin{verbatim}
+key-name: function-name
+\end{verbatim}\ecode
+and options can be set with
+\bcode\begin{verbatim}
+set option-name value
+\end{verbatim}\ecode
+Example:
+\bcode\begin{verbatim}
+# I prefer vi-style editing:
+set editing-mode vi
+# Edit using a single line:
+set horizontal-scroll-mode On
+# Rebind some keys:
+Meta-h: backward-kill-word
+Control-u: universal-argument
+\end{verbatim}\ecode
+Note that the default binding for TAB in \Python\ is to insert a TAB
+instead of Readline's default filename completion function.
+If you insist, you can override this by putting
+\bcode\begin{verbatim}
+TAB: complete
+\end{verbatim}\ecode
+in your
+{\tt \$HOME/.inputrc}.
+(Of course, this makes it hard to type indented continuation lines.)
+
+This facility is an enormous step forward compared to previous versions of
+the interpreter; however, some wishes are left:
+It would be nice if the proper indentation were suggested on
+continuation lines (the parser knows if an indent token is required
+next).
+The completion mechanism might use the interpreter's symbol table.
+A function to check (or even suggest) matching parentheses, quotes
+etc. would also be useful.
+
+\section{An Informal Introduction to Python}
+
+In the following examples, input and output are distinguished by the
+presence or absence of prompts ({\tt >>>} and {\tt ...}): to repeat the
+example, you must type everything after the prompt, when the prompt
+appears; everything on lines that do not begin with a prompt is output
+from the interpreter.
+Note that a secondary prompt on a line by itself in an example means you
+must type a blank line; this is used to end a multi-line command.
+
+\subsection{Using Python as a Calculator}
+
+Let's try some simple \Python\ commands.
+Start the interpreter and wait for the primary prompt,
+{\tt >>>}.
+The interpreter acts as a simple calculator: you can type an expression
+at it and it will write the value.
+Expression syntax is straightforward: the operators
+{\tt +},
+{\tt -},
+{\tt *}
+and
+{\tt /}
+work just as in most other languages (e.g., Pascal or C); parentheses
+can be used for grouping.
+For example:
+\bcode\begin{verbatim}
+>>> # This is a comment
+>>> 2+2
+4
+>>>
+>>> (50-5+5*6+25)/4
+25
+>>> # Division truncates towards zero:
+>>> 7/3
+2
+>>>
+\end{verbatim}\ecode
+As in C, the equal sign ({\tt =}) is used to assign a value to a variable.
+The value of an assignment is not written:
+\bcode\begin{verbatim}
+>>> width = 20
+>>> height = 5*9
+>>> width * height
+900
+>>>
+\end{verbatim}\ecode
+There is some support for floating point, but you can't mix floating
+point and integral numbers in expression (yet):
+\bcode\begin{verbatim}
+>>> 10.0 / 3.3
+3.0303030303
+>>>
+\end{verbatim}\ecode
+Besides numbers, \Python\ can also manipulate strings, enclosed in single
+quotes:
+\bcode\begin{verbatim}
+>>> 'foo bar'
+'foo bar'
+>>> 'doesn\'t'
+'doesn\'t'
+>>>
+\end{verbatim}\ecode
+Strings are written inside quotes and with quotes and other funny
+characters escaped by backslashes, to show the precise value.
+(There is also a way to write strings without quotes and escapes.)
+Strings can be concatenated (glued together) with the
+{\tt +}
+operator, and repeated with~{\tt *}:
+\bcode\begin{verbatim}
+>>> word = 'Help' + 'A'
+>>> word
+'HelpA'
+>>> '<' + word*5 + '>'
+'<HelpAHelpAHelpAHelpAHelpA>'
+>>>
+\end{verbatim}\ecode
+Strings can be subscripted; as in C, the first character of a string has
+subscript 0.
+There is no separate character type; a character is simply a string of
+size one.
+As in Icon, substrings can be specified with the
+{\em slice}
+notation: two subscripts (indices) separated by a colon.
+\bcode\begin{verbatim}
+>>> word[4]
+'A'
+>>> word[0:2]
+'He'
+>>> word[2:4]
+'lp'
+>>> # Slice indices have useful defaults:
+>>> word[:2] # Take first two characters
+'He'
+>>> word[2:] # Drop first two characters
+'lpA'
+>>> # A useful invariant: s[:i] + s[i:] = s
+>>> word[:3] + word[3:]
+'HelpA'
+>>>
+\end{verbatim}\ecode
+Degenerate cases are handled gracefully: an index that is too large is
+replaced by the string size, an upper bound smaller than the lower bound
+returns an empty string.
+\bcode\begin{verbatim}
+>>> word[1:100]
+'elpA'
+>>> word[10:]
+''
+>>> word[2:1]
+''
+>>>
+\end{verbatim}\ecode
+Slice indices (but not simple subscripts) may be negative numbers, to
+start counting from the right.
+For example:
+\bcode\begin{verbatim}
+>>> word[-2:] # Take last two characters
+'pA'
+>>> word[:-2] # Drop last two characters
+'Hel'
+>>> # But -0 does not count from the right!
+>>> word[-0:] # (since -0 equals 0)
+'HelpA'
+>>>
+\end{verbatim}\ecode
+The best way to remember how slices work is to think of the indices as
+pointing
+{\em between}
+characters, with the left edge of the first character numbered 0.
+Then the right edge of the last character of a string of
+{\tt n}
+characters has index
+{\tt n},
+for example:
+\bcode\begin{verbatim}
+ +---+---+---+---+---+
+ | H | e | l | p | A |
+ +---+---+---+---+---+
+ 0 1 2 3 4 5
+-5 -4 -3 -2 -1
+\end{verbatim}\ecode
+The first row of numbers gives the position of the indices 0...5 in the
+string; the second row gives the corresponding negative indices.
+For nonnegative indices, the length of a slice is the difference of the
+indices, if both are within bounds,
+e.g.,
+the length of
+{\tt word[1:3]}
+is 3--1 = 2.
+
+Finally, the built-in function {\tt len()} computes the length of a
+string:
+\bcode\begin{verbatim}
+>>> s = 'supercalifragilisticexpialidocious'
+>>> len(s)
+34
+>>>
+\end{verbatim}\ecode
+\Python\ knows a number of
+{\em compound}
+data types, used to group together other values.
+The most versatile is the
+{\em list},
+which can be written as a list of comma-separated values between square
+brackets:
+\bcode\begin{verbatim}
+>>> a = ['foo', 'bar', 100, 1234]
+>>> a
+['foo', 'bar', 100, 1234]
+>>>
+\end{verbatim}\ecode
+As for strings, list subscripts start at 0:
+\bcode\begin{verbatim}
+>>> a[0]
+'foo'
+>>> a[3]
+1234
+>>>
+\end{verbatim}\ecode
+Lists can be sliced and concatenated like strings:
+\bcode\begin{verbatim}
+>>> a[1:3]
+['bar', 100]
+>>> a[:2] + ['bletch', 2*2]
+['foo', 'bar', 'bletch', 4]
+>>>
+\end{verbatim}\ecode
+Unlike strings, which are
+{\em immutable},
+it is possible to change individual elements of a list:
+\bcode\begin{verbatim}
+>>> a
+['foo', 'bar', 100, 1234]
+>>> a[2] = a[2] + 23
+>>> a
+['foo', 'bar', 123, 1234]
+>>>
+\end{verbatim}\ecode
+Assignment to slices is also possible, and this may even change the size
+of the list:
+\bcode\begin{verbatim}
+>>> # Replace some items:
+>>> a[0:2] = [1, 12]
+>>> a
+[1, 12, 123, 1234]
+>>> # Remove some:
+>>> a[0:2] = []
+>>> a
+[123, 1234]
+>>> # Insert some:
+>>> a[1:1] = ['bletch', 'xyzzy']
+>>> a
+[123, 'bletch', 'xyzzy', 1234]
+>>>
+\end{verbatim}\ecode
+The built-in function {\tt len()} also applies to lists:
+\bcode\begin{verbatim}
+>>> len(a)
+4
+>>>
+\end{verbatim}\ecode
+
+\subsection{Tuples and Sequences}
+
+XXX To Be Done.
+
+\subsection{First Steps Towards Programming}
+
+Of course, we can use \Python\ for more complicated tasks than adding two
+and two together.
+For instance, we can write an initial subsequence of the
+{\em Fibonacci}
+series as follows:
+\bcode\begin{verbatim}
+>>> # Fibonacci series:
+>>> # the sum of two elements defines the next
+>>> a, b = 0, 1
+>>> while b < 100:
+... print b
+... a, b = b, a+b
+...
+1
+1
+2
+3
+5
+8
+13
+21
+34
+55
+89
+>>>
+\end{verbatim}\ecode
+This example introduces several new features.
+\begin{itemize}
+\item
+The first line contains a
+{\em multiple\ assignment}:
+the variables
+{\tt a}
+and
+{\tt b}
+simultaneously get the new values 0 and 1.
+On the last line this is used again, demonstrating that the expressions
+on the right-hand side are all evaluated first before any of the
+assignments take place.
+\item
+The
+{\tt while}
+loop executes as long as the condition (here: $b < 100$) remains true.
+In \Python, as in C, any non-zero integer value is true; zero is false.
+The condition may also be a string or list value, in fact any sequence;
+anything with a non-zero length is true, empty sequences are false.
+The test used in the example is a simple comparison.
+The standard comparison operators are written as
+{\tt <},
+{\tt >},
+{\tt =},
+{\tt <=},
+{\tt >=}
+and
+{\tt <>}.%
+\footnote{
+ The ambiguity of using {\tt =}
+ for both assignment and equality is resolved by disallowing
+ unparenthesized conditions at the right hand side of assignments.
+}
+\item
+The
+{\em body}
+of the loop is
+{\em indented}: indentation is \Python's way of grouping statements.
+\Python\ does not (yet!) provide an intelligent input line editing
+facility, so you have to type a tab or space(s) for each indented line.
+In practice you will prepare more complicated input for \Python\ with a
+text editor; most text editors have an auto-indent facility.
+When a compound statement is entered interactively, it must be
+followed by a blank line to indicate completion (since the parser
+cannot guess when you have typed the last line).
+\item
+The
+{\tt print}
+statement writes the value of the expression(s) it is given.
+It differs from just writing the expression you want to write (as we did
+earlier in the calculator examples) in the way it handles multiple
+expressions and strings.
+Strings are written without quotes and a space is inserted between
+items, so you can format things nicely, like this:
+\bcode\begin{verbatim}
+>>> i = 256*256
+>>> print 'The value of i is', i
+The value of i is 65536
+>>>
+\end{verbatim}\ecode
+A trailing comma avoids the newline after the output:
+\bcode\begin{verbatim}
+>>> a, b = 0, 1
+>>> while b < 1000:
+... print b,
+... a, b = b, a+b
+...
+1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987
+>>>
+\end{verbatim}\ecode
+Note that the interpreter inserts a newline before it prints the next
+prompt if the last line was not completed.
+\end{itemize}
+
+\subsection{More Control Flow Tools}
+
+Besides the {\tt while} statement just introduced, \Python\ knows the
+usual control flow statements known from other languages, with some
+twists.
+
+\subsubsection{If Statements}
+
+Perhaps the most well-known statement type is the {\tt if} statement.
+For example:
+\bcode\begin{verbatim}
+>>> if x < 0:
+... x = 0
+... print 'Negative changed to zero'
+... elif x = 0:
+... print 'Zero'
+... elif x = 1:
+... print 'Single'
+... else:
+... print 'More'
+...
+\end{verbatim}\ecode
+There can be zero or more {\tt elif} parts, and the {\tt else} part is
+optional.
+The keyword `{\tt elif}' is short for `{\tt else if}', and is useful to
+avoid excessive indentation.
+An {\tt if...elif...elif...} sequence is a substitute for the
+{\em switch} or {\em case} statements found in other languages.
+
+\subsubsection{For Statements}
+
+The {\tt for} statement in \Python\ differs a bit from what you may be
+used to in C or Pascal.
+Rather than always iterating over an arithmetic progression of numbers
+(as Pascal), or leaving the user completely free in the iteration test
+and step (as C), \Python's {\tt for} statement iterates over the items
+of any sequence (e.g., a list or a string).
+For example (no pun intended):
+\bcode\begin{verbatim}
+>>> # Measure some strings:
+>>> a = ['cat', 'window', 'defenestrate']
+>>> for x in a:
+... print x, len(x)
+...
+cat 3
+window 6
+defenestrate 12
+>>>
+\end{verbatim}\ecode
+
+\subsubsection{The {\tt range()} Function}
+
+If you do need to iterate over a sequence of numbers, the built-in
+function {\tt range()} comes in handy.
+It generates lists containing arithmetic progressions,
+e.g.:
+\bcode\begin{verbatim}
+>>> range(10)
+[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+>>>
+\end{verbatim}\ecode
+The given end point is never part of the generated list;
+{\tt range(10)} generates a list of 10 values,
+exactly the legal indices for items of a sequence of length 10.
+It is possible to let the range start at another number, or to specify a
+different increment (even negative):
+\bcode\begin{verbatim}
+>>> range(5, 10)
+[5, 6, 7, 8, 9]
+>>> range(0, 10, 3)
+[0, 3, 6, 9]
+>>> range(-10, -100, -30)
+[-10, -40, -70]
+>>>
+\end{verbatim}\ecode
+To iterate over the indices of a sequence, combine {\tt range()}
+and {\tt len()} as follows:
+\bcode\begin{verbatim}
+>>> a = ['Mary', 'had', 'a', 'little', 'boy']
+>>> for i in range(len(a)):
+... print i, a[i]
+...
+0 Mary
+1 had
+2 a
+3 little
+4 boy
+>>>
+\end{verbatim}\ecode
+
+\subsubsection{Break Statements and Else Clauses on Loops}
+
+The {\tt break} statement breaks out of the smallest enclosing {\tt for}
+or {\tt while} loop.
+Loop statements may have an {\tt else} clause; it is executed when the
+loop terminates through exhaustion of the list (with {\tt for}) or when
+the condition becomes false (with {\tt while}) but not when the loop is
+terminated by a {\tt break} statement.
+This is exemplified by the following loop, which searches for a list
+item of value 0:
+\bcode\begin{verbatim}
+>>> for n in range(2, 10):
+... for x in range(2, n):
+... if n % x = 0:
+... print n, 'equals', x, '*', n/x
+... break
+... else:
+... print n, 'is a prime number'
+...
+2 is a prime number
+3 is a prime number
+4 equals 2 * 2
+5 is a prime number
+6 equals 2 * 3
+7 is a prime number
+8 equals 2 * 4
+9 equals 3 * 3
+>>>
+\end{verbatim}\ecode
+
+\subsubsection{Pass Statements}
+
+The {\tt pass} statement does nothing.
+It can be used when a statement is required syntactically but the
+program requires no action.
+For example:
+\bcode\begin{verbatim}
+>>> while 1:
+... pass # Busy-wait for keyboard interrupt
+...
+\end{verbatim}\ecode
+
+\subsubsection{Conditions Revisited}
+
+XXX To Be Done.
+
+\subsection{Defining Functions}
+
+We can create a function that writes the Fibonacci series to an
+arbitrary boundary:
+\bcode\begin{verbatim}
+>>> def fib(n): # write Fibonacci series up to n
+... a, b = 0, 1
+... while b <= n:
+... print b,
+... a, b = b, a+b
+...
+>>> # Now call the function we just defined:
+>>> fib(2000)
+1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597
+>>>
+\end{verbatim}\ecode
+The keyword
+{\tt def}
+introduces a function
+{\em definition}.
+It must be followed by the function name and the parenthesized list of
+formal parameters.
+The statements that form the body of the function starts at the next
+line, indented by a tab stop.
+The
+{\em execution}
+of a function introduces a new symbol table used for the local variables
+of the function.
+More precisely, all variable assignments in a function store the value
+in the local symbol table; variable references first look in the local
+symbol table, then in the global symbol table, and then in the table of
+built-in names.
+Thus, the global symbol table is
+{\em read-only}
+within a function.
+The actual parameters (arguments) to a function call are introduced in
+the local symbol table of the called function when it is called;
+thus, arguments are passed using
+{\em call\ by\ value}.%
+\footnote{
+ Actually, {\em call by object reference} would be a better
+ description, since if a mutable object is passed, the caller
+ will see any changes the callee makes to it (e.g., items
+ inserted into a list).
+}
+When a function calls another function, a new local symbol table is
+created for that call.
+
+A function definition introduces the function name in the global symbol
+table.
+The value has a type that is recognized by the interpreter as a
+user-defined function.
+This value can be assigned to another name which can then also be used
+as a function.
+This serves as a general renaming mechanism:
+\bcode\begin{verbatim}
+>>> fib
+<function object at 10042ed0>
+>>> f = fib
+>>> f(100)
+1 1 2 3 5 8 13 21 34 55 89
+>>>
+\end{verbatim}\ecode
+You might object that
+{\tt fib}
+is not a function but a procedure.
+In \Python, as in C, procedures are just functions that don't return a
+value.
+In fact, technically speaking, procedures do return a value, albeit a
+rather boring one.
+This value is called {\tt None} (it's a built-in name).
+Writing the value {\tt None} is normally suppressed by the interpreter
+if it would be the only value written.
+You can see it if you really want to:
+\bcode\begin{verbatim}
+>>> print fib(0)
+None
+>>>
+\end{verbatim}\ecode
+It is simple to write a function that returns a list of the numbers of
+the Fibonacci series, instead of printing it:
+\bcode\begin{verbatim}
+>>> def fib2(n): # return Fibonacci series up to n
+... result = []
+... a, b = 0, 1
+... while b <= n:
+... result.append(b) # see below
+... a, b = b, a+b
+... return result
+...
+>>> f100 = fib2(100) # call it
+>>> f100 # write the result
+[1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
+>>>
+\end{verbatim}\ecode
+This example, as usual, demonstrates some new \Python\ features:
+\begin{itemize}
+\item
+The
+{\tt return}
+statement returns with a value from a function.
+{\tt return}
+without an expression argument is used to return from the middle of a
+procedure (falling off the end also returns from a proceduce).
+\item
+The statement
+{\tt ret.append(b)}
+calls a
+{\em method}
+of the list object
+{\tt ret}.
+A method is a function that `belongs' to an object and is named
+{\tt obj.methodname},
+where
+{\tt obj}
+is some object (this may be an expression), and
+{\tt methodname}
+is the name of a method that is defined by the object's type.
+Different types define different methods.
+Methods of different types may have the same name without causing
+ambiguity.
+See the section on classes, later, to find out how you can define your
+own object types and methods.
+The method
+{\tt append}
+shown in the example, is defined for list objects; it adds a new element
+at the end of the list.
+In this case it is equivalent to
+{\tt ret = ret + [b]},
+but more efficient.%
+\footnote{
+ There is a subtle semantic difference if the object
+ is referenced from more than one place.
+}
+\end{itemize}
+The list object type has two more methods:
+\begin{description}
+\item[{\tt insert(i, x)}]
+Inserts an item at a given position.
+The first argument is the index of the element before which to insert,
+so {\tt a.insert(0, x)} inserts at the front of the list, and
+{\tt a.insert(len(a), x)} is equivalent to {\tt a.append(x)}.
+\item[{\tt sort()}]
+Sorts the elements of the list.
+\end{description}
+For example:
+\bcode\begin{verbatim}
+>>> a = [10, 100, 1, 1000]
+>>> a.insert(2, -1)
+>>> a
+[10, 100, -1, 1, 1000]
+>>> a.sort()
+>>> a
+[-1, 1, 10, 100, 1000]
+>>> # Strings are sorted according to ASCII:
+>>> b = ['Mary', 'had', 'a', 'little', 'boy']
+>>> b.sort()
+>>> b
+['Mary', 'a', 'boy', 'had', 'little']
+>>>
+\end{verbatim}\ecode
+
+\subsection{Modules}
+
+If you quit from the \Python\ interpreter and enter it again, the
+definitions you have made (functions and variables) are lost.
+Therefore, if you want to write a somewhat longer program, you are
+better off using a text editor to prepare the input for the interpreter
+and run it with that file as input instead.
+This is known as creating a
+{\em script}.
+As your program gets longer, you may want to split it into several files
+for easier maintenance.
+You may also want to use a handy function that you've written in several
+programs without copying its definition into each program.
+To support this, \Python\ has a way to put definitions in a file and use
+them in a script or in an interactive instance of the interpreter.
+Such a file is called a
+{\em module};
+definitions from a module can be
+{\em imported}
+into other modules or into the
+{\em main}
+module (the collection of variables that you have access to in
+a script and in calculator mode).
+
+A module is a file containing \Python\ definitions and statements.
+The file name is the module name with the suffix
+{\tt .py}
+appended.
+For instance, use your favorite text editor to create a file called
+{\tt fibo.py}
+in the current directory with the following contents:
+\bcode\begin{verbatim}
+# Fibonacci numbers module
+
+def fib(n): # write Fibonacci series up to n
+ a, b = 0, 1
+ while b <= n:
+ print b,
+ a, b = b, a+b
+
+def fib2(n): # return Fibonacci series up to n
+ ret = []
+ a, b = 0, 1
+ while b <= n:
+ ret.append(b)
+ a, b = b, a+b
+ return ret
+\end{verbatim}\ecode
+Now enter the \Python\ interpreter and import this module with the
+following command:
+\bcode\begin{verbatim}
+>>> import fibo
+>>>
+\end{verbatim}\ecode
+This does not enter the names of the functions defined in
+{\tt fibo}
+directly in the symbol table; it only enters the module name
+{\tt fibo}
+there.
+Using the module name you can access the functions:
+\bcode\begin{verbatim}
+>>> fibo.fib(1000)
+1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987
+>>> fibo.fib2(100)
+[1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
+>>>
+\end{verbatim}\ecode
+If you intend to use a function often you can assign it to a local name:
+\bcode\begin{verbatim}
+>>> fib = fibo.fib
+>>> fib(500)
+1 1 2 3 5 8 13 21 34 55 89 144 233 377
+>>>
+\end{verbatim}\ecode
+
+\subsubsection{More on Modules}
+
+A module can contain executable statements as well as function
+definitions.
+These statements are intended to initialize the module.
+They are executed only the
+{\em first}
+time the module is imported somewhere.%
+\footnote{
+ In fact function definitions are also `statements' that are
+ `executed'; the execution enters the function name in the
+ module's global symbol table.
+}
+
+Each module has its own private symbol table, which is used as the
+global symbol table by all functions defined in the module.
+Thus, the author of a module can use global variables in the module
+without worrying about accidental clashes with a user's global
+variables.
+On the other hand, if you know what you are doing you can touch a
+module's global variables with the same notation used to refer to its
+functions,
+{\tt modname.itemname}.
+
+Modules can import other modules.
+It is customary but not required to place all
+{\tt import}
+statements at the beginning of a module (or script, for that matter).
+The imported module names are placed in the importing module's global
+symbol table.
+
+There is a variant of the
+{\tt import}
+statement that imports names from a module directly into the importing
+module's symbol table.
+For example:
+\bcode\begin{verbatim}
+>>> from fibo import fib, fib2
+>>> fib(500)
+1 1 2 3 5 8 13 21 34 55 89 144 233 377
+>>>
+\end{verbatim}\ecode
+This does not introduce the module name from which the imports are taken
+in the local symbol table (so in the example, {\tt fibo} is not
+defined).
+
+There is even a variant to import all names that a module defines:
+\bcode\begin{verbatim}
+>>> from fibo import *
+>>> fib(500)
+1 1 2 3 5 8 13 21 34 55 89 144 233 377
+>>>
+\end{verbatim}\ecode
+This imports all names except those beginning with an underscore
+({\tt \_}).
+
+\subsubsection{Standard Modules}
+
+\Python\ comes with a library of standard modules, described in a separate
+document (Python Library and Module Reference).
+Some modules are built into the interpreter; these provide access to
+operations that are not part of the core of the language but are
+nevertheless built in, either for efficiency or to provide access to
+operating system primitives such as system calls.
+The set of such modules is a configuration option; e.g., the
+{\tt amoeba}
+module is only provided on systems that somehow support Amoeba
+primitives.
+One particular module deserves some attention:
+{\tt sys},
+which is built into every \Python\ interpreter.
+The variables
+{\tt sys.ps1}
+and
+{\tt sys.ps2}
+define the strings used as primary and secondary prompts:
+\bcode\begin{verbatim}
+>>> import sys
+>>> sys.ps1
+'>>> '
+>>> sys.ps2
+'... '
+>>> sys.ps1 = 'C> '
+C> print 'Yuck!'
+Yuck!
+C>
+\end{verbatim}\ecode
+These two variables are only defined if the interpreter is in
+interactive mode.
+
+The variable
+{\tt sys.path}
+is a list of strings that determine the interpreter's search path for
+modules.
+It is initialized to a default path taken from the environment variable
+{\tt PYTHONPATH},
+or from a built-in default if
+{\tt PYTHONPATH}
+is not set.
+You can modify it using standard list operations, e.g.:
+\bcode\begin{verbatim}
+>>> import sys
+>>> sys.path.append('/ufs/guido/lib/python')
+>>>
+\end{verbatim}\ecode
+
+\subsection{Errors and Exceptions}
+
+Until now error messages haven't yet been mentioned, but if you have
+tried out the examples you have probably seen some.
+There are (at least) two distinguishable kinds of errors:
+{\em syntax\ errors}
+and
+{\em exceptions}.
+
+\subsubsection{Syntax Errors}
+
+Syntax errors, also known as parsing errors, are perhaps the most common
+kind of complaint you get while you are still learning \Python:
+\bcode\begin{verbatim}
+>>> while 1 print 'Hello world'
+Parsing error: file <stdin>, line 1:
+while 1 print 'Hello world'
+ ^
+Unhandled exception: run-time error: syntax error
+>>>
+\end{verbatim}\ecode
+The parser repeats the offending line and displays a little `arrow'
+pointing at the earliest point in the line where the error was detected.
+The error is caused by (or at least detected at) the token
+{\em preceding}
+the arrow: in the example, the error is detected at the keyword
+{\tt print}, since a colon ({\tt :}) is missing before it.
+File name and line number are printed so you know where to look in case
+the input came from a script.
+
+\subsubsection{Exceptions}
+
+Even if a statement or expression is syntactically correct, it may cause
+an error when an attempt is made to execute it:
+\bcode\small\begin{verbatim}
+>>> 10 * (1/0)
+Unhandled exception: run-time error: integer division by zero
+Stack backtrace (innermost last):
+ File "<stdin>", line 1
+>>> 4 + foo*3
+Unhandled exception: undefined name: foo
+Stack backtrace (innermost last):
+ File "<stdin>", line 1
+>>> '2' + 2
+Unhandled exception: type error: illegal argument type for built-in operation
+Stack backtrace (innermost last):
+ File "<stdin>", line 1
+>>>
+\end{verbatim}\ecode
+Errors detected during execution are called
+{\em exceptions}
+and are not unconditionally fatal: you will soon learn how to handle
+them in \Python\ programs.
+Most exceptions are not handled by programs, however, and result
+in error messages as shown here.
+
+The first line of the error message indicates what happened.
+Exceptions come in different types, and the type is printed as part of
+the message: the types in the example are
+{\tt run-time error},
+{\tt undefined name}
+and
+{\tt type error}.
+The rest of the line is a detail whose interpretation depends on the
+exception type.
+
+The rest of the error message shows the context where the
+exception happened.
+In general it contains a stack backtrace listing source lines; however,
+it will not display lines read from standard input.
+
+Here is a summary of the most common exceptions:
+\begin{itemize}
+\item
+{\em Run-time\ errors}
+are generally caused by wrong data used by the program; this can be the
+programmer's fault or caused by bad input.
+The detail states the cause of the error in more detail.
+\item
+{\em Undefined\ name}
+errors are more serious: these are usually caused by misspelled
+identifiers.%
+\footnote{
+ The parser does not check whether names used in a program are at
+ all defined elsewhere in the program, so such checks are
+ postponed until run-time. The same holds for type checking.
+}
+The detail is the offending identifier.
+\item
+{\em Type\ errors}
+are also pretty serious: this is another case of using wrong data (or
+better, using data the wrong way), but here the error can be glanced
+from the object type(s) alone.
+The detail shows in what context the error was detected.
+\end{itemize}
+
+\subsubsection{Handling Exceptions}
+
+It is possible to write programs that handle selected exceptions.
+Look at the following example, which prints a table of inverses of
+some floating point numbers:
+\bcode\begin{verbatim}
+>>> numbers = [0.3333, 2.5, 0.0, 10.0]
+>>> for x in numbers:
+... print x,
+... try:
+... print 1.0 / x
+... except RuntimeError:
+... print '*** has no inverse ***'
+...
+0.3333 3.00030003
+2.5 0.4
+0 *** has no inverse ***
+10 0.1
+>>>
+\end{verbatim}\ecode
+The {\tt try} statement works as follows.
+\begin{itemize}
+\item
+First, the
+{\em try\ clause}
+(the statement(s) between the {\tt try} and {\tt except} keywords) is
+executed.
+\item
+If no exception occurs, the
+{\em except\ clause}
+is skipped and execution of the {\tt try} statement is finished.
+\item
+If an exception occurs during execution of the try clause, and its
+type matches the exception named after the {\tt except} keyword, the
+rest of the try clause is skipped, the except clause is executed, and
+then execution continues after the {\tt try} statement.
+\item
+If an exception occurs which does not match the exception named in the
+except clause, it is passed on to outer try statements; if no handler is
+found, it is an
+{\em unhandled\ exception}
+and execution stops with a message as shown above.
+\end{itemize}
+A {\tt try} statement may have more than one except clause, to specify
+handlers for different exceptions.
+At most one handler will be executed.
+Handlers only handle exceptions that occur in the corresponding try
+clause, not in other handlers of the same {\tt try} statement.
+An except clause may name multiple exceptions as a parenthesized list,
+e.g.:
+\bcode\begin{verbatim}
+... except (RuntimeError, TypeError, NameError):
+... pass
+\end{verbatim}\ecode
+The last except clause may omit the exception name(s), to serve as a
+wildcard.
+Use this with extreme caution!
+
+When an exception occurs, it may have an associated value, also known as
+the exceptions's
+{\em argument}.
+The presence and type of the argument depend on the exception type.
+For exception types which have an argument, the except clause may
+specify a variable after the exception name (or list) to receive the
+argument's value, as follows:
+\bcode\begin{verbatim}
+>>> try:
+... foo()
+... except NameError, x:
+... print 'name', x, 'undefined'
+...
+name foo undefined
+>>>
+\end{verbatim}\ecode
+If an exception has an argument, it is printed as the third part
+(`detail') of the message for unhandled exceptions.
+
+Standard exception names are built-in identifiers (not reserved
+keywords).
+These are in fact string objects whose
+{\em object\ identity}
+(not their value!) identifies the exceptions.%
+\footnote{
+ There should really be a separate exception type; it is pure
+ laziness that exceptions are identified by strings, and this may
+ be fixed in the future.
+}
+The string is printed as the second part of the message for unhandled
+exceptions.
+Their names and values are:
+\bcode\begin{verbatim}
+EOFError 'end-of-file read'
+KeyboardInterrupt 'keyboard interrupt'
+MemoryError 'out of memory' *
+NameError 'undefined name' *
+RuntimeError 'run-time error' *
+SystemError 'system error' *
+TypeError 'type error' *
+\end{verbatim}\ecode
+The meanings should be clear enough.
+Those exceptions with a {\tt *} in the third column have an argument.
+
+Exception handlers don't just handle exceptions if they occur
+immediately in the try clause, but also if they occur inside functions
+that are called (even indirectly) in the try clause.
+For example:
+\bcode\begin{verbatim}
+>>> def this_fails():
+... x = 1/0
+...
+>>> try:
+... this_fails()
+... except RuntimeError, detail:
+... print 'Handling run-time error:', detail
+...
+Handling run-time error: domain error or zero division
+>>>
+\end{verbatim}\ecode
+
+\subsubsection{Raising Exceptions}
+
+The {\tt raise} statement allows the programmer to force a specified
+exception to occur.
+For example:
+\bcode\begin{verbatim}
+>>> raise NameError, 'Hi There!'
+Unhandled exception: undefined name: Hi There!
+Stack backtrace (innermost last):
+ File "<stdin>", line 1
+>>>
+\end{verbatim}\ecode
+The first argument to {\tt raise} names the exception to be raised.
+The optional second argument specifies the exception's argument.
+
+\subsubsection{User-defined Exceptions}
+
+Programs may name their own exceptions by assigning a string to a
+variable.
+For example:
+\bcode\begin{verbatim}
+>>> my_exc = 'nobody likes me!'
+>>> try:
+... raise my_exc, 2*2
+... except my_exc, val:
+... print 'My exception occured, value:', val
+...
+My exception occured, value: 4
+>>> raise my_exc, 1
+Unhandled exception: nobody likes me!: 1
+Stack backtrace (innermost last):
+ File "<stdin>", line 7
+>>>
+\end{verbatim}\ecode
+Many standard modules use this to report errors that may occur in
+functions they define.
+
+\subsubsection{Defining Clean-up Actions}
+
+The {\tt try} statement has another optional clause which is intended to
+define clean-up actions that must be executed under all circumstances.
+For example:
+\bcode\begin{verbatim}
+>>> try:
+... raise KeyboardInterrupt
+... finally:
+... print 'Goodbye, world!'
+...
+Goodbye, world!
+Unhandled exception: keyboard interrupt
+Stack backtrace (innermost last):
+ File "<stdin>", line 2
+>>>
+\end{verbatim}\ecode
+The
+{\em finally\ clause}
+must follow the except clauses(s), if any.
+It is executed whether or not an exception occurred.
+If the exception is handled, the finally clause is executed after the
+handler (and even if another exception occurred in the handler).
+It is also executed when the {\tt try} statement is left via a
+{\tt break} or {\tt return} statement.
+
+\subsection{Classes}
+
+Classes in \Python\ make it possible to play the game of encapsulation in a
+somewhat different way than it is played with modules.
+Classes are an advanced topic and are probably best skipped on the first
+encounter with \Python.
+
+\subsubsection{Prologue}
+
+\Python's class mechanism is not particularly elegant, but quite powerful.
+It is a mixture of the class mechanisms found in C++ and Modula-3.
+As is true for modules, classes in \Python\ do not put an absolute barrier
+between definition and user, but rather rely on the politeness of the
+user not to ``break into the definition.''
+The most important features of classes are retained with full power,
+however: the class inheritance mechanism allows multiple base classes,
+a derived class can override any method of its base class(es), a method
+can call the method of a base class with the same name.
+Objects can contain an arbitrary amount of private data.
+
+In C++ terminology, all class members (including data members) are
+{\em public},
+and all member functions (methods) are
+{\em virtual}.
+There are no special constructors or destructors.
+As in Modula-3, there are no shorthands for referencing the object's
+members from its methods: the method function is declared with an
+explicit first argument representing the object, which is provided
+implicitly by the call.
+As in Smalltalk, classes themselves are objects, albeit in the wider
+sense of the word: in \Python, all data types are objects.
+This provides semantics for renaming or aliasing.
+But, just like in C++ or Modula-3, the built-in types cannot be used as
+base classes for extension by the user.
+Also, like Modula-3 but unlike C++, the built-in operators with special
+syntax (arithmetic operators, subscripting etc.) cannot be redefined for
+class members.%
+\footnote{
+ They can be redefined for new object types implemented in C in
+ extensions to the interpreter, however. It would require only a
+ naming convention and a relatively small change to the
+ interpreter to allow operator overloading for classes, so
+ perhaps someday...
+}
+
+\subsubsection{A Simple Example}
+
+Consider the following example, which defines a class {\tt Set}
+representing a (finite) mathematical set with operations to add and
+remove elements, a membership test, and a request for the size of the
+set.
+\bcode\begin{verbatim}
+class Set():
+ def new(self):
+ self.elements = []
+ return self
+ def add(self, e):
+ if e not in self.elements:
+ self.elements.append(e)
+ def remove(self, e):
+ if e in self.elements:
+ for i in range(len(self.elements)):
+ if self.elements[i] = e:
+ del self.elements[i]
+ break
+ def is_element(self, e):
+ return e in self.elements
+ def size(self):
+ return len(self.elements)
+\end{verbatim}\ecode
+Note that the class definition looks like a big compound statement,
+with all the function definitons indented repective to the
+{\tt class}
+keyword.
+
+Let's assume that this
+{\em class\ definition}
+is the only contents of the module file
+{\tt SetClass.py}.
+We can then use it in a \Python\ program as follows:
+\bcode\begin{verbatim}
+>>> from SetClass import Set
+>>> a = Set().new() # create a Set object
+>>> a.add(2)
+>>> a.add(3)
+>>> a.add(1)
+>>> a.add(1)
+>>> if a.is_element(3): print '3 is in the set'
+...
+3 is in the set
+>>> if not a.is_element(4): print '4 is not in the set'
+...
+4 is not in the set
+>>> print 'a has', a.size(), 'elements'
+a has 3 elements
+>>> a.remove(1)
+>>> print 'now a has', a.size(), 'elements'
+>>>
+now a has 2 elements
+>>>
+\end{verbatim}\ecode
+From the example we learn in the first place that the functions defined
+in the class (e.g.,
+{\tt add})
+can be called using the
+{\em member}
+notation for the object
+{\tt a}.
+The member function is called with one less argument than it is defined:
+the object is implicitly passed as the first argument.
+Thus, the call
+{\tt a.add(2)}
+is equivalent to
+{\tt Set.add(a, 2)}.
+
+XXX This section is not complete yet!
+
+\section{XXX P.M.}
+
+\begin{itemize}
+\item The {\tt del} statement.
+\item The {\tt dir()} function.
+\item Tuples.
+\item Dictionaries.
+\item Objects and types in general.
+\item Backquotes.
+\item And/Or/Not.
+\end{itemize}
+
+\end{document}
diff --git a/lib/Abstract.py b/lib/Abstract.py
new file mode 100644
index 0000000..385e6e5
--- /dev/null
+++ b/lib/Abstract.py
@@ -0,0 +1,61 @@
+# Abstract classes for parents and children.
+#
+# Do not use as base class -- this is for documentation only.
+#
+# Note that the tree must be built top down (create the parent,
+# then add the children).
+#
+# Also note that the creation methods are not standardized --
+# these have extra parameters dependent on the widget type.
+# For historical reasons, button creation methods are called
+# define() while split creation methods are called create().
+
+class AbstractParent():
+ #
+ # Upcalls from child to parent
+ #
+ def addchild(self, child): unimpl()
+ def delchild(self, child): unimpl()
+ #
+ def need_mouse(self, child): unimpl()
+ def no_mouse(self, child): unimpl()
+ #
+ def need_timer(self, child): unimpl()
+ def no_timer(self, child): unimpl()
+ #
+ # XXX need_kbd, no_kbd; focus???
+ #
+ def begindrawing(self): return unimpl()
+ def beginmeasuring(self): return unimpl()
+ #
+ def change(self, area): unimpl()
+ def scroll(self, (area, (dh, dv))): unimpl()
+ def settimer(self, itimer): unimpl()
+
+class AbstractChild():
+ #
+ # Downcalls from parent to child
+ #
+ def destroy(self): unimpl()
+ #
+ def minsize(self, m): return unimpl()
+ def getbounds(self): return unimpl()
+ def setbounds(self, bounds): unimpl()
+ def draw(self, (d, area)): unimpl()
+ #
+ # Downcalls only made after certain upcalls
+ #
+ def mouse_down(self, detail): unimpl()
+ def mouse_move(self, detail): unimpl()
+ def mouse_up(self, detail): unimpl()
+ #
+ def timer(self): unimpl()
+
+# A "Split" is a child that manages one or more children.
+# (This terminology is due to DEC SRC, except for CSplits.)
+# A child of a split may be another split, a button, a slider, etc.
+# Certain upcalls and downcalls can be handled transparently, but
+# for others (e.g., all geometry related calls) this is not possible.
+
+class AbstractSplit() = AbstractChild(), AbstractParent():
+ pass
diff --git a/lib/Buttons.py b/lib/Buttons.py
new file mode 100644
index 0000000..7c36021
--- /dev/null
+++ b/lib/Buttons.py
@@ -0,0 +1,399 @@
+# Module 'Buttons'
+
+
+# Import module 'rect' renamed as '_rect' to avoid exporting it on
+# 'from Buttons import *'
+#
+import rect
+_rect = rect
+del rect
+
+
+# Field indices in mouse event detail
+#
+_HV = 0
+_CLICKS = 1
+_BUTTON = 2
+_MASK = 3
+
+
+# LabelAppearance provides defaults for all appearance methods.
+# selected state not visible
+# disabled --> crossed out
+# hilited --> inverted
+#
+class LabelAppearance():
+ #
+ # Initialization
+ #
+ def init_appearance(self):
+ self.bounds = _rect.empty
+ self.enabled = 1
+ self.hilited = 0
+ self.selected = 0
+ self.text = ''
+ #
+ # Size enquiry
+ #
+ def minsize(self, m):
+ try:
+ self.text = self.text
+ except NameError:
+ self.text = ''
+ return m.textwidth(self.text) + 6, m.lineheight() + 6
+ #
+ def getbounds(self):
+ return self.bounds
+ #
+ # Changing the parameters
+ #
+ def settext(self, text):
+ self.text = text
+ if self.bounds <> _rect.empty:
+ self.recalctextpos()
+ self.redraw()
+ #
+ def setbounds(self, bounds):
+ if self.bounds <> _rect.empty:
+ self.parent.change(self.bounds)
+ self.bounds = bounds
+ if self.bounds <> _rect.empty:
+ self.recalc()
+ self.parent.change(bounds)
+ #
+ # Changing the state bits
+ #
+ def enable(self, flag):
+ if flag <> self.enabled:
+ self.enabled = flag
+ if self.bounds <> _rect.empty:
+ self.flipenable(self.parent.begindrawing())
+ #
+ def hilite(self, flag):
+ if flag <> self.hilited:
+ self.hilited = flag
+ if self.bounds <> _rect.empty:
+ self.fliphilite(self.parent.begindrawing())
+ #
+ def select(self, flag):
+ if flag <> self.selected:
+ self.selected = flag
+ if self.bounds <> _rect.empty:
+ self.redraw()
+ #
+ # Recalculate the box bounds and text position.
+ # This can be overridden by buttons that draw different boxes
+ # or want their text in a different position.
+ #
+ def recalc(self):
+ if self.bounds <> _rect.empty:
+ self.recalcbounds()
+ self.recalctextpos()
+ #
+ def recalcbounds(self):
+ self.hilitebounds = _rect.inset(self.bounds, (3, 3))
+ self.crossbounds = self.bounds
+ #
+ def recalctextpos(self):
+ (left, top), (right, bottom) = self.bounds
+ m = self.parent.beginmeasuring()
+ h = (left + right - m.textwidth(self.text)) / 2
+ v = (top + bottom - m.lineheight()) / 2
+ self.textpos = h, v
+ #
+ # Generic drawing interface.
+ # Do not override redraw() or draw() methods; override drawit() c.s.
+ #
+ def redraw(self):
+ if self.bounds <> _rect.empty:
+ self.draw(self.parent.begindrawing(), self.bounds)
+ #
+ def draw(self, (d, area)):
+ area = _rect.intersect(area, self.bounds)
+ if area = _rect.empty:
+ return
+ d.cliprect(area)
+ d.erase(self.bounds)
+ self.drawit(d)
+ d.noclip()
+ #
+ # The drawit() method is fairly generic but may be overridden.
+ #
+ def drawit(self, d):
+ self.drawpict(d)
+ if self.text:
+ d.text(self.textpos, self.text)
+ if not self.enabled:
+ self.flipenable(d)
+ if self.hilited:
+ self.fliphilite(d)
+ #
+ # Default drawing detail functions.
+ # Overriding these is normally sufficient to get different
+ # appearances.
+ #
+ def drawpict(self, d):
+ pass
+ #
+ def flipenable(self, d):
+ _xorcross(d, self.crossbounds)
+ #
+ def fliphilite(self, d):
+ d.invert(self.hilitebounds)
+
+
+# ButtonAppearance displays a centered string in a box.
+# selected --> bold border
+# disabled --> crossed out
+# hilited --> inverted
+#
+class ButtonAppearance() = LabelAppearance():
+ #
+ def drawpict(self, d):
+ d.box(_rect.inset(self.bounds, (1, 1)))
+ if self.selected:
+ # Make a thicker box
+ d.box(self.bounds)
+ d.box(_rect.inset(self.bounds, (2, 2)))
+ d.box(_rect.inset(self.bounds, (3, 3)))
+ #
+
+
+# CheckAppearance displays a small square box and a left-justified string.
+# selected --> a cross appears in the box
+# disabled --> whole button crossed out
+# hilited --> box is inverted
+#
+class CheckAppearance() = LabelAppearance():
+ #
+ def minsize(self, m):
+ width, height = m.textwidth(self.text) + 6, m.lineheight() + 6
+ return width + height + m.textwidth(' '), height
+ #
+ def drawpict(self, d):
+ d.box(self.boxbounds)
+ if self.selected: _xorcross(d, self.boxbounds)
+ #
+ def recalcbounds(self):
+ LabelAppearance.recalcbounds(self)
+ (left, top), (right, bottom) = self.bounds
+ self.size = bottom - top - 4
+ self.boxbounds = (left+2, top+2), (left+2+self.size, bottom-2)
+ self.hilitebounds = self.boxbounds
+ #
+ def recalctextpos(self):
+ m = self.parent.beginmeasuring()
+ (left, top), (right, bottom) = self.boxbounds
+ h = right + m.textwidth(' ')
+ v = top + (self.size - m.lineheight()) / 2
+ self.textpos = h, v
+ #
+
+
+# RadioAppearance displays a round indicator and a left-justified string.
+# selected --> a dot appears in the indicator
+# disabled --> whole button crossed out
+# hilited --> indicator is inverted
+#
+class RadioAppearance() = CheckAppearance():
+ #
+ def drawpict(self, d):
+ (left, top), (right, bottom) = self.boxbounds
+ radius = self.size / 2
+ h, v = left + radius, top + radius
+ d.circle((h, v), radius)
+ if self.selected:
+ some = radius/3
+ d.paint((h-some, v-some), (h+some, v+some))
+ #
+
+
+# NoReactivity ignores mouse events.
+#
+class NoReactivity():
+ def init_reactivity(self): pass
+
+
+# BaseReactivity defines hooks and asks for mouse events,
+# but provides only dummy mouse event handlers.
+# The trigger methods call the corresponding hooks set by the user.
+# Hooks (and triggers) mean the following:
+# down_hook called on some mouse-down events
+# move_hook called on some mouse-move events
+# up_hook called on mouse-up events
+# on_hook called for buttons with on/off state, when it goes on
+# hook called when a button 'fires' or a radiobutton goes on
+# There are usually extra conditions, e.g., hooks are only called
+# when the button is enabled, or active, or selected (on).
+#
+class BaseReactivity():
+ #
+ def init_reactivity(self):
+ self.down_hook = self.move_hook = self.up_hook = \
+ self.on_hook = self.off_hook = \
+ self.hook = self.active = 0
+ self.parent.need_mouse(self)
+ #
+ def mousetest(self, hv):
+ return _rect.pointinrect(hv, self.bounds)
+ #
+ def mouse_down(self, detail):
+ pass
+ #
+ def mouse_move(self, detail):
+ pass
+ #
+ def mouse_up(self, detail):
+ pass
+ #
+ def down_trigger(self):
+ if self.down_hook: self.down_hook(self)
+ #
+ def move_trigger(self):
+ if self.move_hook: self.move_hook(self)
+ #
+ def up_trigger(self):
+ if self.up_hook: self.up_hook(self)
+ #
+ def on_trigger(self):
+ if self.on_hook: self.on_hook(self)
+ #
+ def off_trigger(self):
+ if self.off_hook: self.off_hook(self)
+ #
+ def trigger(self):
+ if self.hook: self.hook(self)
+
+
+# ToggleReactivity acts like a simple pushbutton.
+# It toggles its hilite state on mouse down events.
+#
+class ToggleReactivity() = BaseReactivity():
+ #
+ def mouse_down(self, detail):
+ if self.enabled and self.mousetest(detail[_HV]):
+ self.active = 1
+ self.hilite(not self.hilited)
+ self.down_trigger()
+ #
+ def mouse_move(self, detail):
+ if self.active:
+ self.move_trigger()
+ #
+ def mouse_up(self, detail):
+ if self.active:
+ self.up_trigger()
+ self.active = 0
+ #
+ def down_trigger(self):
+ if self.hilited:
+ self.on_trigger()
+ else:
+ self.off_trigger()
+ self.trigger()
+ #
+
+
+# TriggerReactivity acts like a fancy pushbutton.
+# It hilites itself while the mouse is down within its bounds.
+#
+class TriggerReactivity() = BaseReactivity():
+ #
+ def mouse_down(self, detail):
+ if self.enabled and self.mousetest(detail[_HV]):
+ self.active = 1
+ self.hilite(1)
+ self.down_trigger()
+ #
+ def mouse_move(self, detail):
+ if self.active:
+ self.hilite(self.mousetest(detail[_HV]))
+ if self.hilited:
+ self.move_trigger()
+ #
+ def mouse_up(self, detail):
+ if self.active:
+ self.hilite(self.mousetest(detail[_HV]))
+ if self.hilited:
+ self.up_trigger()
+ self.trigger()
+ self.active = 0
+ self.hilite(0)
+ #
+
+
+# CheckReactivity handles mouse events like TriggerReactivity,
+# It overrides the up_trigger method to flip its selected state.
+#
+class CheckReactivity() = TriggerReactivity():
+ #
+ def up_trigger(self):
+ self.select(not self.selected)
+ if self.selected:
+ self.on_trigger()
+ else:
+ self.off_trigger()
+ self.trigger()
+
+
+# RadioReactivity turns itself on and the other buttons in its group
+# off when its up_trigger method is called.
+#
+class RadioReactivity() = TriggerReactivity():
+ #
+ def init_reactivity(self):
+ TriggerReactivity.init_reactivity(self)
+ self.group = []
+ #
+ def up_trigger(self):
+ for b in self.group:
+ if b <> self:
+ if b.selected:
+ b.select(0)
+ b.off_trigger()
+ self.select(1)
+ self.on_trigger()
+ self.trigger()
+
+
+# Auxiliary class for 'define' method.
+# Call the initializers in the right order.
+#
+class Define():
+ #
+ def define(self, parent):
+ self.parent = parent
+ parent.addchild(self)
+ self.init_appearance()
+ self.init_reactivity()
+ return self
+ #
+ def destroy(self):
+ self.parent = 0
+ #
+ def definetext(self, (parent, text)):
+ self = self.define(parent)
+ self.settext(text)
+ return self
+
+
+# Subroutine to cross out a rectangle.
+#
+def _xorcross(d, bounds):
+ ((left, top), (right, bottom)) = bounds
+ # This is s bit funny to make it look better
+ left = left + 2
+ right = right - 2
+ top = top + 2
+ bottom = bottom - 3
+ d.xorline(((left, top), (right, bottom)))
+ d.xorline((left, bottom), (right, top))
+
+
+# Ready-made button classes.
+#
+class Label() = NoReactivity(), LabelAppearance(), Define(): pass
+class PushButton() = TriggerReactivity(), ButtonAppearance(), Define(): pass
+class CheckButton() = CheckReactivity(), CheckAppearance(), Define(): pass
+class RadioButton() = RadioReactivity(), RadioAppearance(), Define(): pass
+class ToggleButton() = ToggleReactivity(), ButtonAppearance(), Define(): pass
diff --git a/lib/CSplit.py b/lib/CSplit.py
new file mode 100644
index 0000000..a28b1c8
--- /dev/null
+++ b/lib/CSplit.py
@@ -0,0 +1,70 @@
+# A CSplit is a Clock-shaped split: the children are grouped in a circle.
+# The numbering is a little different from a real clock: the 12 o'clock
+# position is called 0, not 12. This is a little easier since Python
+# usually counts from zero. (BTW, there needn't be exactly 12 children.)
+
+
+from math import pi, sin, cos
+from Split import Split
+
+class CSplit() = Split():
+ #
+ def minsize(self, m):
+ # Since things look best if the children are spaced evenly
+ # along the circle (and often all children have the same
+ # size anyway) we compute the max child size and assume
+ # this is each child's size.
+ width, height = 0, 0
+ for child in self.children:
+ wi, he = child.minsize(m)
+ width = max(width, wi)
+ height = max(height, he)
+ # In approximation, the diameter of the circle we need is
+ # (diameter of box) * (#children) / pi.
+ # We approximate pi by 3 (so we slightly overestimate
+ # our minimal size requirements -- not so bad).
+ # Because the boxes stick out of the circle we add the
+ # box size to each dimension.
+ # Because we really deal with ellipses, do everything
+ # separate in each dimension.
+ n = len(self.children)
+ return width + (width*n + 2)/3, height + (height*n + 2)/3
+ #
+ def getbounds(self):
+ return self.bounds
+ #
+ def setbounds(self, bounds):
+ self.bounds = bounds
+ # Place the children. This involves some math.
+ # Compute center positions for children as if they were
+ # ellipses with a diameter about 1/N times the
+ # circumference of the big ellipse.
+ # (There is some rounding involved to make it look
+ # reasonable for small and large N alike.)
+ # XXX One day Python will have automatic conversions...
+ n = len(self.children)
+ fn = float(n)
+ if n = 0: return
+ (left, top), (right, bottom) = bounds
+ width, height = right-left, bottom-top
+ child_width, child_height = width*3/(n+4), height*3/(n+4)
+ half_width, half_height = \
+ float(width-child_width)/2.0, \
+ float(height-child_height)/2.0
+ center_h, center_v = center = (left+right)/2, (top+bottom)/2
+ fch, fcv = float(center_h), float(center_v)
+ alpha = 2.0 * pi / fn
+ for i in range(n):
+ child = self.children[i]
+ fi = float(i)
+ fh, fv = \
+ fch + half_width*sin(fi*alpha), \
+ fcv - half_height*cos(fi*alpha)
+ left, top = \
+ int(fh) - child_width/2, \
+ int(fv) - child_height/2
+ right, bottom = \
+ left + child_width, \
+ top + child_height
+ child.setbounds((left, top), (right, bottom))
+ #
diff --git a/lib/DEVICE.py b/lib/DEVICE.py
new file mode 100644
index 0000000..4f2fadc
--- /dev/null
+++ b/lib/DEVICE.py
@@ -0,0 +1,423 @@
+#/**************************************************************************
+# * *
+# * Copyright (C) 1984, Silicon Graphics, Inc. *
+# * *
+# * These coded instructions, statements, and computer programs contain *
+# * unpublished proprietary information of Silicon Graphics, Inc., and *
+# * are protected by Federal copyright law. They may not be disclosed *
+# * to third parties or copied or duplicated in any form, in whole or *
+# * in part, without the prior written consent of Silicon Graphics, Inc. *
+# * *
+# **************************************************************************/
+#/* file with device definitions (see /usr/include/device.h) */
+
+NULLDEV = 0
+BUTOFFSET = 1
+VALOFFSET = 256
+TIMOFFSET = 515
+XKBDOFFSET = 143
+INOFFSET = 1024
+OUTOFFSET = 1033
+BUTCOUNT = 190
+VALCOUNT = 27
+TIMCOUNT = 4
+XKBDCOUNT = 28
+INCOUNT = 8
+OUTCOUNT = 8
+#
+#
+#
+#
+BUT0 = 1
+BUT1 = 2
+BUT2 = 3
+BUT3 = 4
+BUT4 = 5
+BUT5 = 6
+BUT6 = 7
+BUT7 = 8
+BUT8 = 9
+BUT9 = 10
+BUT10 = 11
+BUT11 = 12
+BUT12 = 13
+BUT13 = 14
+BUT14 = 15
+BUT15 = 16
+BUT16 = 17
+BUT17 = 18
+BUT18 = 19
+BUT19 = 20
+BUT20 = 21
+BUT21 = 22
+BUT22 = 23
+BUT23 = 24
+BUT24 = 25
+BUT25 = 26
+BUT26 = 27
+BUT27 = 28
+BUT28 = 29
+BUT29 = 30
+BUT30 = 31
+BUT31 = 32
+BUT32 = 33
+BUT33 = 34
+BUT34 = 35
+BUT35 = 36
+BUT36 = 37
+BUT37 = 38
+BUT38 = 39
+BUT39 = 40
+BUT40 = 41
+BUT41 = 42
+BUT42 = 43
+BUT43 = 44
+BUT44 = 45
+BUT45 = 46
+BUT46 = 47
+BUT47 = 48
+BUT48 = 49
+BUT49 = 50
+BUT50 = 51
+BUT51 = 52
+BUT52 = 53
+BUT53 = 54
+BUT54 = 55
+BUT55 = 56
+BUT56 = 57
+BUT57 = 58
+BUT58 = 59
+BUT59 = 60
+BUT60 = 61
+BUT61 = 62
+BUT62 = 63
+BUT63 = 64
+BUT64 = 65
+BUT65 = 66
+BUT66 = 67
+BUT67 = 68
+BUT68 = 69
+BUT69 = 70
+BUT70 = 71
+BUT71 = 72
+BUT72 = 73
+BUT73 = 74
+BUT74 = 75
+BUT75 = 76
+BUT76 = 77
+BUT77 = 78
+BUT78 = 79
+BUT79 = 80
+BUT80 = 81
+BUT81 = 82
+BUT82 = 83
+MAXKBDBUT = 83
+BUT100 = 101
+BUT101 = 102
+BUT102 = 103
+BUT110 = 111
+BUT111 = 112
+BUT112 = 113
+BUT113 = 114
+BUT114 = 115
+BUT115 = 116
+BUT116 = 117
+BUT117 = 118
+BUT118 = 119
+BUT119 = 120
+BUT120 = 121
+BUT121 = 122
+BUT122 = 123
+BUT123 = 124
+BUT124 = 125
+BUT125 = 126
+BUT126 = 127
+BUT127 = 128
+BUT128 = 129
+BUT129 = 130
+BUT130 = 131
+BUT131 = 132
+BUT132 = 133
+BUT133 = 134
+BUT134 = 135
+BUT135 = 136
+BUT136 = 137
+BUT137 = 138
+BUT138 = 139
+BUT139 = 140
+BUT140 = 141
+BUT141 = 142
+BUT142 = 143
+BUT143 = 144
+BUT144 = 145
+BUT145 = 146
+BUT146 = 147
+BUT147 = 148
+BUT148 = 149
+BUT149 = 150
+BUT150 = 151
+BUT151 = 152
+BUT152 = 153
+BUT153 = 154
+BUT154 = 155
+BUT155 = 156
+BUT156 = 157
+BUT157 = 158
+BUT158 = 159
+BUT159 = 160
+BUT160 = 161
+BUT161 = 162
+BUT162 = 163
+BUT163 = 164
+BUT164 = 165
+BUT165 = 166
+BUT166 = 167
+BUT167 = 168
+BUT168 = 169
+BUT181 = 182
+BUT182 = 183
+BUT183 = 184
+BUT184 = 185
+BUT185 = 186
+BUT186 = 187
+BUT187 = 188
+BUT188 = 189
+BUT189 = 190
+MOUSE1 = 101
+MOUSE2 = 102
+MOUSE3 = 103
+LEFTMOUSE = 103
+MIDDLEMOUSE = 102
+RIGHTMOUSE = 101
+LPENBUT = 104
+BPAD0 = 105
+BPAD1 = 106
+BPAD2 = 107
+BPAD3 = 108
+LPENVALID = 109
+SWBASE = 111
+SW0 = 111
+SW1 = 112
+SW2 = 113
+SW3 = 114
+SW4 = 115
+SW5 = 116
+SW6 = 117
+SW7 = 118
+SW8 = 119
+SW9 = 120
+SW10 = 121
+SW11 = 122
+SW12 = 123
+SW13 = 124
+SW14 = 125
+SW15 = 126
+SW16 = 127
+SW17 = 128
+SW18 = 129
+SW19 = 130
+SW20 = 131
+SW21 = 132
+SW22 = 133
+SW23 = 134
+SW24 = 135
+SW25 = 136
+SW26 = 137
+SW27 = 138
+SW28 = 139
+SW29 = 140
+SW30 = 141
+SW31 = 142
+SBBASE = 182
+SBPICK = 182
+SBBUT1 = 183
+SBBUT2 = 184
+SBBUT3 = 185
+SBBUT4 = 186
+SBBUT5 = 187
+SBBUT6 = 188
+SBBUT7 = 189
+SBBUT8 = 190
+AKEY = 11
+BKEY = 36
+CKEY = 28
+DKEY = 18
+EKEY = 17
+FKEY = 19
+GKEY = 26
+HKEY = 27
+IKEY = 40
+JKEY = 34
+KKEY = 35
+LKEY = 42
+MKEY = 44
+NKEY = 37
+OKEY = 41
+PKEY = 48
+QKEY = 10
+RKEY = 24
+SKEY = 12
+TKEY = 25
+UKEY = 33
+VKEY = 29
+WKEY = 16
+XKEY = 21
+YKEY = 32
+ZKEY = 20
+ZEROKEY = 46
+ONEKEY = 8
+TWOKEY = 14
+THREEKEY = 15
+FOURKEY = 22
+FIVEKEY = 23
+SIXKEY = 30
+SEVENKEY = 31
+EIGHTKEY = 38
+NINEKEY = 39
+BREAKKEY = 1
+SETUPKEY = 2
+CTRLKEY = 3
+LEFTCTRLKEY = CTRLKEY
+CAPSLOCKKEY = 4
+RIGHTSHIFTKEY = 5
+LEFTSHIFTKEY = 6
+NOSCRLKEY = 13
+ESCKEY = 7
+TABKEY = 9
+RETKEY = 51
+SPACEKEY = 83
+LINEFEEDKEY = 60
+BACKSPACEKEY = 61
+DELKEY = 62
+SEMICOLONKEY = 43
+PERIODKEY = 52
+COMMAKEY = 45
+QUOTEKEY = 50
+ACCENTGRAVEKEY = 55
+MINUSKEY = 47
+VIRGULEKEY = 53
+BACKSLASHKEY = 57
+EQUALKEY = 54
+LEFTBRACKETKEY = 49
+RIGHTBRACKETKEY = 56
+LEFTARROWKEY = 73
+DOWNARROWKEY = 74
+RIGHTARROWKEY = 80
+UPARROWKEY = 81
+PAD0 = 59
+PAD1 = 58
+PAD2 = 64
+PAD3 = 65
+PAD4 = 63
+PAD5 = 69
+PAD6 = 70
+PAD7 = 67
+PAD8 = 68
+PAD9 = 75
+PADPF1 = 72
+PADPF2 = 71
+PADPF3 = 79
+PADPF4 = 78
+PADPERIOD = 66
+PADMINUS = 76
+PADCOMMA = 77
+PADENTER = 82
+LEFTALTKEY = 143
+RIGHTALTKEY = 144
+RIGHTCTRLKEY = 145
+F1KEY = 146
+F2KEY = 147
+F3KEY = 148
+F4KEY = 149
+F5KEY = 150
+F6KEY = 151
+F7KEY = 152
+F8KEY = 153
+F9KEY = 154
+F10KEY = 155
+F11KEY = 156
+F12KEY = 157
+PRINTSCREENKEY = 158
+SCROLLLOCKKEY = 159
+PAUSEKEY = 160
+INSERTKEY = 161
+HOMEKEY = 162
+PAGEUPKEY = 163
+ENDKEY = 164
+PAGEDOWNKEY = 165
+NUMLOCKKEY = 166
+PADVIRGULEKEY = 167
+PADASTERKEY = 168
+PADPLUSKEY = 169
+SGIRESERVED = 256
+DIAL0 = 257
+DIAL1 = 258
+DIAL2 = 259
+DIAL3 = 260
+DIAL4 = 261
+DIAL5 = 262
+DIAL6 = 263
+DIAL7 = 264
+DIAL8 = 265
+MOUSEX = 266
+MOUSEY = 267
+LPENX = 268
+LPENY = 269
+BPADX = 270
+BPADY = 271
+CURSORX = 272
+CURSORY = 273
+GHOSTX = 274
+GHOSTY = 275
+SBTX = 276
+SBTY = 277
+SBTZ = 278
+SBRX = 279
+SBRY = 280
+SBRZ = 281
+SBPERIOD = 282
+TIMER0 = 515
+TIMER1 = 516
+TIMER2 = 517
+TIMER3 = 518
+KEYBD = 513
+RAWKEYBD = 514
+VALMARK = 523
+GERROR = 524
+REDRAW = 528
+WMSEND = 529
+WMREPLY = 530
+WMGFCLOSE = 531
+WMTXCLOSE = 532
+MODECHANGE = 533
+INPUTCHANGE = 534
+QFULL = 535
+PIECECHANGE = 536
+WINCLOSE = 537
+QREADERROR = 538
+WINFREEZE = 539
+WINTHAW = 540
+REDRAWICONIC = 541
+WINQUIT = 542
+DEPTHCHANGE = 543
+KEYBDFNAMES = 544
+KEYBDFSTRINGS = 545
+WINSHUT = 546
+INPUT0 = 1024
+INPUT1 = 1025
+INPUT2 = 1026
+INPUT3 = 1027
+INPUT4 = 1028
+INPUT5 = 1029
+INPUT6 = 1030
+INPUT7 = 1032
+OUTPUT0 = 1033
+OUTPUT1 = 1034
+OUTPUT2 = 1035
+OUTPUT3 = 1036
+OUTPUT4 = 1037
+OUTPUT5 = 1038
+OUTPUT6 = 1039
+OUTPUT7 = 1040
+MAXSGIDEVICE = 20000
+MENUBUTTON = RIGHTMOUSE
diff --git a/lib/GL.py b/lib/GL.py
new file mode 100644
index 0000000..b733e51
--- /dev/null
+++ b/lib/GL.py
@@ -0,0 +1,365 @@
+# Constants defined in <gl.h>
+
+#**************************************************************************
+#* *
+#* Copyright (C) 1984, Silicon Graphics, Inc. *
+#* *
+#* These coded instructions, statements, and computer programs contain *
+#* unpublished proprietary information of Silicon Graphics, Inc., and *
+#* are protected by Federal copyright law. They may not be disclosed *
+#* to third parties or copied or duplicated in any form, in whole or *
+#* in part, without the prior written consent of Silicon Graphics, Inc. *
+#* *
+#**************************************************************************
+
+# Graphics Libary constants
+
+# Booleans
+TRUE = 1
+FALSE = 0
+
+# maximum X and Y screen coordinates
+XMAXSCREEN = 1279
+YMAXSCREEN = 1023
+XMAXMEDIUM = 1023 # max for medium res monitor
+YMAXMEDIUM = 767
+XMAX170 = 645 # max for RS-170
+YMAX170 = 484
+XMAXPAL = 779 # max for PAL
+YMAXPAL = 574
+
+# various hardware/software limits
+ATTRIBSTACKDEPTH = 10
+VPSTACKDEPTH = 8
+MATRIXSTACKDEPTH = 32
+NAMESTACKDEPTH = 1025
+STARTTAG = -2
+ENDTAG = -3
+CPOSX_INVALID = -(2*XMAXSCREEN)
+
+# names for colors in color map loaded by greset
+BLACK = 0
+RED = 1
+GREEN = 2
+YELLOW = 3
+BLUE = 4
+MAGENTA = 5
+CYAN = 6
+WHITE = 7
+
+# popup colors
+PUP_CLEAR = 0
+PUP_COLOR = 1
+PUP_BLACK = 2
+PUP_WHITE = 3
+
+# defines for drawmode
+NORMALDRAW = 0
+PUPDRAW = 1
+OVERDRAW = 2
+UNDERDRAW = 3
+CURSORDRAW = 4
+
+# defines for defpattern
+PATTERN_16 = 16
+PATTERN_32 = 32
+PATTERN_64 = 64
+
+PATTERN_16_SIZE = 16
+PATTERN_32_SIZE = 64
+PATTERN_64_SIZE = 256
+
+# defines for readsource
+SRC_AUTO = 0
+SRC_FRONT = 1
+SRC_BACK = 2
+SRC_ZBUFFER = 3
+SRC_PUP = 4
+SRC_OVER = 5
+SRC_UNDER = 6
+SRC_FRAMEGRABBER = 7
+
+# defines for blendfunction
+BF_ZERO = 0
+BF_ONE = 1
+BF_DC = 2
+BF_SC = 2
+BF_MDC = 3
+BF_MSC = 3
+BF_SA = 4
+BF_MSA = 5
+BF_DA = 6
+BF_MDA = 7
+
+# defines for zfunction
+ZF_NEVER = 0
+ZF_LESS = 1
+ZF_EQUAL = 2
+ZF_LEQUAL = 3
+ZF_GREATER = 4
+ZF_NOTEQUAL = 5
+ZF_GEQUAL = 6
+ZF_ALWAYS = 7
+
+# defines for zsource
+ZSRC_DEPTH = 0
+ZSRC_COLOR = 1
+
+# defines for pntsmooth
+SMP_OFF = 0
+SMP_ON = 1
+
+# defines for linesmooth
+SML_OFF = 0
+SML_ON = 1
+
+# defines for setpup
+PUP_NONE = 0
+PUP_GREY = 1
+
+# defines for glcompat
+GLC_OLDPOLYGON = 0
+GLC_ZRANGEMAP = 1
+
+# defines for curstype
+C16X1 = 0
+C16X2 = 1
+C32X1 = 2
+C32X2 = 3
+CCROSS = 4
+
+# defines for shademodel
+FLAT = 0
+GOURAUD = 1
+
+# defines for logicop
+### LO_ZERO = 0x0
+### LO_AND = 0x1
+### LO_ANDR = 0x2
+### LO_SRC = 0x3
+### LO_ANDI = 0x4
+### LO_DST = 0x5
+### LO_XOR = 0x6
+### LO_OR = 0x7
+### LO_NOR = 0x8
+### LO_XNOR = 0x9
+### LO_NDST = 0xa
+### LO_ORR = 0xb
+### LO_NSRC = 0xc
+### LO_ORI = 0xd
+### LO_NAND = 0xe
+### LO_ONE = 0xf
+
+
+#
+# START defines for getgdesc
+#
+
+GD_XPMAX = 0
+GD_YPMAX = 1
+GD_XMMAX = 2
+GD_YMMAX = 3
+GD_ZMIN = 4
+GD_ZMAX = 5
+GD_BITS_NORM_SNG_RED = 6
+GD_BITS_NORM_SNG_GREEN = 7
+GD_BITS_NORM_SNG_BLUE = 8
+GD_BITS_NORM_DBL_RED = 9
+GD_BITS_NORM_DBL_GREEN = 10
+GD_BITS_NORM_DBL_BLUE = 11
+GD_BITS_NORM_SNG_CMODE = 12
+GD_BITS_NORM_DBL_CMODE = 13
+GD_BITS_NORM_SNG_MMAP = 14
+GD_BITS_NORM_DBL_MMAP = 15
+GD_BITS_NORM_ZBUFFER = 16
+GD_BITS_OVER_SNG_CMODE = 17
+GD_BITS_UNDR_SNG_CMODE = 18
+GD_BITS_PUP_SNG_CMODE = 19
+GD_BITS_NORM_SNG_ALPHA = 21
+GD_BITS_NORM_DBL_ALPHA = 22
+GD_BITS_CURSOR = 23
+GD_OVERUNDER_SHARED = 24
+GD_BLEND = 25
+GD_CIFRACT = 26
+GD_CROSSHAIR_CINDEX = 27
+GD_DITHER = 28
+GD_LINESMOOTH_CMODE = 30
+GD_LINESMOOTH_RGB = 31
+GD_LOGICOP = 33
+GD_NSCRNS = 35
+GD_NURBS_ORDER = 36
+GD_NBLINKS = 37
+GD_NVERTEX_POLY = 39
+GD_PATSIZE_64 = 40
+GD_PNTSMOOTH_CMODE = 41
+GD_PNTSMOOTH_RGB = 42
+GD_PUP_TO_OVERUNDER = 43
+GD_READSOURCE = 44
+GD_READSOURCE_ZBUFFER = 48
+GD_STEREO = 50
+GD_SUBPIXEL_LINE = 51
+GD_SUBPIXEL_PNT = 52
+GD_SUBPIXEL_POLY = 53
+GD_TRIMCURVE_ORDER = 54
+GD_WSYS = 55
+GD_ZDRAW_GEOM = 57
+GD_ZDRAW_PIXELS = 58
+GD_SCRNTYPE = 61
+GD_TEXTPORT = 62
+GD_NMMAPS = 63
+GD_FRAMEGRABBER = 64
+GD_TIMERHZ = 66
+GD_DBBOX = 67
+GD_AFUNCTION = 68
+GD_ALPHA_OVERUNDER = 69
+GD_BITS_ACBUF = 70
+GD_BITS_ACBUF_HW = 71
+GD_BITS_STENCIL = 72
+GD_CLIPPLANES = 73
+GD_FOGVERTEX = 74
+GD_LIGHTING_TWOSIDE = 76
+GD_POLYMODE = 77
+GD_POLYSMOOTH = 78
+GD_SCRBOX = 79
+GD_TEXTURE = 80
+
+# return value for inquiries when there is no limit
+GD_NOLIMIT = 2
+
+# return values for GD_WSYS
+GD_WSYS_NONE = 0
+GD_WSYS_4S = 1
+
+# return values for GD_SCRNTYPE
+GD_SCRNTYPE_WM = 0
+GD_SCRNTYPE_NOWM = 1
+
+#
+# END defines for getgdesc
+#
+
+
+#
+# START NURBS interface definitions
+#
+
+# NURBS Rendering Properties
+N_PIXEL_TOLERANCE = 1
+N_CULLING = 2
+N_DISPLAY = 3
+N_ERRORCHECKING = 4
+N_SUBDIVISIONS = 5
+N_S_STEPS = 6
+N_T_STEPS = 7
+N_TILES = 8
+
+N_SHADED = 1.0
+
+# ---------------------------------------------------------------------------
+# FLAGS FOR NURBS SURFACES AND CURVES
+#
+# Bit: 9876 5432 1 0
+# |tttt|nnnn|f|r| : r - 1 bit = 1 if rational coordinate exists
+# : f - 1 bit = 1 if rational coordinate is before rest
+# : = 0 if rational coordinate is after rest
+# : nnnn - 4 bits for number of coordinates
+# : tttt - 4 bits for type of data (color, position, etc.)
+#
+# NURBS data type
+# N_T_ST 0 parametric space data
+# N_T_XYZ 1 model space data
+#
+# rational or non-rational data and position in memory
+# N_NONRATIONAL 0 non-rational data
+# N_RATAFTER 1 rational data with rat coord after rest
+# N_RATBEFORE 3 rational data with rat coord before rest
+#
+# N_MKFLAG(a,b,c) ((a<<6) | (b<<2) | c)
+#
+# ---------------------------------------------------------------------------
+#
+N_ST = 0x8 # N_MKFLAG( N_T_ST, 2, N_NONRATIONAL )
+N_STW = 0xd # N_MKFLAG( N_T_ST, 3, N_RATAFTER )
+N_WST = 0xf # N_MKFLAG( N_T_ST, 3, N_RATBEFORE )
+N_XYZ = 0x4c # N_MKFLAG( N_T_XYZ, 3, N_NONRATIONAL )
+N_XYZW = 0x51 # N_MKFLAG( N_T_XYZ, 4, N_RATAFTER )
+N_WXYZ = 0x53 # N_MKFLAG( N_T_XYZ, 4, N_RATBEFORE )
+
+#
+# END NURBS interface definitions
+#
+
+
+#
+# START lighting model defines
+#
+
+LMNULL = 0.0
+
+# MATRIX modes
+MSINGLE = 0
+MPROJECTION = 1
+MVIEWING = 2
+
+# LIGHT constants
+MAXLIGHTS = 8
+MAXRESTRICTIONS = 4
+
+# MATERIAL properties
+DEFMATERIAL = 0
+EMISSION = 1
+AMBIENT = 2
+DIFFUSE = 3
+SPECULAR = 4
+SHININESS = 5
+COLORINDEXES = 6
+ALPHA = 7
+
+# LIGHT properties
+DEFLIGHT = 100
+LCOLOR = 101
+POSITION = 102
+
+# LIGHTINGMODEL properties
+DEFLMODEL = 200
+LOCALVIEWER = 201
+ATTENUATION = 202
+
+# TARGET constants
+MATERIAL = 1000
+LIGHT0 = 1100
+LIGHT1 = 1101
+LIGHT2 = 1102
+LIGHT3 = 1103
+LIGHT4 = 1104
+LIGHT5 = 1105
+LIGHT6 = 1106
+LIGHT7 = 1107
+LMODEL = 1200
+
+# lmcolor modes
+LMC_COLOR = 0
+LMC_EMISSION = 1
+LMC_AMBIENT = 2
+LMC_DIFFUSE = 3
+LMC_SPECULAR = 4
+LMC_AD = 5
+LMC_NULL = 6
+
+#
+# END lighting model defines
+#
+
+
+#
+# START distributed graphics library defines
+#
+
+DGLSINK = 0 # sink connection
+DGLLOCAL = 1 # local connection
+DGLTSOCKET = 2 # tcp socket connection
+DGL4DDN = 3 # 4DDN (DECnet)
+
+#
+# END distributed graphics library defines
+#
diff --git a/lib/HVSplit.py b/lib/HVSplit.py
new file mode 100644
index 0000000..d52af8e
--- /dev/null
+++ b/lib/HVSplit.py
@@ -0,0 +1,56 @@
+# HVSplit contains generic code for HSplit and VSplit.
+# HSplit and VSplit are specializations to either dimension.
+
+# XXX This does not yet stretch/shrink children if there is too much
+# XXX or too little space in the split dimension.
+# XXX (NB There is no interface to ask children for stretch preferences.)
+
+from Split import Split
+
+class HVSplit() = Split():
+ #
+ def create(self, (parent, hv)):
+ # hv is 0 or 1 for HSplit or VSplit
+ self = Split.create(self, parent)
+ self.hv = hv
+ return self
+ #
+ def minsize(self, m):
+ hv, vh = self.hv, 1 - self.hv
+ size = [0, 0]
+ for c in self.children:
+ csize = c.minsize(m)
+ if csize[vh] > size[vh]: size[vh] = csize[vh]
+ size[hv] = size[hv] + csize[hv]
+ return size[0], size[1]
+ #
+ def getbounds(self):
+ return self.bounds
+ #
+ def setbounds(self, bounds):
+ self.bounds = bounds
+ hv, vh = self.hv, 1 - self.hv
+ mf = self.parent.beginmeasuring
+ size = self.minsize(mf())
+ # XXX not yet used! Later for stretching
+ maxsize_hv = bounds[1][hv] - bounds[0][hv]
+ origin = [self.bounds[0][0], self.bounds[0][1]]
+ for c in self.children:
+ size = c.minsize(mf())
+ corner = [0, 0]
+ corner[vh] = bounds[1][vh]
+ corner[hv] = origin[hv] + size[hv]
+ c.setbounds((origin[0], origin[1]), \
+ (corner[0], corner[1]))
+ origin[hv] = corner[hv]
+ # XXX stretch
+ # XXX too-small
+ #
+
+class HSplit() = HVSplit():
+ def create(self, parent):
+ return HVSplit.create(self, (parent, 0))
+
+class VSplit() = HVSplit():
+ def create(self, parent):
+ return HVSplit.create(self, (parent, 1))
diff --git a/lib/Histogram.py b/lib/Histogram.py
new file mode 100644
index 0000000..3f6da76
--- /dev/null
+++ b/lib/Histogram.py
@@ -0,0 +1,36 @@
+# Module 'Histogram'
+
+from Buttons import *
+
+# A Histogram displays a histogram of numeric data.
+#
+class HistogramAppearance() = LabelAppearance(), Define():
+ #
+ def define(self, parent):
+ Define.define(self, (parent, ''))
+ self.ydata = []
+ self.scale = (0, 100)
+ return self
+ #
+ def setdata(self, (ydata, scale)):
+ self.ydata = ydata
+ self.scale = scale # (min, max)
+ self.parent.change(self.bounds)
+ #
+ def drawpict(self, d):
+ (left, top), (right, bottom) = self.bounds
+ min, max = self.scale
+ size = max-min
+ width, height = right-left, bottom-top
+ ydata = self.ydata
+ npoints = len(ydata)
+ v1 = top + height # constant
+ h1 = left # changed in loop
+ for i in range(npoints):
+ h0 = h1
+ v0 = top + height - (ydata[i]-min)*height/size
+ h1 = left + (i+1) * width/npoints
+ d.paint((h0, v0), (h1, v1))
+ #
+
+class Histogram() = NoReactivity(), HistogramAppearance(): pass
diff --git a/lib/Sliders.py b/lib/Sliders.py
new file mode 100644
index 0000000..e44b466
--- /dev/null
+++ b/lib/Sliders.py
@@ -0,0 +1,175 @@
+# Module 'Sliders'
+
+
+import stdwin
+from stdwinevents import *
+import rect
+from Buttons import *
+from HVSplit import HSplit
+
+
+# Field indices in event detail
+#
+_HV = 0
+_CLICKS = 1
+_BUTTON = 2
+_MASK = 3
+
+
+# DragSlider is the simplest possible slider.
+# It looks like a button but dragging the mouse left or right
+# changes the controlled value.
+# It does not support any of the triggers or hooks defined by Buttons,
+# but defines its own setval_trigger and setval_hook.
+#
+class DragSliderReactivity() = BaseReactivity():
+ #
+ def mouse_down(self, detail):
+ h, v = hv = detail[_HV]
+ if self.enabled and self.mousetest(hv):
+ self.anchor = h
+ self.oldval = self.val
+ self.active = 1
+ #
+ def mouse_move(self, detail):
+ if self.active:
+ h, v = detail[_HV]
+ self.setval(self.oldval + (h - self.anchor))
+ #
+ def mouse_up(self, detail):
+ if self.active:
+ h, v = detail[_HV]
+ self.setval(self.oldval + (h - self.anchor))
+ self.active = 0
+ #
+
+class DragSliderAppearance() = ButtonAppearance():
+ #
+ # INVARIANTS maintained by the setval method:
+ #
+ # self.min <= self.val <= self.max
+ # self.text = self.pretext + `self.val` + self.postext
+ #
+ # (Notice that unlike Python ranges, the end point belongs
+ # to the range.)
+ #
+ def init_appearance(self):
+ ButtonAppearance.init_appearance(self)
+ self.min = 0
+ self.val = 0
+ self.max = 100
+ self.hook = 0
+ self.pretext = self.postext = ''
+ self.recalctext()
+ #
+ # The 'get*' and 'set*' methods belong to the generic slider interface
+ #
+ def getval(self): return self.val
+ #
+ def sethook(self, hook):
+ self.hook = hook
+ #
+ def setminvalmax(self, (min, val, max)):
+ self.min = min
+ self.max = max
+ self.setval(val)
+ #
+ def settexts(self, (pretext, postext)):
+ self.pretext = pretext
+ self.postext = postext
+ self.recalctext()
+ #
+ def setval(self, val):
+ val = min(self.max, max(self.min, val))
+ if val <> self.val:
+ self.val = val
+ self.recalctext()
+ self.trigger()
+ #
+ def trigger(self):
+ if self.hook:
+ self.hook(self)
+ #
+ def recalctext(self):
+ self.settext(self.pretext + `self.val` + self.postext)
+ #
+
+class DragSlider() = DragSliderReactivity(), DragSliderAppearance(), Define():
+ def definetext(self, (parent, text)):
+ raise RuntimeError, 'DragSlider.definetext() not supported'
+
+
+# Auxiliary class for PushButton incorporated in ComplexSlider
+#
+class _StepButton() = PushButton():
+ def define(self, parent):
+ self = PushButton.define(self, parent)
+ self.step = 0
+ return self
+ def setstep(self, step):
+ self.step = step
+ def definetextstep(self, (parent, text, step)):
+ self = self.definetext(parent, text)
+ self.setstep(step)
+ return self
+ def init_reactivity(self):
+ PushButton.init_reactivity(self)
+ self.parent.need_timer(self)
+ def step_trigger(self):
+ self.parent.setval(self.parent.getval() + self.step)
+ def down_trigger(self):
+ self.step_trigger()
+ self.parent.settimer(5)
+ def timer(self):
+ if self.hilited:
+ self.step_trigger()
+ if self.active:
+ self.parent.settimer(1)
+
+
+# A complex slider is an HSplit initialized to three buttons:
+# one to step down, a dragslider, and one to step up.
+#
+class ComplexSlider() = HSplit():
+ #
+ # Override Slider define() method
+ #
+ def define(self, parent):
+ self = self.create(parent) # HSplit
+ #
+ self.downbutton = _StepButton().definetextstep(self, '-', -1)
+ self.dragbutton = DragSlider().define(self)
+ self.upbutton = _StepButton().definetextstep(self, '+', 1)
+ #
+ return self
+ #
+ # Override HSplit methods
+ #
+ def minsize(self, m):
+ w1, h1 = self.downbutton.minsize(m)
+ w2, h2 = self.dragbutton.minsize(m)
+ w3, h3 = self.upbutton.minsize(m)
+ height = max(h1, h2, h3)
+ w1 = max(w1, height)
+ w3 = max(w3, height)
+ return w1+w2+w3, height
+ #
+ def setbounds(self, bounds):
+ (left, top), (right, bottom) = self.bounds = bounds
+ size = bottom - top
+ self.downbutton.setbounds((left, top), (left+size, bottom))
+ self.dragbutton.setbounds((left+size, top), \
+ (right-size, bottom))
+ self.upbutton.setbounds((right-size, top), (right, bottom))
+ #
+ # Pass other Slider methods on to dragbutton
+ #
+ def getval(self): return self.dragbutton.getval()
+ def sethook(self, hook): self.dragbutton.sethook(hook)
+ def setminvalmax(self, args): self.dragbutton.setminvalmax(args)
+ def settexts(self, args): self.dragbutton.settexts(args)
+ def setval(self, val): self.dragbutton.setval(val)
+ def enable(self, flag):
+ self.downbutton.enable(flag)
+ self.dragbutton.enable(flag)
+ self.upbutton.enable(flag)
diff --git a/lib/Soundogram.py b/lib/Soundogram.py
new file mode 100644
index 0000000..38dd5ef
--- /dev/null
+++ b/lib/Soundogram.py
@@ -0,0 +1,36 @@
+# Module 'Soundogram'
+
+import audio
+from Histogram import Histogram
+
+class Soundogram() = Histogram():
+ #
+ def define(self, (win, chunk)):
+ width, height = corner = win.getwinsize()
+ bounds = (0, 0), corner
+ self.chunk = chunk
+ self.step = (len(chunk)-1)/(width/2+1) + 1
+ ydata = _make_ydata(chunk, self.step)
+ return Histogram.define(self, (win, bounds, ydata, (0, 128)))
+ #
+ def setchunk(self, chunk):
+ self.chunk = chunk
+ self.recompute()
+ #
+ def recompute(self):
+ (left, top), (right, bottom) = self.bounds
+ width = right - left
+ self.step = (len(chunk)-1)/width + 1
+ ydata = _make_ydata(chunk, self.step)
+ self.setdata(ydata, (0, 128))
+ #
+
+
+def _make_ydata(chunk, step):
+ ydata = []
+ for i in range(0, len(chunk), step):
+ piece = audio.chr2num(chunk[i:i+step])
+ mi, ma = min(piece), max(piece)
+ y = max(abs(mi), abs(ma))
+ ydata.append(y)
+ return ydata
diff --git a/lib/Split.py b/lib/Split.py
new file mode 100644
index 0000000..8c0a8dc
--- /dev/null
+++ b/lib/Split.py
@@ -0,0 +1,116 @@
+# Generic Split implementation.
+# Use as a base class for other splits.
+# Derived classes should at least implement the methods that call
+# unimpl() below: minsize(), getbounds() and setbounds().
+
+Error = 'Split.Error' # Exception
+
+import rect
+from util import remove
+
+class Split():
+ #
+ # Calls from creator
+ # NB derived classes may add parameters to create()
+ #
+ def create(self, parent):
+ parent.addchild(self)
+ self.parent = parent
+ self.children = []
+ self.mouse_interest = []
+ self.timer_interest = []
+ self.mouse_focus = 0
+ return self
+ #
+ # Downcalls from parent to child
+ #
+ def destroy(self):
+ self.parent = None
+ for child in self.children:
+ child.destroy()
+ del self.children[:]
+ del self.mouse_interest[:]
+ del self.timer_interest[:]
+ self.mouse_focus = None
+ #
+ def minsize(self, m): return unimpl()
+ def getbounds(self): return unimpl()
+ def setbounds(self, bounds): unimpl()
+ #
+ def draw(self, d_detail):
+ # (Could avoid calls to children outside the area)
+ for child in self.children:
+ child.draw(d_detail)
+ #
+ # Downcalls only made after certain upcalls
+ #
+ def mouse_down(self, detail):
+ if self.mouse_focus:
+ self.mouse_focus.mouse_down(detail)
+ p = detail[0]
+ for child in self.mouse_interest:
+ if rect.pointinrect(p, child.getbounds()):
+ self.mouse_focus = child
+ child.mouse_down(detail)
+ def mouse_move(self, detail):
+ if self.mouse_focus:
+ self.mouse_focus.mouse_move(detail)
+ def mouse_up(self, detail):
+ if self.mouse_focus:
+ self.mouse_focus.mouse_up(detail)
+ self.mouse_focus = 0
+ #
+ def timer(self):
+ for child in self.timer_interest:
+ child.timer()
+ #
+ # Upcalls from child to parent
+ #
+ def addchild(self, child):
+ if child in self.children:
+ raise Error, 'addchild: child already inlist'
+ self.children.append(child)
+ def delchild(self, child):
+ if child not in self.children:
+ raise Error, 'delchild: child not in list'
+ remove(child, self.children)
+ if child in self.mouse_interest:
+ remove(child, self.mouse_interest)
+ if child in self.timer_interest:
+ remove(child, self.timer_interest)
+ if child = self.mouse_focus:
+ self.mouse_focus = 0
+ #
+ def need_mouse(self, child):
+ if child not in self.mouse_interest:
+ self.mouse_interest.append(child)
+ self.parent.need_mouse(self)
+ def no_mouse(self, child):
+ if child in self.mouse_interest:
+ remove(child, self.mouse_interest)
+ if not self.mouse_interest:
+ self.parent.no_mouse(self)
+ #
+ def need_timer(self, child):
+ if child not in self.timer_interest:
+ self.timer_interest.append(child)
+ self.parent.need_timer(self)
+ def no_timer(self, child):
+ if child in self.timer_interest:
+ remove(child, self.timer_interest)
+ if not self.timer_interest:
+ self.parent.no_timer(self)
+ #
+ # The rest are transparent:
+ #
+ def begindrawing(self):
+ return self.parent.begindrawing()
+ def beginmeasuring(self):
+ return self.parent.beginmeasuring()
+ #
+ def change(self, area):
+ self.parent.change(area)
+ def scroll(self, area_vector):
+ self.parent.scroll(area_vector)
+ def settimer(self, itimer):
+ self.parent.settimer(itimer)
diff --git a/lib/StripChart.py b/lib/StripChart.py
new file mode 100644
index 0000000..fc707cb
--- /dev/null
+++ b/lib/StripChart.py
@@ -0,0 +1,68 @@
+# Module 'StripChart'
+
+import rect
+from Buttons import LabelAppearance, NoReactivity
+
+# A StripChart doesn't really look like a label but it needs a base class.
+# LabelAppearance allows it to be disabled and hilited.
+
+class StripChart() = LabelAppearance(), NoReactivity():
+ #
+ def define(self, (parent, scale)):
+ self.parent = parent
+ parent.addchild(self)
+ self.init_appearance()
+ self.init_reactivity()
+ self.ydata = []
+ self.scale = scale
+ self.resetbounds()
+ return self
+ #
+ def setbounds(self, bounds):
+ LabelAppearance.setbounds(self, bounds)
+ self.resetbounds()
+ #
+ def resetbounds(self):
+ (left, top), (right, bottom) = self.bounds
+ self.width = right-left
+ self.height = bottom-top
+ excess = len(self.ydata) - self.width
+ if excess > 0:
+ del self.ydata[:excess]
+ elif excess < 0:
+ while len(self.ydata) < self.width:
+ self.ydata.insert(0, 0)
+ #
+ def append(self, y):
+ self.ydata.append(y)
+ excess = len(self.ydata) - self.width
+ if excess > 0:
+ del self.ydata[:excess]
+ if self.bounds <> rect.empty:
+ self.parent.scroll(self.bounds, (-excess, 0))
+ if self.bounds <> rect.empty:
+ (left, top), (right, bottom) = self.bounds
+ i = len(self.ydata)
+ area = (left+i-1, top), (left+i, bottom)
+ self.draw(self.parent.begindrawing(), area)
+ #
+ def draw(self, (d, area)):
+ area = rect.intersect(area, self.bounds)
+ if area = rect.empty:
+ print 'mt'
+ return
+ d.cliprect(area)
+ d.erase(self.bounds)
+ (a_left, a_top), (a_right, a_bottom) = area
+ (left, top), (right, bottom) = self.bounds
+ height = bottom - top
+ i1 = a_left - left
+ i2 = a_right - left
+ for i in range(max(0, i1), min(len(self.ydata), i2)):
+ split = bottom-self.ydata[i]*height/self.scale
+ d.paint((left+i, split), (left+i+1, bottom))
+ if not self.enabled:
+ self.flipenable(d)
+ if self.hilited:
+ self.fliphilite(d)
+ d.noclip()
diff --git a/lib/Tcl.py b/lib/Tcl.py
new file mode 100644
index 0000000..9d45e37
--- /dev/null
+++ b/lib/Tcl.py
@@ -0,0 +1,421 @@
+# An emulator for John Ousterhout's 'Tcl' language in Python (wow!).
+# Currently only the most basic commands are implemented.
+#
+# Design choices:
+#
+# - Names used for functions are not exactly those used by C Tcl.
+# In Python, names without 'Tcl_' prefix are acceptable because
+# names are less global than in C (and often they are prefixed
+# with a module name anyway). Parameter conventions also differ.
+#
+# - The Tcl Interpreter type is implemented using a Python class.
+# Almost all functions with an Interpreter as first parameter are
+# methods of this class.
+# Applications can create derived classes to add additional commands
+# or to override specific internal functions.
+#
+# - Tcl errors are mapped to Python exceptions.
+# (I bet Ousterhout would have done the same in a language with
+# a proper exception mechanism).
+#
+# - Tcl expressions are evaluated by Python's built-in function eval().
+# This makes Python Tcl scripts incompatible with C Tcl scripts,
+# but is the only sensible solution for a quick-and-dirty version.
+# It also makes an escape to Python possible.
+#
+# - The Backslash function interprets \<newline>, since it
+# can return a string instead of a character.
+
+
+from TclUtil import *
+
+
+# Exceptions used to signify 'break' and 'continue'
+
+TclBreak = 'TclBreak'
+TclContinue = 'TclContinue'
+TclReturn = 'TclReturn'
+
+
+class CmdBuf():
+ #
+ def Create(buffer):
+ buffer.string = ''
+ return buffer
+ #
+ def Assemble(buffer, str):
+ buffer.string = buffer.string + str
+ if buffer.string[-1:] = '\n':
+ i, end = 0, len(buffer.string)
+ try:
+ while i < end:
+ list, i = FindNextCommand( \
+ buffer.string, i, end, 0)
+ except TclMatchingError:
+ return ''
+ except TclSyntaxError:
+ pass # Let Eval() return the error
+ ret = buffer.string
+ buffer.string = ''
+ return ret
+ else:
+ return ''
+
+
+class _Frame():
+ def Create(frame):
+ frame.locals = {}
+ return frame
+
+class _Proc():
+ #
+ def Create(proc, (interp, args, body)):
+ proc.interp = interp
+ proc.args = SplitList(args) # Do this once here
+ proc.body = body
+ return proc
+ #
+ def Call(proc, argv):
+ if len(argv) <> len(proc.args)+1:
+ raise TclRuntimeError, \
+ 'wrong # args to proc "' + \
+ argv[0] + '"'
+ # XXX No defaults or variable length 'args' yet
+ frame = _Frame().Create()
+ for i in range(len(proc.args)):
+ frame.locals[proc.args[i]] = argv[i+1]
+ proc.interp.stack.append(frame)
+ try:
+ value = proc.interp.Eval(proc.body)
+ except TclReturn, value:
+ pass
+ del proc.interp.stack[-1:]
+ return value
+
+
+import regexp
+_expand_prog = regexp.compile('([^[$\\]+|\n)*')
+del regexp
+
+class Interpreter():
+ #
+ def Create(interp):
+ interp.globals = {}
+ interp.commands = {}
+ interp.stack = []
+ interp.commands['break'] = interp.BreakCmd
+ interp.commands['concat'] = interp.ConcatCmd
+ interp.commands['continue'] = interp.ContinueCmd
+ interp.commands['echo'] = interp.EchoCmd
+ interp.commands['eval'] = interp.EvalCmd
+ interp.commands['expr'] = interp.ExprCmd
+ interp.commands['for'] = interp.ForCmd
+ interp.commands['glob'] = interp.GlobCmd
+ interp.commands['global'] = interp.GlobalCmd
+ interp.commands['if'] = interp.IfCmd
+ interp.commands['index'] = interp.IndexCmd
+ interp.commands['list'] = interp.ListCmd
+ interp.commands['proc'] = interp.ProcCmd
+ interp.commands['rename'] = interp.RenameCmd
+ interp.commands['return'] = interp.ReturnCmd
+ interp.commands['set'] = interp.SetCmd
+ return interp
+ #
+ def Delete(interp):
+ #
+ # Only break circular references here;
+ # most things will be garbage-collected.
+ #
+ for name in interp.commands.keys():
+ del interp.commands[name]
+ #
+ def CreateCommand(interp, (name, proc)):
+ interp.commands[name] = proc
+ #
+ def DeleteCommand(interp, (name)):
+ del interp.commands[name]
+ #
+ # Local variables are maintained on the stack.
+ # A local variable with value "None" is a dummy
+ # meaning that the corresponding global variable
+ # should be used.
+ #
+ def GetVar(interp, varName):
+ dict = interp.globals
+ if interp.stack:
+ d = interp.stack[-1:][0].locals
+ if d.has_key(varName) and d[varName] = None:
+ pass
+ else:
+ dict = d
+ if not dict.has_key(varName):
+ raise TclRuntimeError, \
+ 'Variable "' + varName + '" not found'
+ return dict[varName]
+ #
+ def SetVar(interp, (varName, newValue)):
+ dict = interp.globals
+ if interp.stack:
+ d = interp.stack[-1:][0].locals
+ if d.has_key(varName) and d[varName] = None:
+ pass
+ else:
+ dict = d
+ dict[varName] = newValue
+ #
+ def Expand(interp, (str, i, end)):
+ if end <= i: return ''
+ if str[i] = '{' and str[end-1] = '}':
+ return str[i+1:end-1]
+ if str[i] = '"' and str[end-1] = '"':
+ i, end = i+1, end-1
+ result = ''
+ while i < end:
+ c = str[i]
+ if c = '\\':
+ x, i = Backslash(str, i, end)
+ result = result + x
+ elif c = '[':
+ j = BalanceBrackets(str, i, end)
+ x = interp.EvalBasic(str, i+1, j-1, 1)
+ result = result + x
+ i = j
+ elif c = '$':
+ i = i+1
+ j = FindVarName(str, i, end)
+ name = str[i:j]
+ i = j
+ if not name:
+ result = result + '$'
+ else:
+ if name[:1] = '{' and name[-1:] = '}':
+ name = name[1:-1]
+ result = result + interp.GetVar(name)
+ else:
+ j = _expand_prog.exec(str, i)
+ j = min(j, end)
+ result = result + str[i:j]
+ i = j
+ return result
+ #
+ def EvalBasic(interp, (str, i, end, bracketed)):
+ result = ''
+ while i < end:
+ indexargv, i = FindNextCommand( \
+ str, i, end, bracketed)
+ if indexargv:
+ argv = []
+ for x, y in indexargv:
+ arg = interp.Expand(str, x, y)
+ argv.append(arg)
+ name = argv[0]
+ if not interp.commands.has_key(name):
+ raise TclRuntimeError, \
+ 'Command "' + name + \
+ '" not found'
+ result = interp.commands[name](argv)
+ return result
+ #
+ def Eval(interp, str):
+ return interp.EvalBasic(str, 0, len(str), 0)
+ #
+ def ExprBasic(interp, (str, begin, end)):
+ expr = interp.Expand(str, begin, end)
+ i = SkipSpaces(expr, 0, len(expr))
+ expr = expr[i:]
+ try:
+ return eval(expr, {})
+ except (NameError, TypeError, RuntimeError, EOFError), msg:
+ import sys
+ raise TclRuntimeError, sys.exc_type + ': ' + msg
+ #
+ def Expr(interp, str):
+ return interp.ExprBasic(str, 0, len(str))
+ #
+ # The rest are command implementations
+ #
+ def BreakCmd(interp, argv):
+ if len(argv) <> 1:
+ raise TclRuntimeError, 'usage: break'
+ raise TclBreak
+ #
+ def ConcatCmd(interp, argv):
+ if len(argv) < 2:
+ raise TclRuntimeError, 'usage: concat arg ...'
+ return Concat(argv[1:])
+ #
+ def ContinueCmd(interp, argv):
+ if len(argv) <> 1:
+ raise TclRuntimeError, 'usage: continue'
+ raise TclContinue
+ #
+ def EchoCmd(interp, argv):
+ for arg in argv[1:]: print arg,
+ print
+ return ''
+ #
+ def EvalCmd(interp, argv):
+ if len(argv) < 2:
+ raise TclRuntimeError, 'usage: eval arg [arg ...]'
+ str = Concat(argv[1:])
+ return interp.Eval(str)
+ #
+ def ExprCmd(interp, argv):
+ if len(argv) <> 2:
+ raise TclRuntimeError, 'usage: expr expression'
+ expr = argv[1]
+ result = interp.Expr(expr)
+ if type(result) <> type(''): result = `result`
+ return result
+ #
+ def ForCmd(interp, argv):
+ if len(argv) <> 5:
+ raise TclRuntimeError, \
+ 'usage: for start test next body'
+ x = interp.Eval(argv[1])
+ while interp.Expr(argv[2]):
+ try:
+ x = interp.Eval(argv[4])
+ except TclBreak:
+ break
+ except TclContinue:
+ pass
+ x = interp.Eval(argv[3])
+ return ''
+ #
+ def GlobCmd(interp, argv):
+ import macglob
+ if len(argv) < 2:
+ raise TclRuntimeError, 'usage: glob pattern ...'
+ list = []
+ for pat in argv[1:]:
+ list = list + macglob.glob(pat)
+ if not list:
+ raise TclRuntimeError, 'no match for glob pattern(s)'
+ return BuildList(list)
+ #
+ def GlobalCmd(interp, argv):
+ if len(argv) < 2:
+ raise TclRuntimeError, 'usage: global varname ...'
+ if not interp.stack:
+ raise TclRuntimeError, 'global used outside proc'
+ dict = interp.stack[-1:][0].locals
+ for name in argv[1:]:
+ dict[name] = None
+ return ''
+ #
+ def IfCmd(interp, argv):
+ argv = argv[:]
+ if len(argv) > 2 and argv[2] = 'then': del argv[2]
+ if len(argv) > 3 and argv[3] = 'else': del argv[3]
+ if not 3 <= len(argv) <= 4:
+ raise TclRuntimeError, \
+ 'usage: if test [then] trueBody [else] falseBody'
+ if interp.Expr(argv[1]):
+ return interp.Eval(argv[2])
+ if len(argv) > 3:
+ return interp.Eval(argv[3])
+ return ''
+ #
+ def IndexCmd(interp, argv):
+ if len(argv) <> 3:
+ raise TclRuntimeError, 'usage: index value index'
+ import string
+ try:
+ index = string.atoi(argv[2])
+ if index < 0: raise string.atoi_error
+ except string.atoi_error:
+ raise TclRuntimeError, 'bad index: ' + argv[2]
+ list = SplitList(argv[1])
+ if index >= len(list): return ''
+ return list[index]
+ #
+ def ListCmd(interp, argv):
+ if len(argv) < 2:
+ raise TclRuntimeError, 'usage: list arg ...'
+ return BuildList(argv[1:])
+ #
+ def ProcCmd(interp, argv):
+ if len(argv) <> 4:
+ raise TclRuntimeError, 'usage: proc name args body'
+ x = _Proc().Create(interp, argv[2], argv[3])
+ interp.CreateCommand(argv[1], x.Call)
+ return ''
+ #
+ def RenameCmd(interp, argv):
+ if len(argv) <> 3:
+ raise TclRuntimeError, 'usage: rename oldName newName'
+ oldName, newName = argv[1], argv[2]
+ if not interp.commands.has_key(oldName):
+ raise TclRuntimeError, \
+ 'command "' + oldName + '" not found'
+ if newName: interp.commands[newName] = interp.commands[oldName]
+ del interp.commands[oldName]
+ return ''
+ #
+ def ReturnCmd(interp, argv):
+ if not 1 <= len(argv) <= 2:
+ raise TclRuntimeError, 'usage: return [arg]'
+ if len(argv) = 1: raise TclReturn, ''
+ raise TclReturn, argv[1]
+ #
+ def SetCmd(interp, argv):
+ n = len(argv)
+ if not 2 <= n <= 3:
+ raise TclRuntimeError, 'usage: set varname [newvalue]'
+ if n = 2: return interp.GetVar(argv[1])
+ interp.SetVar(argv[1], argv[2])
+ return ''
+
+
+# The rest are just demos:
+
+def MainLoop(interp):
+ buffer = CmdBuf().Create()
+ if not interp.globals.has_key('ps1'): interp.globals['ps1'] = '% '
+ if not interp.globals.has_key('ps2'): interp.globals['ps2'] = ''
+ psname = 'ps1'
+ while 1:
+ try:
+ line = raw_input(interp.globals[psname])
+ except (EOFError, KeyboardInterrupt):
+ print
+ break
+ line = buffer.Assemble(line + '\n')
+ if not line:
+ psname = 'ps2'
+ else:
+ psname = 'ps1'
+ try:
+ x = interp.Eval(line)
+ if x <> '': print 'Result:', `x`
+ except (TclRuntimeError, TclSyntaxError, \
+ TclMatchingError), msg:
+ print 'Error:', msg
+ except (TclBreak, TclContinue):
+ print 'Error: break or continue outside loop'
+ except TclReturn, value:
+ # Return outside proc returns to main loop
+ if value: print value
+
+
+the_interpreter = Interpreter().Create()
+
+def main():
+ MainLoop(the_interpreter)
+
+
+# XXX To do:
+# for proc: "args" and default arguments
+# More commands:
+# case
+# uplevel
+# info
+# string
+# list operations
+# error, catch
+# print
+# scan, format
+# source
+# history?
+# others?
diff --git a/lib/TclShell.py b/lib/TclShell.py
new file mode 100644
index 0000000..78d8dc4
--- /dev/null
+++ b/lib/TclShell.py
@@ -0,0 +1,255 @@
+# Tcl-based shell (for the Macintosh)
+
+import TclUtil
+import Tcl
+from Tcl import Interpreter, TclRuntimeError
+import mac
+import macpath
+from macpath import isfile, isdir, exists
+
+UsageError = TclRuntimeError
+
+class ShellInterpreter() = Interpreter():
+ #
+ def ResetVariables(interp):
+ interp.globals['ps1'] = '$ '
+ interp.globals['ps2'] = '> '
+ interp.globals['home'] = mac.getcwd()
+ #
+ def DefineCommands(interp):
+ interp.commands['cd'] = interp.CdCmd
+ interp.commands['grep'] = interp.GrepCmd
+ interp.commands['ls'] = interp.LsCmd
+ interp.commands['mkdir'] = interp.MkdirCmd
+ interp.commands['mv'] = interp.MvCmd
+ interp.commands['pg'] = interp.PgCmd
+ interp.commands['pwd'] = interp.PwdCmd
+ interp.commands['rm'] = interp.RmCmd
+ interp.commands['rmdir'] = interp.RmdirCmd
+ interp.commands['sync'] = interp.SyncCmd
+ #
+ def Reset(interp):
+ interp.ResetVariables()
+ interp.DefineCommands()
+ #
+ def Create(interp):
+ interp = Interpreter.Create(interp) # initialize base class
+ interp.Reset()
+ return interp
+ #
+ # Command-implementing functions
+ #
+ def CdCmd(interp, argv):
+ if len(argv) > 2:
+ raise UsageError, 'usage: cd [dirname]'
+ if len(argv) = 2:
+ chdirto(argv[1])
+ else:
+ chdirto(interp.globals['home'])
+ return ''
+ #
+ def GrepCmd(interp, argv):
+ if len(argv) < 3:
+ raise UsageError, 'usage: grep regexp file ...'
+ import regexp
+ try:
+ prog = regexp.compile(argv[1])
+ except regexp.error, msg:
+ raise TclRuntimeError, \
+ ('grep', argv[1], ': bad regexp :', msg)
+ for file in argv[2:]:
+ grepfile(prog, file)
+ return ''
+ #
+ def LsCmd(interp, argv):
+ if len(argv) < 2:
+ lsdir(':')
+ else:
+ for dirname in argv[1:]:
+ lsdir(dirname)
+ return ''
+ #
+ def MkdirCmd(interp, argv):
+ if len(argv) < 2:
+ raise UsageError, 'usage: mkdir name ...'
+ for name in argv[1:]:
+ makedir(name)
+ return ''
+ #
+ def MvCmd(interp, argv):
+ if len(argv) <> 3:
+ raise UsageError, 'usage: mv src dst'
+ src, dst = argv[1], argv[2]
+ if not exists(src):
+ raise TclRuntimeError, \
+ ('mv', src, dst, ': source does not exist')
+ if exists(dst):
+ raise TclRuntimeError, \
+ ('mv', src, dst, ': destination already exists')
+ try:
+ mac.rename(src, dst)
+ except mac.error, msg:
+ raise TclRuntimeError, \
+ (src, dst, ': rename failed :', msg)
+ return ''
+ #
+ def PgCmd(interp, argv):
+ if len(argv) < 2:
+ raise UsageError, 'usage: page file ...'
+ for name in argv[1:]:
+ pagefile(name)
+ return ''
+ #
+ def PwdCmd(interp, argv):
+ if len(argv) > 1:
+ raise UsageError, 'usage: pwd'
+ else:
+ return mac.getcwd()
+ #
+ def RmCmd(interp, argv):
+ if len(argv) < 2:
+ raise UsageError, 'usage: rm file ...'
+ for name in argv[1:]:
+ remove(name)
+ return ''
+ #
+ def RmdirCmd(interp, argv):
+ if len(argv) < 2:
+ raise UsageError, 'usage: rmdir dir ...'
+ for name in argv[1:]:
+ rmdir(name)
+ return ''
+ #
+ def SyncCmd(interp, argv):
+ if len(argv) > 1:
+ raise UsageError, 'usage: sync'
+ try:
+ mac.sync()
+ except mac.error, msg:
+ raise TclRuntimeError, ('sync failed :', msg)
+ #
+
+def chdirto(dirname):
+ try:
+ mac.chdir(dirname)
+ except mac.error, msg:
+ raise TclRuntimeError, (dirname, ': chdir failed :', msg)
+
+def grepfile(prog, file):
+ try:
+ fp = open(file, 'r')
+ except RuntimeError, msg:
+ raise TclRuntimeError, (file, ': open failed :', msg)
+ lineno = 0
+ while 1:
+ line = fp.readline()
+ if not line: break
+ lineno = lineno+1
+ if prog.exec(line):
+ print file+'('+`lineno`+'):', line,
+
+def lsdir(dirname):
+ if not isdir(dirname):
+ print dirname, ': no such directory'
+ return
+ names = mac.listdir(dirname)
+ lsfiles(names, dirname)
+
+def lsfiles(names, dirname):
+ names = names[:] # Make a copy so we can modify it
+ for i in range(len(names)):
+ name = names[i]
+ if isdir(macpath.cat(dirname, name)):
+ names[i] = ':' + name + ':'
+ columnize(names)
+
+def makedir(name):
+ if exists(name):
+ print name, ': already exists'
+ return
+ try:
+ mac.mkdir(name, 0777)
+ except mac.error, msg:
+ raise TclRuntimeError, (name, ': mkdir failed :', msg)
+
+def pagefile(name):
+ import string
+ if not isfile(name):
+ print name, ': no such file'
+ return
+ LINES = 24 - 1
+ # For THINK C 3.0, make the path absolute:
+ # if not macpath.isabs(name):
+ # name = macpath.cat(mac.getcwd(), name)
+ try:
+ fp = open(name, 'r')
+ except RuntimeError, msg:
+ raise TclRuntimeError, (name, ': open failed :', msg)
+ line = fp.readline()
+ while line:
+ for i in range(LINES):
+ print line,
+ line = fp.readline()
+ if not line: break
+ if line:
+ try:
+ more = raw_input('[more]')
+ except (EOFError, KeyboardInterrupt):
+ print
+ break
+ if string.strip(more)[:1] in ('q', 'Q'):
+ break
+
+def remove(name):
+ if not isfile(name):
+ print name, ': no such file'
+ return
+ try:
+ mac.unlink(name)
+ except mac.error, msg:
+ raise TclRuntimeError, (name, ': unlink failed :', msg)
+
+def rmdir(name):
+ if not isdir(name):
+ raise TclRuntimeError, (name, ': no such directory')
+ try:
+ mac.rmdir(name)
+ except mac.error, msg:
+ raise TclRuntimeError, (name, ': rmdir failed :', msg)
+
+def printlist(list):
+ for word in list:
+ print word,
+
+def columnize(list):
+ import string
+ COLUMNS = 80-1
+ n = len(list)
+ colwidth = maxwidth(list)
+ ncols = (COLUMNS + 1) / (colwidth + 1)
+ if ncols < 1: ncols = 1
+ nrows = (n + ncols - 1) / ncols
+ for irow in range(nrows):
+ line = ''
+ for icol in range(ncols):
+ i = irow + nrows*icol
+ if 0 <= i < n:
+ word = list[i]
+ if i+nrows < n:
+ word = string.ljust(word, colwidth)
+ if icol > 0:
+ word = ' ' + word
+ line = line + word
+ print line
+
+def maxwidth(list):
+ width = 0
+ for word in list:
+ if len(word) > width:
+ width = len(word)
+ return width
+
+the_interpreter = ShellInterpreter().Create()
+
+def main():
+ Tcl.MainLoop(the_interpreter)
diff --git a/lib/TclUtil.py b/lib/TclUtil.py
new file mode 100644
index 0000000..0990530
--- /dev/null
+++ b/lib/TclUtil.py
@@ -0,0 +1,377 @@
+# Utilities used by 'Tcl' emulator.
+
+
+# Many functions in this file parse specific constructs from strings.
+# In order to limit the number of slice operations (the strings can
+# be very large), they always receive indices into the string that
+# indicate the slice of the string that should be considered.
+# The return value is in general another index, pointing to the first
+# character in the string beyond the recognized construct.
+# Errors are reported as exceptions (TclSyntaxError, TclMatchingError).
+# A few functions have multiple return values.
+
+
+# For efficiency, the Tcl "tokenizing" routines used pre-compiled
+# regular expressions. This is less readable but should be much faster
+# than scanning the string a character at a time.
+#
+# The global variables
+# containing the compiled regexp's are named _foo_prog where foo is
+# an indication of the function that uses them.
+#
+# The patterns always
+# have the form <something>* so they always match at the start of the
+# search buffer---maybe with the empty string. This makes it possible
+# to use the expression "_foo_prog.exec(str, i)[0][1]" to find the first
+# character beyond the matched string. Note that this may be beyond the
+# end variable -- where this matters, "min(i, end)" is used.
+
+# Constructs that cannot
+# be recognized by a finite automaton (like matching braces) are scanned
+# by a hybrid technique where the regular expression excludes the
+# braces.
+#
+# Many regular expressions contain an expression that matches
+# a Tcl backslash sequence as a subpart:
+# \\\\C?M?(.|\n)
+#
+# This is a bit hard to
+# read because the backslash contained in it must be doubled twice:
+# once to get past Python's backslash mechanism, once to get past that
+# of regular expressions. It uses (.|\n) to match absolutely
+# *every character*, becase the MULTILINE regular expression package does
+# not accept '\n' as a match for '.'.
+#
+# There is also a simplification in the pattern for backslashes:
+# *any* single character following a backslash is escaped,
+# so hex and octal
+# excapes are not scanned fully. The forms \Cx, \Mx and \CMx are
+# scanned correctly, as these may hide a special character.
+# (This does not invalidate the recognition of strings, although the
+# match is effectuated in a different way than by the Backslash function.)
+
+import regexp
+
+
+# Exceptions raised for various error conditions.
+
+TclAssertError = 'Tcl assert error'
+TclSyntaxError = 'Tcl syntax error'
+TclRuntimeError = 'Tcl runtime error'
+TclMatchingError = 'Tcl matching error'
+
+
+# Find a variable name.
+# A variable name is either a (possiblly empty) sequence of letters,
+# digits and underscores, or anything enclosed in matching braces.
+# Return the index past the end of the name.
+
+_varname_prog = regexp.compile('[a-zA-Z0-9_]*')
+
+def FindVarName(str, i, end):
+ if i < end and str[i] = '{': return BalanceBraces(str, i, end)
+ i = _varname_prog.exec(str, i)[0][1]
+ return min(i, end)
+
+
+# Split a list into its elements.
+# Return a list of elements (strings).
+
+def SplitList(str):
+ i, end = 0, len(str)
+ list = []
+ while 1:
+ i = SkipSpaces(str, i, end)
+ if i >= end: break
+ j = i
+ i = FindNextElement(str, i, end)
+ if str[j] = '{' and str[i-1] = '}':
+ element = str[j+1:i-1]
+ else:
+ element = Collapse(str[j:i])
+ list.append(element)
+ return list
+
+
+# Find the next element from a list.
+
+_element_prog = regexp.compile('([^ \t\n\\]+|\\\\C?M?(.|\n))*')
+
+def FindNextElement(str, i, end):
+ if i < end and str[i] = '{':
+ i = BalanceBraces(str, i, end)
+ if i < end and str[i] not in ' \t\n':
+ raise TclSyntaxError, 'Garbage after } in list'
+ return i
+ i = _element_prog.exec(str, i)[0][1]
+ return min(i, end)
+
+
+# Copy a string, expanding all backslash sequences.
+
+_collapse_prog = regexp.compile('(\n|[^\\]+)*')
+
+def Collapse(str):
+ if '\\' not in str: return str
+ i, end = 0, len(str)
+ result = ''
+ while i < end:
+ j = _collapse_prog.exec(str, i)[0][1]
+ j = min(j, end)
+ result = result + str[i:j]
+ if j >= end: break
+ c = str[j]
+ if c <> '\\': raise TclAssertError, 'collapse error'
+ x, i = Backslash(str, j, end)
+ result = result + x
+ return result
+
+
+# Find the next full command.
+# Return a list of begin, end indices of words in the string,
+# and an index pointing just after the terminating newline or
+# semicolon.
+# Initial spaces are skipped.
+# If the command begins with '#', it is considered empty and
+# characters until '\n' are skipped.
+
+_eol_prog = regexp.compile('[^\n]*')
+
+def FindNextCommand(str, i, end, bracketed):
+ i = SkipSpaces(str, i, end)
+ if i >= end: return [], end
+ if str[i] = '#':
+ i = _eol_prog.exec(str, i)
+ i = min(i, end)
+ if i < end and str[i] = '\n': i = i+1
+ return [], i
+ if bracketed: terminators = [';']
+ else: terminators = [';', '\n']
+ list = []
+ while i < end:
+ j = FindNextWord(str, i, end)
+ word = str[i:j]
+ if word in terminators:
+ i = j
+ break
+ if word <> '\n': list.append(i, j)
+ i = SkipSpaces(str, j, end)
+ return list, i
+
+
+# Find the next word of a command.
+# Semicolon and newline terminate words but also count as a word
+# themselves.
+# The start index must point to the start of the word.
+
+_word_prog = regexp.compile('([^ \t\n;[\\]+|\\\\C?M?(.|\n))*')
+
+def FindNextWord(str, i, end):
+ if i >= end: return end
+ if str[i] in '{"':
+ if str[i] = '{': i = BalanceBraces(str, i, end)
+ else: i = BalanceQuotes(str, i, end)
+ if i >= end or str[i] in ' \t\n;': return min(i, end)
+ raise TclSyntaxError, 'Garbage after } or "'
+ begin = i
+ while i < end:
+ i = _word_prog.exec(str, i)[0][1]
+ if i >= end:
+ i = end
+ break
+ c = str[i]
+ if c in ' \t': break
+ if c in ';\n':
+ if i = begin: i = i+1
+ break
+ if c = '[': i = BalanceBrackets(str, i, end)
+ else: raise TclAssertError, 'word error'
+ return i
+
+
+# Parse balanced brackets from str[i:end].
+# str[i] must be '['.
+# Returns end such that str[i:end] ends with ']'
+# and contains balanced braces and brackets.
+
+_brackets_prog = regexp.compile('([^][{\\]+|\n|\\\\C?M?(.|\n))*')
+
+def BalanceBrackets(str, i, end):
+ if i >= end or str[i] <> '[':
+ raise TclAssertError, 'BalanceBrackets'
+ nesting = 0
+ while i < end:
+ i = _brackets_prog.exec(str, i)[0][1]
+ if i >= end: break
+ c = str[i]
+ if c = '{': i = BalanceBraces(str, i, end)
+ else:
+ i = i+1
+ if c = '[': nesting = nesting + 1
+ elif c = ']':
+ nesting = nesting - 1
+ if nesting = 0: return i
+ else: raise TclAssertError, 'brackets error'
+ raise TclMatchingError, 'Unmatched bracket ([)'
+
+
+# Parse balanced braces from str[i:end].
+# str[i] must be '{'.
+# Returns end such that str[i:end] ends with '}'
+# and contains balanced braces.
+
+_braces_prog = regexp.compile('([^{}\\]+|\n|\\\\C?M?(.|\n))*')
+
+def BalanceBraces(str, i, end):
+ if i >= end or str[i] <> '{':
+ raise TclAssertError, 'BalanceBraces'
+ nesting = 0
+ while i < end:
+ i = _braces_prog.exec(str, i)[0][1]
+ if i >= end: break
+ c = str[i]
+ i = i+1
+ if c = '{': nesting = nesting + 1
+ elif c = '}':
+ nesting = nesting - 1
+ if nesting = 0: return i
+ else: raise TclAssertError, 'braces error'
+ raise TclMatchingError, 'Unmatched brace ({)'
+
+
+# Parse double quotes from str[i:end].
+# str[i] must be '"'.
+# Returns end such that str[i:end] ends with an unescaped '"'.
+
+_quotes_prog = regexp.compile('([^"\\]+|\n|\\\\C?M?(.|\n))*')
+
+def BalanceQuotes(str, i, end):
+ if i >= end or str[i] <> '"':
+ raise TclAssertError, 'BalanceQuotes'
+ i = _quotes_prog.exec(str, i+1)[0][1]
+ if i < end and str[i] = '"': return i+1
+ raise TclMatchingError, 'Unmatched quote (")'
+
+
+# Static data used by Backslash()
+
+_bstab = {}
+_bstab['n'] = '\n'
+_bstab['r'] = '\r'
+_bstab['t'] = '\t'
+_bstab['b'] = '\b'
+_bstab['e'] = '\033'
+_bstab['\n'] = ''
+for c in ' {}[]$";\\': _bstab[c] = c
+del c
+
+# Backslash interpretation.
+# First character must be a backslash.
+# Return a pair (<replacement string>, <end of sequence>).
+# Unrecognized or incomplete backslash sequences are not errors;
+# this takes only the backslash itself off the string.
+
+def Backslash(str, i, end):
+ if i >= end or str[i] <> '\\':
+ raise TclAssertError, 'Backslash'
+ i = i+1
+ if i = end: return '\\', i
+ c = str[i]
+ i = i+1
+ if _bstab.has_key(c): return _bstab[c], i
+ if c = 'C':
+ if i = end: return '\\', i-1
+ c = str[i]
+ i = i+1
+ if c = 'M':
+ if i = end: return '\\', i-2
+ c = str[i]
+ i = i+1
+ x = ord(c) % 040 + 0200
+ else:
+ x = ord(c) % 040
+ return chr(x), i
+ elif c = 'M':
+ if i = end: return '\\', i-1
+ c = str[i]
+ i = i+1
+ x = ord(c)
+ if x < 0200: x = x + 0200
+ return chr(x), i
+ elif c and c in '0123456789':
+ x = ord(c) - ord('0')
+ end = min(end, i+2)
+ while i < end:
+ c = str[i]
+ if c not in '0123456789': break
+ i = i+1
+ x = x*8 + ord(c) - ord('0')
+ return ord(x), i
+ else:
+ # Not something that we recognize
+ return '\\', i-1
+
+
+# Skip over spaces and tabs (but not newlines).
+
+_spaces_prog = regexp.compile('[ \t]*')
+
+def SkipSpaces(str, i, end):
+ i = _spaces_prog.exec(str, i)[0][1]
+ return min(i, end)
+
+
+# Concatenate the elements of a list with intervening spaces.
+
+def Concat(argv):
+ result = ''
+ sep = ''
+ for arg in argv:
+ result = result + (sep + arg)
+ sep = ' '
+ return result
+
+
+# Concatenate list elements, adding braces etc. to make them parseable
+# again with SplitList.
+
+def BuildList(argv):
+ result = ''
+ sep = ''
+ for arg in argv:
+ arg = AddBraces(arg)
+ result = result + (sep + arg)
+ sep = ' '
+ return result
+
+
+# Add braces around a string if necessary to make it parseable by SplitList.
+
+def AddBraces(str):
+ # Special case for empty string
+ if str = '': return '{}'
+ # See if it contains balanced braces
+ res = '{' + str + '}'
+ if TryNextElement(res):
+ # See if it would survive unquoted
+ # XXX should escape [] and $ as well???
+ if TryNextElement(str) and Collapse(str) = str: return str
+ # No -- return with added braces
+ return res
+ # Unbalanced braces. Add backslashes before suspect characters
+ res = ''
+ for c in str:
+ if c in '$\\[]{} ;': c = '\\' + c
+ elif c = '\n': c = '\\n'
+ elif c = '\t': c = '\\t'
+ res = res + c
+ return res
+
+
+def TryNextElement(str):
+ end = len(str)
+ try:
+ i = FindNextElement(str, 0, end)
+ return i = end
+ except (TclSyntaxError, TclMatchingError):
+ return 0
diff --git a/lib/TestCSplit.py b/lib/TestCSplit.py
new file mode 100644
index 0000000..b638f81
--- /dev/null
+++ b/lib/TestCSplit.py
@@ -0,0 +1,26 @@
+# TestCSplit
+
+import stdwin
+from stdwinevents import WE_CLOSE
+from WindowParent import WindowParent
+from Buttons import PushButton
+
+def main(n):
+ from CSplit import CSplit
+
+ the_window = WindowParent().create('TestCSplit', (0, 0))
+ the_csplit = CSplit().create(the_window)
+
+ for i in range(n):
+ the_child = PushButton().define(the_csplit)
+ the_child.settext(`(i+n-1)%n+1`)
+
+ the_window.realize()
+
+ while 1:
+ the_event = stdwin.getevent()
+ if the_event[0] = WE_CLOSE: break
+ the_window.dispatch(the_event)
+ the_window.destroy()
+
+main(12)
diff --git a/lib/TransParent.py b/lib/TransParent.py
new file mode 100644
index 0000000..a07b4c4
--- /dev/null
+++ b/lib/TransParent.py
@@ -0,0 +1,96 @@
+# A class that sits transparently between a parent and one child.
+# First create the parent, then this thing, then the child.
+# Use this as a base class for objects that are almost transparent.
+# Don't use as a base class for parents with multiple children.
+
+Error = 'TransParent.Error' # Exception
+
+class ManageOneChild():
+ #
+ # Upcalls shared with other single-child parents
+ #
+ def addchild(self, child):
+ if self.child:
+ raise Error, 'addchild: one child only'
+ if not child:
+ raise Error, 'addchild: bad child'
+ self.child = child
+ #
+ def delchild(self, child):
+ if not self.child:
+ raise Error, 'delchild: no child'
+ if child <> self.child:
+ raise Error, 'delchild: not my child'
+ self.child = 0
+
+class TransParent() = ManageOneChild():
+ #
+ # Calls from creator
+ # NB derived classes may add parameters to create()
+ #
+ def create(self, parent):
+ parent.addchild(self)
+ self.parent = parent
+ self.child = 0 # No child yet
+ #
+ # Downcalls from parent to child
+ #
+ def destroy(self):
+ del self.parent
+ if self.child: self.child.destroy()
+ del self.child
+ #
+ def minsize(self, m):
+ if not self.child:
+ return 0, 0
+ else:
+ return self.child.minsize(m)
+ def getbounds(self, bounds):
+ if not self.child:
+ raise Error, 'getbounds w/o child'
+ else:
+ return self.child.getbounds()
+ def setbounds(self, bounds):
+ if not self.child:
+ raise Error, 'setbounds w/o child'
+ else:
+ self.child.setbounds(bounds)
+ def draw(self, args):
+ if self.child:
+ self.child.draw(args)
+ #
+ # Downcalls only made after certain upcalls
+ #
+ def mouse_down(self, detail):
+ if self.child: self.child.mouse_down(detail)
+ def mouse_move(self, detail):
+ if self.child: self.child.mouse_move(detail)
+ def mouse_up(self, detail):
+ if self.child: self.child.mouse_up(detail)
+ #
+ def timer(self):
+ if self.child: self.child.timer()
+ #
+ # Upcalls from child to parent
+ #
+ def need_mouse(self, child):
+ self.parent.need_mouse(self)
+ def no_mouse(self, child):
+ self.parent.no_mouse(self)
+ #
+ def need_timer(self, child):
+ self.parent.need_timer(self)
+ def no_timer(self, child):
+ self.parent.no_timer(self)
+ #
+ def begindrawing(self):
+ return self.parent.begindrawing()
+ def beginmeasuring(self):
+ return self.parent.beginmeasuring()
+ #
+ def change(self, area):
+ self.parent.change(area)
+ def scroll(self, args):
+ self.parent.scroll(args)
+ def settimer(self, itimer):
+ self.parent.settimer(itimer)
diff --git a/lib/VUMeter.py b/lib/VUMeter.py
new file mode 100644
index 0000000..c862452
--- /dev/null
+++ b/lib/VUMeter.py
@@ -0,0 +1,47 @@
+# Module 'VUMeter'
+
+import audio
+from StripChart import StripChart
+
+K = 1024
+Rates = [0, 32*K, 16*K, 8*K]
+
+class VUMeter() = StripChart():
+ #
+ # Override define() and timer() methods
+ #
+ def define(self, parent):
+ self = StripChart.define(self, (parent, 128))
+ self.parent.need_timer(self)
+ self.sampling = 0
+ self.rate = 3
+ self.enable(0)
+ return self
+ #
+ def timer(self):
+ if self.sampling:
+ chunk = audio.wait_recording()
+ self.sampling = 0
+ nums = audio.chr2num(chunk)
+ ampl = max(abs(min(nums)), abs(max(nums)))
+ self.append(ampl)
+ if self.enabled and not self.sampling:
+ audio.setrate(self.rate)
+ size = Rates[self.rate]/10
+ size = size/48*48
+ audio.start_recording(size)
+ self.sampling = 1
+ if self.sampling:
+ self.parent.settimer(1)
+ #
+ # New methods: start() and stop()
+ #
+ def stop(self):
+ if self.sampling:
+ chunk = audio.stop_recording()
+ self.sampling = 0
+ self.enable(0)
+ #
+ def start(self):
+ self.enable(1)
+ self.timer()
diff --git a/lib/WindowParent.py b/lib/WindowParent.py
new file mode 100644
index 0000000..1e18930
--- /dev/null
+++ b/lib/WindowParent.py
@@ -0,0 +1,101 @@
+# A 'WindowParent' is the only module that uses real stdwin functionality.
+# It is the root of the tree.
+# It should have exactly one child when realized.
+
+import stdwin
+from stdwinevents import *
+
+from TransParent import ManageOneChild
+
+Error = 'WindowParent.Error' # Exception
+
+class WindowParent() = ManageOneChild():
+ #
+ def create(self, (title, size)):
+ self.title = title
+ self.size = size # (width, height)
+ self._reset()
+ return self
+ #
+ def _reset(self):
+ self.child = 0
+ self.win = 0
+ self.itimer = 0
+ self.do_mouse = 0
+ self.do_timer = 0
+ #
+ def destroy(self):
+ if self.child: self.child.destroy()
+ self._reset()
+ #
+ def need_mouse(self, child): self.do_mouse = 1
+ def no_mouse(self, child): self.do_mouse = 0
+ #
+ def need_timer(self, child): self.do_timer = 1
+ def no_timer(self, child): self.do_timer = 0
+ #
+ def realize(self):
+ if self.win:
+ raise Error, 'realize(): called twice'
+ if not self.child:
+ raise Error, 'realize(): no child'
+ size = self.child.minsize(self.beginmeasuring())
+ self.size = max(self.size[0], size[0]), \
+ max(self.size[1], size[1])
+ #stdwin.setdefwinsize(self.size)
+ # XXX Compensate stdwin bug:
+ stdwin.setdefwinsize(self.size[0]+4, self.size[1]+2)
+ self.win = stdwin.open(self.title)
+ if self.itimer:
+ self.win.settimer(self.itimer)
+ bounds = (0, 0), self.win.getwinsize()
+ self.child.setbounds(bounds)
+ #
+ def beginmeasuring(self):
+ # Return something with which a child can measure text
+ if self.win:
+ return self.win.begindrawing()
+ else:
+ return stdwin
+ #
+ def begindrawing(self):
+ if self.win:
+ return self.win.begindrawing()
+ else:
+ raise Error, 'begindrawing(): not realized yet'
+ #
+ def change(self, area):
+ if self.win:
+ self.win.change(area)
+ #
+ def scroll(self, args):
+ if self.win:
+ self.win.scroll(args)
+ #
+ def settimer(self, itimer):
+ if self.win:
+ self.win.settimer(itimer)
+ else:
+ self.itimer = itimer
+ #
+ # Only call dispatch if we have a child
+ #
+ def dispatch(self, (type, win, detail)):
+ if win <> self.win:
+ return
+ elif type = WE_DRAW:
+ d = self.win.begindrawing()
+ self.child.draw(d, detail)
+ elif type = WE_MOUSE_DOWN:
+ if self.do_mouse: self.child.mouse_down(detail)
+ elif type = WE_MOUSE_MOVE:
+ if self.do_mouse: self.child.mouse_move(detail)
+ elif type = WE_MOUSE_UP:
+ if self.do_mouse: self.child.mouse_up(detail)
+ elif type = WE_TIMER:
+ if self.do_timer: self.child.timer()
+ elif type = WE_SIZE:
+ self.win.change((0, 0), (10000, 10000)) # XXX
+ bounds = (0, 0), self.win.getwinsize()
+ self.child.setbounds(bounds)
+ #
diff --git a/lib/adv.py b/lib/adv.py
new file mode 100644
index 0000000..f32f91b
--- /dev/null
+++ b/lib/adv.py
@@ -0,0 +1,366 @@
+#! /ufs/guido/bin/sgi/python
+
+# Module 'adv' -- text-oriented adventure game.
+
+
+# Name a constant that may once appear in the language...
+
+def return_nil(): return
+nil = return_nil()
+
+
+# Copy of string.split() (to avoid loading all of string.py)
+
+whitespace = ' \t\n'
+def split(s):
+ res = []
+ i, n = 0, len(s)
+ while i < n:
+ while i < n and s[i] in whitespace: i = i+1
+ if i = n: break
+ j = i
+ while j < n and s[j] not in whitespace: j = j+1
+ res.append(s[i:j])
+ i = j
+ return res
+
+
+# Constants to name directions
+
+N = 'north'
+S = 'south'
+W = 'west'
+E = 'east'
+U = 'up'
+D = 'down'
+NW = 'nw'
+NE = 'ne'
+SW = 'sw'
+SE = 'se'
+
+
+# Constants to name other commands
+
+INVENT = 'invent'
+LOOK = 'look'
+BACK = 'back'
+HELP = 'help'
+GET = 'get'
+PUT = 'put'
+
+
+# Aliases recognized by the parser
+
+alias = {}
+alias['n'] = N
+alias['s'] = S
+alias['e'] = E
+alias['w'] = W
+alias['u'] = U
+alias['d'] = D
+alias['i'] = INVENT
+alias['l'] = LOOK
+alias['b'] = BACK
+alias['take'] = GET
+alias['drop'] = PUT
+
+
+# Normalize a command, in place: truncate words to 6 chars, and expand aliases.
+
+def normalize(cmd):
+ for i in range(len(cmd)):
+ word = cmd[i][:6]
+ if alias.has_key(word):
+ word = alias[word]
+ cmd[i] = word
+
+
+# The Object class describes objects that the player can carry around.
+
+class Object():
+ def init(this, name):
+ this.name = name
+ return this
+ def describe(this):
+ print 'A', this.name + '.'
+ def get(this, (player, room)):
+ del room.objects[this.name]
+ player.objects[this.name] = this
+ def put(this, (player, room)):
+ del player.objects[this.name]
+ room.objects[this.name] = this
+
+
+# The Player class embodies first person control.
+
+class Player():
+ # Set initial state, except current room.
+ def init(self, initial_room):
+ self.blind = 0
+ self.here = initial_room
+ self.prev = nil
+ self.objects = {}
+ return self
+ # Read and execute commands forever.
+ def play(self):
+ self.here.casualdescribe()
+ while 1:
+ self.move()
+ # Read and execute one command.
+ def move(self):
+ next = self.here.parser()
+ if next and next <> self.here:
+ self.prev = self.here
+ self.here = next
+ if not self.blind:
+ self.here.casualdescribe()
+ # Print inventory.
+ def inventory(self):
+ if not self.objects:
+ print 'You aren\'t carrying anything.'
+ return
+ print 'You are carrying:'
+ for key in self.objects.keys():
+ self.objects[key].describe()
+ # Go back to previous room.
+ def back(self):
+ if self.prev: return self.prev
+ print 'You can\'t go back now.'
+ # Get an object from the room.
+ def get(self, name):
+ if self.here.objects.has_key(name):
+ self.here.objects[name].get(self, self.here)
+ else:
+ print 'I see no', name, 'here.'
+ # Put an object in the room.
+ def put(self, name):
+ if self.objects.has_key(name):
+ self.objects[name].put(self, self.here)
+ else:
+ print 'You have no', name, 'with you.'
+
+
+# The Room class describes a generic room.
+# Rooms with special properties are defined by derived classes
+# that override certain operations.
+
+class Room():
+ # Initialize a featureless room.
+ def init(here, name):
+ here.seen = 0
+ here.name = name
+ here.exits = {}
+ here.objects = {}
+ here.description = []
+ return here
+ # Add an object to the room. Used during initialization.
+ def add(here, obj):
+ here.objects[obj.name] = obj
+ # Print a casual description.
+ def casualdescribe(here):
+ if here.seen:
+ print here.name + '.'
+ here.listobjects()
+ return
+ here.seen = 1
+ here.describe()
+ # Print a full description, including all exits and objects seen.
+ def describe(here):
+ if not here.description:
+ print here.name + '.'
+ here.listexits()
+ else:
+ for line in here.description: print line
+ here.listobjects()
+ # List exits.
+ def listexits(here):
+ there = here.exits.keys()
+ if there:
+ if len(there) = 1:
+ print 'There is an exit leading',
+ else:
+ print 'There are exits leading',
+ for name in there[:-2]:
+ print name + ',',
+ print there[len(there)-2], 'and',
+ print there[len(there)-1] + '.'
+ # List objects
+ def listobjects(here):
+ if here.objects:
+ print 'I see:'
+ for key in here.objects.keys():
+ here.objects[key].describe()
+ # Default parser. Returns next room (possibly the same) or nil.
+ def parser(here):
+ cmd = here.getcmd(here.prompt())
+ return here.decide(cmd)
+ # Return default prompt string.
+ def prompt(here): return '> '
+ # Default input routine. Returns a non-empty list of words.
+ def getcmd(here, prompt):
+ # Loop until non-empty command gotten
+ # EOFError and KeyboardInterrupt may be caught elsewhere
+ while 1:
+ line = raw_input(prompt)
+ cmd = split(line)
+ if cmd:
+ normalize(cmd)
+ return cmd
+ # Default decision routine. Override for room-specific commands.
+ def decide(here, cmd):
+ key, args = cmd[0], cmd[1:]
+ if not args:
+ if key = N: return here.north()
+ if key = S: return here.south()
+ if key = E: return here.east()
+ if key = W: return here.west()
+ if key = U: return here.up()
+ if key = D: return here.down()
+ if key = NW: return here.nw()
+ if key = NE: return here.ne()
+ if key = SW: return here.sw()
+ if key = SE: return here.se()
+ if key = LOOK: return here.look()
+ if key = INVENT: return here.inventory()
+ if key = BACK: return here.back()
+ if here.objects.has_key(key):
+ print 'What do you want to do with the', key+'?'
+ else:
+ print 'Huh?'
+ return
+ if key = GET:
+ for arg in args:
+ player.get(arg)
+ return
+ if key = PUT:
+ for arg in args:
+ player.put(arg)
+ # Standard commands.
+ def look(here):
+ here.describe()
+ def inventory(here):
+ player.inventory()
+ def back(here):
+ return player.back()
+ # Standard exits.
+ def north(here): return here.take_exit(N)
+ def south(here): return here.take_exit(S)
+ def west(here): return here.take_exit(W)
+ def east(here): return here.take_exit(E)
+ def up(here): return here.take_exit(U)
+ def down(here): return here.take_exit(D)
+ def nw(here): return here.take_exit(NW)
+ def ne(here): return here.take_exit(NE)
+ def sw(here): return here.take_exit(SW)
+ def se(here): return here.take_exit(SE)
+ # Subroutine for standard exits.
+ def take_exit(here, key):
+ if here.exits.has_key(key):
+ return here.exits[key]
+ print 'You cannot go in that direction.'
+ return here
+
+
+# Create the objects we know about.
+# Object names begin with 'o_'.
+
+o_lamp = Object().init('lamp')
+o_python = Object().init('python')
+
+
+# Subroutine to connect two rooms.
+
+def connect(rm1, rm2, dir1, dir2):
+ if dir1:
+ rm1.exits[dir1] = rm2
+ if dir2:
+ rm2.exits[dir2] = rm1
+
+
+# Create the rooms and connect them together.
+# Room names begin with 'r_'.
+
+r_front = Room().init('Front of building')
+r_initial = r_front
+r_front.description = [ \
+ 'You are standing in front of a large, desolate building.', \
+ 'Huge neon letters spell "CWI". The "I" is blinking.', \
+ 'There are entrances north and west from where you are standing.', \
+ ]
+
+r_entrance = Room().init('Entrance')
+r_entrance.description = [ \
+ 'You are standing in a small entrance room.', \
+ 'On the east side is a window to a reception room.', \
+ 'South is a door leading outside the building.', \
+ 'North is a large hall.' \
+ ]
+
+r_hall_s = Room().init('South of hall')
+r_hall_s.description = [ \
+ 'You are standing at the south side of a very large hall.', \
+ 'There are doors leading west, southwest, south and southeast,', \
+ 'and a corridor leads east.', \
+ 'The hall continues to the north.' \
+ ]
+
+r_hall_n = Room().init('North of hall')
+r_hall_n.description = [ \
+ 'You are stanting at the north side of a very large hall.', \
+ 'There are corridors leading west, northwest, northeast,', \
+ 'an elevator door north, and a door leading outside east.', \
+ 'There are stairs leading up, and the hall continues to the south.' \
+ ]
+
+r_reception = Room().init('Reception')
+
+r_mail = Room().init('Mail room')
+
+connect(r_front, r_entrance, N, S)
+connect(r_entrance, r_hall_s, N, SW)
+connect(r_hall_s, r_hall_n, N, S)
+connect(r_hall_s, r_reception, S, N)
+connect(r_hall_s, r_mail, SE, N)
+connect(r_reception, r_mail, E, W)
+
+r_aud_front = Room().init('Front of Auditorium')
+r_aud_back = Room().init('Back of Auditorium')
+r_aud_tech = Room().init('Technician\'s room in Auditorium')
+r_aud_proj = Room().init('Projection room in Auditorium')
+
+connect(r_aud_front, r_hall_s, E, W)
+connect(r_aud_front, r_aud_back, S, N)
+connect(r_aud_back, r_aud_proj, SE, N)
+connect(r_aud_front, r_aud_tech, W, E)
+
+r_floor1 = Room().init('First floor')
+r_floor2 = Room().init('Second floor')
+r_floor3 = Room().init('Third floor')
+
+connect(r_hall_n, r_floor1, U, D)
+connect(r_floor1, r_floor2, U, D)
+connect(r_floor2, r_floor3, U, D)
+
+
+# Drop objects here and there
+
+r_aud_proj.add(o_python)
+r_reception.add(o_lamp)
+
+# Create an uninitialized player object.
+# It is initialized by main(), but must be created here (as global)
+# since some Room methods reference it. (Though maybe they shouldn't?)
+
+player = Player()
+
+
+# Play the game from the beginning.
+
+def main():
+ x = player.init(r_initial)
+ try:
+ player.play()
+ except (EOFError, KeyboardInterrupt):
+ pass
+
+main()
diff --git a/lib/anywin.py b/lib/anywin.py
new file mode 100644
index 0000000..6de3605
--- /dev/null
+++ b/lib/anywin.py
@@ -0,0 +1,14 @@
+# Module 'anywin'
+# Open a file or directory in a window
+
+import dirwin
+import filewin
+import path
+
+def open(name):
+ print 'opening', name, '...'
+ if path.isdir(name):
+ w = dirwin.open(name)
+ else:
+ w = filewin.open(name)
+ return w
diff --git a/lib/auds.py b/lib/auds.py
new file mode 100644
index 0000000..53db6aa
--- /dev/null
+++ b/lib/auds.py
@@ -0,0 +1,106 @@
+import audio
+
+RATE = 8192
+
+# Initialize the audio stuff
+audio.setrate(3)
+audio.setoutgain(100) # for speaker
+
+play = audio.write
+
+def samp(n):
+ savegain = audio.getoutgain()
+ try:
+ audio.setoutgain(0)
+ x = raw_input('Hit Enter to sample ' + `n` + ' seconds: ')
+ return audio.read(n*RATE)
+ finally:
+ audio.setoutgain(savegain)
+
+def echo(s, delay, gain):
+ return s[:delay] + audio.add(s[delay:], audio.amplify(s, gain, gain))
+
+def save(s, file):
+ f = open(file, 'w')
+ f.write(s)
+
+def load(file):
+ return loadfp(open(file, 'r'))
+
+def loadfp(fp):
+ s = ''
+ while 1:
+ buf = fp.read(16*1024)
+ if not buf: break
+ s = s + buf
+ return s
+
+def unbias(s):
+ if not s: return s
+ a = audio.chr2num(s)
+ sum = 0
+ for i in a: sum = sum + i
+ bias = (sum + len(a)/2) / len(a)
+ print 'Bias value:', bias
+ if bias:
+ for i in range(len(a)):
+ a[i] = a[i] - bias
+ s = audio.num2chr(a)
+ return s
+
+# Stretch by a/b.
+# Think of this as converting the sampling rate from a samples/sec
+# to b samples/sec. Or, if the input is a bytes long, the output
+# will be b bytes long.
+#
+def stretch(s, a, b):
+ y = audio.chr2num(s)
+ m = len(y)
+ out = []
+ n = m * b / a
+ # i, j will walk through y and out (step 1)
+ # ib, ja are i*b, j*a and are kept as close together as possible
+ i, ib = 0, 0
+ j, ja = 0, 0
+ for j in range(n):
+ ja = ja+a
+ while ib < ja:
+ i = i+1
+ ib = ib+b
+ if i >= m:
+ break
+ if ib = ja:
+ out.append(y[i])
+ else:
+ out.append((y[i]*(ja-(ib-b)) + y[i-1]*(ib-ja)) / b)
+ return audio.num2chr(out)
+
+def sinus(freq): # return a 1-second sine wave
+ from math import sin, pi
+ factor = 2.0*pi*float(freq)/float(RATE)
+ list = range(RATE)
+ for i in list:
+ list[i] = int(sin(float(i) * factor) * 127.0)
+ return audio.num2chr(list)
+
+def softclip(s):
+ if '\177' not in s and '\200' not in s:
+ return s
+ num = audio.chr2num(s)
+ extremes = (-128, 127)
+ for i in range(1, len(num)-1):
+ if num[i] in extremes:
+ num[i] = (num[i-1] + num[i+1]) / 2
+ return audio.num2chr(num)
+
+def demo():
+ gday = load('gday')[1000:6000]
+ save(gday, 'gday0')
+ gg = [gday]
+ for i in range(1, 10):
+ for g in gg: play(g)
+ g = stretch(gday, 10, 10-i)
+ save(g, 'gday' + `i`)
+ gg.append(g)
+ while 1:
+ for g in gg: play(g)
diff --git a/lib/calendar.py b/lib/calendar.py
new file mode 100644
index 0000000..97ca86f
--- /dev/null
+++ b/lib/calendar.py
@@ -0,0 +1,213 @@
+# module calendar
+
+##############################
+# Calendar support functions #
+##############################
+
+# This is based on UNIX ctime() et al. (also Standard C and POSIX)
+# Subtle but crucial differences:
+# - the order of the elements of a 'struct tm' differs, to ease sorting
+# - months numbers are 1-12, not 0-11; month arrays have a dummy element 0
+# - Monday is the first day of the week (numbered 0)
+
+# These are really parameters of the 'time' module:
+epoch = 1970 # Time began on January 1 of this year (00:00:00 UCT)
+day_0 = 3 # The epoch begins on a Thursday (Monday = 0)
+
+# Return 1 for leap years, 0 for non-leap years
+def isleap(year):
+ return year % 4 = 0 and (year % 100 <> 0 or year % 400 = 0)
+
+# Constants for months referenced later
+January = 1
+February = 2
+
+# Number of days per month (except for February in leap years)
+mdays = (0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)
+
+# Exception raised for bad input (with string parameter for details)
+error = 'calendar error'
+
+# Turn seconds since epoch into calendar time
+def gmtime(secs):
+ if secs < 0: raise error, 'negative input to gmtime()'
+ mins, secs = divmod(secs, 60)
+ hours, mins = divmod(mins, 60)
+ days, hours = divmod(hours, 24)
+ wday = (days + day_0) % 7
+ year = epoch
+ # XXX Most of the following loop can be replaced by one division
+ while 1:
+ yd = 365 + isleap(year)
+ if days < yd: break
+ days = days - yd
+ year = year + 1
+ yday = days
+ month = January
+ while 1:
+ md = mdays[month] + (month = February and isleap(year))
+ if days < md: break
+ days = days - md
+ month = month + 1
+ return year, month, days + 1, hours, mins, secs, yday, wday
+ # XXX Week number also?
+
+# Return number of leap years in range [y1, y2)
+# Assume y1 <= y2 and no funny (non-leap century) years
+def leapdays(y1, y2):
+ return (y2+3)/4 - (y1+3)/4
+
+# Inverse of gmtime():
+# Turn UCT calendar time (less yday, wday) into seconds since epoch
+def mktime(year, month, day, hours, mins, secs):
+ days = day - 1
+ for m in range(January, month): days = days + mdays[m]
+ if isleap(year) and month > February: days = days+1
+ days = days + (year-epoch)*365 + leapdays(epoch, year)
+ return ((days*24 + hours)*60 + mins)*60 + secs
+
+# Full and abbreviated names of weekdays
+day_name = ('Monday', 'Tuesday', 'Wednesday', 'Thursday')
+day_name = day_name + ('Friday', 'Saturday', 'Sunday')
+day_abbr = ('Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun')
+
+# Full and abbreviated of months (1-based arrays!!!)
+month_name = ('', 'January', 'February', 'March', 'April')
+month_name = month_name + ('May', 'June', 'July', 'August')
+month_name = month_name + ('September', 'October', 'November', 'December')
+month_abbr = (' ', 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun')
+month_abbr = month_abbr + ('Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec')
+
+# Zero-fill string to two positions (helper for asctime())
+def dd(s):
+ while len(s) < 2: s = '0' + s
+ return s
+
+# Blank-fill string to two positions (helper for asctime())
+def zd(s):
+ while len(s) < 2: s = ' ' + s
+ return s
+
+# Turn calendar time as returned by gmtime() into a string
+# (the yday parameter is for compatibility with gmtime())
+def asctime(year, month, day, hours, mins, secs, yday, wday):
+ s = day_abbr[wday] + ' ' + month_abbr[month] + ' ' + zd(`day`)
+ s = s + ' ' + dd(`hours`) + ':' + dd(`mins`) + ':' + dd(`secs`)
+ return s + ' ' + `year`
+
+# Localization: Minutes West from Greenwich
+# timezone = -2*60 # Middle-European time with DST on
+timezone = 5*60 # EST (sigh -- THINK time() doesn't return UCT)
+
+# Local time ignores DST issues for now -- adjust 'timezone' to fake it
+def localtime(secs):
+ return gmtime(secs - timezone*60)
+
+# UNIX-style ctime (except it doesn't append '\n'!)
+def ctime(secs):
+ return asctime(localtime(secs))
+
+######################
+# Non-UNIX additions #
+######################
+
+# Calendar printing etc.
+
+# Return weekday (0-6 ~ Mon-Sun) for year (1970-...), month (1-12), day (1-31)
+def weekday(year, month, day):
+ secs = mktime(year, month, day, 0, 0, 0)
+ days = secs / (24*60*60)
+ return (days + day_0) % 7
+
+# Return weekday (0-6 ~ Mon-Sun) and number of days (28-31) for year, month
+def monthrange(year, month):
+ day1 = weekday(year, month, 1)
+ ndays = mdays[month] + (month = February and isleap(year))
+ return day1, ndays
+
+# Return a matrix representing a month's calendar
+# Each row represents a week; days outside this month are zero
+def _monthcalendar(year, month):
+ day1, ndays = monthrange(year, month)
+ rows = []
+ r7 = range(7)
+ day = 1 - day1
+ while day <= ndays:
+ row = [0, 0, 0, 0, 0, 0, 0]
+ for i in r7:
+ if 1 <= day <= ndays: row[i] = day
+ day = day + 1
+ rows.append(row)
+ return rows
+
+# Caching interface to _monthcalendar
+mc_cache = {}
+def monthcalendar(year, month):
+ key = `year` + month_abbr[month]
+ try:
+ return mc_cache[key]
+ except RuntimeError:
+ mc_cache[key] = ret = _monthcalendar(year, month)
+ return ret
+
+# Center a string in a field
+def center(str, width):
+ n = width - len(str)
+ if n < 0: return str
+ return ' '*(n/2) + str + ' '*(n-n/2)
+
+# XXX The following code knows that print separates items with space!
+
+# Print a single week (no newline)
+def prweek(week, width):
+ for day in week:
+ if day = 0: print ' '*width,
+ else:
+ if width > 2: print ' '*(width-3),
+ if day < 10: print '',
+ print day,
+
+# Return a header for a week
+def weekheader(width):
+ str = ''
+ for i in range(7):
+ if str: str = str + ' '
+ str = str + day_abbr[i%7][:width]
+ return str
+
+# Print a month's calendar
+def prmonth(year, month):
+ print weekheader(3)
+ for week in monthcalendar(year, month):
+ prweek(week, 3)
+ print
+
+# Spacing between month columns
+spacing = ' '
+
+# 3-column formatting for year calendars
+def format3c(a, b, c):
+ print center(a, 20), spacing, center(b, 20), spacing, center(c, 20)
+
+# Print a year's calendar
+def prcal(year):
+ header = weekheader(2)
+ format3c('', `year`, '')
+ for q in range(January, January+12, 3):
+ print
+ format3c(month_name[q], month_name[q+1], month_name[q+2])
+ format3c(header, header, header)
+ data = []
+ height = 0
+ for month in range(q, q+3):
+ cal = monthcalendar(year, month)
+ if len(cal) > height: height = len(cal)
+ data.append(cal)
+ for i in range(height):
+ for cal in data:
+ if i >= len(cal):
+ print ' '*20,
+ else:
+ prweek(cal[i], 2)
+ print spacing,
+ print
diff --git a/lib/clock.py b/lib/clock.py
new file mode 100644
index 0000000..ec5301e
--- /dev/null
+++ b/lib/clock.py
@@ -0,0 +1,202 @@
+# 'klok' -- A simple alarm clock
+
+# The alarm can be set at 5 minute intervals on a 12 hour basis.
+# It is controlled with the mouse:
+# - Click and drag around the circle to set the alarm.
+# - Click far outside the circle to clear the alarm.
+# - Click near the center to set the alarm at the last time set.
+# The alarm time is indicated by a small triangle just outside the circle,
+# and also by a digital time at the bottom.
+# The indicators disappear when the alarm is not set.
+# When the alarm goes off, it beeps every minute for five minutes,
+# and the clock turns into inverse video.
+# Click or activate the window to turn the ringing off.
+
+import stdwin
+from stdwinevents import WE_MOUSE_DOWN, WE_MOUSE_MOVE, WE_MOUSE_UP, \
+ WE_TIMER, WE_DRAW, WE_SIZE, WE_CLOSE, WE_ACTIVATE
+import time
+from math import sin, cos, atan2, pi, sqrt
+
+DEFWIDTH, DEFHEIGHT = 200, 200
+
+mouse_events = (WE_MOUSE_DOWN, WE_MOUSE_MOVE, WE_MOUSE_UP)
+origin = 0, 0
+faraway = 2000, 2000
+everywhere = origin, faraway
+
+class struct(): pass # A class to declare featureless objects
+
+G = struct() # Global variables (most set in setdimensions())
+G.tzdiff = 5*3600 # THINK computes UCT from local time assuming EST!
+
+A = struct() # Globals used by the alarm
+A.set = 1 # True when alarm is set
+A.time = 11*60 + 40 # Time when alarm must go off
+A.ring = 0 # True when alarm is ringing
+
+def main():
+ try:
+ realmain()
+ except KeyboardInterrupt:
+ print 'KeyboardInterrupt'
+ finally:
+ G.w = 0
+
+def realmain():
+ setdimensions(DEFWIDTH, DEFHEIGHT)
+ stdwin.setdefwinsize(G.farcorner)
+ G.w = stdwin.open('klok')
+ settimer()
+ while 1:
+ type, window, detail = stdwin.getevent()
+ if type = WE_DRAW:
+ drawproc(detail)
+ elif type = WE_TIMER:
+ settimer()
+ drawproc(everywhere)
+ elif type in mouse_events:
+ mouseclick(type, detail)
+ elif type = WE_ACTIVATE:
+ if A.ring:
+ # Turn the ringing off
+ A.ring = 0
+ G.w.begindrawing().invert(G.mainarea)
+ elif type = WE_SIZE:
+ G.w.change(everywhere)
+ width, height = G.w.getwinsize()
+ height = height - stdwin.lineheight()
+ setdimensions(width, height)
+ elif type = WE_CLOSE:
+ break
+
+def setdimensions(width, height):
+ if width < height: size = width
+ else: size = height
+ halfwidth = width/2
+ halfheight = height/2
+ G.center = halfwidth, halfheight
+ G.radius = size*45/100
+ G.width = width
+ G.height = height
+ G.corner = width, height
+ G.mainarea = origin, G.corner
+ G.lineheight = stdwin.lineheight()
+ G.farcorner = width, height + G.lineheight
+ G.statusarea = (0, height), G.farcorner
+ G.fullarea = origin, G.farcorner
+
+def settimer():
+ now = getlocaltime()
+ G.times = calctime(now)
+ delay = 61 - now % 60
+ G.w.settimer(10 * delay)
+ minutes = (now/60) % 720
+ if A.ring:
+ # Is it time to stop the alarm ringing?
+ since = (minutes - A.time + 720) % 720
+ if since >= 5:
+ # Stop it now
+ A.ring = 0
+ else:
+ # Ring again, once every minute
+ stdwin.fleep()
+ elif A.set and minutes = A.time:
+ # Start the alarm ringing
+ A.ring = 1
+ stdwin.fleep()
+
+def drawproc(area):
+ hours, minutes, seconds = G.times
+ d = G.w.begindrawing()
+ d.cliprect(area)
+ d.erase(everywhere)
+ d.circle(G.center, G.radius)
+ d.line(G.center, calcpoint(hours*30 + minutes/2, 0.6))
+ d.line(G.center, calcpoint(minutes*6, 1.0))
+ str = dd(hours) + ':' + dd(minutes)
+ p = (G.width - d.textwidth(str))/2, G.height * 3 / 4
+ d.text(p, str)
+ if A.set:
+ drawalarm(d)
+ drawalarmtime(d)
+ if A.ring:
+ d.invert(G.mainarea)
+
+def mouseclick(type, detail):
+ d = G.w.begindrawing()
+ if A.ring:
+ # First turn the ringing off
+ A.ring = 0
+ d.invert(G.mainarea)
+ h, v = detail[0]
+ ch, cv = G.center
+ x, y = h-ch, cv-v
+ dist = sqrt(x*x + y*y) / float(G.radius)
+ if dist > 1.2:
+ if A.set:
+ drawalarm(d)
+ erasealarmtime(d)
+ A.set = 0
+ elif dist < 0.8:
+ if not A.set:
+ A.set = 1
+ drawalarm(d)
+ drawalarmtime(d)
+ else:
+ # Convert to half-degrees (range 0..720)
+ alpha = atan2(y, x)
+ hdeg = alpha*360.0/pi
+ hdeg = 180.0 - hdeg
+ hdeg = (hdeg + 720.0) % 720.0
+ atime = 5*int(hdeg/5.0 + 0.5)
+ if atime <> A.time or not A.set:
+ if A.set:
+ drawalarm(d)
+ erasealarmtime(d)
+ A.set = 1
+ A.time = atime
+ drawalarm(d)
+ drawalarmtime(d)
+
+def drawalarm(d):
+ p1 = calcpoint(float(A.time)/2.0, 1.02)
+ p2 = calcpoint(float(A.time)/2.0 - 4.0, 1.1)
+ p3 = calcpoint(float(A.time)/2.0 + 4.0, 1.1)
+ d.xorline(p1, p2)
+ d.xorline(p2, p3)
+ d.xorline(p3, p1)
+
+def erasealarmtime(d):
+ d.erase(G.statusarea)
+
+def drawalarmtime(d):
+ # A.time is in the range 0..720 with origin at 12 o'clock
+ # Convert to hours (0..12) and minutes (12*(0..60))
+ hh = A.time/60
+ mm = A.time%60
+ str = 'Alarm@' + dd(hh) + ':' + dd(mm)
+ p1 = (G.width - d.textwidth(str))/2, G.height
+ d.text(p1, str)
+
+def calctime(now):
+ seconds = now % 60
+ minutes = (now/60) % 60
+ hours = (now/3600) % 12
+ return hours, minutes, seconds
+
+def calcpoint(degrees, size):
+ alpha = pi/2.0 - float(degrees) * pi/180.0
+ x, y = cos(alpha), sin(alpha)
+ h, v = G.center
+ r = float(G.radius)
+ return h + int(x*size*r), v - int(y*size*r)
+
+def dd(n):
+ s = `n`
+ return '0'*(2-len(s)) + s
+
+def getlocaltime():
+ return time.time() - G.tzdiff
+
+#main()
diff --git a/lib/cmp.py b/lib/cmp.py
new file mode 100644
index 0000000..8dc315e
--- /dev/null
+++ b/lib/cmp.py
@@ -0,0 +1,61 @@
+# Module 'cmp'
+
+# Efficiently compare files, boolean outcome only (equal / not equal).
+
+# Tricks (used in this order):
+# - Files with identical type, size & mtime are assumed to be clones
+# - Files with different type or size cannot be identical
+# - We keep a cache of outcomes of earlier comparisons
+# - We don't fork a process to run 'cmp' but read the files ourselves
+
+import posix
+
+cache = {}
+
+def cmp(f1, f2): # Compare two files, use the cache if possible.
+ # Return 1 for identical files, 0 for different.
+ # Raise exceptions if either file could not be statted, read, etc.
+ s1, s2 = sig(posix.stat(f1)), sig(posix.stat(f2))
+ if s1[0] <> 8 or s2[0] <> 8:
+ # Either is a not a plain file -- always report as different
+ return 0
+ if s1 = s2:
+ # type, size & mtime match -- report same
+ return 1
+ if s1[:2] <> s2[:2]: # Types or sizes differ, don't bother
+ # types or sizes differ -- report different
+ return 0
+ # same type and size -- look in the cache
+ key = f1 + ' ' + f2
+ try:
+ cs1, cs2, outcome = cache[key]
+ # cache hit
+ if s1 = cs1 and s2 = cs2:
+ # cached signatures match
+ return outcome
+ # stale cached signature(s)
+ except RuntimeError:
+ # cache miss
+ pass
+ # really compare
+ outcome = do_cmp(f1, f2)
+ cache[key] = s1, s2, outcome
+ return outcome
+
+def sig(st): # Return signature (i.e., type, size, mtime) from raw stat data
+ # 0-5: st_mode, st_ino, st_dev, st_nlink, st_uid, st_gid
+ # 6-9: st_size, st_atime, st_mtime, st_ctime
+ type = st[0] / 4096
+ size = st[6]
+ mtime = st[8]
+ return type, size, mtime
+
+def do_cmp(f1, f2): # Compare two files, really
+ bufsize = 8096 # Could be tuned
+ fp1 = open(f1, 'r')
+ fp2 = open(f2, 'r')
+ while 1:
+ b1 = fp1.read(bufsize)
+ b2 = fp2.read(bufsize)
+ if b1 <> b2: return 0
+ if not b1: return 1
diff --git a/lib/cmpcache.py b/lib/cmpcache.py
new file mode 100644
index 0000000..4aea356
--- /dev/null
+++ b/lib/cmpcache.py
@@ -0,0 +1,68 @@
+# Module 'cmpcache'
+#
+# Efficiently compare files, boolean outcome only (equal / not equal).
+#
+# Tricks (used in this order):
+# - Use the statcache module to avoid statting files more than once
+# - Files with identical type, size & mtime are assumed to be clones
+# - Files with different type or size cannot be identical
+# - We keep a cache of outcomes of earlier comparisons
+# - We don't fork a process to run 'cmp' but read the files ourselves
+
+import posix
+from stat import *
+import statcache
+
+
+# The cache.
+#
+cache = {}
+
+
+# Compare two files, use the cache if possible.
+# May raise posix.error if a stat or open of either fails.
+#
+def cmp(f1, f2):
+ # Return 1 for identical files, 0 for different.
+ # Raise exceptions if either file could not be statted, read, etc.
+ s1, s2 = sig(statcache.stat(f1)), sig(statcache.stat(f2))
+ if not S_ISREG(s1[0]) or not S_ISREG(s2[0]):
+ # Either is a not a plain file -- always report as different
+ return 0
+ if s1 = s2:
+ # type, size & mtime match -- report same
+ return 1
+ if s1[:2] <> s2[:2]: # Types or sizes differ, don't bother
+ # types or sizes differ -- report different
+ return 0
+ # same type and size -- look in the cache
+ key = f1 + ' ' + f2
+ if cache.has_key(key):
+ cs1, cs2, outcome = cache[key]
+ # cache hit
+ if s1 = cs1 and s2 = cs2:
+ # cached signatures match
+ return outcome
+ # stale cached signature(s)
+ # really compare
+ outcome = do_cmp(f1, f2)
+ cache[key] = s1, s2, outcome
+ return outcome
+
+# Return signature (i.e., type, size, mtime) from raw stat data.
+#
+def sig(st):
+ return S_IFMT(st[ST_MODE]), st[ST_SIZE], st[ST_MTIME]
+
+# Compare two files, really.
+#
+def do_cmp(f1, f2):
+ #print ' cmp', f1, f2 # XXX remove when debugged
+ bufsize = 8096 # Could be tuned
+ fp1 = open(f1, 'r')
+ fp2 = open(f2, 'r')
+ while 1:
+ b1 = fp1.read(bufsize)
+ b2 = fp2.read(bufsize)
+ if b1 <> b2: return 0
+ if not b1: return 1
diff --git a/lib/commands.py b/lib/commands.py
new file mode 100644
index 0000000..3cb6e69
--- /dev/null
+++ b/lib/commands.py
@@ -0,0 +1,77 @@
+# Module 'commands'
+#
+# Various tools for executing commands and looking at their output and status.
+
+import rand
+import posix
+import stat
+import path
+
+
+# Get 'ls -l' status for an object into a string
+#
+def getstatus(file):
+ return getoutput('ls -ld' + mkarg(file))
+
+
+# Get the output from a shell command into a string.
+# The exit status is ignored; a trailing newline is stripped.
+# Assume the command will work with ' >tempfile 2>&1' appended.
+# XXX This should use posix.popen() instead, should it exist.
+#
+def getoutput(cmd):
+ return getstatusoutput(cmd)[1]
+
+
+# Ditto but preserving the exit status.
+# Returns a pair (sts, output)
+#
+def getstatusoutput(cmd):
+ tmp = '/usr/tmp/wdiff' + `rand.rand()`
+ sts = -1
+ try:
+ sts = posix.system(cmd + ' >' + tmp + ' 2>&1')
+ text = readfile(tmp)
+ finally:
+ altsts = posix.system('rm -f ' + tmp)
+ if text[-1:] = '\n': text = text[:-1]
+ return sts, text
+
+
+# Return a string containing a file's contents.
+#
+def readfile(fn):
+ st = posix.stat(fn)
+ size = st[stat.ST_SIZE]
+ if not size: return ''
+ try:
+ fp = open(fn, 'r')
+ except:
+ raise posix.error, 'readfile(' + fn + '): open failed'
+ try:
+ return fp.read(size)
+ except:
+ raise posix.error, 'readfile(' + fn + '): read failed'
+
+
+# Make command argument from directory and pathname (prefix space, add quotes).
+#
+def mk2arg(head, x):
+ return mkarg(path.cat(head, x))
+
+
+# Make a shell command argument from a string.
+# Two strategies: enclose in single quotes if it contains none;
+# otherwis, enclose in double quotes and prefix quotable characters
+# with backslash.
+#
+def mkarg(x):
+ if '\'' not in x:
+ return ' \'' + x + '\''
+ s = ' "'
+ for c in x:
+ if c in '\\$"':
+ s = s + '\\'
+ s = s + c
+ s = s + '"'
+ return s
diff --git a/lib/dircache.py b/lib/dircache.py
new file mode 100644
index 0000000..c14db3e
--- /dev/null
+++ b/lib/dircache.py
@@ -0,0 +1,36 @@
+# Module 'dircache'
+#
+# Return a sorted list of the files in a POSIX directory, using a cache
+# to avoid reading the directory more often than necessary.
+# Also contains a subroutine to append slashes to directories.
+
+import posix
+import path
+
+cache = {}
+
+def listdir(path): # List directory contents, using cache
+ try:
+ cached_mtime, list = cache[path]
+ del cache[path]
+ except RuntimeError:
+ cached_mtime, list = -1, []
+ try:
+ mtime = posix.stat(path)[8]
+ except posix.error:
+ return []
+ if mtime <> cached_mtime:
+ try:
+ list = posix.listdir(path)
+ except posix.error:
+ return []
+ list.sort()
+ cache[path] = mtime, list
+ return list
+
+opendir = listdir # XXX backward compatibility
+
+def annotate(head, list): # Add '/' suffixes to directories
+ for i in range(len(list)):
+ if path.isdir(path.cat(head, list[i])):
+ list[i] = list[i] + '/'
diff --git a/lib/dircmp.py b/lib/dircmp.py
new file mode 100644
index 0000000..31e712c
--- /dev/null
+++ b/lib/dircmp.py
@@ -0,0 +1,205 @@
+# Module 'dirmp'
+#
+# Defines a class to build directory diff tools on.
+
+import posix
+
+import path
+
+import dircache
+import cmpcache
+import statcache
+from stat import *
+
+# Directory comparison class.
+#
+class dircmp():
+ #
+ def new(dd, (a, b)): # Initialize
+ dd.a = a
+ dd.b = b
+ # Properties that caller may change before callingdd. run():
+ dd.hide = ['.', '..'] # Names never to be shown
+ dd.ignore = ['RCS', 'tags'] # Names ignored in comparison
+ #
+ return dd
+ #
+ def run(dd): # Compare everything except common subdirectories
+ dd.a_list = filter(dircache.listdir(dd.a), dd.hide)
+ dd.b_list = filter(dircache.listdir(dd.b), dd.hide)
+ dd.a_list.sort()
+ dd.b_list.sort()
+ dd.phase1()
+ dd.phase2()
+ dd.phase3()
+ #
+ def phase1(dd): # Compute common names
+ dd.a_only = []
+ dd.common = []
+ for x in dd.a_list:
+ if x in dd.b_list:
+ dd.common.append(x)
+ else:
+ dd.a_only.append(x)
+ #
+ dd.b_only = []
+ for x in dd.b_list:
+ if x not in dd.common:
+ dd.b_only.append(x)
+ #
+ def phase2(dd): # Distinguish files, directories, funnies
+ dd.common_dirs = []
+ dd.common_files = []
+ dd.common_funny = []
+ #
+ for x in dd.common:
+ a_path = path.cat(dd.a, x)
+ b_path = path.cat(dd.b, x)
+ #
+ ok = 1
+ try:
+ a_stat = statcache.stat(a_path)
+ except posix.error, why:
+ # print 'Can\'t stat', a_path, ':', why[1]
+ ok = 0
+ try:
+ b_stat = statcache.stat(b_path)
+ except posix.error, why:
+ # print 'Can\'t stat', b_path, ':', why[1]
+ ok = 0
+ #
+ if ok:
+ a_type = S_IFMT(a_stat[ST_MODE])
+ b_type = S_IFMT(b_stat[ST_MODE])
+ if a_type <> b_type:
+ dd.common_funny.append(x)
+ elif S_ISDIR(a_type):
+ dd.common_dirs.append(x)
+ elif S_ISREG(a_type):
+ dd.common_files.append(x)
+ else:
+ dd.common_funny.append(x)
+ else:
+ dd.common_funny.append(x)
+ #
+ def phase3(dd): # Find out differences between common files
+ xx = cmpfiles(dd.a, dd.b, dd.common_files)
+ dd.same_files, dd.diff_files, dd.funny_files = xx
+ #
+ def phase4(dd): # Find out differences between common subdirectories
+ # A new dircmp object is created for each common subdirectory,
+ # these are stored in a dictionary indexed by filename.
+ # The hide and ignore properties are inherited from the parent
+ dd.subdirs = {}
+ for x in dd.common_dirs:
+ a_x = path.cat(dd.a, x)
+ b_x = path.cat(dd.b, x)
+ dd.subdirs[x] = newdd = dircmp().new(a_x, b_x)
+ newdd.hide = dd.hide
+ newdd.ignore = dd.ignore
+ newdd.run()
+ #
+ def phase4_closure(dd): # Recursively call phase4() on subdirectories
+ dd.phase4()
+ for x in dd.subdirs.keys():
+ dd.subdirs[x].phase4_closure()
+ #
+ def report(dd): # Print a report on the differences between a and b
+ # Assume that phases 1 to 3 have been executed
+ # Output format is purposely lousy
+ print 'diff', dd.a, dd.b
+ if dd.a_only:
+ print 'Only in', dd.a, ':', dd.a_only
+ if dd.b_only:
+ print 'Only in', dd.b, ':', dd.b_only
+ if dd.same_files:
+ print 'Identical files :', dd.same_files
+ if dd.diff_files:
+ print 'Differing files :', dd.diff_files
+ if dd.funny_files:
+ print 'Trouble with common files :', dd.funny_files
+ if dd.common_dirs:
+ print 'Common subdirectories :', dd.common_dirs
+ if dd.common_funny:
+ print 'Common funny cases :', dd.common_funny
+ #
+ def report_closure(dd): # Print reports on dd and on subdirs
+ # If phase 4 hasn't been done, no subdir reports are printed
+ dd.report()
+ try:
+ x = dd.subdirs
+ except NameError:
+ return # No subdirectories computed
+ for x in dd.subdirs.keys():
+ print
+ dd.subdirs[x].report_closure()
+ #
+ def report_phase4_closure(dd): # Report and do phase 4 recursively
+ dd.report()
+ dd.phase4()
+ for x in dd.subdirs.keys():
+ print
+ dd.subdirs[x].report_phase4_closure()
+
+
+# Compare common files in two directories.
+# Return:
+# - files that compare equal
+# - files that compare different
+# - funny cases (can't stat etc.)
+#
+def cmpfiles(a, b, common):
+ res = ([], [], [])
+ for x in common:
+ res[cmp(path.cat(a, x), path.cat(b, x))].append(x)
+ return res
+
+
+# Compare two files.
+# Return:
+# 0 for equal
+# 1 for different
+# 2 for funny cases (can't stat, etc.)
+#
+def cmp(a, b):
+ try:
+ if cmpcache.cmp(a, b): return 0
+ return 1
+ except posix.error:
+ return 2
+
+
+# Remove a list item.
+# NB: This modifies the list argument.
+#
+def remove(list, item):
+ for i in range(len(list)):
+ if list[i] = item:
+ del list[i]
+ break
+
+
+# Return a copy with items that occur in skip removed.
+#
+def filter(list, skip):
+ result = []
+ for item in list:
+ if item not in skip: result.append(item)
+ return result
+
+
+# Demonstration and testing.
+#
+def demo():
+ import sys
+ import getopt
+ options, args = getopt.getopt(sys.argv[1:], 'r')
+ if len(args) <> 2: raise getopt.error, 'need exactly two args'
+ dd = dircmp().new(args[0], args[1])
+ dd.run()
+ if ('-r', '') in options:
+ dd.report_phase4_closure()
+ else:
+ dd.report()
+
+# demo()
diff --git a/lib/dirwin.py b/lib/dirwin.py
new file mode 100644
index 0000000..76e0b5e
--- /dev/null
+++ b/lib/dirwin.py
@@ -0,0 +1,29 @@
+# Module 'dirwin'
+
+# Directory windows, a subclass of listwin
+
+import gwin
+import listwin
+import anywin
+import path
+import dircache
+
+def action(w, string, i, detail):
+ (h, v), clicks, button, mask = detail
+ if clicks = 2:
+ name = path.cat(w.name, string)
+ try:
+ w2 = anywin.open(name)
+ w2.parent = w
+ except posix.error, why:
+ stdwin.message('Can\'t open ' + name + ': ' + why[1])
+
+def open(name):
+ name = path.cat(name, '')
+ list = dircache.opendir(name)[:]
+ list.sort()
+ dircache.annotate(name, list)
+ w = listwin.open(name, list)
+ w.name = name
+ w.action = action
+ return w
diff --git a/lib/dis.py b/lib/dis.py
new file mode 100644
index 0000000..d13b08f
--- /dev/null
+++ b/lib/dis.py
@@ -0,0 +1,176 @@
+# Disassembler
+
+import sys
+import string
+
+def dis():
+ tb = sys.last_traceback
+ while tb.tb_next: tb = tb.tb_next
+ distb(tb)
+
+def distb(tb):
+ disassemble(tb.tb_frame.f_code, tb.tb_lasti)
+
+def disco(co):
+ disassemble(co, -1)
+
+def disassemble(co, lasti):
+ code = co.co_code
+ labels = findlabels(code)
+ n = len(code)
+ i = 0
+ while i < n:
+ c = code[i]
+ op = ord(c)
+ if op = SET_LINENO and i > 0: print # Extra blank line
+ if i = lasti: print '-->',
+ else: print ' ',
+ if i in labels: print '>>',
+ else: print ' ',
+ print string.rjust(`i`, 4),
+ print string.ljust(opname[op], 15),
+ i = i+1
+ if op >= HAVE_ARGUMENT:
+ oparg = ord(code[i]) + ord(code[i+1])*256
+ i = i+2
+ print string.rjust(`oparg`, 5),
+ if op in hasconst:
+ print '(' + `co.co_consts[oparg]` + ')',
+ elif op in hasname:
+ print '(' + co.co_names[oparg] + ')',
+ elif op in hasjrel:
+ print '(to ' + `i + oparg` + ')',
+ print
+
+def findlabels(code):
+ labels = []
+ n = len(code)
+ i = 0
+ while i < n:
+ c = code[i]
+ op = ord(c)
+ i = i+1
+ if op >= HAVE_ARGUMENT:
+ oparg = ord(code[i]) + ord(code[i+1])*256
+ i = i+2
+ label = -1
+ if op in hasjrel:
+ label = i+oparg
+ elif op in hasjabs:
+ label = oparg
+ if label >= 0:
+ if label not in labels:
+ labels.append(label)
+ return labels
+
+hasconst = []
+hasname = []
+hasjrel = []
+hasjabs = []
+
+opname = range(256)
+for op in opname: opname[op] = '<' + `op` + '>'
+
+def def_op(name, op):
+ opname[op] = name
+
+def name_op(name, op):
+ opname[op] = name
+ hasname.append(op)
+
+def jrel_op(name, op):
+ opname[op] = name
+ hasjrel.append(op)
+
+def jabs_op(name, op):
+ opname[op] = name
+ hasjabs.append(op)
+
+# Instruction opcodes for compiled code
+
+def_op('STOP_CODE', 0)
+def_op('POP_TOP', 1)
+def_op('ROT_TWO', 2)
+def_op('ROT_THREE', 3)
+def_op('DUP_TOP', 4)
+
+def_op('UNARY_POSITIVE', 10)
+def_op('UNARY_NEGATIVE', 11)
+def_op('UNARY_NOT', 12)
+def_op('UNARY_CONVERT', 13)
+def_op('UNARY_CALL', 14)
+
+def_op('BINARY_MULTIPLY', 20)
+def_op('BINARY_DIVIDE', 21)
+def_op('BINARY_MODULO', 22)
+def_op('BINARY_ADD', 23)
+def_op('BINARY_SUBTRACT', 24)
+def_op('BINARY_SUBSCR', 25)
+def_op('BINARY_CALL', 26)
+
+def_op('SLICE+0', 30)
+def_op('SLICE+1', 31)
+def_op('SLICE+2', 32)
+def_op('SLICE+3', 33)
+
+def_op('STORE_SLICE+0', 40)
+def_op('STORE_SLICE+1', 41)
+def_op('STORE_SLICE+2', 42)
+def_op('STORE_SLICE+3', 43)
+
+def_op('DELETE_SLICE+0', 50)
+def_op('DELETE_SLICE+1', 51)
+def_op('DELETE_SLICE+2', 52)
+def_op('DELETE_SLICE+3', 53)
+
+def_op('STORE_SUBSCR', 60)
+def_op('DELETE_SUBSCR', 61)
+
+def_op('PRINT_EXPR', 70)
+def_op('PRINT_ITEM', 71)
+def_op('PRINT_NEWLINE', 72)
+
+def_op('BREAK_LOOP', 80)
+def_op('RAISE_EXCEPTION', 81)
+def_op('LOAD_LOCALS', 82)
+def_op('RETURN_VALUE', 83)
+def_op('REQUIRE_ARGS', 84)
+def_op('REFUSE_ARGS', 85)
+def_op('BUILD_FUNCTION', 86)
+def_op('POP_BLOCK', 87)
+def_op('END_FINALLY', 88)
+def_op('BUILD_CLASS', 89)
+
+HAVE_ARGUMENT = 90 # Opcodes from here have an argument:
+
+name_op('STORE_NAME', 90) # Index in name list
+name_op('DELETE_NAME', 91) # ""
+def_op('UNPACK_TUPLE', 92) # Number of tuple items
+def_op('UNPACK_LIST', 93) # Number of list items
+# unused: 94
+name_op('STORE_ATTR', 95) # Index in name list
+name_op('DELETE_ATTR', 96) # ""
+
+def_op('LOAD_CONST', 100) # Index in const list
+hasconst.append(100)
+name_op('LOAD_NAME', 101) # Index in name list
+def_op('BUILD_TUPLE', 102) # Number of tuple items
+def_op('BUILD_LIST', 103) # Number of list items
+def_op('BUILD_MAP', 104) # Always zero for now
+name_op('LOAD_ATTR', 105) # Index in name list
+def_op('COMPARE_OP', 106) # Comparison operator
+name_op('IMPORT_NAME', 107) # Index in name list
+name_op('IMPORT_FROM', 108) # Index in name list
+
+jrel_op('JUMP_FORWARD', 110) # Number of bytes to skip
+jrel_op('JUMP_IF_FALSE', 111) # ""
+jrel_op('JUMP_IF_TRUE', 112) # ""
+jabs_op('JUMP_ABSOLUTE', 113) # Target byte offset from beginning of code
+jrel_op('FOR_LOOP', 114) # Number of bytes to skip
+
+jrel_op('SETUP_LOOP', 120) # Distance to target address
+jrel_op('SETUP_EXCEPT', 121) # ""
+jrel_op('SETUP_FINALLY', 122) # ""
+
+def_op('SET_LINENO', 127) # Current line number
+SET_LINENO = 127
diff --git a/lib/dump.py b/lib/dump.py
new file mode 100644
index 0000000..0510092
--- /dev/null
+++ b/lib/dump.py
@@ -0,0 +1,63 @@
+# Module 'dump'
+#
+# Print python code that reconstructs a variable.
+# This only works in certain cases.
+#
+# It works fine for:
+# - ints and floats (except NaNs and other weird things)
+# - strings
+# - compounds and lists, provided it works for all their elements
+# - imported modules, provided their name is the module name
+#
+# It works for top-level dictionaries but not for dictionaries
+# contained in other objects (could be made to work with some hassle
+# though).
+#
+# It does not work for functions (all sorts), classes, class objects,
+# windows, files etc.
+#
+# Finally, objects referenced by more than one name or contained in more
+# than one other object lose their sharing property (this is bad for
+# strings used as exception identifiers, for instance).
+
+# Dump a whole symbol table
+#
+def dumpsymtab(dict):
+ for key in dict.keys():
+ dumpvar(key, dict[key])
+
+# Dump a single variable
+#
+def dumpvar(name, x):
+ import sys
+ t = type(x)
+ if t = type({}):
+ print name, '= {}'
+ for key in x.keys():
+ item = x[key]
+ if not printable(item):
+ print '#',
+ print name, '[', `key`, '] =', `item`
+ elif t in (type(''), type(0), type(0.0), type([]), type(())):
+ if not printable(x):
+ print '#',
+ print name, '=', `x`
+ elif t = type(sys):
+ print 'import', name, '#', x
+ else:
+ print '#', name, '=', x
+
+# check if a value is printable in a way that can be read back with input()
+#
+def printable(x):
+ t = type(x)
+ if t in (type(''), type(0), type(0.0)):
+ return 1
+ if t in (type([]), type(())):
+ for item in x:
+ if not printable(item):
+ return 0
+ return 1
+ if x = {}:
+ return 1
+ return 0
diff --git a/lib/fact.py b/lib/fact.py
new file mode 100644
index 0000000..ba961c4
--- /dev/null
+++ b/lib/fact.py
@@ -0,0 +1,37 @@
+# Factorize numbers -- slow, could use a table of all primes <= 2*16
+
+import sys
+import math
+
+error = 'fact.error' # exception
+
+def fact(n):
+ if n < 1: raise error # fact() argument should be >= 1
+ if n = 1: return [] # special case
+ res = []
+ _fact(n, 2, res)
+ return res
+
+def _fact(n, lowest, res):
+ highest = int(math.sqrt(float(n+1)))
+ for i in range(lowest, highest+1):
+ if n%i = 0:
+ res.append(i)
+ _fact(n/i, i, res)
+ break
+ else:
+ res.append(n)
+
+def main():
+ if len(sys.argv) > 1:
+ for arg in sys.argv[1:]:
+ n = eval(arg)
+ print n, fact(n)
+ else:
+ try:
+ while 1:
+ print fact(input())
+ except EOFError:
+ pass
+
+main()
diff --git a/lib/filewin.py b/lib/filewin.py
new file mode 100644
index 0000000..ad35ea4
--- /dev/null
+++ b/lib/filewin.py
@@ -0,0 +1,18 @@
+# Module 'filewin'
+# File windows, a subclass of textwin (which is a subclass of gwin)
+
+import textwin
+from util import readfile
+
+
+# FILE WINDOW
+
+def open_readonly(fn): # Open a file window
+ w = textwin.open_readonly(fn, readfile(fn))
+ w.fn = fn
+ return w
+
+def open(fn): # Open a file window
+ w = textwin.open(fn, readfile(fn))
+ w.fn = fn
+ return w
diff --git a/lib/fnmatch.py b/lib/fnmatch.py
new file mode 100644
index 0000000..8f9e318
--- /dev/null
+++ b/lib/fnmatch.py
@@ -0,0 +1,35 @@
+# module 'fnmatch' -- filename matching with shell patterns
+
+# XXX [] patterns are not supported (but recognized)
+
+def fnmatch(name, pat):
+ if '*' in pat or '?' in pat or '[' in pat:
+ return fnmatch1(name, pat)
+ return name = pat
+
+def fnmatch1(name, pat):
+ for i in range(len(pat)):
+ c = pat[i]
+ if c = '*':
+ restpat = pat[i+1:]
+ if '*' in restpat or '?' in restpat or '[' in restpat:
+ for i in range(i, len(name)):
+ if fnmatch1(name[i:], restpat):
+ return 1
+ return 0
+ else:
+ return name[len(name)-len(restpat):] = restpat
+ elif c = '?':
+ if len(name) <= i : return 0
+ elif c = '[':
+ return 0 # XXX
+ else:
+ if name[i:i+1] <> c:
+ return 0
+ return 1
+
+def fnmatchlist(names, pat):
+ res = []
+ for name in names:
+ if fnmatch(name, pat): res.append(name)
+ return res
diff --git a/lib/getopt.py b/lib/getopt.py
new file mode 100644
index 0000000..f343c22
--- /dev/null
+++ b/lib/getopt.py
@@ -0,0 +1,47 @@
+# module getopt -- Standard command line processing.
+
+# Function getopt.getopt() has a different interface but provides the
+# same functionality as the Unix getopt() function.
+
+# It has two arguments: the first should be argv[1:] (it doesn't want
+# the script name), the second the string of option letters as passed
+# to Unix getopt() (i.e., a string of allowable option letters, with
+# options requiring an argument followed by a colon).
+
+# It raises the exception getopt.error with a string argument if it
+# detects an error.
+
+# It returns two items:
+# (1) a list of pairs (option, option_argument) giving the options in
+# the order in which they were specified. (I'd use a dictionary
+# but applications may depend on option order or multiple
+# occurrences.) Boolean options have '' as option_argument.
+# (2) the list of remaining arguments (may be empty).
+
+error = 'getopt error'
+
+def getopt(args, options):
+ list = []
+ while args and args[0][0] = '-' and args[0] <> '-':
+ if args[0] = '--':
+ args = args[1:]
+ break
+ optstring, args = args[0][1:], args[1:]
+ while optstring <> '':
+ opt, optstring = optstring[0], optstring[1:]
+ if classify(opt, options): # May raise exception as well
+ if optstring = '':
+ if not args:
+ raise error, 'option -' + opt + ' requires argument'
+ optstring, args = args[0], args[1:]
+ optarg, optstring = optstring, ''
+ else:
+ optarg = ''
+ list.append('-' + opt, optarg)
+ return list, args
+
+def classify(opt, options): # Helper to check type of option
+ for i in range(len(options)):
+ if opt = options[i] <> ':':
+ return options[i+1:i+2] = ':'
+ raise error, 'option -' + opt + ' not recognized'
diff --git a/lib/glob.py b/lib/glob.py
new file mode 100644
index 0000000..b711094
--- /dev/null
+++ b/lib/glob.py
@@ -0,0 +1,44 @@
+# Module 'glob' -- filename globbing.
+
+import posix
+import path
+import fnmatch
+
+def glob(pathname):
+ if not has_magic(pathname): return [pathname]
+ dirname, basename = path.split(pathname)
+ if dirname[-1:] = '/' and dirname <> '/':
+ dirname = dirname[:-1]
+ if has_magic(dirname):
+ list = glob(dirname)
+ else:
+ list = [dirname]
+ if not has_magic(basename):
+ result = []
+ for dirname in list:
+ if basename or path.isdir(dirname):
+ name = path.cat(dirname, basename)
+ if path.exists(name):
+ result.append(name)
+ else:
+ result = []
+ for dirname in list:
+ sublist = glob1(dirname, basename)
+ for name in sublist:
+ result.append(path.cat(dirname, name))
+ return result
+
+def glob1(dirname, pattern):
+ if not dirname: dirname = '.'
+ try:
+ names = posix.listdir(dirname)
+ except posix.error:
+ return []
+ result = []
+ for name in names:
+ if name[0] <> '.' or pattern[0] = '.':
+ if fnmatch.fnmatch(name, pattern): result.append(name)
+ return result
+
+def has_magic(s):
+ return '*' in s or '?' in s or '[' in s
diff --git a/lib/grep.py b/lib/grep.py
new file mode 100644
index 0000000..66eb08d
--- /dev/null
+++ b/lib/grep.py
@@ -0,0 +1,32 @@
+# 'grep'
+
+import regexp
+import string
+
+def grep(expr, filename):
+ prog = regexp.compile(expr)
+ fp = open(filename, 'r')
+ lineno = 0
+ while 1:
+ line = fp.readline()
+ if not line: break
+ lineno = lineno + 1
+ res = prog.exec(line)
+ if res:
+ #print res
+ start, end = res[0]
+ if line[-1:] = '\n': line = line[:-1]
+ prefix = string.rjust(`lineno`, 3) + ': '
+ print prefix + line
+ if 0:
+ line = line[:start]
+ if '\t' not in line:
+ prefix = ' ' * (len(prefix) + start)
+ else:
+ prefix = ' ' * len(prefix)
+ for c in line:
+ if c <> '\t': c = ' '
+ prefix = prefix + c
+ if start = end: prefix = prefix + '\\'
+ else: prefix = prefix + '^'*(end-start)
+ print prefix
diff --git a/lib/gwin.py b/lib/gwin.py
new file mode 100644
index 0000000..f6291e1
--- /dev/null
+++ b/lib/gwin.py
@@ -0,0 +1,122 @@
+# Module 'gwin'
+# Generic stdwin windows
+
+# This is used as a base class from which to derive other window types.
+# The mainloop() function here is an event dispatcher for all window types.
+
+import stdwin
+from stdwinevents import *
+
+# XXX Old version of stdwinevents, should go
+import stdwinsupport
+S = stdwinsupport # Shorthand
+
+windows = [] # List of open windows
+
+
+# Open a window
+
+def open(title): # Open a generic window
+ w = stdwin.open(title)
+ stdwin.setdefwinsize(0, 0)
+ # Set default event handlers
+ w.draw = nop
+ w.char = nop
+ w.mdown = nop
+ w.mmove = nop
+ w.mup = nop
+ w.m2down = m2down
+ w.m2up = m2up
+ w.size = nop
+ w.move = nop
+ w.activate = w.deactivate = nop
+ w.timer = nop
+ # default command handlers
+ w.close = close
+ w.tab = tab
+ w.enter = enter
+ w.backspace = backspace
+ w.arrow = arrow
+ w.kleft = w.kup = w.kright = w.kdown = nop
+ windows.append(w)
+ return w
+
+
+# Generic event dispatching
+
+def mainloop(): # Handle events until no windows left
+ while windows:
+ treatevent(stdwin.getevent())
+
+def treatevent(e): # Handle a stdwin event
+ type, w, detail = e
+ if type = S.we_draw:
+ w.draw(w, detail)
+ elif type = S.we_menu:
+ m, item = detail
+ m.action[item](w, m, item)
+ elif type = S.we_command:
+ treatcommand(w, detail)
+ elif type = S.we_char:
+ w.char(w, detail)
+ elif type = S.we_mouse_down:
+ if detail[1] > 1: w.m2down(w, detail)
+ else: w.mdown(w, detail)
+ elif type = S.we_mouse_move:
+ w.mmove(w, detail)
+ elif type = S.we_mouse_up:
+ if detail[1] > 1: w.m2up(w, detail)
+ else: w.mup(w, detail)
+ elif type = S.we_size:
+ w.size(w, w.getwinsize())
+ elif type = S.we_activate:
+ w.activate(w)
+ elif type = S.we_deactivate:
+ w.deactivate(w)
+ elif type = S.we_move:
+ w.move(w)
+ elif type = S.we_timer:
+ w.timer(w)
+ elif type = WE_CLOSE:
+ w.close(w)
+
+def treatcommand(w, type): # Handle a we_command event
+ if type = S.wc_close:
+ w.close(w)
+ elif type = S.wc_return:
+ w.enter(w)
+ elif type = S.wc_tab:
+ w.tab(w)
+ elif type = S.wc_backspace:
+ w.backspace(w)
+ elif type in (S.wc_left, S.wc_up, S.wc_right, S.wc_down):
+ w.arrow(w, type)
+
+
+# Methods
+
+def close(w): # Close method
+ for i in range(len(windows)):
+ if windows[i] is w:
+ del windows[i]
+ break
+
+def arrow(w, detail): # Arrow key method
+ if detail = S.wc_left:
+ w.kleft(w)
+ elif detail = S.wc_up:
+ w.kup(w)
+ elif detail = S.wc_right:
+ w.kright(w)
+ elif detail = S.wc_down:
+ w.kdown(w)
+
+
+# Trivial methods
+
+def tab(w): w.char(w, '\t')
+def enter(w): w.char(w, '\n') # 'return' is a Python reserved word
+def backspace(w): w.char(w, '\b')
+def m2down(w, detail): w.mdown(w, detail)
+def m2up(w, detail): w.mup(w, detail)
+def nop(args): pass
diff --git a/lib/lambda.py b/lib/lambda.py
new file mode 100644
index 0000000..7d62b83
--- /dev/null
+++ b/lib/lambda.py
@@ -0,0 +1,151 @@
+# A bit of Lambda Calculus illustrated in Python.
+#
+# This does not use Python's built-in 'eval' or 'exec' functions!
+
+
+# Currying
+#
+# From a function with 2 args, f(x, y), and a value for the 1st arg,
+# we can create a new function with one argument fx(y) = f(x, y).
+# This is called "Currying" (after the idea's inventor, a Mr. Curry).
+#
+# To implement this we create a class member, of which fx is a method;
+# f and x are stored as data attributes of the member.
+
+class _CurryClass():
+ def new(self, (f, x)):
+ self.f = f
+ self.x = x
+ return self
+ def fx(self, y):
+ return self.f(self.x, y)
+
+def CURRY(f, x):
+ # NB: f is not "simple": it has 2 arguments
+ return _CurryClass().new(f, x).fx
+
+
+# Numbers in Lambda Calculus
+#
+# In the lambda calculus, natural numbers are represented by
+# higher-order functions Ntimes(f, x) that yield f applied N
+# times to x, e.g., Twice(f, x) = f(f(x)).
+# As far as I understand, there is no difference in real lambda
+# calculus between
+# lambda f x : f(f(x))
+# and
+# lambda f : f o f # 'o' means function composition
+# but in Python we have to write the first as Twice(f, x) and
+# the second as twice(f).
+
+def Never(f, x): return x
+def Once(f, x): return f(x)
+def Twice(f, x): return f(f(x))
+def Thrice(f, x): return f(f(f(x)))
+def Fourfold(f, x): return f(f(f(f(x))))
+# (etc.)
+
+def never(f): return CURRY(Never, f)
+def once(f): return CURRY(Once, f)
+def twice(f): return CURRY(Twice, f)
+def thrice(f): return CURRY(Thrice, f)
+def fourfold(f): return CURRY(Fourfold, f)
+# (etc.)
+
+
+# NB: actually 'ntimes' is less concrete than 'Ntimes', as
+# 'ntimes' returns a function, while 'Ntimes' returns a value
+# similar to what f(x) returns. 'Ntimes' can be derived
+# from 'ntimes', as follows:
+# def Ntimes(f, x): return ntimes(f)(x)
+# but this doesn't help us since 'ntimes' can only be defined
+# using Ntimes (or a trick like the one used by CURRY).
+
+
+# Arithmetic in Lambda Calculus
+#
+# We can perform simple arithmetic on the un-curried versions, e.g.,
+# Successor(Twice) = Thrice (2+1)
+# Sum(Thrice, Twice) = Fivefold (3+2)
+# Product(Thrice, Twice) = Sixfold (3*2)
+# Power(Thrice, Twice) = Ninefold (3**2)
+#
+# First we define versions that need f and x arguments.
+# They have funny argument forms so the final functions can
+# use CURRY, which only works on functions of exactly 2 arguments.
+
+def SUCCESSOR(Ntimes, (f, x)): return f(Ntimes(f, x))
+def SUCCESSOR(Ntimes, (f, x)): return Ntimes(f, f(x)) # Same effect
+def SUM(Ntimes, (Mtimes, (f, x))): return Ntimes(f, Mtimes(f, x))
+def PRODUCT(Ntimes, (Mtimes, (f, x))): return Ntimes(CURRY(Mtimes, f), x)
+def POWER(Ntimes, (Mtimes, (f, x))):
+ return Mtimes(CURRY(CURRY, Ntimes), f)(x)
+
+def Successor(Ntimes): return CURRY(SUCCESSOR, Ntimes)
+def Sum(Ntimes, Mtimes): return CURRY(CURRY(SUM, Ntimes), Mtimes)
+def Product(Ntimes, Mtimes): return CURRY(CURRY(PRODUCT, Ntimes), Mtimes)
+def Power(Ntimes, Mtimes): return CURRY(CURRY(POWER, Ntimes), Mtimes)
+
+
+# Sorry, I don't have a clue on how to do subtraction or division...
+
+
+# References
+#
+# All I know about lambda calculus is from Roger Penrose's
+# The Emperor's New Mind, Chapter 2.
+
+
+# P.S.: Here is a Lambda function in Python.
+# It uses 'exec' and expects two strings to describe the arguments
+# and the function expression. Example:
+# lambda('x', 'x+1')
+# defines the successor function.
+
+def lambda(args, expr):
+ if '\n' in args or '\n' in expr:
+ raise RuntimeError, 'lambda: no cheating!'
+ stmt = 'def func(' + args + '): return ' + expr + '\n'
+ print 'lambda:', stmt,
+ exec(stmt)
+ return func
+
+
+# P.P.S.S.: Here is a way to construct Ntimes and ntimes directly.
+# Example:
+# GenericNtimes(4)
+# is equivalent to Fourfold.
+
+class _GenericNtimesClass():
+ def new(self, n):
+ self.n = n
+ return self
+ def Ntimes(self, (f, x)):
+ n = self.n
+ while n > 0: x, n = f(x), n-1
+ return x
+
+def GenericNtimes(n):
+ return _GenericNtimesClass().new(n).Ntimes
+
+
+# To construct any 'ntimes' function from the corresponding 'Ntimes',
+# we use a trick as used by CURRY. For example,
+# Ntimes2ntimes(Fourfold)
+# yields a function equivalent to fourfold.
+
+class _Ntimes2ntimesClass():
+ def new(self, Ntimes):
+ self.Ntimes = Ntimes
+ return self
+ def ntimes(self, f):
+ return CURRY(self.Ntimes, f)
+
+def Ntimes2ntimes(Ntimes): return _Ntimes2ntimesClass().new(Ntimes).ntimes
+
+
+# This allows us to construct generic 'ntimes' functions. Example:
+# generic_ntimes(3)
+# is the same as thrice.
+
+def generic_ntimes(n): return Ntimes2ntimes(GenericNtimes(n))
diff --git a/lib/listwin.py b/lib/listwin.py
new file mode 100644
index 0000000..aac127c
--- /dev/null
+++ b/lib/listwin.py
@@ -0,0 +1,47 @@
+# Module 'listwin'
+# List windows, a subclass of gwin
+
+import gwin
+import stdwin
+
+def maxlinewidth(a): # Compute maximum textwidth of lines in a sequence
+ max = 0
+ for line in a:
+ width = stdwin.textwidth(line)
+ if width > max: max = width
+ return max
+
+def action(w, string, i, detail): # Default item selection method
+ pass
+
+def mup(w, detail): # Mouse up method
+ (h, v), clicks, button, mask = detail
+ i = divmod(v, w.lineheight)[0]
+ if 0 <= i < len(w.data):
+ w.action(w, w.data[i], i, detail)
+
+def draw(w, ((left, top), (right, bottom))): # Text window draw method
+ data = w.data
+ d = w.begindrawing()
+ lh = w.lineheight
+ itop = top/lh
+ ibot = (bottom-1)/lh + 1
+ if itop < 0: itop = 0
+ if ibot > len(data): ibot = len(data)
+ for i in range(itop, ibot): d.text((0, i*lh), data[i])
+
+def open(title, data): # Display a list of texts in a window
+ lineheight = stdwin.lineheight()
+ h, v = maxlinewidth(data), len(data)*lineheight
+ h0, v0 = h + stdwin.textwidth(' '), v + lineheight
+ if h0 > stdwin.textwidth(' ')*80: h0 = 0
+ if v0 > stdwin.lineheight()*24: v0 = 0
+ stdwin.setdefwinsize(h0, v0)
+ w = gwin.open(title)
+ w.setdocsize(h, v)
+ w.lineheight = lineheight
+ w.data = data
+ w.draw = draw
+ w.action = action
+ w.mup = mup
+ return w
diff --git a/lib/localtime.py b/lib/localtime.py
new file mode 100644
index 0000000..5ce6529
--- /dev/null
+++ b/lib/localtime.py
@@ -0,0 +1,53 @@
+# module localtime -- Time conversions
+
+import posix
+
+epoch = 1970 # 1 jan 00:00:00, UCT
+day0 = 4 # day 0 was a thursday
+
+day_names = ('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat')
+
+month_names = ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun')
+month_names = month_names + ('Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec')
+
+month_sizes = (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)
+
+def isleap(year):
+ return year % 4 = 0 and (year % 100 <> 0 or year % 400 = 0)
+
+def gmtime(secs): # decode time into UCT
+ mins, secs = divmod(secs, 60)
+ hours, mins = divmod(mins, 60)
+ days, hours = divmod(hours, 24)
+ wday = (day0 + days) % 7
+ year = epoch
+ lp = isleap(year)
+ dpy = 365 + lp
+ while days >= dpy:
+ days = days - dpy
+ year = year + 1
+ lp = isleap(year)
+ dpy = 365 + lp
+ yday = days
+ month = 0
+ dpm = month_sizes[month] + (lp and month = 1)
+ while days >= dpm:
+ days = days - dpm
+ month = month + 1
+ dpm = month_sizes[month] + (lp and month = 1)
+ return (year, month, days+1, hours, mins, secs, yday, wday)
+
+def dd(x):
+ s = `x`
+ while len(s) < 2: s = '0' + s
+ return s
+
+def zd(x):
+ s = `x`
+ while len(s) < 2: s = ' ' + s
+ return s
+
+def format(year, month, days, hours, mins, secs, yday, wday):
+ s = day_names[wday] + ' ' + zd(days) + ' ' + month_names[month] + ' '
+ s = s + dd(hours) + ':' + dd(mins) + ':' + dd(secs)
+ return s
diff --git a/lib/maccache.py b/lib/maccache.py
new file mode 100644
index 0000000..329e514
--- /dev/null
+++ b/lib/maccache.py
@@ -0,0 +1,61 @@
+# Module 'maccache'
+#
+# Maintain a cache of listdir(), isdir(), isfile() or exists() outcomes.
+
+import mac
+import macpath
+
+
+# The cache.
+# Keys are absolute pathnames;
+# values are 0 (nothing), 1 (file) or [...] (dir).
+#
+cache = {}
+
+
+# Current working directory.
+#
+cwd = mac.getcwd()
+
+
+# Constants.
+#
+NONE = 0
+FILE = 1
+LISTTYPE = type([])
+
+def _stat(name):
+ name = macpath.cat(cwd, name)
+ if cache.has_key(name):
+ return cache[name]
+ if macpath.isfile(name):
+ cache[name] = FILE
+ return FILE
+ try:
+ list = mac.listdir(name)
+ except:
+ cache[name] = NONE
+ return NONE
+ cache[name] = list
+ if name[-1:] = ':': cache[name[:-1]] = list
+ else: cache[name+':'] = list
+ return list
+
+def isdir(name):
+ st = _stat(name)
+ return type(st) = LISTTYPE
+
+def isfile(name):
+ st = _stat(name)
+ return st = FILE
+
+def exists(name):
+ st = _stat(name)
+ return st <> NONE
+
+def listdir(name):
+ st = _stat(name)
+ if type(st) = LISTTYPE:
+ return st
+ else:
+ raise RuntimeError, 'list non-directory'
diff --git a/lib/macglob.py b/lib/macglob.py
new file mode 100644
index 0000000..cad2c79
--- /dev/null
+++ b/lib/macglob.py
@@ -0,0 +1,46 @@
+# Module 'macglob' -- version of 'glob' for the Macintosh.
+
+# XXX At least one bug is left: a pattern like '*:' is treated
+# XXX as a relative pathname (and returns as if it was ':*:').
+
+import mac
+import macpath
+import fnmatch
+
+def glob(pathname):
+ if not has_magic(pathname): return [pathname]
+ dirname, basename = macpath.split(pathname)
+ if has_magic(dirname):
+ if dirname[-1:] = ':': dirname = dirname[:-1]
+ list = glob(dirname)
+ else:
+ list = [dirname]
+ if not has_magic(basename):
+ result = []
+ for dirname in list:
+ if basename or macpath.isdir(dirname):
+ name = macpath.cat(dirname, basename)
+ if macpath.exists(name):
+ result.append(name)
+ else:
+ result = []
+ for dirname in list:
+ sublist = glob1(dirname, basename)
+ for name in sublist:
+ result.append(macpath.cat(dirname, name))
+ return result
+
+def glob1(dirname, pattern):
+ if not dirname: dirname = ':'
+ try:
+ names = mac.listdir(dirname)
+ except mac.error:
+ return []
+ result = []
+ for name in names:
+ if name[0] <> '.' or pattern[0] = '.':
+ if fnmatch.fnmatch(name, pattern): result.append(name)
+ return result
+
+def has_magic(s):
+ return '*' in s or '?' in s or '[' in s
diff --git a/lib/macpath.py b/lib/macpath.py
new file mode 100644
index 0000000..99ba6b8
--- /dev/null
+++ b/lib/macpath.py
@@ -0,0 +1,108 @@
+# module 'macpath' -- pathname (or -related) operations for the Macintosh
+
+import mac
+
+from stat import *
+
+
+# Return true if a path is absolute.
+# On the Mac, relative paths begin with a colon,
+# but as a special case, paths with no colons at all are also relative.
+# Anything else is absolute (the string up to the first colon is the
+# volume name).
+
+def isabs(s):
+ return ':' in s and s[0] <> ':'
+
+
+# Concatenate two pathnames.
+# The result is equivalent to what the second pathname would refer to
+# if the first pathname were the current directory.
+
+def cat(s, t):
+ if (not s) or isabs(t): return t
+ if t[:1] = ':': t = t[1:]
+ if ':' not in s:
+ s = ':' + s
+ if s[-1:] <> ':':
+ s = s + ':'
+ return s + t
+
+
+# Split a pathname in two parts: the directory leading up to the final bit,
+# and the basename (the filename, without colons, in that directory).
+# The result (s, t) is such that cat(s, t) yields the original argument.
+
+def split(s):
+ if ':' not in s: return '', s
+ colon = 0
+ for i in range(len(s)):
+ if s[i] = ':': colon = i+1
+ return s[:colon], s[colon:]
+
+
+# Normalize a pathname: get rid of '::' sequences by backing up,
+# e.g., 'foo:bar::bletch' becomes 'foo:bletch'.
+# Raise the exception norm_error below if backing up is impossible,
+# e.g., for '::foo'.
+
+norm_error = 'macpath.norm_error: path cannot be normalized'
+
+def norm(s):
+ import string
+ if ':' not in s:
+ return ':' + s
+ f = string.splitfields(s, ':')
+ pre = []
+ post = []
+ if not f[0]:
+ pre = f[:1]
+ f = f[1:]
+ if not f[len(f)-1]:
+ post = f[-1:]
+ f = f[:-1]
+ res = []
+ for seg in f:
+ if seg:
+ res.append(seg)
+ else:
+ if not res: raise norm_error, 'path starts with ::'
+ del res[len(res)-1]
+ if not (pre or res):
+ raise norm_error, 'path starts with volume::'
+ if pre: res = pre + res
+ if post: res = res + post
+ s = res[0]
+ for seg in res[1:]:
+ s = s + ':' + seg
+ return s
+
+
+# Return true if the pathname refers to an existing directory.
+
+def isdir(s):
+ try:
+ st = mac.stat(s)
+ except mac.error:
+ return 0
+ return S_ISDIR(st[ST_MODE])
+
+
+# Return true if the pathname refers to an existing regular file.
+
+def isfile(s):
+ try:
+ st = mac.stat(s)
+ except mac.error:
+ return 0
+ return S_ISREG(st[ST_MODE])
+
+
+# Return true if the pathname refers to an existing file or directory.
+
+def exists(s):
+ try:
+ st = mac.stat(s)
+ except mac.error:
+ return 0
+ return 1
diff --git a/lib/macshell.py b/lib/macshell.py
new file mode 100644
index 0000000..c96d65b
--- /dev/null
+++ b/lib/macshell.py
@@ -0,0 +1,399 @@
+# Macintosh 'shell'
+# vi:set tabsize=4:
+
+# XXX string quoting in arguments
+# XXX directory stack
+# XXX $macros?
+# XXX ^C during any command
+# XXX 'sh' builtin command?
+# XXX why does open require absolute path? (need to fix chdir.c)
+
+
+import mac
+
+import macpath
+import string
+import glob
+from macpath import isfile, isdir, exists
+import TclUtil # For splitting/quoting mechanisms
+
+class Struct(): pass
+G = Struct()
+
+def reset():
+ G.debug = 0
+ G.ps1 = '$ '
+ G.homedir = mac.getcwd()
+ G.commands = mkcmdtab()
+ G.aliases = {}
+
+def mkcmdtab():
+ tab = {}
+ tab['alias'] = do_alias
+ tab['cd'] = do_cd
+ tab['debug'] = do_debug
+ tab['grep'] = do_grep
+ tab['help'] = do_help
+ tab['ls'] = do_ls
+ tab['mkdir'] = do_mkdir
+ tab['mv'] = do_mv
+ tab['page'] = do_page
+ tab['pwd'] = do_pwd
+ tab['reset'] = do_reset
+ tab['rm'] = do_rm
+ tab['rmdir'] = do_rmdir
+ tab['sync'] = do_sync
+ tab['unalias'] = do_unalias
+ return tab
+
+def main():
+ while 1:
+ try:
+ line = raw_input(G.ps1)
+ except EOFError:
+ print '[EOF]'
+ break
+ except KeyboardInterrupt:
+ print '[Intr]'
+ line = ''
+ if G.debug:
+ print 'line:', `line`
+ words = TclUtil.SplitList(line)
+ if G.debug:
+ print 'words:', words
+ if words and words[0][0] <> '#':
+ run(words)
+
+def run(words):
+ expandaliases(words)
+ cmd = words[0]
+ args = words[1:]
+ if G.commands.has_key(cmd):
+ if args:
+ try:
+ args = expandgloblist(args)
+ except glob_error, msg:
+ print cmd, ': glob error :', msg
+ return
+ G.commands[cmd](args)
+ return
+ if hasglobchar(cmd):
+ if args:
+ print cmd, ': cannot glob pattern with arguments'
+ return
+ try:
+ words = expandglobword(cmd)
+ except glob_error, msg:
+ print cmd, ': glob error :', msg
+ return
+ if len(words) > 1:
+ columnize(words)
+ return
+ cmd = words[0]
+ print cmd
+ if isfile(cmd):
+ if args:
+ print cmd, ': file command expects no arguments'
+ return
+ do_page([cmd])
+ elif isdir(cmd):
+ if args:
+ print cmd, ': directory command expects no arguments'
+ return
+ do_cd([cmd])
+ else:
+ print cmd, ': no such command, file or directory'
+
+glob_error = 'glob error'
+
+def expandgloblist(words):
+ res = []
+ for word in words:
+ if hasglobchar(word):
+ res = res + expandglobword(word)
+ else:
+ res.append(word)
+ return res
+
+def expandglobword(word):
+ names = glob.globlist(mac.listdir(':'), word)
+ if not names: raise glob_error, 'no match for pattern ' + word
+ return names
+
+def hasglobchar(word):
+ return '*' in word or '?' in word
+
+def expandaliases(words):
+ seen = []
+ cmd = words[0]
+ while cmd not in seen and G.aliases.has_key(cmd):
+ seen.append(cmd)
+ words[:1] = G.aliases[cmd]
+ cmd = words[0]
+
+def do_alias(args):
+ if not args:
+ listaliases()
+ elif len(args) = 1:
+ listalias(args[0])
+ else:
+ defalias(args[0], args[1:])
+
+def listaliases():
+ names = G.aliases.keys()
+ names.sort()
+ for name in names: listalias(name)
+
+def listalias(name):
+ if not G.aliases.has_key(name):
+ print name, ': no such alias'
+ return
+ print 'alias', name,
+ printlist(G.aliases[name])
+ print
+
+def defalias(name, expansion):
+ G.aliases[name] = expansion
+
+def do_cd(args):
+ if len(args) > 1:
+ print 'usage: cd [dirname]'
+ elif args:
+ chdirto(args[0])
+ else:
+ chdirto(G.homedir)
+
+def chdirto(dirname):
+ try:
+ mac.chdir(dirname)
+ except mac.error, msg:
+ print dirname, ':', msg
+ return
+
+def do_debug(args):
+ G.debug = (not G.debug)
+
+def do_grep(args):
+ if len(args) < 2:
+ print 'usage: grep regexp file ...'
+ return
+ import regexp
+ try:
+ prog = regexp.compile(args[0])
+ except regexp.error, msg:
+ print 'regexp.compile error for', args[0], ':', msg
+ return
+ for file in args[1:]:
+ grepfile(prog, file)
+
+def grepfile(prog, file):
+ try:
+ fp = open(file, 'r')
+ except RuntimeError, msg:
+ print file, ': cannot open :', msg
+ return
+ lineno = 0
+ while 1:
+ line = fp.readline()
+ if not line: break
+ lineno = lineno+1
+ if prog.exec(line):
+ print file+'('+`lineno`+'):', line,
+
+def do_help(args):
+ if args:
+ print 'usage: help'
+ return
+ names = G.commands.keys()
+ names.sort()
+ columnize(names)
+
+def do_ls(args):
+ if not args:
+ lsdir(':')
+ else:
+ for dirname in args:
+ lsdir(dirname)
+
+def lsdir(dirname):
+ if not isdir(dirname):
+ print dirname, ': no such directory'
+ return
+ names = mac.listdir(dirname)
+ lsfiles(names, dirname)
+
+def lsfiles(names, dirname):
+ names = names[:] # Make a copy so we can modify it
+ for i in range(len(names)):
+ name = names[i]
+ if G.debug: print i, name
+ if isdir(macpath.cat(dirname, name)):
+ names[i] = ':' + name + ':'
+ columnize(names)
+
+def columnize(list):
+ COLUMNS = 80-1
+ n = len(list)
+ colwidth = maxwidth(list)
+ ncols = (COLUMNS + 1) / (colwidth + 1)
+ if ncols < 1: ncols = 1
+ nrows = (n + ncols - 1) / ncols
+ for irow in range(nrows):
+ line = ''
+ for icol in range(ncols):
+ i = irow + nrows*icol
+ if 0 <= i < n:
+ word = list[i]
+ if i+nrows < n:
+ word = string.ljust(word, colwidth)
+ if icol > 0:
+ word = ' ' + word
+ line = line + word
+ print line
+
+def maxwidth(list):
+ width = 0
+ for word in list:
+ if len(word) > width:
+ width = len(word)
+ return width
+
+def do_mv(args):
+ if len(args) <> 2:
+ print 'usage: mv src dst'
+ return
+ src, dst = args[0], args[1]
+ if not exists(src):
+ print src, ': source does not exist'
+ return
+ if exists(dst):
+ print src, ': destination already exists'
+ return
+ try:
+ mac.rename(src, dst)
+ except mac.error, msg:
+ print src, dst, ': rename failed:', msg
+
+def do_mkdir(args):
+ if not args:
+ print 'usage: mkdir name ...'
+ return
+ for name in args:
+ makedir(name)
+
+def makedir(name):
+ if exists(name):
+ print name, ': already exists'
+ return
+ try:
+ mac.mkdir(name, 0777)
+ except mac.error, msg:
+ print name, ': mkdir failed:', msg
+
+def do_page(args):
+ if not args:
+ print 'usage: page file ...'
+ return
+ for name in args:
+ pagefile(name)
+
+def pagefile(name):
+ if not isfile(name):
+ print name, ': no such file'
+ return
+ LINES = 24 - 1
+ # For THINK C 3.0, make the path absolute:
+ # if not macpath.isabs(name):
+ # name = macpath.cat(mac.getcwd(), name)
+ try:
+ fp = open(name, 'r')
+ except:
+ print name, ': cannot open'
+ return
+ line = fp.readline()
+ while line:
+ for i in range(LINES):
+ print line,
+ line = fp.readline()
+ if not line: break
+ if line:
+ try:
+ more = raw_input('[more]')
+ except (EOFError, KeyboardInterrupt):
+ print
+ break
+ if string.strip(more)[:1] in ('q', 'Q'):
+ break
+
+def do_pwd(args):
+ if args:
+ print 'usage: pwd'
+ else:
+ print mac.getcwd()
+
+def do_reset(args):
+ if args:
+ print 'usage: reset'
+ else:
+ reset()
+
+def do_rm(args):
+ if not args:
+ print 'usage: rm file ...'
+ return
+ for name in args:
+ remove(name)
+
+def remove(name):
+ if not isfile(name):
+ print name, ': no such file'
+ return
+ try:
+ mac.unlink(name)
+ except mac.error, msg:
+ print name, ': unlink failed:', msg
+
+def do_rmdir(args):
+ if not args:
+ print 'usage: rmdir dir ...'
+ return
+ for name in args:
+ rmdir(name)
+
+def rmdir(name):
+ if not isdir(name):
+ print name, ': no such directory'
+ return
+ try:
+ mac.rmdir(name)
+ except mac.error, msg:
+ print name, ': rmdir failed:', msg
+
+def do_sync(args):
+ if args:
+ print 'usage: sync'
+ return
+ try:
+ mac.sync()
+ except mac.error, msg:
+ print 'sync failed:', msg
+
+def do_unalias(args):
+ if not args:
+ print 'usage: unalias name ...'
+ return
+ for name in args:
+ unalias(name)
+
+def unalias(name):
+ if not G.aliases.has_key(name):
+ print name, ': no such alias'
+ return
+ del G.aliases[name]
+
+def printlist(list):
+ for word in list:
+ print word,
+
+reset()
+main()
diff --git a/lib/minmax.py b/lib/minmax.py
new file mode 100644
index 0000000..38e20d1
--- /dev/null
+++ b/lib/minmax.py
@@ -0,0 +1,6 @@
+# Module 'minmax'
+# These are now built in functions.
+# For compatibility, we export the builtins
+
+min = min
+max = max
diff --git a/lib/packmail.py b/lib/packmail.py
new file mode 100644
index 0000000..40b5b7a
--- /dev/null
+++ b/lib/packmail.py
@@ -0,0 +1,48 @@
+# Module 'packmail' -- create a shell script out of some files.
+
+import mac
+import macpath
+from stat import ST_MTIME
+
+# Pack one file
+def pack(outfp, file, name):
+ fp = open(file, 'r')
+ outfp.write('sed "s/^X//" >' + name + ' <<"!"\n')
+ while 1:
+ line = fp.readline()
+ if not line: break
+ if line[-1:] <> '\n':
+ line = line + '\n'
+ outfp.write('X' + line)
+ outfp.write('!\n')
+
+# Pack some files from a directory
+def packsome(outfp, dirname, names):
+ for name in names:
+ print name
+ file = macpath.cat(dirname, name)
+ pack(outfp, file, name)
+
+# Pack all files from a directory
+def packall(outfp, dirname):
+ names = mac.listdir(dirname)
+ names.sort()
+ packsome(outfp, dirname, names)
+
+# Pack all files from a directory that are not older than a give one
+def packnotolder(outfp, dirname, oldest):
+ names = mac.listdir(dirname)
+ oldest = macpath.cat(dirname, oldest)
+ st = mac.stat(oldest)
+ mtime = st[ST_MTIME]
+ todo = []
+ for name in names:
+ print name, '...',
+ st = mac.stat(macpath.cat(dirname, name))
+ if st[ST_MTIME] >= mtime:
+ print 'Yes.'
+ todo.append(name)
+ else:
+ print 'No.'
+ todo.sort()
+ packsome(outfp, dirname, todo)
diff --git a/lib/panel.py b/lib/panel.py
new file mode 100644
index 0000000..8b0b45c
--- /dev/null
+++ b/lib/panel.py
@@ -0,0 +1,281 @@
+# Module 'panel'
+#
+# Support for the Panel library.
+# Uses built-in module 'pnl'.
+# Applciations should use 'panel.function' instead of 'pnl.function';
+# most 'pnl' functions are transparently exported by 'panel',
+# but dopanel() is overridden and you have to use this version
+# if you want to use callbacks.
+
+
+import pnl
+
+
+debug = 0
+
+
+# Test if an object is a list.
+#
+def is_list(x):
+ return type(x) = type([])
+
+
+# Reverse a list.
+#
+def reverse(list):
+ res = []
+ for item in list:
+ res.insert(0, item)
+ return res
+
+
+# Get an attribute of a list, which may itself be another list.
+# Don't use 'prop' for name.
+#
+def getattrlist(list, name):
+ for item in list:
+ if item and is_list(item) and item[0] = name:
+ return item[1:]
+ return []
+
+
+# Get a property of a list, which may itself be another list.
+#
+def getproplist(list, name):
+ for item in list:
+ if item and is_list(item) and item[0] = 'prop':
+ if len(item) > 1 and item[1] = name:
+ return item[2:]
+ return []
+
+
+# Test if an actuator description contains the property 'end-of-group'
+#
+def is_endgroup(list):
+ x = getproplist(list, 'end-of-group')
+ return (x and x[0] = '#t')
+
+
+# Neatly display an actuator definition given as S-expression
+# the prefix string is printed before each line.
+#
+def show_actuator(prefix, a):
+ for item in a:
+ if not is_list(item):
+ print prefix, item
+ elif item and item[0] = 'al':
+ print prefix, 'Subactuator list:'
+ for a in item[1:]:
+ show_actuator(prefix + ' ', a)
+ elif len(item) = 2:
+ print prefix, item[0], '=>', item[1]
+ elif len(item) = 3 and item[0] = 'prop':
+ print prefix, 'Prop', item[1], '=>',
+ print item[2]
+ else:
+ print prefix, '?', item
+
+
+# Neatly display a panel.
+#
+def show_panel(prefix, p):
+ for item in p:
+ if not is_list(item):
+ print prefix, item
+ elif item and item[0] = 'al':
+ print prefix, 'Actuator list:'
+ for a in item[1:]:
+ show_actuator(prefix + ' ', a)
+ elif len(item) = 2:
+ print prefix, item[0], '=>', item[1]
+ elif len(item) = 3 and item[0] = 'prop':
+ print prefix, 'Prop', item[1], '=>',
+ print item[2]
+ else:
+ print prefix, '?', item
+
+
+# Exception raised by build_actuator or build_panel.
+#
+panel_error = 'panel error'
+
+
+# Dummy callback used to initialize the callbacks.
+#
+def dummy_callback(arg):
+ pass
+
+
+# Assign attributes to members of the target.
+# Attribute names in exclist are ignored.
+# The member name is the attribute name prefixed with the prefix.
+#
+def assign_members(target, attrlist, exclist, prefix):
+ for item in attrlist:
+ if is_list(item) and len(item) = 2 and item[0] not in exclist:
+ name, value = item[0], item[1]
+ ok = 1
+ if value[0] in '-0123456789':
+ value = eval(value)
+ elif value[0] = '"':
+ value = value[1:-1]
+ elif value = 'move-then-resize':
+ # Strange default set by Panel Editor...
+ ok = 0
+ else:
+ print 'unknown value', value, 'for', name
+ ok = 0
+ if ok:
+ lhs = 'target.' + prefix + name
+ stmt = lhs + '=' + `value`
+ if debug: print 'exec', stmt
+ try:
+ exec(stmt + '\n')
+ except KeyboardInterrupt: # Don't catch this!
+ raise KeyboardInterrupt
+ except:
+ print 'assign failed:', stmt
+
+
+# Build a real actuator from an actuator descriptior.
+# Return a pair (actuator, name).
+#
+def build_actuator(descr):
+ namelist = getattrlist(descr, 'name')
+ if namelist:
+ # Assume it is a string
+ actuatorname = namelist[0][1:-1]
+ else:
+ actuatorname = ''
+ type = descr[0]
+ if type[:4] = 'pnl_': type = type[4:]
+ act = pnl.mkact(type)
+ act.downfunc = act.activefunc = act.upfunc = dummy_callback
+ #
+ assign_members(act, descr[1:], ['al', 'data', 'name'], '')
+ #
+ # Treat actuator-specific data
+ #
+ datalist = getattrlist(descr, 'data')
+ prefix = ''
+ if type[-4:] = 'puck':
+ prefix = 'puck_'
+ elif type = 'mouse':
+ prefix = 'mouse_'
+ assign_members(act, datalist, [], prefix)
+ #
+ return act, actuatorname
+
+
+# Build all sub-actuators and add them to the super-actuator.
+# The super-actuator must already have been added to the panel.
+# Sub-actuators with defined names are added as members to the panel
+# so they can be referenced as p.name.
+#
+# Note: I have no idea how panel.endgroup() works when applied
+# to a sub-actuator.
+#
+def build_subactuators(panel, super_act, al):
+ #
+ # This is nearly the same loop as below in build_panel(),
+ # except a call is made to addsubact() instead of addact().
+ #
+ for a in al:
+ act, name = build_actuator(a)
+ act.addsubact(super_act)
+ if name:
+ stmt = 'panel.' + name + ' = act'
+ if debug: print 'exec', stmt
+ exec(stmt + '\n')
+ if is_endgroup(a):
+ panel.endgroup()
+ sub_al = getattrlist(a, 'al')
+ if sub_al:
+ build_subactuators(panel, act, sub_al)
+ #
+ # Fix the actuator to which whe just added subactuators.
+ # This can't hurt (I hope) and is needed for the scroll actuator.
+ #
+ super_act.fixact()
+
+
+# Build a real panel from a panel definition.
+# Return a panel object p, where for each named actuator a, p.name is a
+# reference to a.
+#
+def build_panel(descr):
+ #
+ # Sanity check
+ #
+ if (not descr) or descr[0] <> 'panel':
+ raise panel_error, 'panel description must start with "panel"'
+ #
+ if debug: show_panel('', descr)
+ #
+ # Create an empty panel
+ #
+ panel = pnl.mkpanel()
+ #
+ # Assign panel attributes
+ #
+ assign_members(panel, descr[1:], ['al'], '')
+ #
+ # Look for actuator list
+ #
+ al = getattrlist(descr, 'al')
+ #
+ # The order in which actuators are created is important
+ # because of the endgroup() operator.
+ # Unfortunately the Panel Editor outputs the actuator list
+ # in reverse order, so we reverse it here.
+ #
+ al = reverse(al)
+ #
+ for a in al:
+ act, name = build_actuator(a)
+ act.addact(panel)
+ if name:
+ stmt = 'panel.' + name + ' = act'
+ exec(stmt + '\n')
+ if is_endgroup(a):
+ panel.endgroup()
+ sub_al = getattrlist(a, 'al')
+ if sub_al:
+ build_subactuators(panel, act, sub_al)
+ #
+ return panel
+
+
+# Wrapper around pnl.dopanel() which calls call-back functions.
+#
+def my_dopanel():
+ # Extract only the first 4 elements to allow for future expansion
+ a, down, active, up = pnl.dopanel()[:4]
+ if down:
+ down.downfunc(down)
+ if active:
+ active.activefunc(active)
+ if up:
+ up.upfunc(up)
+ return a
+
+
+# Create one or more panels from a description file (S-expressions)
+# generated by the Panel Editor.
+#
+def defpanellist(file):
+ import panelparser
+ descrlist = panelparser.parse_file(open(file, 'r'))
+ panellist = []
+ for descr in descrlist:
+ panellist.append(build_panel(descr))
+ return panellist
+
+
+# Import everything from built-in method pnl, so the user can always
+# use panel.foo() instead of pnl.foo().
+# This gives *no* performance penalty once this module is imported.
+#
+from pnl import * # for export
+
+dopanel = my_dopanel # override pnl.dopanel
diff --git a/lib/panelparser.py b/lib/panelparser.py
new file mode 100644
index 0000000..5eb2f2b
--- /dev/null
+++ b/lib/panelparser.py
@@ -0,0 +1,128 @@
+# Module 'parser'
+#
+# Parse S-expressions output by the Panel Editor
+# (which is written in Scheme so it can't help writing S-expressions).
+#
+# See notes at end of file.
+
+
+whitespace = ' \t\n'
+operators = '()\''
+separators = operators + whitespace + ';' + '"'
+
+
+# Tokenize a string.
+# Return a list of tokens (strings).
+#
+def tokenize_string(s):
+ tokens = []
+ while s:
+ c = s[:1]
+ if c in whitespace:
+ s = s[1:]
+ elif c = ';':
+ s = ''
+ elif c = '"':
+ n = len(s)
+ i = 1
+ while i < n:
+ c = s[i]
+ i = i+1
+ if c = '"': break
+ if c = '\\': i = i+1
+ tokens.append(s[:i])
+ s = s[i:]
+ elif c in operators:
+ tokens.append(c)
+ s = s[1:]
+ else:
+ n = len(s)
+ i = 1
+ while i < n:
+ if s[i] in separators: break
+ i = i+1
+ tokens.append(s[:i])
+ s = s[i:]
+ return tokens
+
+
+# Tokenize a whole file (given as file object, not as file name).
+# Return a list of tokens (strings).
+#
+def tokenize_file(fp):
+ tokens = []
+ while 1:
+ line = fp.readline()
+ if not line: break
+ tokens = tokens + tokenize_string(line)
+ return tokens
+
+
+# Exception raised by parse_exr.
+#
+syntax_error = 'syntax error'
+
+
+# Parse an S-expression.
+# Input is a list of tokens as returned by tokenize_*().
+# Return a pair (expr, tokens)
+# where expr is a list representing the s-expression,
+# and tokens contains the remaining tokens.
+# May raise syntax_error.
+#
+def parse_expr(tokens):
+ if (not tokens) or tokens[0] <> '(':
+ raise syntax_error, 'expected "("'
+ tokens = tokens[1:]
+ expr = []
+ while 1:
+ if not tokens:
+ raise syntax_error, 'missing ")"'
+ if tokens[0] = ')':
+ return expr, tokens[1:]
+ elif tokens[0] = '(':
+ subexpr, tokens = parse_expr(tokens)
+ expr.append(subexpr)
+ else:
+ expr.append(tokens[0])
+ tokens = tokens[1:]
+
+
+# Parse a file (given as file object, not as file name).
+# Return a list of parsed S-expressions found at the top level.
+#
+def parse_file(fp):
+ tokens = tokenize_file(fp)
+ exprlist = []
+ while tokens:
+ expr, tokens = parse_expr(tokens)
+ exprlist.append(expr)
+ return exprlist
+
+
+# EXAMPLE:
+#
+# The input
+# '(hip (hop hur-ray))'
+#
+# passed to tokenize_string() returns the token list
+# ['(', 'hip', '(', 'hop', 'hur-ray', ')', ')']
+#
+# When this is passed to parse_expr() it returns the expression
+# ['hip', ['hop', 'hur-ray']]
+# plus an empty token list (because there are no tokens left.
+#
+# When a file containing the example is passed to parse_file() it returns
+# a list whose only element is the output of parse_expr() above:
+# [['hip', ['hop', 'hur-ray']]]
+
+
+# TOKENIZING:
+#
+# Comments start with semicolon (;) and continue till the end of the line.
+#
+# Tokens are separated by whitespace, except the following characters
+# always form a separate token (outside strings):
+# ( ) '
+# Strings are enclosed in double quotes (") and backslash (\) is used
+# as escape character in strings.
diff --git a/lib/path.py b/lib/path.py
new file mode 100644
index 0000000..be2340f
--- /dev/null
+++ b/lib/path.py
@@ -0,0 +1,125 @@
+# Module 'path' -- common operations on POSIX pathnames
+
+import posix
+import stat
+
+
+# Intelligent pathname concatenation.
+# Inserts a '/' unless the first part is empty or already ends in '/'.
+# Ignores the first part altogether if the second part is absolute
+# (begins with '/').
+#
+def cat(a, b):
+ if b[:1] = '/': return b
+ if a = '' or a[-1:] = '/': return a + b
+ return a + '/' + b
+
+
+# Split a path in head (empty or ending in '/') and tail (no '/').
+# The tail will be empty if the path ends in '/'.
+#
+def split(p):
+ head, tail = '', ''
+ for c in p:
+ tail = tail + c
+ if c = '/':
+ head, tail = head + tail, ''
+ return head, tail
+
+
+# Return the tail (basename) part of a path.
+#
+def basename(p):
+ return split(p)[1]
+
+
+# Return the longest prefix of all list elements.
+#
+def commonprefix(m):
+ if not m: return ''
+ prefix = m[0]
+ for item in m:
+ for i in range(len(prefix)):
+ if prefix[:i+1] <> item[:i+1]:
+ prefix = prefix[:i]
+ if i = 0: return ''
+ break
+ return prefix
+
+
+# Does a file/directory exist?
+#
+def exists(path):
+ try:
+ st = posix.stat(path)
+ except posix.error:
+ return 0
+ return 1
+
+
+# Is a path a posix directory?
+#
+def isdir(path):
+ try:
+ st = posix.stat(path)
+ except posix.error:
+ return 0
+ return stat.S_ISDIR(st[stat.ST_MODE])
+
+
+# Is a path a symbolic link?
+# This will always return false on systems where posix.lstat doesn't exist.
+#
+def islink(path):
+ try:
+ st = posix.lstat(path)
+ except (posix.error, NameError):
+ return 0
+ return stat.S_ISLNK(st[stat.ST_MODE])
+
+
+_mounts = []
+
+def _getmounts():
+ import commands, string
+ mounts = []
+ data = commands.getoutput('/etc/mount')
+ lines = string.splitfields(data, '\n')
+ for line in lines:
+ words = string.split(line)
+ if len(words) >= 3 and words[1] = 'on':
+ mounts.append(words[2])
+ return mounts
+
+
+# Is a path a mount point?
+# This only works for normalized, absolute paths,
+# and only if the mount table as printed by /etc/mount is correct.
+# Sorry.
+#
+def ismount(path):
+ if not _mounts:
+ _mounts[:] = _getmounts()
+ return path in _mounts
+
+
+# Directory tree walk.
+# For each directory under top (including top itself),
+# func(arg, dirname, filenames) is called, where dirname
+# is the name of the directory and filenames is the list of
+# files (and subdirectories etc.) in the directory.
+# func may modify the filenames list, to implement a filter,
+# or to impose a different order of visiting.
+#
+def walk(top, func, arg):
+ try:
+ names = posix.listdir(top)
+ except posix.error:
+ return
+ func(arg, top, names)
+ exceptions = ('.', '..')
+ for name in names:
+ if name not in exceptions:
+ name = cat(top, name)
+ if isdir(name):
+ walk(name, func, arg)
diff --git a/lib/poly.py b/lib/poly.py
new file mode 100644
index 0000000..a7c24ec
--- /dev/null
+++ b/lib/poly.py
@@ -0,0 +1,55 @@
+# module 'poly' -- Polynomials
+
+# A polynomial is represented by a list of coefficients, e.g.,
+# [1, 10, 5] represents 1*x**0 + 10*x**1 + 5*x**2 (or 1 + 10x + 5x**2).
+# There is no way to suppress internal zeros; trailing zeros are
+# taken out by normalize().
+
+def normalize(p): # Strip unnecessary zero coefficients
+ n = len(p)
+ while p:
+ if p[n-1]: return p[:n]
+ n = n-1
+ return []
+
+def plus(a, b):
+ if len(a) < len(b): a, b = b, a # make sure a is the longest
+ res = a[:] # make a copy
+ for i in range(len(b)):
+ res[i] = res[i] + b[i]
+ return normalize(res)
+
+def minus(a, b):
+ if len(a) < len(b): a, b = b, a # make sure a is the longest
+ res = a[:] # make a copy
+ for i in range(len(b)):
+ res[i] = res[i] - b[i]
+ return normalize(res)
+
+def one(power, coeff): # Representation of coeff * x**power
+ res = []
+ for i in range(power): res.append(0)
+ return res + [coeff]
+
+def times(a, b):
+ res = []
+ for i in range(len(a)):
+ for j in range(len(b)):
+ res = plus(res, one(i+j, a[i]*b[j]))
+ return res
+
+def power(a, n): # Raise polynomial a to the positive integral power n
+ if n = 0: return [1]
+ if n = 1: return a
+ if n/2*2 = n:
+ b = power(a, n/2)
+ return times(b, b)
+ return times(power(a, n-1), a)
+
+def der(a): # First derivative
+ res = a[1:]
+ for i in range(len(res)):
+ res[i] = res[i] * (i+1)
+ return res
+
+# Computing a primitive function would require rational arithmetic...
diff --git a/lib/rand.py b/lib/rand.py
new file mode 100644
index 0000000..0ca1a53
--- /dev/null
+++ b/lib/rand.py
@@ -0,0 +1,12 @@
+# Module 'rand'
+
+import whrandom
+
+def srand(seed):
+ whrandom.seed(seed%256, seed/256%256, seed/65536%256)
+
+def rand():
+ return int(whrandom.random() * 32768.0) % 32768
+
+def choice(seq):
+ return seq[rand() % len(seq)]
diff --git a/lib/rect.py b/lib/rect.py
new file mode 100644
index 0000000..8f61e11
--- /dev/null
+++ b/lib/rect.py
@@ -0,0 +1,88 @@
+# Module 'rect'.
+#
+# Operations on rectangles.
+# There is some normalization: all results return the object 'empty'
+# if their result would contain no points.
+
+
+# Exception.
+#
+error = 'rect.error'
+
+
+# The empty rectangle.
+#
+empty = (0, 0), (0, 0)
+
+
+# Check if a rectangle is empty.
+#
+def is_empty((left, top), (right, bottom)):
+ return left >= right or top >= bottom
+
+
+# Compute the intersection or two or more rectangles.
+# This works with a list or tuple argument.
+#
+def intersect(list):
+ if not list: raise error, 'intersect called with empty list'
+ if is_empty(list[0]): return empty
+ (left, top), (right, bottom) = list[0]
+ for rect in list[1:]:
+ if is_empty(rect):
+ return empty
+ (l, t), (r, b) = rect
+ if left < l: left = l
+ if top < t: top = t
+ if right > r: right = r
+ if bottom > b: bottom = b
+ if is_empty((left, top), (right, bottom)):
+ return empty
+ return (left, top), (right, bottom)
+
+
+# Compute the smallest rectangle containing all given rectangles.
+# This works with a list or tuple argument.
+#
+def union(list):
+ (left, top), (right, bottom) = empty
+ for (l, t), (r, b) in list[1:]:
+ if not is_empty((l, t), (r, b)):
+ if l < left: left = l
+ if t < top: top = t
+ if r > right: right = r
+ if b > bottom: bottom = b
+ res = (left, top), (right, bottom)
+ if is_empty(res):
+ return empty
+ return res
+
+
+# Check if a point is in a rectangle.
+#
+def pointinrect((h, v), ((left, top), (right, bottom))):
+ return left <= h < right and top <= v < bottom
+
+
+# Return a rectangle that is dh, dv inside another
+#
+def inset(((left, top), (right, bottom)), (dh, dv)):
+ left = left + dh
+ top = top + dv
+ right = right - dh
+ bottom = bottom - dv
+ r = (left, top), (right, bottom)
+ if is_empty(r):
+ return empty
+ else:
+ return r
+
+
+# Conversions between rectangles and 'geometry tuples',
+# given as origin (h, v) and dimensions (width, height).
+#
+def rect2geom((left, top), (right, bottom)):
+ return (left, top), (right-left, bottom-top)
+
+def geom2rect((h, v), (width, height)):
+ return (h, v), (h+width, v+height)
diff --git a/lib/selection.py b/lib/selection.py
new file mode 100644
index 0000000..22a0ea9
--- /dev/null
+++ b/lib/selection.py
@@ -0,0 +1,72 @@
+# DAWKINS' BLIND WATCHMAKER -- "METHINKS IT IS LIKE A WEASEL" EXAMPLE
+#
+# Start with a random phrase. Successively:
+# Breed a next generation by copying with small mutations.
+# Choose the member of the next generation that most closely resembles
+# the target phrase to start breeding the next generation.
+# How many generations will it take before the target is reached?
+
+from whrandom import random
+
+# Parameters determining the problem space
+Target = 'methinks it is like a weasel'
+Alphabet = ' abcdefghijklmnopqrstuvwxyz'
+
+# Parameters to play with
+GenerationSize = 100
+MutationChance = 1.0/28.0
+
+IndexSet = range(len(Target)) # Used to speed up loops
+
+def choice(sequence):
+ n = len(sequence)
+ i = int(random() * float(n)) % n
+ return sequence[i]
+
+def random_phrase():
+ phrase = ''
+ for i in IndexSet:
+ phrase = phrase + choice(Alphabet)
+ return phrase
+
+def mutate_phrase(phrase):
+ mutant = phrase
+ for i in range(int(0.5 + MutationChance*float(len(phrase)))):
+ i = choice(IndexSet)
+ c = choice(Alphabet)
+ mutant = mutant[:i] + c + mutant[i+1:]
+ #print `mutant`
+ return mutant
+
+def matching_factor(phrase):
+ factor = 0
+ for i in IndexSet:
+ if phrase[i] = Target[i]: factor = factor + 1
+ return factor
+
+def breed_generation(phrase):
+ generation = [phrase]
+ while len(generation) < GenerationSize:
+ generation.append(mutate_phrase(phrase))
+ return generation
+
+def select_best(generation):
+ factor, selected = -1, ''
+ for phrase in generation:
+ f = matching_factor(phrase)
+ if f > factor:
+ factor, selected = f, phrase
+ return selected
+
+def main():
+ gen = 0
+ phrase = random_phrase()
+ print gen, `phrase`
+ while phrase <> Target:
+ next_generation = breed_generation(phrase)
+ #print next_generation
+ phrase = select_best(next_generation)
+ gen = gen+1
+ print gen, `phrase`
+
+main()
diff --git a/lib/shutil.py b/lib/shutil.py
new file mode 100644
index 0000000..c01d889
--- /dev/null
+++ b/lib/shutil.py
@@ -0,0 +1,70 @@
+# Module 'shutil' -- utility functions usable in a shell-like program
+
+import posix
+import path
+
+MODEBITS = 010000 # Lower 12 mode bits
+# Change this to 01000 (9 mode bits) to avoid copying setuid etc.
+
+# Copy data from src to dst
+#
+def copyfile(src, dst):
+ fsrc = open(src, 'r')
+ fdst = open(dst, 'w')
+ while 1:
+ buf = fsrc.read(16*1024)
+ if not buf: break
+ fdst.write(buf)
+
+# Copy mode bits from src to dst
+#
+def copymode(src, dst):
+ st = posix.stat(src)
+ mode = divmod(st[0], MODEBITS)[1]
+ posix.chmod(dst, mode)
+
+# Copy all stat info (mode bits, atime and mtime) from src to dst
+#
+def copystat(src, dst):
+ st = posix.stat(src)
+ mode = divmod(st[0], MODEBITS)[1]
+ posix.chmod(dst, mode)
+ posix.utimes(dst, st[7:9])
+
+# Copy data and mode bits ("cp src dst")
+#
+def copy(src, dst):
+ copyfile(src, dst)
+ copymode(src, dst)
+
+# Copy data and all stat info ("cp -p src dst")
+#
+def copy2(src, dst):
+ copyfile(src, dst)
+ copystat(src, dst)
+
+# Recursively copy a directory tree.
+# The destination must not already exist.
+#
+def copytree(src, dst):
+ names = posix.listdir(src)
+ posix.mkdir(dst, 0777)
+ dot_dotdot = '.', '..'
+ for name in names:
+ if name not in dot_dotdot:
+ srcname = path.cat(src, name)
+ dstname = path.cat(dst, name)
+ #print 'Copying', srcname, 'to', dstname
+ try:
+ #if path.islink(srcname):
+ # linkto = posix.readlink(srcname)
+ # posix.symlink(linkto, dstname)
+ #elif path.isdir(srcname):
+ if path.isdir(srcname):
+ copytree(srcname, dstname)
+ else:
+ copy2(srcname, dstname)
+ # XXX What about devices, sockets etc.?
+ except posix.error, why:
+ print 'Could not copy', srcname, 'to', dstname,
+ print '(', why[1], ')'
diff --git a/lib/stat.py b/lib/stat.py
new file mode 100644
index 0000000..83855b6
--- /dev/null
+++ b/lib/stat.py
@@ -0,0 +1,57 @@
+# Module 'stat'
+
+# Defines constants and functions for interpreting stat/lstat struct
+# as returned by posix.stat() and posix.lstat() (if it exists).
+
+# XXX This module may have to be adapted for UNIXoid systems whose
+# <sys/stat.h> deviates from AT&T or BSD UNIX; their S_IF* constants
+# may differ.
+
+# Suggested usage: from stat import *
+
+# Tuple indices for stat struct members
+
+ST_MODE = 0
+ST_INO = 1
+ST_DEV = 2
+ST_NLINK = 3
+ST_UID = 4
+ST_GID = 5
+ST_SIZE = 6
+ST_ATIME = 7
+ST_MTIME = 8
+ST_CTIME = 9
+
+def S_IMODE(mode):
+ return mode%4096
+def S_IFMT(mode):
+ return mode - mode%4096
+
+S_IFDIR = 0040000
+S_IFCHR = 0020000
+S_IFBLK = 0060000
+S_IFREG = 0100000
+S_IFIFO = 0010000
+S_IFLNK = 0120000
+S_IFSOCK = 0140000
+
+def S_ISDIR(mode):
+ return S_IFMT(mode) = S_IFDIR
+
+def S_ISCHR(mode):
+ return S_IFMT(mode) = S_IFCHR
+
+def S_ISBLK(mode):
+ return S_IFMT(mode) = S_IFBLK
+
+def S_ISREG(mode):
+ return S_IFMT(mode) = S_IFREG
+
+def S_ISFIFO(mode):
+ return S_IFMT(mode) = S_IFIFO
+
+def S_ISLNK(mode):
+ return S_IFMT(mode) = S_IFLNK
+
+def S_ISSOCK(mode):
+ return S_IFMT(mode) = S_IFSOCK
diff --git a/lib/statcache.py b/lib/statcache.py
new file mode 100644
index 0000000..0eaf810
--- /dev/null
+++ b/lib/statcache.py
@@ -0,0 +1,86 @@
+# Module 'statcache'
+#
+# Maintain a cache of file stats.
+# There are functions to reset the cache or to selectively remove items.
+
+import posix
+from stat import *
+
+# The cache.
+# Keys are pathnames, values are `posix.stat' outcomes.
+#
+cache = {}
+
+
+# Stat a file, possibly out of the cache.
+#
+def stat(path):
+ if cache.has_key(path):
+ return cache[path]
+ cache[path] = ret = posix.stat(path)
+ return ret
+
+
+# Reset the cache completely.
+# Hack: to reset a global variable, we import this module.
+#
+def reset():
+ import statcache
+ # Check that we really imported the same module
+ if cache is not statcache.cache:
+ raise 'sorry, statcache identity crisis'
+ statcache.cache = {}
+
+
+# Remove a given item from the cache, if it exists.
+#
+def forget(path):
+ if cache.has_key(path):
+ del cache[path]
+
+
+# Remove all pathnames with a given prefix.
+#
+def forget_prefix(prefix):
+ n = len(prefix)
+ for path in cache.keys():
+ if path[:n] = prefix:
+ del cache[path]
+
+
+# Forget about a directory and all entries in it, but not about
+# entries in subdirectories.
+#
+def forget_dir(prefix):
+ if prefix[-1:] = '/' and prefix <> '/':
+ prefix = prefix[:-1]
+ forget(prefix)
+ if prefix[-1:] <> '/':
+ prefix = prefix + '/'
+ n = len(prefix)
+ for path in cache.keys():
+ if path[:n] = prefix:
+ rest = path[n:]
+ if rest[-1:] = '/': rest = rest[:-1]
+ if '/' not in rest:
+ del cache[path]
+
+
+# Remove all pathnames except with a given prefix.
+# Normally used with prefix = '/' after a chdir().
+#
+def forget_except_prefix(prefix):
+ n = len(prefix)
+ for path in cache.keys():
+ if path[:n] <> prefix:
+ del cache[path]
+
+
+# Check for directory.
+#
+def isdir(path):
+ try:
+ st = stat(path)
+ except posix.error:
+ return 0
+ return S_ISDIR(st[ST_MODE])
diff --git a/lib/stdwinevents.py b/lib/stdwinevents.py
new file mode 100644
index 0000000..fc1c1e7
--- /dev/null
+++ b/lib/stdwinevents.py
@@ -0,0 +1,46 @@
+# Module 'stdwinevents' -- Constants for stdwin event types
+#
+# Suggested usage:
+# from stdwinevents import *
+
+# The function stdwin.getevent() returns a tuple containing:
+# (type, window, detail)
+# where detail may be <no value> or a value depending on type, see below:
+
+# Values for type:
+
+WE_NULL = 0 # not reported -- means 'no event' internally
+WE_ACTIVATE = 1 # detail is <no object>
+WE_CHAR = 2 # detail is the character
+WE_COMMAND = 3 # detail is one of the WC_* constants below
+WE_MOUSE_DOWN = 4 # detail is ((h, v), clicks, button, mask)
+WE_MOUSE_MOVE = 5 # ditto
+WE_MOUSE_UP = 6 # ditto
+WE_MENU = 7 # detail is (menu, item)
+WE_SIZE = 8 # detail is (width, height) [???]
+WE_MOVE = 9 # not reported -- reserved for future use
+WE_DRAW = 10 # detail is ((left, top), (right, bottom))
+WE_TIMER = 11 # detail is <no object>
+WE_DEACTIVATE = 12 # detail is <no object>
+WE_EXTERN = 13 # detail is <no object>
+WE_KEY = 14 # detail is ???
+WE_LOST_SEL = 15 # detail is selection number
+WE_CLOSE = 16 # detail is <no object>
+
+# Values for detail when type is WE_COMMAND:
+
+WC_CLOSE = 1 # user hit close box
+WC_LEFT = 2 # left arrow key
+WC_RIGHT = 3 # right arrow key
+WC_UP = 4 # up arrow key
+WC_DOWN = 5 # down arrow key
+WC_CANCEL = 6 # not reported -- turned into KeyboardInterrupt
+WC_BACKSPACE = 7 # backspace key
+WC_TAB = 8 # tab key
+WC_RETURN = 9 # return or enter key
+
+# Selection numbers
+
+WS_CLIPBOARD = 0
+WS_PRIMARY = 1
+WS_SECONDARY = 2
diff --git a/lib/stdwinsupport.py b/lib/stdwinsupport.py
new file mode 100644
index 0000000..1a28072
--- /dev/null
+++ b/lib/stdwinsupport.py
@@ -0,0 +1,34 @@
+# Module 'stdwinsupport'
+
+import stdwin
+
+eventnames = ['null', 'activate', 'char', 'command']
+eventnames = eventnames + ['mouse_down', 'mouse_move', 'mouse_up', 'menu']
+eventnames = eventnames + ['size', 'move', 'draw', 'timer', 'deactivate']
+
+we_null = 0
+we_activate = 1
+we_char = 2
+we_command = 3
+we_mouse_down = 4
+we_mouse_move = 5
+we_mouse_up = 6
+we_menu = 7
+we_size = 8
+we_move = 9
+we_draw = 10
+we_timer = 11
+we_deactivate = 12
+
+commandnames = ['?', 'close', 'left', 'right', 'up', 'down', 'cancel']
+commandnames = commandnames + ['backspace', 'tab', 'return']
+
+wc_close = 1
+wc_left = 2
+wc_right = 3
+wc_up = 4
+wc_down = 5
+wc_cancel = 6 # not reported -- turned into KeyboardInterrupt
+wc_backspace = 7
+wc_tab = 8
+wc_return = 9
diff --git a/lib/string.py b/lib/string.py
new file mode 100644
index 0000000..5262013
--- /dev/null
+++ b/lib/string.py
@@ -0,0 +1,129 @@
+# module 'string' -- A collection of string operations
+
+# XXX Some of these operations are incredibly slow and should be built in
+
+# Some strings for ctype-style character classification
+whitespace = ' \t\n'
+lowercase = 'abcdefghijklmnopqrstuvwxyz'
+uppercase = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+letters = lowercase + uppercase
+digits = '0123456789'
+hexdigits = digits + 'abcdef' + 'ABCDEF'
+octdigits = '01234567'
+
+# Case conversion helpers
+_caseswap = {}
+for i in range(26):
+ _caseswap[lowercase[i]] = uppercase[i]
+ _caseswap[uppercase[i]] = lowercase[i]
+del i
+
+# convert UPPER CASE letters to lower case
+def lower(s):
+ res = ''
+ for c in s:
+ if 'A' <= c <= 'Z': c = _caseswap[c]
+ res = res + c
+ return res
+
+# Convert lower case letters to UPPER CASE
+def upper(s):
+ res = ''
+ for c in s:
+ if 'a' <= c <= 'z': c = _caseswap[c]
+ res = res + c
+ return res
+
+# Swap lower case letters and UPPER CASE
+def swapcase(s):
+ res = ''
+ for c in s:
+ if 'a' <= c <= 'z' or 'A' <= c <= 'Z': c = _caseswap[c]
+ res = res + c
+ return res
+
+# Strip leading and trailing tabs and spaces
+def strip(s):
+ i, j = 0, len(s)
+ while i < j and s[i] in whitespace: i = i+1
+ while i < j and s[j-1] in whitespace: j = j-1
+ return s[i:j]
+
+# Split a string into a list of space/tab-separated words
+# NB: split(s) is NOT the same as splitfields(s, ' ')!
+def split(s):
+ res = []
+ i, n = 0, len(s)
+ while i < n:
+ while i < n and s[i] in whitespace: i = i+1
+ if i = n: break
+ j = i
+ while j < n and s[j] not in whitespace: j = j+1
+ res.append(s[i:j])
+ i = j
+ return res
+
+# Split a list into fields separated by a given string
+# NB: splitfields(s, ' ') is NOT the same as split(s)!
+def splitfields(s, sep):
+ res = []
+ ns = len(s)
+ nsep = len(sep)
+ i = j = 0
+ while j+nsep <= ns:
+ if s[j:j+nsep] = sep:
+ res.append(s[i:j])
+ i = j = j + nsep
+ else:
+ j = j + 1
+ res.append(s[i:])
+ return res
+
+# Find substring
+index_error = 'substring not found in string.index'
+def index(s, sub):
+ n = len(sub)
+ for i in range(len(s) + 1 - n):
+ if sub = s[i:i+n]: return i
+ raise index_error, (s, sub)
+
+# Convert string to integer
+atoi_error = 'non-numeric argument to string.atoi'
+def atoi(str):
+ s = str
+ if s[:1] in '+-': s = s[1:]
+ if not s: raise atoi_error, str
+ for c in s:
+ if c not in digits: raise atoi_error, str
+ return eval(str)
+
+# Left-justify a string
+def ljust(s, width):
+ n = len(s)
+ if n >= width: return s
+ return s + ' '*(width-n)
+
+# Right-justify a string
+def rjust(s, width):
+ n = len(s)
+ if n >= width: return s
+ return ' '*(width-n) + s
+
+# Center a string
+def center(s, width):
+ n = len(s)
+ if n >= width: return s
+ return ' '*((width-n)/2) + s + ' '*(width -(width-n)/2)
+
+# Zero-fill a number, e.g., (12, 3) --> '012' and (-3, 3) --> '-03'
+# Decadent feature: the argument may be a string or a number
+# (Use of this is deprecated; it should be a string as with ljust c.s.)
+def zfill(x, width):
+ if type(x) = type(''): s = x
+ else: s = `x`
+ n = len(s)
+ if n >= width: return s
+ sign = ''
+ if s[0] = '-':
+ sign, s = '-', s[1:]
+ return sign + '0'*(width-n) + s
diff --git a/lib/sunaudio.py b/lib/sunaudio.py
new file mode 100644
index 0000000..ed1b6e4
--- /dev/null
+++ b/lib/sunaudio.py
@@ -0,0 +1,54 @@
+# Module 'sunaudio' -- interpret sun audio headers
+
+import audio
+
+MAGIC = '.snd'
+
+error = 'sunaudio sound header conversion error'
+
+
+# convert a 4-char value to integer
+
+def c2i(data):
+ if type(data) <> type('') or len(data) <> 4:
+ raise error, 'c2i: bad arg (not string[4])'
+ bytes = audio.chr2num(data)
+ for i in (1, 2, 3):
+ if bytes[i] < 0:
+ bytes[i] = bytes[i] + 256
+ return ((bytes[0]*256 + bytes[1])*256 + bytes[2])*256 + bytes[3]
+
+
+# read a sound header from an open file
+
+def gethdr(fp):
+ if fp.read(4) <> MAGIC:
+ raise error, 'gethdr: bad magic word'
+ hdr_size = c2i(fp.read(4))
+ data_size = c2i(fp.read(4))
+ encoding = c2i(fp.read(4))
+ sample_rate = c2i(fp.read(4))
+ channels = c2i(fp.read(4))
+ excess = hdr_size - 24
+ if excess < 0:
+ raise error, 'gethdr: bad hdr_size'
+ if excess > 0:
+ info = fp.read(excess)
+ else:
+ info = ''
+ return (data_size, encoding, sample_rate, channels, info)
+
+
+# read and print the sound header of a named file
+
+def printhdr(file):
+ hdr = gethdr(open(file, 'r'))
+ data_size, encoding, sample_rate, channels, info = hdr
+ while info[-1:] = '\0':
+ info = info[:-1]
+ print 'File name: ', file
+ print 'Data size: ', data_size
+ print 'Encoding: ', encoding
+ print 'Sample rate:', sample_rate
+ print 'Channels: ', channels
+ print 'Info: ', `info`
diff --git a/lib/tablewin.py b/lib/tablewin.py
new file mode 100644
index 0000000..df06476
--- /dev/null
+++ b/lib/tablewin.py
@@ -0,0 +1,237 @@
+# Module 'tablewin'
+
+# Display a table, with per-item actions:
+
+# A1 | A2 | A3 | .... | AN
+# B1 | B2 | B3 | .... | BN
+# C1 | C2 | C3 | .... | CN
+# .. | .. | .. | .... | ..
+# Z1 | Z2 | Z3 | .... | ZN
+
+# Not all columns need to have the same length.
+# The data structure is a list of columns;
+# each column is a list of items.
+# Each item is a pair of a string and an action procedure.
+# The first item may be a column title.
+
+import stdwin
+import gwin
+
+def open(title, data): # Public function to open a table window
+ #
+ # Set geometry parameters (one day, these may be changeable)
+ #
+ margin = stdwin.textwidth(' ')
+ lineheight = stdwin.lineheight()
+ #
+ # Geometry calculations
+ #
+ colstarts = [0]
+ totwidth = 0
+ maxrows = 0
+ for coldata in data:
+ # Height calculations
+ rows = len(coldata)
+ if rows > maxrows: maxrows = rows
+ # Width calculations
+ width = colwidth(coldata) + margin
+ totwidth = totwidth + width
+ colstarts.append(totwidth)
+ #
+ # Calculate document and window height
+ #
+ docwidth, docheight = totwidth, maxrows*lineheight
+ winwidth, winheight = docwidth, docheight
+ if winwidth > stdwin.textwidth('n')*100: winwidth = 0
+ if winheight > stdwin.lineheight()*30: winheight = 0
+ #
+ # Create the window
+ #
+ stdwin.setdefwinsize(winwidth, winheight)
+ w = gwin.open(title)
+ #
+ # Set properties and override methods
+ #
+ w.data = data
+ w.margin = margin
+ w.lineheight = lineheight
+ w.colstarts = colstarts
+ w.totwidth = totwidth
+ w.maxrows = maxrows
+ w.selection = (-1, -1)
+ w.lastselection = (-1, -1)
+ w.selshown = 0
+ w.setdocsize(docwidth, docheight)
+ w.draw = draw
+ w.mup = mup
+ w.arrow = arrow
+ #
+ # Return
+ #
+ return w
+
+def update(w, data): # Change the data
+ #
+ # Hide selection
+ #
+ hidesel(w, w.begindrawing())
+ #
+ # Get old geometry parameters
+ #
+ margin = w.margin
+ lineheight = w.lineheight
+ #
+ # Geometry calculations
+ #
+ colstarts = [0]
+ totwidth = 0
+ maxrows = 0
+ for coldata in data:
+ # Height calculations
+ rows = len(coldata)
+ if rows > maxrows: maxrows = rows
+ # Width calculations
+ width = colwidth(coldata) + margin
+ totwidth = totwidth + width
+ colstarts.append(totwidth)
+ #
+ # Calculate document and window height
+ #
+ docwidth, docheight = totwidth, maxrows*lineheight
+ #
+ # Set changed properties and change window size
+ #
+ w.data = data
+ w.colstarts = colstarts
+ w.totwidth = totwidth
+ w.maxrows = maxrows
+ w.change((0, 0), (10000, 10000))
+ w.setdocsize(docwidth, docheight)
+ w.change((0, 0), (docwidth, docheight))
+ #
+ # Show selection, or forget it if out of range
+ #
+ showsel(w, w.begindrawing())
+ if not w.selshown: w.selection = (-1, -1)
+
+def colwidth(coldata): # Subroutine to calculate column width
+ maxwidth = 0
+ for string, action in coldata:
+ width = stdwin.textwidth(string)
+ if width > maxwidth: maxwidth = width
+ return maxwidth
+
+def draw(w, ((left, top), (right, bottom))): # Draw method
+ ileft = whichcol(w, left)
+ iright = whichcol(w, right-1) + 1
+ if iright > len(w.data): iright = len(w.data)
+ itop = divmod(top, w.lineheight)[0]
+ if itop < 0: itop = 0
+ ibottom, remainder = divmod(bottom, w.lineheight)
+ if remainder: ibottom = ibottom + 1
+ d = w.begindrawing()
+ if ileft <= w.selection[0] < iright:
+ if itop <= w.selection[1] < ibottom:
+ hidesel(w, d)
+ d.erase((left, top), (right, bottom))
+ for i in range(ileft, iright):
+ col = w.data[i]
+ jbottom = len(col)
+ if ibottom < jbottom: jbottom = ibottom
+ h = w.colstarts[i]
+ v = itop * w.lineheight
+ for j in range(itop, jbottom):
+ string, action = col[j]
+ d.text((h, v), string)
+ v = v + w.lineheight
+ showsel(w, d)
+
+def mup(w, detail): # Mouse up method
+ (h, v), nclicks, button, mask = detail
+ icol = whichcol(w, h)
+ if 0 <= icol < len(w.data):
+ irow = divmod(v, w.lineheight)[0]
+ col = w.data[icol]
+ if 0 <= irow < len(col):
+ string, action = col[irow]
+ action(w, string, (icol, irow), detail)
+
+def whichcol(w, h): # Return column number (may be >= len(w.data))
+ for icol in range(0, len(w.data)):
+ if h < w.colstarts[icol+1]:
+ return icol
+ return len(w.data)
+
+def arrow(w, type):
+ import stdwinsupport
+ S = stdwinsupport
+ if type = S.wc_left:
+ incr = -1, 0
+ elif type = S.wc_up:
+ incr = 0, -1
+ elif type = S.wc_right:
+ incr = 1, 0
+ elif type = S.wc_down:
+ incr = 0, 1
+ else:
+ return
+ icol, irow = w.lastselection
+ icol = icol + incr[0]
+ if icol < 0: icol = len(w.data)-1
+ if icol >= len(w.data): icol = 0
+ if 0 <= icol < len(w.data):
+ irow = irow + incr[1]
+ if irow < 0: irow = len(w.data[icol]) - 1
+ if irow >= len(w.data[icol]): irow = 0
+ else:
+ irow = 0
+ if 0 <= icol < len(w.data) and 0 <= irow < len(w.data[icol]):
+ w.lastselection = icol, irow
+ string, action = w.data[icol][irow]
+ detail = (0, 0), 1, 1, 1
+ action(w, string, (icol, irow), detail)
+
+
+# Selection management
+# TO DO: allow multiple selected entries
+
+def select(w, selection): # Public function to set the item selection
+ d = w.begindrawing()
+ hidesel(w, d)
+ w.selection = selection
+ showsel(w, d)
+ if w.selshown: lastselection = selection
+
+def hidesel(w, d): # Hide the selection, if shown
+ if w.selshown: invertsel(w, d)
+
+def showsel(w, d): # Show the selection, if hidden
+ if not w.selshown: invertsel(w, d)
+
+def invertsel(w, d): # Invert the selection, if valid
+ icol, irow = w.selection
+ if 0 <= icol < len(w.data) and 0 <= irow < len(w.data[icol]):
+ left = w.colstarts[icol]
+ right = w.colstarts[icol+1]
+ top = irow * w.lineheight
+ bottom = (irow+1) * w.lineheight
+ d.invert((left, top), (right, bottom))
+ w.selshown = (not w.selshown)
+
+
+# Demonstration
+
+def demo_action(w, string, (icol, irow), detail): # Action function for demo
+ select(w, (irow, icol))
+
+def demo(): # Demonstration
+ da = demo_action # shorthand
+ col0 = [('a1', da), ('bbb1', da), ('c1', da)]
+ col1 = [('a2', da), ('bbb2', da)]
+ col2 = [('a3', da), ('b3', da), ('c3', da), ('d4', da), ('d5', da)]
+ col3 = []
+ for i in range(1, 31): col3.append('xxx' + `i`, da)
+ data = [col0, col1, col2, col3]
+ w = open('tablewin.demo', data)
+ gwin.mainloop()
+ return w
diff --git a/lib/tb.py b/lib/tb.py
new file mode 100644
index 0000000..9f2c92c
--- /dev/null
+++ b/lib/tb.py
@@ -0,0 +1,220 @@
+# Print tracebacks, with a dump of local variables.
+# Also an interactive stack trace browser.
+
+import sys
+try:
+ import mac
+ os = mac
+except NameError:
+ import posix
+ os = posix
+from stat import *
+import string
+
+def br(): browser(sys.last_traceback)
+
+def tb(): printtb(sys.last_traceback)
+
+def browser(tb):
+ if not tb:
+ print 'No traceback.'
+ return
+ tblist = []
+ while tb:
+ tblist.append(tb)
+ tb = tb.tb_next
+ ptr = len(tblist)-1
+ tb = tblist[ptr]
+ while 1:
+ if tb <> tblist[ptr]:
+ tb = tblist[ptr]
+ print `ptr` + ':',
+ printtbheader(tb)
+ try:
+ line = raw_input('TB: ')
+ except KeyboardInterrupt:
+ print '\n[Interrupted]'
+ break
+ except EOFError:
+ print '\n[EOF]'
+ break
+ cmd = string.strip(line)
+ if cmd:
+ if cmd = 'quit':
+ break
+ elif cmd = 'list':
+ browserlist(tb)
+ elif cmd = 'up':
+ if ptr-1 >= 0: ptr = ptr-1
+ else: print 'Bottom of stack.'
+ elif cmd = 'down':
+ if ptr+1 < len(tblist): ptr = ptr+1
+ else: print 'Top of stack.'
+ elif cmd = 'locals':
+ printsymbols(tb.tb_frame.f_locals)
+ elif cmd = 'globals':
+ printsymbols(tb.tb_frame.f_globals)
+ elif cmd in ('?', 'help'):
+ browserhelp()
+ else:
+ browserexec(tb, cmd)
+
+def browserlist(tb):
+ filename = tb.tb_frame.f_code.co_filename
+ lineno = tb.tb_lineno
+ last = lineno
+ first = max(1, last-10)
+ for i in range(first, last+1):
+ if i = lineno: prefix = '***' + string.rjust(`i`, 4) + ':'
+ else: prefix = string.rjust(`i`, 7) + ':'
+ line = readfileline(filename, i)
+ if line[-1:] = '\n': line = line[:-1]
+ print prefix + line
+
+def browserexec(tb, cmd):
+ locals = tb.tb_frame.f_locals
+ globals = tb.tb_frame.f_globals
+ try:
+ exec(cmd+'\n', globals, locals)
+ except:
+ print '*** Exception:',
+ print sys.exc_type,
+ if sys.exc_value <> None:
+ print ':', sys.exc_value,
+ print
+ print 'Type help to get help.'
+
+def browserhelp():
+ print
+ print ' This is the traceback browser. Commands are:'
+ print ' up : move one level up in the call stack'
+ print ' down : move one level down in the call stack'
+ print ' locals : print all local variables at this level'
+ print ' globals : print all global variables at this level'
+ print ' list : list source code around the failure'
+ print ' help : print help (what you are reading now)'
+ print ' quit : back to command interpreter'
+ print ' Typing any other 1-line statement will execute it'
+ print ' using the current level\'s symbol tables'
+ print
+
+def printtb(tb):
+ while tb:
+ print1tb(tb)
+ tb = tb.tb_next
+
+def print1tb(tb):
+ printtbheader(tb)
+ if tb.tb_frame.f_locals is not tb.tb_frame.f_globals:
+ printsymbols(tb.tb_frame.f_locals)
+
+def printtbheader(tb):
+ filename = tb.tb_frame.f_code.co_filename
+ lineno = tb.tb_lineno
+ info = '"' + filename + '"(' + `lineno` + ')'
+ line = readfileline(filename, lineno)
+ if line:
+ info = info + ': ' + string.strip(line)
+ print info
+
+def printsymbols(d):
+ keys = d.keys()
+ keys.sort()
+ for name in keys:
+ print ' ' + string.ljust(name, 12) + ':',
+ printobject(d[name], 4)
+ print
+
+def printobject(v, maxlevel):
+ if v = None:
+ print 'None',
+ elif type(v) in (type(0), type(0.0)):
+ print v,
+ elif type(v) = type(''):
+ if len(v) > 20:
+ print `v[:17] + '...'`,
+ else:
+ print `v`,
+ elif type(v) = type(()):
+ print '(',
+ printlist(v, maxlevel)
+ print ')',
+ elif type(v) = type([]):
+ print '[',
+ printlist(v, maxlevel)
+ print ']',
+ elif type(v) = type({}):
+ print '{',
+ printdict(v, maxlevel)
+ print '}',
+ else:
+ print v,
+
+def printlist(v, maxlevel):
+ n = len(v)
+ if n = 0: return
+ if maxlevel <= 0:
+ print '...',
+ return
+ for i in range(min(6, n)):
+ printobject(v[i], maxlevel-1)
+ if i+1 < n: print ',',
+ if n > 6: print '...',
+
+def printdict(v, maxlevel):
+ keys = v.keys()
+ n = len(keys)
+ if n = 0: return
+ if maxlevel <= 0:
+ print '...',
+ return
+ keys.sort()
+ for i in range(min(6, n)):
+ key = keys[i]
+ print `key` + ':',
+ printobject(v[key], maxlevel-1)
+ if i+1 < n: print ',',
+ if n > 6: print '...',
+
+_filecache = {}
+
+def readfileline(filename, lineno):
+ try:
+ stat = os.stat(filename)
+ except os.error, msg:
+ print 'Cannot stat', filename, '--', msg
+ return ''
+ cache_ok = 0
+ if _filecache.has_key(filename):
+ cached_stat, lines = _filecache[filename]
+ if stat[ST_SIZE] = cached_stat[ST_SIZE] and \
+ stat[ST_MTIME] = cached_stat[ST_MTIME]:
+ cache_ok = 1
+ else:
+ print 'Stale cache entry for', filename
+ del _filecache[filename]
+ if not cache_ok:
+ lines = readfilelines(filename)
+ if not lines:
+ return ''
+ _filecache[filename] = stat, lines
+ if 0 <= lineno-1 < len(lines):
+ return lines[lineno-1]
+ else:
+ print 'Line number out of range, last line is', len(lines)
+ return ''
+
+def readfilelines(filename):
+ try:
+ fp = open(filename, 'r')
+ except:
+ print 'Cannot open', filename
+ return []
+ lines = []
+ while 1:
+ line = fp.readline()
+ if not line: break
+ lines.append(line)
+ if not lines:
+ print 'Empty file', filename
+ return lines
diff --git a/lib/testall.py b/lib/testall.py
new file mode 100644
index 0000000..d9fd7e5
--- /dev/null
+++ b/lib/testall.py
@@ -0,0 +1,416 @@
+# Module 'testall'
+#
+# Python test set, should exercise:
+# - all lexical and grammatical constructs
+# - all opcodes from "opcode.h"
+# - all operations on all object types
+# - all builtin functions
+# Ideally also:
+# - all possible exception situations (Thank God we've got 'try')
+# - all boundary cases
+
+
+TestFailed = 'testall -- test failed' # Exception
+
+
+#########################################################
+# Part 1. Test all lexical and grammatical constructs.
+# This just tests whether the parser accepts them all.
+#########################################################
+
+print '1. Parser'
+
+print '1.1 Tokens'
+
+print '1.1.1 Backslashes'
+
+# Backslash means line continuation:
+x = 1 \
++ 1
+if x <> 2: raise TestFailed, 'backslash for line continuation'
+
+# Backslash does not means continuation in comments :\
+x = 0
+if x <> 0: raise TestFailed, 'backslash ending comment'
+
+print '1.1.2 Number formats'
+
+if 0xff <> 255: raise TestFailed, 'hex number'
+if 0377 <> 255: raise TestFailed, 'octal number'
+x = 3.14
+x = 0.314
+x = 3e14
+x = 3E14
+x = 3e-14
+
+print '1.2 Grammar'
+
+print 'single_input' # NEWLINE | simple_stmt | compound_stmt NEWLINE
+# XXX can't test in a script -- this rule is only used when interactive
+
+print 'file_input' # (NEWLINE | stmt)* ENDMARKER
+# Being tested as this very moment this very module
+
+print 'expr_input' # testlist NEWLINE
+# XXX Hard to test -- used only in calls to input()
+
+print 'eval_input' # testlist ENDMARKER
+x = eval('1, 0 or 1')
+
+print 'funcdef' # 'def' NAME parameters ':' suite
+### parameters: '(' [fplist] ')'
+### fplist: fpdef (',' fpdef)*
+### fpdef: NAME | '(' fplist ')'
+def f1(): pass
+def f2(one_argument): pass
+def f3(two, arguments): pass
+def f4(two, (compound, (arguments))): pass
+
+### stmt: simple_stmt | compound_stmt
+### simple_stmt: expr_stmt | print_stmt | pass_stmt | del_stmt | flow_stmt | import_stmt
+# Tested below
+
+print 'expr_stmt' # (exprlist '=')* exprlist NEWLINE
+1
+1, 2, 3
+x = 1
+x = 1, 2, 3
+x = y = z = 1, 2, 3
+x, y, z = 1, 2, 3
+abc = a, b, c = x, y, z = xyz = 1, 2, (3, 4)
+# NB these variables are deleted below
+
+print 'print_stmt' # 'print' (test ',')* [test] NEWLINE
+print 1, 2, 3
+print 1, 2, 3,
+print
+print 0 or 1, 0 or 1,
+print 0 or 1
+
+print 'del_stmt' # 'del' exprlist NEWLINE
+del abc
+del x, y, (z, xyz)
+
+print 'pass_stmt' # 'pass' NEWLINE
+pass
+
+print 'flow_stmt' # break_stmt | return_stmt | raise_stmt
+# Tested below
+
+print 'break_stmt' # 'break' NEWLINE
+while 1: break
+
+print 'return_stmt' # 'return' [testlist] NEWLINE
+def g1(): return
+def g2(): return 1
+g1()
+x = g2()
+
+print 'raise_stmt' # 'raise' expr [',' expr] NEWLINE
+try: raise RuntimeError, 'just testing'
+except RuntimeError: pass
+try: raise KeyboardInterrupt
+except KeyboardInterrupt: pass
+
+print 'import_stmt' # 'import' NAME (',' NAME)* NEWLINE | 'from' NAME 'import' ('*' | NAME (',' NAME)*) NEWLINE
+[1]
+import sys
+[2]
+import time, math
+[3]
+from time import sleep
+[4]
+from math import *
+[5]
+from sys import modules, path
+[6]
+
+### compound_stmt: if_stmt | while_stmt | for_stmt | try_stmt | funcdef | classdef
+# Tested below
+
+print 'if_stmt' # 'if' test ':' suite ('elif' test ':' suite)* ['else' ':' suite]
+if 1: pass
+if 1: pass
+else: pass
+if 0: pass
+elif 0: pass
+if 0: pass
+elif 0: pass
+elif 0: pass
+elif 0: pass
+else: pass
+
+print 'while_stmt' # 'while' test ':' suite ['else' ':' suite]
+while 0: pass
+while 0: pass
+else: pass
+
+print 'for_stmt' # 'for' exprlist 'in' exprlist ':' suite ['else' ':' suite]
+[1]
+for i in 1, 2, 3: pass
+[2]
+for i, j, k in (): pass
+else: pass
+[3]
+
+print 'try_stmt' # 'try' ':' suite (except_clause ':' suite)* ['finally' ':' suite]
+### except_clause: 'except' [expr [',' expr]]
+try: pass
+try: 1/0
+except RuntimeError: pass
+try: 1/0
+except EOFError: pass
+except TypeError, msg: pass
+except RuntimeError, msg: pass
+except: pass
+try: pass
+finally: pass
+try: 1/0
+except: pass
+finally: pass
+
+print 'suite' # simple_stmt | NEWLINE INDENT NEWLINE* (stmt NEWLINE*)+ DEDENT
+if 1: pass
+if 1:
+ pass
+if 1:
+ #
+ #
+ #
+ pass
+ pass
+ #
+ pass
+ #
+
+print 'test' # and_test ('or' and_test)*
+### and_test: not_test ('and' not_test)*
+### not_test: 'not' not_test | comparison
+### comparison: expr (comp_op expr)*
+### comp_op: '<'|'>'|'='|'>' '='|'<' '='|'<' '>'|'in'|'not' 'in'|'is'|'is' 'not'
+if 1: pass
+if 1 = 1: pass
+if 1 < 1 > 1 = 1 >= 1 <= 1 <> 1 in 1 not in 1 is 1 is not 1: pass
+if not 1 = 1 = 1: pass
+if not 1 = 1 and 1 and 1: pass
+if 1 and 1 or 1 and 1 and 1 or not 1 = 1 = 1 and 1: pass
+
+print 'expr' # term (('+'|'-') term)*
+x = 1
+x = 1 + 1
+x = 1 - 1 - 1
+x = 1 - 1 + 1 - 1 + 1
+
+print 'term' # factor (('*'|'/'|'%') factor)*
+x = 1 * 1
+x = 1 / 1
+x = 1 % 1
+x = 1 / 1 * 1 % 1
+
+print 'factor' # ('+'|'-') factor | atom trailer*
+### trailer: '(' [testlist] ')' | '[' subscript ']' | '.' NAME
+### subscript: expr | [expr] ':' [expr]
+x = +1
+x = -1
+x = 1
+c = sys.path[0]
+x = time.time()
+x = sys.modules['time'].time()
+a = '01234'
+c = a[0]
+c = a[0:5]
+c = a[:5]
+c = a[0:]
+c = a[:]
+c = a[-5:]
+c = a[:-1]
+c = a[-4:-3]
+
+print 'atom' # '(' [testlist] ')' | '[' [testlist] ']' | '{' '}' | '`' testlist '`' | NAME | NUMBER | STRING
+x = (1)
+x = (1 or 2 or 3)
+x = (1 or 2 or 3, 2, 3)
+x = []
+x = [1]
+x = [1 or 2 or 3]
+x = [1 or 2 or 3, 2, 3]
+x = []
+x = {}
+x = `x`
+x = x
+x = 'x'
+x = 123
+
+### exprlist: expr (',' expr)* [',']
+### testlist: test (',' test)* [',']
+# These have been exercised enough above
+
+print 'classdef' # 'class' NAME parameters ['=' baselist] ':' suite
+### baselist: atom arguments (',' atom arguments)*
+### arguments: '(' [testlist] ')'
+class B(): pass
+class C1() = B(): pass
+class C2() = B(): pass
+class D() = C1(), C2(), B(): pass
+class C():
+ def meth1(self): pass
+ def meth2(self, arg): pass
+ def meth3(self, (a1, a2)): pass
+
+
+#########################################################
+# Part 2. Test all opcodes from "opcode.h"
+#########################################################
+
+print '2. Opcodes'
+print 'XXX Not yet fully implemented'
+
+print '2.1 try inside for loop'
+n = 0
+for i in range(10):
+ n = n+i
+ try: 1/0
+ except NameError: pass
+ except RuntimeError: pass
+ except TypeError: pass
+ finally: pass
+ try: pass
+ except: pass
+ try: pass
+ finally: pass
+ n = n+i
+if n <> 90:
+ raise TestFailed, 'try inside for'
+
+
+#########################################################
+# Part 3. Test all operations on all object types
+#########################################################
+
+print '3. Object types'
+print 'XXX Not yet implemented'
+
+
+#########################################################
+# Part 4. Test all built-in functions
+#########################################################
+
+print '4. Built-in functions'
+
+print 'abs'
+if abs(0) <> 0: raise TestFailed, 'abs(0)'
+if abs(1234) <> 1234: raise TestFailed, 'abs(1234)'
+if abs(-1234) <> 1234: raise TestFailed, 'abs(-1234)'
+if abs(0.0) <> 0.0: raise TestFailed, 'abs(0.0)'
+if abs(3.14) <> 3.14: raise TestFailed, 'abs(3.14)'
+if abs(-3.14) <> 3.14: raise TestFailed, 'abs(-3.14)'
+
+print 'dir'
+if 'x' not in dir(): raise TestFailed, 'dir()'
+if 'modules' not in dir(sys): raise TestFailed, 'dir(sys)'
+
+print 'divmod'
+if divmod(12, 7) <> (1, 5): raise TestFailed, 'divmod(12, 7)'
+if divmod(-12, 7) <> (-2, 2): raise TestFailed, 'divmod(-12, 7)'
+if divmod(12, -7) <> (-2, -2): raise TestFailed, 'divmod(12, -7)'
+if divmod(-12, -7) <> (1, -5): raise TestFailed, 'divmod(-12, -7)'
+
+print 'eval'
+if eval('1+1') <> 2: raise TestFailed, 'eval(\'1+1\')'
+
+print 'exec'
+exec('z=1+1\n')
+if z <> 2: raise TestFailed, 'exec(\'z=1+1\'\\n)'
+
+print 'float'
+if float(3.14) <> 3.14: raise TestFailed, 'float(3.14)'
+if float(314) <> 314.0: raise TestFailed, 'float(314)'
+
+print 'input'
+# Can't test in a script
+
+print 'int'
+if int(100) <> 100: raise TestFailed, 'int(100)'
+if int(3.14) <> 3: raise TestFailed, 'int(3.14)'
+
+print 'len'
+if len('123') <> 3: raise TestFailed, 'len(\'123\')'
+if len(()) <> 0: raise TestFailed, 'len(())'
+if len((1, 2, 3, 4)) <> 4: raise TestFailed, 'len((1, 2, 3, 4))'
+if len([1, 2, 3, 4]) <> 4: raise TestFailed, 'len([1, 2, 3, 4])'
+if len({}) <> 0: raise TestFailed, 'len({})'
+
+print 'min'
+if min('123123') <> '1': raise TestFailed, 'min(\'123123\')'
+if min(1, 2, 3) <> 1: raise TestFailed, 'min(1, 2, 3)'
+if min((1, 2, 3, 1, 2, 3)) <> 1: raise TestFailed, 'min((1, 2, 3, 1, 2, 3))'
+if min([1, 2, 3, 1, 2, 3]) <> 1: raise TestFailed, 'min([1, 2, 3, 1, 2, 3])'
+
+print 'max'
+if max('123123') <> '3': raise TestFailed, 'max(\'123123\')'
+if max(1, 2, 3) <> 3: raise TestFailed, 'max(1, 2, 3)'
+if max((1, 2, 3, 1, 2, 3)) <> 3: raise TestFailed, 'max((1, 2, 3, 1, 2, 3))'
+if max([1, 2, 3, 1, 2, 3]) <> 3: raise TestFailed, 'max([1, 2, 3, 1, 2, 3])'
+
+print 'open'
+print 'NB! This test creates a file named "@test" in the current directory.'
+fp = open('@test', 'w')
+fp.write('The quick brown fox jumps over the lazy dog')
+fp.write('.\n')
+fp.write('Dear John\n')
+fp.write('XXX'*100)
+fp.write('YYY'*100)
+fp.close()
+del fp
+fp = open('@test', 'r')
+if fp.readline() <> 'The quick brown fox jumps over the lazy dog.\n':
+ raise TestFailed, 'readline()'
+if fp.readline(4) <> 'Dear': raise TestFailed, 'readline(4) # short'
+if fp.readline(100) <> ' John\n': raise TestFailed, 'readline(100)'
+if fp.read(300) <> 'XXX'*100: raise TestFailed, 'read(300)'
+if fp.read(1000) <> 'YYY'*100: raise TestFailed, 'read(1000) # truncate'
+fp.close()
+del fp
+
+print 'range'
+if range(3) <> [0, 1, 2]: raise TestFailed, 'range(3)'
+if range(1, 5) <> [1, 2, 3, 4]: raise TestFailed, 'range(1, 5)'
+if range(0) <> []: raise TestFailed, 'range(0)'
+if range(-3) <> []: raise TestFailed, 'range(-3)'
+if range(1, 10, 3) <> [1, 4, 7]: raise TestFailed, 'range(1, 10, 3)'
+if range(5, -5, -3) <> [5, 2, -1, -4]: raise TestFailed, 'range(5, -5, -3)'
+
+print 'raw_input'
+savestdin = sys.stdin
+try:
+ sys.stdin = open('@test', 'r')
+ if raw_input() <> 'The quick brown fox jumps over the lazy dog.':
+ raise TestFailed, 'raw_input()'
+ if raw_input('testing\n') <> 'Dear John':
+ raise TestFailed, 'raw_input(\'testing\\n\')'
+finally:
+ sys.stdin = savestdin
+
+print 'reload'
+import string
+reload(string)
+
+print 'type'
+if type('') <> type('123') or type('') = type(()):
+ raise TestFailed, 'type()'
+
+
+print 'Passed all tests.'
+
+try:
+ import mac
+ unlink = mac.unlink
+except NameError:
+ try:
+ import posix
+ unlink = posix.unlink
+ except NameError:
+ pass
+
+unlink('@test')
+print 'Unlinked @test'
diff --git a/lib/textwin.py b/lib/textwin.py
new file mode 100644
index 0000000..d12342f
--- /dev/null
+++ b/lib/textwin.py
@@ -0,0 +1,119 @@
+# Module 'textwin'
+
+# Text windows, a subclass of gwin
+
+import stdwin
+import stdwinsupport
+import gwin
+
+S = stdwinsupport # Shorthand
+
+
+def fixsize(w):
+ docwidth, docheight = w.text.getrect()[1]
+ winheight = w.getwinsize()[1]
+ if winheight > docheight: docheight = winheight
+ w.setdocsize(0, docheight)
+ fixeditmenu(w)
+
+def cut(w, m, id):
+ s = w.text.getfocustext()
+ if s:
+ stdwin.setcutbuffer(0, s)
+ w.text.replace('')
+ fixsize(w)
+
+def copy(w, m, id):
+ s = w.text.getfocustext()
+ if s:
+ stdwin.setcutbuffer(0, s)
+ fixeditmenu(w)
+
+def paste(w, m, id):
+ w.text.replace(stdwin.getcutbuffer(0))
+ fixsize(w)
+
+def addeditmenu(w):
+ m = w.editmenu = w.menucreate('Edit')
+ m.action = []
+ m.additem('Cut', 'X')
+ m.action.append(cut)
+ m.additem('Copy', 'C')
+ m.action.append(copy)
+ m.additem('Paste', 'V')
+ m.action.append(paste)
+
+def fixeditmenu(w):
+ m = w.editmenu
+ f = w.text.getfocus()
+ can_copy = (f[0] < f[1])
+ m.enable(1, can_copy)
+ if not w.readonly:
+ m.enable(0, can_copy)
+ m.enable(2, (stdwin.getcutbuffer(0) <> ''))
+
+def draw(w, area): # Draw method
+ w.text.draw(area)
+
+def size(w, newsize): # Size method
+ w.text.move((0, 0), newsize)
+ fixsize(w)
+
+def close(w): # Close method
+ del w.text # Break circular ref
+ gwin.close(w)
+
+def char(w, c): # Char method
+ w.text.replace(c)
+ fixsize(w)
+
+def backspace(w): # Backspace method
+ void = w.text.event(S.we_command, w, S.wc_backspace)
+ fixsize(w)
+
+def arrow(w, detail): # Arrow method
+ w.text.arrow(detail)
+ fixeditmenu(w)
+
+def mdown(w, detail): # Mouse down method
+ void = w.text.event(S.we_mouse_down, w, detail)
+ fixeditmenu(w)
+
+def mmove(w, detail): # Mouse move method
+ void = w.text.event(S.we_mouse_move, w, detail)
+
+def mup(w, detail): # Mouse up method
+ void = w.text.event(S.we_mouse_up, w, detail)
+ fixeditmenu(w)
+
+def activate(w): # Activate method
+ fixeditmenu(w)
+
+def open(title, str): # Display a string in a window
+ w = gwin.open(title)
+ w.readonly = 0
+ w.text = w.textcreate((0, 0), w.getwinsize())
+ w.text.replace(str)
+ w.text.setfocus(0, 0)
+ addeditmenu(w)
+ fixsize(w)
+ w.draw = draw
+ w.size = size
+ w.close = close
+ w.mdown = mdown
+ w.mmove = mmove
+ w.mup = mup
+ w.char = char
+ w.backspace = backspace
+ w.arrow = arrow
+ w.activate = activate
+ return w
+
+def open_readonly(title, str): # Same with char input disabled
+ w = open(title, str)
+ w.readonly = 1
+ w.char = w.backspace = gwin.nop
+ # Disable Cut and Paste menu item; leave Copy alone
+ w.editmenu.enable(0, 0)
+ w.editmenu.enable(2, 0)
+ return w
diff --git a/lib/util.py b/lib/util.py
new file mode 100644
index 0000000..0b7778f
--- /dev/null
+++ b/lib/util.py
@@ -0,0 +1,30 @@
+# Module 'util' -- some useful functions that don't fit elsewhere
+
+
+# Remove an item from a list.
+# No complaints if it isn't in the list at all.
+# If it occurs more than once, remove the first occurrence.
+#
+def remove(item, list):
+ for i in range(len(list)):
+ if list[i] = item:
+ del list[i]
+ break
+
+
+# Return a string containing a file's contents.
+#
+def readfile(fn):
+ return readopenfile(open(fn, 'r'))
+
+
+# Read an open file until EOF.
+#
+def readopenfile(fp):
+ BUFSIZE = 512*8
+ data = ''
+ while 1:
+ buf = fp.read(BUFSIZE)
+ if not buf: break
+ data = data + buf
+ return data
diff --git a/lib/whrandom.py b/lib/whrandom.py
new file mode 100644
index 0000000..ee8dc67
--- /dev/null
+++ b/lib/whrandom.py
@@ -0,0 +1,74 @@
+# WICHMANN-HILL RANDOM NUMBER GENERATOR
+#
+# Wichmann, B. A. & Hill, I. D. (1982)
+# Algorithm AS 183:
+# An efficient and portable pseudo-random number generator
+# Applied Statistics 31 (1982) 188-190
+#
+# see also:
+# Correction to Algorithm AS 183
+# Applied Statistics 33 (1984) 123
+#
+# McLeod, A. I. (1985)
+# A remark on Algorithm AS 183
+# Applied Statistics 34 (1985),198-200
+#
+#
+# USE:
+# whrandom.random() yields double precision random numbers
+# uniformly distributed between 0 and 1.
+#
+# whrandom.seed() must be called before whrandom.random()
+# to seed the generator
+
+
+# Translated by Guido van Rossum from C source provided by
+# Adrian Baddeley.
+
+
+# The seed
+#
+_seed = [0, 0, 0]
+
+
+# Set the seed
+#
+def seed(x, y, z):
+ _seed[:] = [x, y, z]
+
+
+# Return the next random number in the range [0.0 .. 1.0)
+#
+def random():
+ from math import floor # floor() function
+ #
+ [x, y, z] = _seed
+ x = 171 * (x % 177) - 2 * (x/177)
+ y = 172 * (y % 176) - 35 * (y/176)
+ z = 170 * (z % 178) - 63 * (z/178)
+ #
+ if x < 0: x = x + 30269
+ if y < 0: y = y + 30307
+ if z < 0: z = z + 30323
+ #
+ _seed[:] = [x, y, z]
+ #
+ term = float(x)/30269.0 + float(y)/30307.0 + float(z)/30323.0
+ rand = term - floor(term)
+ #
+ if rand >= 1.0: rand = 0.0 # floor() inaccuracy?
+ #
+ return rand
+
+
+# Initialize from the current time
+#
+def init():
+ import time
+ t = time.time()
+ seed(t%256, t/256%256, t/65536%256)
+
+
+# Make sure the generator is preset to a nonzero value
+#
+init()
diff --git a/lib/zmod.py b/lib/zmod.py
new file mode 100644
index 0000000..3b38df9
--- /dev/null
+++ b/lib/zmod.py
@@ -0,0 +1,94 @@
+# module 'zmod'
+
+# Compute properties of mathematical "fields" formed by taking
+# Z/n (the whole numbers modulo some whole number n) and an
+# irreducible polynomial (i.e., a polynomial with only complex zeros),
+# e.g., Z/5 and X**2 + 2.
+#
+# The field is formed by taking all possible linear combinations of
+# a set of d base vectors (where d is the degree of the polynomial).
+#
+# Note that this procedure doesn't yield a field for all combinations
+# of n and p: it may well be that some numbers have more than one
+# inverse and others have none. This is what we check.
+#
+# Remember that a field is a ring where each element has an inverse.
+# A ring has commutative addition and multiplication, a zero and a one:
+# 0*x = x*0 = 0, 0+x = x+0 = x, 1*x = x*1 = x. Also, the distributive
+# property holds: a*(b+c) = a*b + b*c.
+# (XXX I forget if this is an axiom or follows from the rules.)
+
+import poly
+
+
+# Example N and polynomial
+
+N = 5
+P = poly.plus(poly.one(0, 2), poly.one(2, 1)) # 2 + x**2
+
+
+# Return x modulo y. Returns >= 0 even if x < 0.
+
+def mod(x, y):
+ return divmod(x, y)[1]
+
+
+# Normalize a polynomial modulo n and modulo p.
+
+def norm(a, n, p):
+ a = poly.modulo(a, p)
+ a = a[:]
+ for i in range(len(a)): a[i] = mod(a[i], n)
+ a = poly.normalize(a)
+ return a
+
+
+# Make a list of all n^d elements of the proposed field.
+
+def make_all(mat):
+ all = []
+ for row in mat:
+ for a in row:
+ all.append(a)
+ return all
+
+def make_elements(n, d):
+ if d = 0: return [poly.one(0, 0)]
+ sub = make_elements(n, d-1)
+ all = []
+ for a in sub:
+ for i in range(n):
+ all.append(poly.plus(a, poly.one(d-1, i)))
+ return all
+
+def make_inv(all, n, p):
+ x = poly.one(1, 1)
+ inv = []
+ for a in all:
+ inv.append(norm(poly.times(a, x), n, p))
+ return inv
+
+def checkfield(n, p):
+ all = make_elements(n, len(p)-1)
+ inv = make_inv(all, n, p)
+ all1 = all[:]
+ inv1 = inv[:]
+ all1.sort()
+ inv1.sort()
+ if all1 = inv1: print 'BINGO!'
+ else:
+ print 'Sorry:', n, p
+ print all
+ print inv
+
+def rj(s, width):
+ if type(s) <> type(''): s = `s`
+ n = len(s)
+ if n >= width: return s
+ return ' '*(width - n) + s
+
+def lj(s, width):
+ if type(s) <> type(''): s = `s`
+ n = len(s)
+ if n >= width: return s
+ return s + ' '*(width - n)
diff --git a/python.man b/python.man
new file mode 100644
index 0000000..f222b55
--- /dev/null
+++ b/python.man
@@ -0,0 +1,79 @@
+.TH PYTHON "19 February 1991"
+.SH NAME
+python \(en an extensible interpreted programming language
+.SH SYNOPSIS
+.B python
+[
+.I X11-options
+] [
+.I script
+[
+.I arguments
+] ]
+.SH DESCRIPTION
+Python is an extensible interpreted programming language that
+combines remarkable power with very clear syntax.
+For an introduction to programming in Python you are referred to the
+Python Tutorial.
+.PP
+The interpreter operates somewhat like the UNIX shell: when called with
+standard input connected to a tty device, it reads and executes commands
+interactively until an EOF is read;
+when called with a file name argument or with a file as standard
+input, it reads and executes a
+.I script
+from that file.
+If available, the script name and additional arguments thereafter are
+passed to the script in the variable
+.I sys.argv ,
+which is a list of strings.
+In interactive mode, the primary prompt is `>>>'; the second prompt
+(which appears when a command is not complete) is `...'.
+.SH FILES AND DIRECTORIES
+.IP /usr/local/lib/python
+This might be the directory containing the library of standard modules.
+(Installation-dependent.)
+.SH ENVIRONMENT VARIABLES
+.IP PYTHONPATH
+Sets the search path for module files.
+The format is the same as the shell's $PATH: one or more directory
+pathnames separated by colons.
+Non-existant directories are silently ignored.
+The default search path is installation dependent, but always begins
+with `.', (for example,
+.I .:/usr/local/lib/python ).
+.SH SEE ALSO
+Python Tutorial
+.br
+Python Library Reference
+.SH AUTHOR
+.nf
+Guido van Rossum
+CWI, dept. CST
+Kruislaan 413
+1098 SJ Amsterdam
+The Netherlands
+.PP
+.fi
+.SH COPYRIGHT
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+.IP " "
+All Rights Reserved
+.PP
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
diff --git a/shar/python-0.9.1-01-21.shar b/shar/python-0.9.1-01-21.shar
new file mode 100644
index 0000000..75c124e
--- /dev/null
+++ b/shar/python-0.9.1-01-21.shar
@@ -0,0 +1,1952 @@
+: This is a shell archive.
+: Extract with 'sh this_file'.
+: Extract this part first since it makes all directories
+echo 'Start of pack.out, part 01 out of 21:'
+echo -n 'Making directories ... '
+err="no"
+test -d 'demo' || mkdir 'demo' || err="yes"
+test -d 'demo/scripts' || mkdir 'demo/scripts' || err="yes"
+test -d 'demo/sgi' || mkdir 'demo/sgi' || err="yes"
+test -d 'demo/sgi/audio' || mkdir 'demo/sgi/audio' || err="yes"
+test -d 'demo/sgi/audio_stdwin' || mkdir 'demo/sgi/audio_stdwin' || err="yes"
+test -d 'demo/sgi/gl' || mkdir 'demo/sgi/gl' || err="yes"
+test -d 'demo/sgi/gl_panel' || mkdir 'demo/sgi/gl_panel' || err="yes"
+test -d 'demo/sgi/gl_panel/apanel' || mkdir 'demo/sgi/gl_panel/apanel' || err="yes"
+test -d 'demo/sgi/gl_panel/flying' || mkdir 'demo/sgi/gl_panel/flying' || err="yes"
+test -d 'demo/sgi/gl_panel/nurbs' || mkdir 'demo/sgi/gl_panel/nurbs' || err="yes"
+test -d 'demo/sgi/gl_panel/twoview' || mkdir 'demo/sgi/gl_panel/twoview' || err="yes"
+test -d 'demo/stdwin' || mkdir 'demo/stdwin' || err="yes"
+test -d 'doc' || mkdir 'doc' || err="yes"
+test -d 'lib' || mkdir 'lib' || err="yes"
+test -d 'src' || mkdir 'src' || err="yes"
+echo 'done'
+if test "$err" = "yes"
+then echo "didn't make it."
+fi
+if test -s 'README'
+then echo '*** I will not over-write existing file README'
+else
+echo 'x - README'
+sed 's/^X//' > 'README' << 'EOF'
+XThis is Python, an extensible interpreted programming language that
+Xcombines remarkable power with very clear syntax.
+X
+XThis is version 0.9 (the first beta release), patchlevel 1.
+X
+XPython can be used instead of shell, Awk or Perl scripts, to write
+Xprototypes of real applications, or as an extension language of large
+Xsystems, you name it. There are built-in modules that interface to
+Xthe operating system and to various window systems: X11, the Mac
+Xwindow system (you need STDWIN for these two), and Silicon Graphics'
+XGL library. It runs on most modern versions of UNIX, on the Mac, and
+XI wouldn't be surprised if it ran on MS-DOS unchanged. I developed it
+Xmostly on an SGI IRIS workstation (using IRIX 3.1 and 3.2) and on the
+XMac, but have tested it also on SunOS (4.1) and BSD 4.3 (tahoe).
+X
+XBuilding and installing Python is easy (but do read the Makefile).
+XA UNIX style manual page and extensive documentation (in LaTeX format)
+Xare provided. (In the beta release, the documentation is still under
+Xdevelopment.)
+X
+XPlease try it out and send me your comments (on anything -- the
+Xlanguage design, implementation, portability, installation,
+Xdocumentation) and the modules you wrote for it, to make the first
+Xreal release better. If you needed to hack the source to get it to
+Xcompile and run on a particular machine, send me the fixes -- I'll try
+Xto incorporate them into the next patch. If you can't get it to work
+Xat all, send me a *detailed* description of the problem and I may look
+Xinto it.
+X
+XIf you want to profit of the X11 or Mac window interface, you'll need
+XSTDWIN. This is a portable window system interface by the same
+Xauthor. The versions of STDWIN floating around on some archives are
+Xnot sufficiently up-to-date for use with Python. I will distribute
+Xthe latest and greatest STDWIN version at about the same time as Python.
+X
+XI am the author of Python:
+X
+X Guido van Rossum
+X CWI, dept. CST
+X Kruislaan 413
+X 1098 SJ Amsterdam
+X The Netherlands
+X
+X
+XThe Python source is copyrighted, but you can freely use and copy it
+Xas long as you don't change or remove the copyright:
+X
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+EOF
+fi
+if test -s 'python.man'
+then echo '*** I will not over-write existing file python.man'
+else
+echo 'x - python.man'
+sed 's/^X//' > 'python.man' << 'EOF'
+X.TH PYTHON "19 February 1991"
+X.SH NAME
+Xpython \(en an extensible interpreted programming language
+X.SH SYNOPSIS
+X.B python
+X[
+X.I X11-options
+X] [
+X.I script
+X[
+X.I arguments
+X] ]
+X.SH DESCRIPTION
+XPython is an extensible interpreted programming language that
+Xcombines remarkable power with very clear syntax.
+XFor an introduction to programming in Python you are referred to the
+XPython Tutorial.
+X.PP
+XThe interpreter operates somewhat like the UNIX shell: when called with
+Xstandard input connected to a tty device, it reads and executes commands
+Xinteractively until an EOF is read;
+Xwhen called with a file name argument or with a file as standard
+Xinput, it reads and executes a
+X.I script
+Xfrom that file.
+XIf available, the script name and additional arguments thereafter are
+Xpassed to the script in the variable
+X.I sys.argv ,
+Xwhich is a list of strings.
+XIn interactive mode, the primary prompt is `>>>'; the second prompt
+X(which appears when a command is not complete) is `...'.
+X.SH FILES AND DIRECTORIES
+X.IP /usr/local/lib/python
+XThis might be the directory containing the library of standard modules.
+X(Installation-dependent.)
+X.SH ENVIRONMENT VARIABLES
+X.IP PYTHONPATH
+XSets the search path for module files.
+XThe format is the same as the shell's $PATH: one or more directory
+Xpathnames separated by colons.
+XNon-existant directories are silently ignored.
+XThe default search path is installation dependent, but always begins
+Xwith `.', (for example,
+X.I .:/usr/local/lib/python ).
+X.SH SEE ALSO
+XPython Tutorial
+X.br
+XPython Library Reference
+X.SH AUTHOR
+X.nf
+XGuido van Rossum
+XCWI, dept. CST
+XKruislaan 413
+X1098 SJ Amsterdam
+XThe Netherlands
+X.PP
+X.fi
+X.SH COPYRIGHT
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X.IP " "
+XAll Rights Reserved
+X.PP
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+EOF
+fi
+if test -s 'demo/sgi/gl_panel/nurbs/nurbs.py'
+then echo '*** I will not over-write existing file demo/sgi/gl_panel/nurbs/nurbs.py'
+else
+echo 'x - demo/sgi/gl_panel/nurbs/nurbs.py'
+sed 's/^X//' > 'demo/sgi/gl_panel/nurbs/nurbs.py' << 'EOF'
+X#! /ufs/guido/bin/sgi/python
+X
+X# Fancy NURBS demo. Require Z buffer and Panel Library.
+X
+Xfrom gl import *
+Xfrom GL import *
+Xfrom DEVICE import *
+Xfrom nurbsdata import *
+Ximport panel
+X
+X#
+X# flags = trim_f, invis_f, cpvis_f, tpvis_f, axvis_f, freeze_f
+X#
+XTRIM = 0
+XVIS = 1
+XCPVIS = 2
+XTPVIS = 3
+XAXVIS = 4
+XFREEZE = 5
+Xflags = [0, 1, 0, 0, 0, 0]
+X
+Xdef draw_axis () :
+X cpack (0x0)
+X zero = (0.0, 0.0, 0.0)
+X #
+X one = (1.0, 0.0, 0.0)
+X smallline (zero, one)
+X cmov (1.0, 0.0, 0.0)
+X charstr ('x')
+X #
+X one = (0.0, 1.0, 0.0)
+X smallline (zero, one)
+X cmov (0.0, 1.0, 0.0)
+X charstr ('y')
+X #
+X one = (0.0, 0.0, 1.0)
+X smallline (zero, one)
+X cmov (0.0, 0.0, 1.0)
+X charstr ('z')
+X
+XDELTA = 0.1
+X
+Xdef cross (p) :
+X p0 = [p[0], p[1], p[2]]
+X p1 = [p[0], p[1], p[2]]
+X for i in range (0, 3) :
+X p0[i] = p0[i] + DELTA
+X p1[i] = p1[i] - DELTA
+X smallline (p0, p1)
+X p0[i] = p0[i] - DELTA
+X p1[i] = p1[i] + DELTA
+X
+Xdef smallline (p0, p1) :
+X bgnline ()
+X v3f (p0)
+X v3f (p1)
+X endline ()
+X
+Xdef draw_pts (pnts, color) :
+X linewidth (2)
+X cpack (color)
+X for i in pnts :
+X cross (i)
+X
+Xdef init_windows():
+X foreground()
+X wid = winopen('nurbs')
+X wintitle('NURBS Surface')
+X doublebuffer()
+X RGBmode()
+X gconfig()
+X lsetdepth(0x000, 0x7fffff)
+X zbuffer( TRUE )
+X
+Xdef init_view():
+X mmode(MPROJECTION)
+X ortho( -5., 5., -5., 5., -5., 5. )
+X #
+X mmode(MVIEWING)
+X loadmatrix(idmat)
+X #
+X lmbind(MATERIAL, 1)
+X
+Xdef set_scene(flags):
+X #
+X lmbind(MATERIAL, 0)
+X RGBcolor(150,150,150)
+X lmbind(MATERIAL, 1)
+X clear()
+X zclear()
+X #
+X if not flags[FREEZE] :
+X rotate( 100, 'y' )
+X rotate( 100, 'z' )
+X
+Xdef draw_trim_surface(flags):
+X pnts = ctlpoints
+X if flags[VIS] :
+X bgnsurface()
+X nurbssurface(surfknots,surfknots,pnts,ORDER,ORDER,N_XYZ)
+X if flags[TRIM]:
+X bgntrim()
+X nurbscurve(trimknots,trimpoints,ORDER-1,N_STW)
+X endtrim()
+X endsurface()
+X #
+X if flags[CPVIS] :
+X for i in pnts :
+X draw_pts (i, RED)
+X #
+X if flags[TPVIS] :
+X tpts = trimpoints
+X draw_pts (tpts, YELLOW)
+X #
+X if flags[AXVIS] :
+X draw_axis ()
+X #
+X swapbuffers()
+X
+Xdef make_lights():
+X lmdef(DEFLMODEL,1,[])
+X lmdef(DEFLIGHT,1,[])
+X #
+X # define material #1
+X #
+X a = []
+X a = a + [EMISSION, 0.0, 0.0, 0.0]
+X a = a + [AMBIENT, 0.1, 0.1, 0.1]
+X a = a + [DIFFUSE, 0.6, 0.3, 0.3]
+X a = a + [SPECULAR, 0.0, 0.6, 0.0]
+X a = a + [SHININESS, 2.0]
+X a = a + [LMNULL]
+X lmdef(DEFMATERIAL, 1, a)
+X #
+X # turn on lighting
+X #
+X lmbind(LIGHT0, 1)
+X lmbind(LMODEL, 1)
+X
+Xdef main():
+X init_windows()
+X make_lights()
+X init_view()
+X #
+X panel.needredraw()
+X panels = panel.defpanellist('nurbs.s')
+X p = panels[0]
+X #
+X def cbtrim (a) :
+X flags[TRIM:TRIM+1] = [int (a.val)]
+X p.trim.upfunc = cbtrim
+X #
+X def cbquit (a) :
+X import sys
+X sys.exit (1)
+X p.quit.upfunc = cbquit
+X #
+X def cbmotion (a) :
+X flags[FREEZE:FREEZE+1] = [int (a.val)]
+X p.motion.upfunc = cbmotion
+X #
+X def cbxyzaxis (a) :
+X flags[AXVIS:AXVIS+1] = [int (a.val)]
+X p.xyzaxis.upfunc = cbxyzaxis
+X #
+X def cbtrimpnts (a) :
+X flags[TPVIS:TPVIS+1] = [int (a.val)]
+X p.trimpnts.upfunc = cbtrimpnts
+X #
+X def cbcntlpnts (a) :
+X flags[CPVIS:CPVIS+1] = [int (a.val)]
+X p.cntlpnts.upfunc = cbcntlpnts
+X #
+X def cbnurb (a) :
+X flags[VIS:VIS+1] = [int (a.val)]
+X p.nurb.upfunc = cbnurb
+X #
+X set_scene(flags)
+X setnurbsproperty( N_ERRORCHECKING, 1.0 )
+X setnurbsproperty( N_PIXEL_TOLERANCE, 50.0 )
+X draw_trim_surface(flags)
+X #
+X while 1:
+X act = panel.dopanel()
+X #
+X wid = panel.userredraw ()
+X if wid :
+X winset (wid)
+X reshapeviewport()
+X set_scene(flags)
+X draw_trim_surface(flags)
+X #
+X set_scene(flags)
+X draw_trim_surface(flags)
+X
+Xmain()
+EOF
+chmod +x 'demo/sgi/gl_panel/nurbs/nurbs.py'
+fi
+if test -s 'doc/tut.tex'
+then echo '*** I will not over-write existing file doc/tut.tex'
+else
+echo 'x - doc/tut.tex'
+sed 's/^X//' > 'doc/tut.tex' << 'EOF'
+X% Format this file with latex.
+X
+X%\documentstyle[garamond,11pt,myformat]{article}
+X\documentstyle[11pt,myformat]{article}
+X
+X\title{\bf
+X Python Tutorial \\
+X (DRAFT)
+X}
+X
+X\author{
+X Guido van Rossum \\
+X Dept. CST, CWI, Kruislaan 413 \\
+X 1098 SJ Amsterdam, The Netherlands \\
+X E-mail: {\tt [email protected]}
+X}
+X
+X\begin{document}
+X
+X\pagenumbering{roman}
+X
+X\maketitle
+X
+X\begin{abstract}
+X
+X\noindent
+X\Python\ is a simple, yet powerful programming language that bridges the
+Xgap between C and shell programming, and is thus ideally suited for rapid
+Xprototyping.
+XIts syntax is put together from constructs borrowed from a variety of other
+Xlanguages; most prominent are influences from ABC, C, Modula-3 and Icon.
+X
+XThe \Python\ interpreter is easily extended with new functions and data
+Xtypes implemented in C.
+X\Python\ is also suitable as an extension language for highly
+Xcustomizable C applications such as editors or window managers.
+X
+X\Python\ is available for various operating systems, amongst which
+Xseveral flavors of \UNIX, Amoeba, and the Apple Macintosh O.S.
+X
+XThis tutorial introduces the reader informally to the basic concepts and
+Xfeatures of the \Python\ language and system.
+XIt helps to have a \Python\ interpreter handy for hands-on experience,
+Xbut as the examples are self-contained, the tutorial can be read
+Xoff-line as well.
+X
+XFor a description of standard objects and modules, see the Library
+XReference document.
+XThe Language Reference document (XXX not yet existing)
+Xgives a more formal reference to the language.
+X
+X\end{abstract}
+X
+X\pagebreak
+X
+X\tableofcontents
+X
+X\pagebreak
+X
+X\pagenumbering{arabic}
+X
+X\section{Whetting Your Appetite}
+X
+XIf you ever wrote a large shell script, you probably know this feeling:
+Xyou'd love to add yet another feature, but it's already so slow, and so
+Xbig, and so complicated; or the feature involves a system call or other
+Xfuncion that is only accessible from C \ldots
+XUsually the problem at hand isn't serious enough to warrant rewriting
+Xthe script in C; perhaps because the problem requires variable-length
+Xstrings or other data types (like sorted lists of file names) that
+Xare easy in the shell but lots of work to implement in C; or perhaps
+Xjust because you're not sufficiently familiar with C.
+X
+XIn all such cases, \Python\ is just the language for you.
+X\Python\ is simple to use, but it is a real programming language, offering
+Xmuch more structure and support for large programs than the shell has.
+XOn the other hand, it also offers much more error checking than C, and,
+Xbeing a
+X{\em very-high-level language},
+Xit has high-level data types built in, such as flexible arrays and
+Xdictionaries that would cost you days to implement efficiently in C.
+XBecause of its more general data types \Python\ is applicable to a
+Xmuch larger problem domain than
+X{\em Awk}
+Xor even
+X{\em Perl},
+Xyet most simple things are at least as easy in \Python\ as in those
+Xlanguages.
+X
+X\Python\ allows you to split up your program in modules that can be reused
+Xin other \Python\ programs.
+XIt comes with a large collection of standard modules that you can use as
+Xthe basis for your programs --- or as examples to start learning to
+Xprogram in \Python.
+XThere are also built-in modules that provide things like file I/O,
+Xsystem calls, and even a generic interface to window systems (STDWIN).
+X
+X\Python\ is an interpreted language, which saves you considerable time
+Xduring program development because no compilation and linking is
+Xnecessary.
+XThe interpreter can be used interactively, which makes it easy to
+Xexperiment with features of the language, to write throw-away programs,
+Xor to test functions during bottom-up program development.
+XIt is also a handy desk calculator.
+X
+X\Python\ allows writing very compact and readable programs.
+XPrograms written in \Python\ are typically much shorter than equivalent C
+Xprograms:
+XNo declarations are necessary (all type checking is
+Xdynamic); statement grouping is done by indentation instead of begin/end
+Xbrackets; and the high-level data types allow you to express complex
+Xoperations in a single statement.
+X
+X\Python\ is
+X{\em extensible}:
+Xif you know how to program in C it is easy to add a new built-in module
+Xto the interpreter, either to perform critical operations at maximum
+Xspeed, or to link \Python\ programs to libraries that may be only available
+Xin binary form (such as a vendor-specific graphics library).
+XOnce you are really hooked, you can link the \Python\ interpreter into an
+Xapplication written in C and use it as an extension or command language.
+X
+X\subsection{Where From Here}
+X
+XNow that you are all excited about \Python, you'll want to examine it in
+Xsome more detail.
+XSince the best introduction to a language is using it, you are invited
+Xhere to do so.
+X
+XIn the next section, the mechanics of using the interpreter are
+Xexplained.
+XThis is rather mundane information, but essential for trying out the
+Xexamples shown later.
+XThe rest of the tutorial introduces various features of the \Python\
+Xlanguage and system though examples, beginning with simple expressions,
+Xstatements and data types, through functions and modules, and finally
+Xtouching upon advanced concepts like exceptions and classes.
+X
+X\section{Using the Python Interpreter}
+X
+XThe \Python\ interpreter is usually installed as
+X{\tt /usr/local/python}
+Xon those machines where it is available; putting
+X{\tt /usr/local}
+Xin your \UNIX\ shell's search path makes it possible to start it by
+Xtyping the command
+X\bcode\begin{verbatim}
+Xpython
+X\end{verbatim}\ecode
+Xto the shell.
+XSince the choice of the directory where the interpreter lives is an
+Xinstallation option, other places instead of
+X{\tt /usr/local}
+Xare possible; check with your local \Python\ guru or system
+Xadministrator.%
+X\footnote{
+X At CWI, at the time of writing, the interpreter can be found in
+X the following places:
+X On the Amoeba Ultrix machines, use the standard path,
+X {\tt /usr/local/python}.
+X On the Sun file servers, use
+X {\tt /ufs/guido/bin/}{\em arch}{\tt /python},
+X where {\em arch} can be {\tt sgi} or {\tt sun4}.
+X On piring, use {\tt /userfs3/amoeba/bin/python}.
+X (If you can't find a binary advertised here, get in touch with me.)
+X}
+X
+XThe interpreter operates somewhat like the \UNIX\ shell: when called with
+Xstandard input connected to a tty device, it reads and executes commands
+Xinteractively; when called with a file name argument or with a file as
+Xstandard input, it reads and executes a
+X{\em script}
+Xfrom that file.%
+X\footnote{
+X There is a difference between ``{\tt python file}'' and
+X ``{\tt python $<$file}''. In the latter case {\tt input()} and
+X {\tt raw\_input()} are satisfied from {\em file}, which has
+X already been read until the end by the parser, so they will read
+X EOF immediately. In the former case (which is usually what
+X you want) they are satisfied from whatever file or device is
+X connected to standard input of the \Python\ interpreter.
+X}
+XIf available, the script name and additional arguments thereafter are
+Xpassed to the script in the variable
+X{\tt sys.argv},
+Xwhich is a list of strings.
+X
+XWhen standard input is a tty, the interpreter is said to be in
+X{\em interactive\ mode}.
+XIn this mode it prompts for the next command with the
+X{\em primary\ prompt},
+Xusually three greater-than signs ({\tt >>>}); for continuation lines
+Xit prompts with the
+X{\em secondary\ prompt},
+Xby default three dots ({\tt ...}).
+XTyping an EOF (Control-D) at the primary prompt causes the interpreter
+Xto exit with a zero exit status.
+X
+XWhen an error occurs in interactive mode, the interpreter prints a
+Xmessage and a stack trace and returns to the primary prompt; with input
+Xfrom a file, it exits with a nonzero exit status.
+X(Exceptions handled by an
+X{\tt except}
+Xclause in a
+X{\tt try}
+Xstatement are not errors in this context.)
+XSome errors are unconditionally fatal and cause an exit with a nonzero
+Xexit; this applies to internal inconsistencies and some cases of running
+Xout of memory.
+XAll error messages are written to the standard error stream; normal
+Xoutput from the executed commands is written to standard output.
+X
+XTyping an interrupt (normally Control-C or DEL) to the primary or
+Xsecondary prompt cancels the input and returns to the primary prompt.
+XTyping an interrupt while a command is being executed raises the
+X{\tt KeyboardInterrupt}
+Xexception, which may be handled by a
+X{\tt try}
+Xstatement.
+X
+XWhen a module named
+X{\tt foo}
+Xis imported, the interpreter searches for a file named
+X{\tt foo.py}
+Xin a list of directories specified by the environment variable
+X{\tt PYTHONPATH}.
+XIt has the same syntax as the \UNIX\ shell variable
+X{\tt PATH},
+Xi.e., a list of colon-separated directory names.
+XWhen
+X{\tt PYTHONPATH}
+Xis not set, an installation-dependent default path is used, usually
+X{\tt .:/usr/local/lib/python}.%
+X\footnote{
+X Modules are really searched in the list of directories given by
+X the variable {\tt sys.path} which is initialized from
+X {\tt PYTHONPATH} or from the installation-dependent default.
+X See the section on Standard Modules later.
+X}
+X
+XOn BSD'ish \UNIX\ systems, \Python\ scripts can be made directly executable,
+Xlike shell scripts, by putting the line
+X\bcode\begin{verbatim}
+X#! /usr/local/python
+X\end{verbatim}\ecode
+X(assuming that's the name of the interpreter) at the beginning of the
+Xscript and giving the file an executable mode.
+X(The
+X{\tt \#!}
+Xmust be the first two characters of the file.)
+X
+X\subsection{Interactive Input Editing and History Substitution}
+X
+XSome versions of the \Python\ interpreter support editing of the current
+Xinput line and history substitution, similar to facilities found in the
+XKorn shell and the GNU Bash shell.
+XThis is implemented using the
+X{\em GNU\ Readline}
+Xlibrary, which supports Emacs-style and vi-style editing.
+XThis library has its own documentation which I won't duplicate here;
+Xhowever, the basics are easily explained.
+X
+XIf supported,%
+X\footnote{
+X Perhaps the quickest check to see whether command line editing
+X is supported is typing Control-P to the first \Python\ prompt
+X you get. If it beeps, you have command line editing.
+X If not, you can skip the rest of this section.
+X}
+Xinput line editing is active whenever the interpreter prints a primary
+Xor secondary prompt.
+XThe current line can be edited using the conventional Emacs control
+Xcharacters.
+XThe most important of these are:
+XC-A (Control-A) moves the cursor to the beginning of the line, C-E to
+Xthe end, C-B moves it one position to the left, C-F to the right.
+XBackspace erases the character to the left of the cursor, C-D the
+Xcharacter to its right.
+XC-K kills (erases) the rest of the line to the right of the cursor, C-Y
+Xyanks back the last killed string.
+XC-underscore undoes the last change you made; it can be repeated for
+Xcumulative effect.
+X
+XHistory substitution works as follows.
+XAll non-empty input lines issued are saved in a history buffer,
+Xand when a new prompt is given you are positioned on a new line at the
+Xbottom of this buffer.
+XC-P moves one line up (back) in the history buffer, C-N moves one down.
+XAny line in the history buffer can be edited; an asterisk appears in
+Xfront of the prompt to mark a line as modified.
+XPressing the Return key passes the current line to the interpreter.
+XC-R starts an incremental reverse search; C-S starts a forward search.
+X
+XThe key bindings and some other parameters of the Readline library can
+Xbe customized by placing commands in an initialization file called
+X{\tt \$HOME/.initrc}.
+XKey bindings have the form
+X\bcode\begin{verbatim}
+Xkey-name: function-name
+X\end{verbatim}\ecode
+Xand options can be set with
+X\bcode\begin{verbatim}
+Xset option-name value
+X\end{verbatim}\ecode
+XExample:
+X\bcode\begin{verbatim}
+X# I prefer vi-style editing:
+Xset editing-mode vi
+X# Edit using a single line:
+Xset horizontal-scroll-mode On
+X# Rebind some keys:
+XMeta-h: backward-kill-word
+XControl-u: universal-argument
+X\end{verbatim}\ecode
+XNote that the default binding for TAB in \Python\ is to insert a TAB
+Xinstead of Readline's default filename completion function.
+XIf you insist, you can override this by putting
+X\bcode\begin{verbatim}
+XTAB: complete
+X\end{verbatim}\ecode
+Xin your
+X{\tt \$HOME/.inputrc}.
+X(Of course, this makes it hard to type indented continuation lines.)
+X
+XThis facility is an enormous step forward compared to previous versions of
+Xthe interpreter; however, some wishes are left:
+XIt would be nice if the proper indentation were suggested on
+Xcontinuation lines (the parser knows if an indent token is required
+Xnext).
+XThe completion mechanism might use the interpreter's symbol table.
+XA function to check (or even suggest) matching parentheses, quotes
+Xetc. would also be useful.
+X
+X\section{An Informal Introduction to Python}
+X
+XIn the following examples, input and output are distinguished by the
+Xpresence or absence of prompts ({\tt >>>} and {\tt ...}): to repeat the
+Xexample, you must type everything after the prompt, when the prompt
+Xappears; everything on lines that do not begin with a prompt is output
+Xfrom the interpreter.
+XNote that a secondary prompt on a line by itself in an example means you
+Xmust type a blank line; this is used to end a multi-line command.
+X
+X\subsection{Using Python as a Calculator}
+X
+XLet's try some simple \Python\ commands.
+XStart the interpreter and wait for the primary prompt,
+X{\tt >>>}.
+XThe interpreter acts as a simple calculator: you can type an expression
+Xat it and it will write the value.
+XExpression syntax is straightforward: the operators
+X{\tt +},
+X{\tt -},
+X{\tt *}
+Xand
+X{\tt /}
+Xwork just as in most other languages (e.g., Pascal or C); parentheses
+Xcan be used for grouping.
+XFor example:
+X\bcode\begin{verbatim}
+X>>> # This is a comment
+X>>> 2+2
+X4
+X>>>
+X>>> (50-5+5*6+25)/4
+X25
+X>>> # Division truncates towards zero:
+X>>> 7/3
+X2
+X>>>
+X\end{verbatim}\ecode
+XAs in C, the equal sign ({\tt =}) is used to assign a value to a variable.
+XThe value of an assignment is not written:
+X\bcode\begin{verbatim}
+X>>> width = 20
+X>>> height = 5*9
+X>>> width * height
+X900
+X>>>
+X\end{verbatim}\ecode
+XThere is some support for floating point, but you can't mix floating
+Xpoint and integral numbers in expression (yet):
+X\bcode\begin{verbatim}
+X>>> 10.0 / 3.3
+X3.0303030303
+X>>>
+X\end{verbatim}\ecode
+XBesides numbers, \Python\ can also manipulate strings, enclosed in single
+Xquotes:
+X\bcode\begin{verbatim}
+X>>> 'foo bar'
+X'foo bar'
+X>>> 'doesn\'t'
+X'doesn\'t'
+X>>>
+X\end{verbatim}\ecode
+XStrings are written inside quotes and with quotes and other funny
+Xcharacters escaped by backslashes, to show the precise value.
+X(There is also a way to write strings without quotes and escapes.)
+XStrings can be concatenated (glued together) with the
+X{\tt +}
+Xoperator, and repeated with~{\tt *}:
+X\bcode\begin{verbatim}
+X>>> word = 'Help' + 'A'
+X>>> word
+X'HelpA'
+X>>> '<' + word*5 + '>'
+X'<HelpAHelpAHelpAHelpAHelpA>'
+X>>>
+X\end{verbatim}\ecode
+XStrings can be subscripted; as in C, the first character of a string has
+Xsubscript 0.
+XThere is no separate character type; a character is simply a string of
+Xsize one.
+XAs in Icon, substrings can be specified with the
+X{\em slice}
+Xnotation: two subscripts (indices) separated by a colon.
+X\bcode\begin{verbatim}
+X>>> word[4]
+X'A'
+X>>> word[0:2]
+X'He'
+X>>> word[2:4]
+X'lp'
+X>>> # Slice indices have useful defaults:
+X>>> word[:2] # Take first two characters
+X'He'
+X>>> word[2:] # Drop first two characters
+X'lpA'
+X>>> # A useful invariant: s[:i] + s[i:] = s
+X>>> word[:3] + word[3:]
+X'HelpA'
+X>>>
+X\end{verbatim}\ecode
+XDegenerate cases are handled gracefully: an index that is too large is
+Xreplaced by the string size, an upper bound smaller than the lower bound
+Xreturns an empty string.
+X\bcode\begin{verbatim}
+X>>> word[1:100]
+X'elpA'
+X>>> word[10:]
+X''
+X>>> word[2:1]
+X''
+X>>>
+X\end{verbatim}\ecode
+XSlice indices (but not simple subscripts) may be negative numbers, to
+Xstart counting from the right.
+XFor example:
+X\bcode\begin{verbatim}
+X>>> word[-2:] # Take last two characters
+X'pA'
+X>>> word[:-2] # Drop last two characters
+X'Hel'
+X>>> # But -0 does not count from the right!
+X>>> word[-0:] # (since -0 equals 0)
+X'HelpA'
+X>>>
+X\end{verbatim}\ecode
+XThe best way to remember how slices work is to think of the indices as
+Xpointing
+X{\em between}
+Xcharacters, with the left edge of the first character numbered 0.
+XThen the right edge of the last character of a string of
+X{\tt n}
+Xcharacters has index
+X{\tt n},
+Xfor example:
+X\bcode\begin{verbatim}
+X +---+---+---+---+---+
+X | H | e | l | p | A |
+X +---+---+---+---+---+
+X 0 1 2 3 4 5
+X-5 -4 -3 -2 -1
+X\end{verbatim}\ecode
+XThe first row of numbers gives the position of the indices 0...5 in the
+Xstring; the second row gives the corresponding negative indices.
+XFor nonnegative indices, the length of a slice is the difference of the
+Xindices, if both are within bounds,
+Xe.g.,
+Xthe length of
+X{\tt word[1:3]}
+Xis 3--1 = 2.
+X
+XFinally, the built-in function {\tt len()} computes the length of a
+Xstring:
+X\bcode\begin{verbatim}
+X>>> s = 'supercalifragilisticexpialidocious'
+X>>> len(s)
+X34
+X>>>
+X\end{verbatim}\ecode
+X\Python\ knows a number of
+X{\em compound}
+Xdata types, used to group together other values.
+XThe most versatile is the
+X{\em list},
+Xwhich can be written as a list of comma-separated values between square
+Xbrackets:
+X\bcode\begin{verbatim}
+X>>> a = ['foo', 'bar', 100, 1234]
+X>>> a
+X['foo', 'bar', 100, 1234]
+X>>>
+X\end{verbatim}\ecode
+XAs for strings, list subscripts start at 0:
+X\bcode\begin{verbatim}
+X>>> a[0]
+X'foo'
+X>>> a[3]
+X1234
+X>>>
+X\end{verbatim}\ecode
+XLists can be sliced and concatenated like strings:
+X\bcode\begin{verbatim}
+X>>> a[1:3]
+X['bar', 100]
+X>>> a[:2] + ['bletch', 2*2]
+X['foo', 'bar', 'bletch', 4]
+X>>>
+X\end{verbatim}\ecode
+XUnlike strings, which are
+X{\em immutable},
+Xit is possible to change individual elements of a list:
+X\bcode\begin{verbatim}
+X>>> a
+X['foo', 'bar', 100, 1234]
+X>>> a[2] = a[2] + 23
+X>>> a
+X['foo', 'bar', 123, 1234]
+X>>>
+X\end{verbatim}\ecode
+XAssignment to slices is also possible, and this may even change the size
+Xof the list:
+X\bcode\begin{verbatim}
+X>>> # Replace some items:
+X>>> a[0:2] = [1, 12]
+X>>> a
+X[1, 12, 123, 1234]
+X>>> # Remove some:
+X>>> a[0:2] = []
+X>>> a
+X[123, 1234]
+X>>> # Insert some:
+X>>> a[1:1] = ['bletch', 'xyzzy']
+X>>> a
+X[123, 'bletch', 'xyzzy', 1234]
+X>>>
+X\end{verbatim}\ecode
+XThe built-in function {\tt len()} also applies to lists:
+X\bcode\begin{verbatim}
+X>>> len(a)
+X4
+X>>>
+X\end{verbatim}\ecode
+X
+X\subsection{Tuples and Sequences}
+X
+XXXX To Be Done.
+X
+X\subsection{First Steps Towards Programming}
+X
+XOf course, we can use \Python\ for more complicated tasks than adding two
+Xand two together.
+XFor instance, we can write an initial subsequence of the
+X{\em Fibonacci}
+Xseries as follows:
+X\bcode\begin{verbatim}
+X>>> # Fibonacci series:
+X>>> # the sum of two elements defines the next
+X>>> a, b = 0, 1
+X>>> while b < 100:
+X... print b
+X... a, b = b, a+b
+X...
+X1
+X1
+X2
+X3
+X5
+X8
+X13
+X21
+X34
+X55
+X89
+X>>>
+X\end{verbatim}\ecode
+XThis example introduces several new features.
+X\begin{itemize}
+X\item
+XThe first line contains a
+X{\em multiple\ assignment}:
+Xthe variables
+X{\tt a}
+Xand
+X{\tt b}
+Xsimultaneously get the new values 0 and 1.
+XOn the last line this is used again, demonstrating that the expressions
+Xon the right-hand side are all evaluated first before any of the
+Xassignments take place.
+X\item
+XThe
+X{\tt while}
+Xloop executes as long as the condition (here: $b < 100$) remains true.
+XIn \Python, as in C, any non-zero integer value is true; zero is false.
+XThe condition may also be a string or list value, in fact any sequence;
+Xanything with a non-zero length is true, empty sequences are false.
+XThe test used in the example is a simple comparison.
+XThe standard comparison operators are written as
+X{\tt <},
+X{\tt >},
+X{\tt =},
+X{\tt <=},
+X{\tt >=}
+Xand
+X{\tt <>}.%
+X\footnote{
+X The ambiguity of using {\tt =}
+X for both assignment and equality is resolved by disallowing
+X unparenthesized conditions at the right hand side of assignments.
+X}
+X\item
+XThe
+X{\em body}
+Xof the loop is
+X{\em indented}: indentation is \Python's way of grouping statements.
+X\Python\ does not (yet!) provide an intelligent input line editing
+Xfacility, so you have to type a tab or space(s) for each indented line.
+XIn practice you will prepare more complicated input for \Python\ with a
+Xtext editor; most text editors have an auto-indent facility.
+XWhen a compound statement is entered interactively, it must be
+Xfollowed by a blank line to indicate completion (since the parser
+Xcannot guess when you have typed the last line).
+X\item
+XThe
+X{\tt print}
+Xstatement writes the value of the expression(s) it is given.
+XIt differs from just writing the expression you want to write (as we did
+Xearlier in the calculator examples) in the way it handles multiple
+Xexpressions and strings.
+XStrings are written without quotes and a space is inserted between
+Xitems, so you can format things nicely, like this:
+X\bcode\begin{verbatim}
+X>>> i = 256*256
+X>>> print 'The value of i is', i
+XThe value of i is 65536
+X>>>
+X\end{verbatim}\ecode
+XA trailing comma avoids the newline after the output:
+X\bcode\begin{verbatim}
+X>>> a, b = 0, 1
+X>>> while b < 1000:
+X... print b,
+X... a, b = b, a+b
+X...
+X1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987
+X>>>
+X\end{verbatim}\ecode
+XNote that the interpreter inserts a newline before it prints the next
+Xprompt if the last line was not completed.
+X\end{itemize}
+X
+X\subsection{More Control Flow Tools}
+X
+XBesides the {\tt while} statement just introduced, \Python\ knows the
+Xusual control flow statements known from other languages, with some
+Xtwists.
+X
+X\subsubsection{If Statements}
+X
+XPerhaps the most well-known statement type is the {\tt if} statement.
+XFor example:
+X\bcode\begin{verbatim}
+X>>> if x < 0:
+X... x = 0
+X... print 'Negative changed to zero'
+X... elif x = 0:
+X... print 'Zero'
+X... elif x = 1:
+X... print 'Single'
+X... else:
+X... print 'More'
+X...
+X\end{verbatim}\ecode
+XThere can be zero or more {\tt elif} parts, and the {\tt else} part is
+Xoptional.
+XThe keyword `{\tt elif}' is short for `{\tt else if}', and is useful to
+Xavoid excessive indentation.
+XAn {\tt if...elif...elif...} sequence is a substitute for the
+X{\em switch} or {\em case} statements found in other languages.
+X
+X\subsubsection{For Statements}
+X
+XThe {\tt for} statement in \Python\ differs a bit from what you may be
+Xused to in C or Pascal.
+XRather than always iterating over an arithmetic progression of numbers
+X(as Pascal), or leaving the user completely free in the iteration test
+Xand step (as C), \Python's {\tt for} statement iterates over the items
+Xof any sequence (e.g., a list or a string).
+XFor example (no pun intended):
+X\bcode\begin{verbatim}
+X>>> # Measure some strings:
+X>>> a = ['cat', 'window', 'defenestrate']
+X>>> for x in a:
+X... print x, len(x)
+X...
+Xcat 3
+Xwindow 6
+Xdefenestrate 12
+X>>>
+X\end{verbatim}\ecode
+X
+X\subsubsection{The {\tt range()} Function}
+X
+XIf you do need to iterate over a sequence of numbers, the built-in
+Xfunction {\tt range()} comes in handy.
+XIt generates lists containing arithmetic progressions,
+Xe.g.:
+X\bcode\begin{verbatim}
+X>>> range(10)
+X[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+X>>>
+X\end{verbatim}\ecode
+XThe given end point is never part of the generated list;
+X{\tt range(10)} generates a list of 10 values,
+Xexactly the legal indices for items of a sequence of length 10.
+XIt is possible to let the range start at another number, or to specify a
+Xdifferent increment (even negative):
+X\bcode\begin{verbatim}
+X>>> range(5, 10)
+X[5, 6, 7, 8, 9]
+X>>> range(0, 10, 3)
+X[0, 3, 6, 9]
+X>>> range(-10, -100, -30)
+X[-10, -40, -70]
+X>>>
+X\end{verbatim}\ecode
+XTo iterate over the indices of a sequence, combine {\tt range()}
+Xand {\tt len()} as follows:
+X\bcode\begin{verbatim}
+X>>> a = ['Mary', 'had', 'a', 'little', 'boy']
+X>>> for i in range(len(a)):
+X... print i, a[i]
+X...
+X0 Mary
+X1 had
+X2 a
+X3 little
+X4 boy
+X>>>
+X\end{verbatim}\ecode
+X
+X\subsubsection{Break Statements and Else Clauses on Loops}
+X
+XThe {\tt break} statement breaks out of the smallest enclosing {\tt for}
+Xor {\tt while} loop.
+XLoop statements may have an {\tt else} clause; it is executed when the
+Xloop terminates through exhaustion of the list (with {\tt for}) or when
+Xthe condition becomes false (with {\tt while}) but not when the loop is
+Xterminated by a {\tt break} statement.
+XThis is exemplified by the following loop, which searches for a list
+Xitem of value 0:
+X\bcode\begin{verbatim}
+X>>> for n in range(2, 10):
+X... for x in range(2, n):
+X... if n % x = 0:
+X... print n, 'equals', x, '*', n/x
+X... break
+X... else:
+X... print n, 'is a prime number'
+X...
+X2 is a prime number
+X3 is a prime number
+X4 equals 2 * 2
+X5 is a prime number
+X6 equals 2 * 3
+X7 is a prime number
+X8 equals 2 * 4
+X9 equals 3 * 3
+X>>>
+X\end{verbatim}\ecode
+X
+X\subsubsection{Pass Statements}
+X
+XThe {\tt pass} statement does nothing.
+XIt can be used when a statement is required syntactically but the
+Xprogram requires no action.
+XFor example:
+X\bcode\begin{verbatim}
+X>>> while 1:
+X... pass # Busy-wait for keyboard interrupt
+X...
+X\end{verbatim}\ecode
+X
+X\subsubsection{Conditions Revisited}
+X
+XXXX To Be Done.
+X
+X\subsection{Defining Functions}
+X
+XWe can create a function that writes the Fibonacci series to an
+Xarbitrary boundary:
+X\bcode\begin{verbatim}
+X>>> def fib(n): # write Fibonacci series up to n
+X... a, b = 0, 1
+X... while b <= n:
+X... print b,
+X... a, b = b, a+b
+X...
+X>>> # Now call the function we just defined:
+X>>> fib(2000)
+X1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597
+X>>>
+X\end{verbatim}\ecode
+XThe keyword
+X{\tt def}
+Xintroduces a function
+X{\em definition}.
+XIt must be followed by the function name and the parenthesized list of
+Xformal parameters.
+XThe statements that form the body of the function starts at the next
+Xline, indented by a tab stop.
+XThe
+X{\em execution}
+Xof a function introduces a new symbol table used for the local variables
+Xof the function.
+XMore precisely, all variable assignments in a function store the value
+Xin the local symbol table; variable references first look in the local
+Xsymbol table, then in the global symbol table, and then in the table of
+Xbuilt-in names.
+XThus, the global symbol table is
+X{\em read-only}
+Xwithin a function.
+XThe actual parameters (arguments) to a function call are introduced in
+Xthe local symbol table of the called function when it is called;
+Xthus, arguments are passed using
+X{\em call\ by\ value}.%
+X\footnote{
+X Actually, {\em call by object reference} would be a better
+X description, since if a mutable object is passed, the caller
+X will see any changes the callee makes to it (e.g., items
+X inserted into a list).
+X}
+XWhen a function calls another function, a new local symbol table is
+Xcreated for that call.
+X
+XA function definition introduces the function name in the global symbol
+Xtable.
+XThe value has a type that is recognized by the interpreter as a
+Xuser-defined function.
+XThis value can be assigned to another name which can then also be used
+Xas a function.
+XThis serves as a general renaming mechanism:
+X\bcode\begin{verbatim}
+X>>> fib
+X<function object at 10042ed0>
+X>>> f = fib
+X>>> f(100)
+X1 1 2 3 5 8 13 21 34 55 89
+X>>>
+X\end{verbatim}\ecode
+XYou might object that
+X{\tt fib}
+Xis not a function but a procedure.
+XIn \Python, as in C, procedures are just functions that don't return a
+Xvalue.
+XIn fact, technically speaking, procedures do return a value, albeit a
+Xrather boring one.
+XThis value is called {\tt None} (it's a built-in name).
+XWriting the value {\tt None} is normally suppressed by the interpreter
+Xif it would be the only value written.
+XYou can see it if you really want to:
+X\bcode\begin{verbatim}
+X>>> print fib(0)
+XNone
+X>>>
+X\end{verbatim}\ecode
+XIt is simple to write a function that returns a list of the numbers of
+Xthe Fibonacci series, instead of printing it:
+X\bcode\begin{verbatim}
+X>>> def fib2(n): # return Fibonacci series up to n
+X... result = []
+X... a, b = 0, 1
+X... while b <= n:
+X... result.append(b) # see below
+X... a, b = b, a+b
+X... return result
+X...
+X>>> f100 = fib2(100) # call it
+X>>> f100 # write the result
+X[1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
+X>>>
+X\end{verbatim}\ecode
+XThis example, as usual, demonstrates some new \Python\ features:
+X\begin{itemize}
+X\item
+XThe
+X{\tt return}
+Xstatement returns with a value from a function.
+X{\tt return}
+Xwithout an expression argument is used to return from the middle of a
+Xprocedure (falling off the end also returns from a proceduce).
+X\item
+XThe statement
+X{\tt ret.append(b)}
+Xcalls a
+X{\em method}
+Xof the list object
+X{\tt ret}.
+XA method is a function that `belongs' to an object and is named
+X{\tt obj.methodname},
+Xwhere
+X{\tt obj}
+Xis some object (this may be an expression), and
+X{\tt methodname}
+Xis the name of a method that is defined by the object's type.
+XDifferent types define different methods.
+XMethods of different types may have the same name without causing
+Xambiguity.
+XSee the section on classes, later, to find out how you can define your
+Xown object types and methods.
+XThe method
+X{\tt append}
+Xshown in the example, is defined for list objects; it adds a new element
+Xat the end of the list.
+XIn this case it is equivalent to
+X{\tt ret = ret + [b]},
+Xbut more efficient.%
+X\footnote{
+X There is a subtle semantic difference if the object
+X is referenced from more than one place.
+X}
+X\end{itemize}
+XThe list object type has two more methods:
+X\begin{description}
+X\item[{\tt insert(i, x)}]
+XInserts an item at a given position.
+XThe first argument is the index of the element before which to insert,
+Xso {\tt a.insert(0, x)} inserts at the front of the list, and
+X{\tt a.insert(len(a), x)} is equivalent to {\tt a.append(x)}.
+X\item[{\tt sort()}]
+XSorts the elements of the list.
+X\end{description}
+XFor example:
+X\bcode\begin{verbatim}
+X>>> a = [10, 100, 1, 1000]
+X>>> a.insert(2, -1)
+X>>> a
+X[10, 100, -1, 1, 1000]
+X>>> a.sort()
+X>>> a
+X[-1, 1, 10, 100, 1000]
+X>>> # Strings are sorted according to ASCII:
+X>>> b = ['Mary', 'had', 'a', 'little', 'boy']
+X>>> b.sort()
+X>>> b
+X['Mary', 'a', 'boy', 'had', 'little']
+X>>>
+X\end{verbatim}\ecode
+X
+X\subsection{Modules}
+X
+XIf you quit from the \Python\ interpreter and enter it again, the
+Xdefinitions you have made (functions and variables) are lost.
+XTherefore, if you want to write a somewhat longer program, you are
+Xbetter off using a text editor to prepare the input for the interpreter
+Xand run it with that file as input instead.
+XThis is known as creating a
+X{\em script}.
+XAs your program gets longer, you may want to split it into several files
+Xfor easier maintenance.
+XYou may also want to use a handy function that you've written in several
+Xprograms without copying its definition into each program.
+XTo support this, \Python\ has a way to put definitions in a file and use
+Xthem in a script or in an interactive instance of the interpreter.
+XSuch a file is called a
+X{\em module};
+Xdefinitions from a module can be
+X{\em imported}
+Xinto other modules or into the
+X{\em main}
+Xmodule (the collection of variables that you have access to in
+Xa script and in calculator mode).
+X
+XA module is a file containing \Python\ definitions and statements.
+XThe file name is the module name with the suffix
+X{\tt .py}
+Xappended.
+XFor instance, use your favorite text editor to create a file called
+X{\tt fibo.py}
+Xin the current directory with the following contents:
+X\bcode\begin{verbatim}
+X# Fibonacci numbers module
+X
+Xdef fib(n): # write Fibonacci series up to n
+X a, b = 0, 1
+X while b <= n:
+X print b,
+X a, b = b, a+b
+X
+Xdef fib2(n): # return Fibonacci series up to n
+X ret = []
+X a, b = 0, 1
+X while b <= n:
+X ret.append(b)
+X a, b = b, a+b
+X return ret
+X\end{verbatim}\ecode
+XNow enter the \Python\ interpreter and import this module with the
+Xfollowing command:
+X\bcode\begin{verbatim}
+X>>> import fibo
+X>>>
+X\end{verbatim}\ecode
+XThis does not enter the names of the functions defined in
+X{\tt fibo}
+Xdirectly in the symbol table; it only enters the module name
+X{\tt fibo}
+Xthere.
+XUsing the module name you can access the functions:
+X\bcode\begin{verbatim}
+X>>> fibo.fib(1000)
+X1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987
+X>>> fibo.fib2(100)
+X[1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
+X>>>
+X\end{verbatim}\ecode
+XIf you intend to use a function often you can assign it to a local name:
+X\bcode\begin{verbatim}
+X>>> fib = fibo.fib
+X>>> fib(500)
+X1 1 2 3 5 8 13 21 34 55 89 144 233 377
+X>>>
+X\end{verbatim}\ecode
+X
+X\subsubsection{More on Modules}
+X
+XA module can contain executable statements as well as function
+Xdefinitions.
+XThese statements are intended to initialize the module.
+XThey are executed only the
+X{\em first}
+Xtime the module is imported somewhere.%
+X\footnote{
+X In fact function definitions are also `statements' that are
+X `executed'; the execution enters the function name in the
+X module's global symbol table.
+X}
+X
+XEach module has its own private symbol table, which is used as the
+Xglobal symbol table by all functions defined in the module.
+XThus, the author of a module can use global variables in the module
+Xwithout worrying about accidental clashes with a user's global
+Xvariables.
+XOn the other hand, if you know what you are doing you can touch a
+Xmodule's global variables with the same notation used to refer to its
+Xfunctions,
+X{\tt modname.itemname}.
+X
+XModules can import other modules.
+XIt is customary but not required to place all
+X{\tt import}
+Xstatements at the beginning of a module (or script, for that matter).
+XThe imported module names are placed in the importing module's global
+Xsymbol table.
+X
+XThere is a variant of the
+X{\tt import}
+Xstatement that imports names from a module directly into the importing
+Xmodule's symbol table.
+XFor example:
+X\bcode\begin{verbatim}
+X>>> from fibo import fib, fib2
+X>>> fib(500)
+X1 1 2 3 5 8 13 21 34 55 89 144 233 377
+X>>>
+X\end{verbatim}\ecode
+XThis does not introduce the module name from which the imports are taken
+Xin the local symbol table (so in the example, {\tt fibo} is not
+Xdefined).
+X
+XThere is even a variant to import all names that a module defines:
+X\bcode\begin{verbatim}
+X>>> from fibo import *
+X>>> fib(500)
+X1 1 2 3 5 8 13 21 34 55 89 144 233 377
+X>>>
+X\end{verbatim}\ecode
+XThis imports all names except those beginning with an underscore
+X({\tt \_}).
+X
+X\subsubsection{Standard Modules}
+X
+X\Python\ comes with a library of standard modules, described in a separate
+Xdocument (Python Library and Module Reference).
+XSome modules are built into the interpreter; these provide access to
+Xoperations that are not part of the core of the language but are
+Xnevertheless built in, either for efficiency or to provide access to
+Xoperating system primitives such as system calls.
+XThe set of such modules is a configuration option; e.g., the
+X{\tt amoeba}
+Xmodule is only provided on systems that somehow support Amoeba
+Xprimitives.
+XOne particular module deserves some attention:
+X{\tt sys},
+Xwhich is built into every \Python\ interpreter.
+XThe variables
+X{\tt sys.ps1}
+Xand
+X{\tt sys.ps2}
+Xdefine the strings used as primary and secondary prompts:
+X\bcode\begin{verbatim}
+X>>> import sys
+X>>> sys.ps1
+X'>>> '
+X>>> sys.ps2
+X'... '
+X>>> sys.ps1 = 'C> '
+XC> print 'Yuck!'
+XYuck!
+XC>
+X\end{verbatim}\ecode
+XThese two variables are only defined if the interpreter is in
+Xinteractive mode.
+X
+XThe variable
+X{\tt sys.path}
+Xis a list of strings that determine the interpreter's search path for
+Xmodules.
+XIt is initialized to a default path taken from the environment variable
+X{\tt PYTHONPATH},
+Xor from a built-in default if
+X{\tt PYTHONPATH}
+Xis not set.
+XYou can modify it using standard list operations, e.g.:
+X\bcode\begin{verbatim}
+X>>> import sys
+X>>> sys.path.append('/ufs/guido/lib/python')
+X>>>
+X\end{verbatim}\ecode
+X
+X\subsection{Errors and Exceptions}
+X
+XUntil now error messages haven't yet been mentioned, but if you have
+Xtried out the examples you have probably seen some.
+XThere are (at least) two distinguishable kinds of errors:
+X{\em syntax\ errors}
+Xand
+X{\em exceptions}.
+X
+X\subsubsection{Syntax Errors}
+X
+XSyntax errors, also known as parsing errors, are perhaps the most common
+Xkind of complaint you get while you are still learning \Python:
+X\bcode\begin{verbatim}
+X>>> while 1 print 'Hello world'
+XParsing error: file <stdin>, line 1:
+Xwhile 1 print 'Hello world'
+X ^
+XUnhandled exception: run-time error: syntax error
+X>>>
+X\end{verbatim}\ecode
+XThe parser repeats the offending line and displays a little `arrow'
+Xpointing at the earliest point in the line where the error was detected.
+XThe error is caused by (or at least detected at) the token
+X{\em preceding}
+Xthe arrow: in the example, the error is detected at the keyword
+X{\tt print}, since a colon ({\tt :}) is missing before it.
+XFile name and line number are printed so you know where to look in case
+Xthe input came from a script.
+X
+X\subsubsection{Exceptions}
+X
+XEven if a statement or expression is syntactically correct, it may cause
+Xan error when an attempt is made to execute it:
+X\bcode\small\begin{verbatim}
+X>>> 10 * (1/0)
+XUnhandled exception: run-time error: integer division by zero
+XStack backtrace (innermost last):
+X File "<stdin>", line 1
+X>>> 4 + foo*3
+XUnhandled exception: undefined name: foo
+XStack backtrace (innermost last):
+X File "<stdin>", line 1
+X>>> '2' + 2
+XUnhandled exception: type error: illegal argument type for built-in operation
+XStack backtrace (innermost last):
+X File "<stdin>", line 1
+X>>>
+X\end{verbatim}\ecode
+XErrors detected during execution are called
+X{\em exceptions}
+Xand are not unconditionally fatal: you will soon learn how to handle
+Xthem in \Python\ programs.
+XMost exceptions are not handled by programs, however, and result
+Xin error messages as shown here.
+X
+XThe first line of the error message indicates what happened.
+XExceptions come in different types, and the type is printed as part of
+Xthe message: the types in the example are
+X{\tt run-time error},
+X{\tt undefined name}
+Xand
+X{\tt type error}.
+XThe rest of the line is a detail whose interpretation depends on the
+Xexception type.
+X
+XThe rest of the error message shows the context where the
+Xexception happened.
+XIn general it contains a stack backtrace listing source lines; however,
+Xit will not display lines read from standard input.
+X
+XHere is a summary of the most common exceptions:
+X\begin{itemize}
+X\item
+X{\em Run-time\ errors}
+Xare generally caused by wrong data used by the program; this can be the
+Xprogrammer's fault or caused by bad input.
+XThe detail states the cause of the error in more detail.
+X\item
+X{\em Undefined\ name}
+Xerrors are more serious: these are usually caused by misspelled
+Xidentifiers.%
+X\footnote{
+X The parser does not check whether names used in a program are at
+X all defined elsewhere in the program, so such checks are
+X postponed until run-time. The same holds for type checking.
+X}
+XThe detail is the offending identifier.
+X\item
+X{\em Type\ errors}
+Xare also pretty serious: this is another case of using wrong data (or
+Xbetter, using data the wrong way), but here the error can be glanced
+Xfrom the object type(s) alone.
+XThe detail shows in what context the error was detected.
+X\end{itemize}
+X
+X\subsubsection{Handling Exceptions}
+X
+XIt is possible to write programs that handle selected exceptions.
+XLook at the following example, which prints a table of inverses of
+Xsome floating point numbers:
+X\bcode\begin{verbatim}
+X>>> numbers = [0.3333, 2.5, 0.0, 10.0]
+X>>> for x in numbers:
+X... print x,
+X... try:
+X... print 1.0 / x
+X... except RuntimeError:
+X... print '*** has no inverse ***'
+X...
+X0.3333 3.00030003
+X2.5 0.4
+X0 *** has no inverse ***
+X10 0.1
+X>>>
+X\end{verbatim}\ecode
+XThe {\tt try} statement works as follows.
+X\begin{itemize}
+X\item
+XFirst, the
+X{\em try\ clause}
+X(the statement(s) between the {\tt try} and {\tt except} keywords) is
+Xexecuted.
+X\item
+XIf no exception occurs, the
+X{\em except\ clause}
+Xis skipped and execution of the {\tt try} statement is finished.
+X\item
+XIf an exception occurs during execution of the try clause, and its
+Xtype matches the exception named after the {\tt except} keyword, the
+Xrest of the try clause is skipped, the except clause is executed, and
+Xthen execution continues after the {\tt try} statement.
+X\item
+XIf an exception occurs which does not match the exception named in the
+Xexcept clause, it is passed on to outer try statements; if no handler is
+Xfound, it is an
+X{\em unhandled\ exception}
+Xand execution stops with a message as shown above.
+X\end{itemize}
+XA {\tt try} statement may have more than one except clause, to specify
+Xhandlers for different exceptions.
+XAt most one handler will be executed.
+XHandlers only handle exceptions that occur in the corresponding try
+Xclause, not in other handlers of the same {\tt try} statement.
+XAn except clause may name multiple exceptions as a parenthesized list,
+Xe.g.:
+X\bcode\begin{verbatim}
+X... except (RuntimeError, TypeError, NameError):
+X... pass
+X\end{verbatim}\ecode
+XThe last except clause may omit the exception name(s), to serve as a
+Xwildcard.
+XUse this with extreme caution!
+X
+XWhen an exception occurs, it may have an associated value, also known as
+Xthe exceptions's
+X{\em argument}.
+XThe presence and type of the argument depend on the exception type.
+XFor exception types which have an argument, the except clause may
+Xspecify a variable after the exception name (or list) to receive the
+Xargument's value, as follows:
+X\bcode\begin{verbatim}
+X>>> try:
+X... foo()
+X... except NameError, x:
+X... print 'name', x, 'undefined'
+X...
+Xname foo undefined
+X>>>
+X\end{verbatim}\ecode
+XIf an exception has an argument, it is printed as the third part
+X(`detail') of the message for unhandled exceptions.
+X
+XStandard exception names are built-in identifiers (not reserved
+Xkeywords).
+XThese are in fact string objects whose
+X{\em object\ identity}
+X(not their value!) identifies the exceptions.%
+X\footnote{
+X There should really be a separate exception type; it is pure
+X laziness that exceptions are identified by strings, and this may
+X be fixed in the future.
+X}
+XThe string is printed as the second part of the message for unhandled
+Xexceptions.
+XTheir names and values are:
+X\bcode\begin{verbatim}
+XEOFError 'end-of-file read'
+XKeyboardInterrupt 'keyboard interrupt'
+XMemoryError 'out of memory' *
+XNameError 'undefined name' *
+XRuntimeError 'run-time error' *
+XSystemError 'system error' *
+XTypeError 'type error' *
+X\end{verbatim}\ecode
+XThe meanings should be clear enough.
+XThose exceptions with a {\tt *} in the third column have an argument.
+X
+XException handlers don't just handle exceptions if they occur
+Ximmediately in the try clause, but also if they occur inside functions
+Xthat are called (even indirectly) in the try clause.
+XFor example:
+X\bcode\begin{verbatim}
+X>>> def this_fails():
+X... x = 1/0
+X...
+X>>> try:
+X... this_fails()
+X... except RuntimeError, detail:
+X... print 'Handling run-time error:', detail
+X...
+XHandling run-time error: domain error or zero division
+X>>>
+X\end{verbatim}\ecode
+X
+X\subsubsection{Raising Exceptions}
+X
+XThe {\tt raise} statement allows the programmer to force a specified
+Xexception to occur.
+XFor example:
+X\bcode\begin{verbatim}
+X>>> raise NameError, 'Hi There!'
+XUnhandled exception: undefined name: Hi There!
+XStack backtrace (innermost last):
+X File "<stdin>", line 1
+X>>>
+X\end{verbatim}\ecode
+XThe first argument to {\tt raise} names the exception to be raised.
+XThe optional second argument specifies the exception's argument.
+X
+X\subsubsection{User-defined Exceptions}
+X
+XPrograms may name their own exceptions by assigning a string to a
+Xvariable.
+XFor example:
+X\bcode\begin{verbatim}
+X>>> my_exc = 'nobody likes me!'
+X>>> try:
+X... raise my_exc, 2*2
+X... except my_exc, val:
+X... print 'My exception occured, value:', val
+X...
+XMy exception occured, value: 4
+X>>> raise my_exc, 1
+XUnhandled exception: nobody likes me!: 1
+XStack backtrace (innermost last):
+X File "<stdin>", line 7
+X>>>
+X\end{verbatim}\ecode
+XMany standard modules use this to report errors that may occur in
+Xfunctions they define.
+X
+X\subsubsection{Defining Clean-up Actions}
+X
+XThe {\tt try} statement has another optional clause which is intended to
+Xdefine clean-up actions that must be executed under all circumstances.
+XFor example:
+X\bcode\begin{verbatim}
+X>>> try:
+X... raise KeyboardInterrupt
+X... finally:
+X... print 'Goodbye, world!'
+X...
+XGoodbye, world!
+XUnhandled exception: keyboard interrupt
+XStack backtrace (innermost last):
+X File "<stdin>", line 2
+X>>>
+X\end{verbatim}\ecode
+XThe
+X{\em finally\ clause}
+Xmust follow the except clauses(s), if any.
+XIt is executed whether or not an exception occurred.
+XIf the exception is handled, the finally clause is executed after the
+Xhandler (and even if another exception occurred in the handler).
+XIt is also executed when the {\tt try} statement is left via a
+X{\tt break} or {\tt return} statement.
+X
+X\subsection{Classes}
+X
+XClasses in \Python\ make it possible to play the game of encapsulation in a
+Xsomewhat different way than it is played with modules.
+XClasses are an advanced topic and are probably best skipped on the first
+Xencounter with \Python.
+X
+X\subsubsection{Prologue}
+X
+X\Python's class mechanism is not particularly elegant, but quite powerful.
+XIt is a mixture of the class mechanisms found in C++ and Modula-3.
+XAs is true for modules, classes in \Python\ do not put an absolute barrier
+Xbetween definition and user, but rather rely on the politeness of the
+Xuser not to ``break into the definition.''
+XThe most important features of classes are retained with full power,
+Xhowever: the class inheritance mechanism allows multiple base classes,
+Xa derived class can override any method of its base class(es), a method
+Xcan call the method of a base class with the same name.
+XObjects can contain an arbitrary amount of private data.
+X
+XIn C++ terminology, all class members (including data members) are
+X{\em public},
+Xand all member functions (methods) are
+X{\em virtual}.
+XThere are no special constructors or destructors.
+XAs in Modula-3, there are no shorthands for referencing the object's
+Xmembers from its methods: the method function is declared with an
+Xexplicit first argument representing the object, which is provided
+Ximplicitly by the call.
+XAs in Smalltalk, classes themselves are objects, albeit in the wider
+Xsense of the word: in \Python, all data types are objects.
+XThis provides semantics for renaming or aliasing.
+XBut, just like in C++ or Modula-3, the built-in types cannot be used as
+Xbase classes for extension by the user.
+XAlso, like Modula-3 but unlike C++, the built-in operators with special
+Xsyntax (arithmetic operators, subscripting etc.) cannot be redefined for
+Xclass members.%
+X\footnote{
+X They can be redefined for new object types implemented in C in
+X extensions to the interpreter, however. It would require only a
+X naming convention and a relatively small change to the
+X interpreter to allow operator overloading for classes, so
+X perhaps someday...
+X}
+X
+X\subsubsection{A Simple Example}
+X
+XConsider the following example, which defines a class {\tt Set}
+Xrepresenting a (finite) mathematical set with operations to add and
+Xremove elements, a membership test, and a request for the size of the
+Xset.
+X\bcode\begin{verbatim}
+Xclass Set():
+X def new(self):
+X self.elements = []
+X return self
+X def add(self, e):
+X if e not in self.elements:
+X self.elements.append(e)
+X def remove(self, e):
+X if e in self.elements:
+X for i in range(len(self.elements)):
+X if self.elements[i] = e:
+X del self.elements[i]
+X break
+X def is_element(self, e):
+X return e in self.elements
+X def size(self):
+X return len(self.elements)
+X\end{verbatim}\ecode
+XNote that the class definition looks like a big compound statement,
+Xwith all the function definitons indented repective to the
+X{\tt class}
+Xkeyword.
+X
+XLet's assume that this
+X{\em class\ definition}
+Xis the only contents of the module file
+X{\tt SetClass.py}.
+XWe can then use it in a \Python\ program as follows:
+X\bcode\begin{verbatim}
+X>>> from SetClass import Set
+X>>> a = Set().new() # create a Set object
+X>>> a.add(2)
+X>>> a.add(3)
+X>>> a.add(1)
+X>>> a.add(1)
+X>>> if a.is_element(3): print '3 is in the set'
+X...
+X3 is in the set
+X>>> if not a.is_element(4): print '4 is not in the set'
+X...
+X4 is not in the set
+X>>> print 'a has', a.size(), 'elements'
+Xa has 3 elements
+X>>> a.remove(1)
+X>>> print 'now a has', a.size(), 'elements'
+X>>>
+Xnow a has 2 elements
+X>>>
+X\end{verbatim}\ecode
+XFrom the example we learn in the first place that the functions defined
+Xin the class (e.g.,
+X{\tt add})
+Xcan be called using the
+X{\em member}
+Xnotation for the object
+X{\tt a}.
+XThe member function is called with one less argument than it is defined:
+Xthe object is implicitly passed as the first argument.
+XThus, the call
+X{\tt a.add(2)}
+Xis equivalent to
+X{\tt Set.add(a, 2)}.
+X
+XXXX This section is not complete yet!
+X
+X\section{XXX P.M.}
+X
+X\begin{itemize}
+X\item The {\tt del} statement.
+X\item The {\tt dir()} function.
+X\item Tuples.
+X\item Dictionaries.
+X\item Objects and types in general.
+X\item Backquotes.
+X\item And/Or/Not.
+X\end{itemize}
+X
+X\end{document}
+EOF
+fi
+echo 'Part 01 out of 21 of pack.out complete.'
+exit 0
diff --git a/shar/python-0.9.1-01.patch b/shar/python-0.9.1-01.patch
new file mode 100644
index 0000000..b27b7f6
--- /dev/null
+++ b/shar/python-0.9.1-01.patch
@@ -0,0 +1,163 @@
+Here is official patch #1 for Python. It fixes an embarrassing bug in
+patchlevel.h, fixes the testall.py module to work non-interactively, and
+adds some comments and a fix to the Makefile.
+IMPORTANT NOTE: Use "patch -p <thisfile" in the top level directory of
+the Python distribution.
+
+--Guido van Rossum <[email protected]>
+
+*** /usr/people/guido/python-dist/src/Makefile Tue Feb 19 13:42:10 1991
+--- src/Makefile Wed Feb 20 13:37:32 1991
+***************
+*** 65,74 ****
+# Installation Options
+# ====================
+
+! # You may want to change PYTHONPATH to reflect where you install the
+! # Python module library.
+
+! PYTHONPATH= .:/usr/local/lib/python:/ufs/guido/lib/python
+
+
+# For "Pure" BSD Systems
+--- 65,76 ----
+# Installation Options
+# ====================
+
+! # You may want to change DEFPYTHONPATH to reflect where you install the
+! # Python module library. The default contains "../lib" so running
+! # the interpreter from the source/build directory as distributed will
+! # find the library (admittedly a hack).
+
+! DEFPYTHONPATH= .:/usr/local/lib/python:/ufs/guido/lib/python:../lib
+
+
+# For "Pure" BSD Systems
+***************
+*** 248,257 ****
+# about 70K to the Python text size and about 260K to the unstripped
+# binary size.
+#
+! # Note: the file 'glmodule.c' is created by a Python script. If you
+! # lost the file and have no working Python interpreter, turn off the GL
+! # and Panel options, rebuild the Python interpreter, use it to create
+! # glmodule.c, and then turn the options back on.
+#
+# Uncomment the following block to use the GL option.
+
+--- 250,265 ----
+# about 70K to the Python text size and about 260K to the unstripped
+# binary size.
+#
+! # NOTE WHEN BUILDING FOR THE FIRST TIME:
+! # There is a circular dependency in the build process: you need to have
+! # a working Python interpreter before you can build a Python interpreter
+! # that incorporates the 'gl' module -- the source file 'glmodule.c' is
+! # not distributed (it's about 140K!) and a Python script is used to
+! # create it. Thus, you first have to build python without the the GL
+! # and Panel options, then edit the Makefile to turn them (or at least GL)
+! # on and rebuild. You may also have to set PYTHONPATH to point to
+! # the place where the module library is for the generation script to
+! # work.
+#
+# Uncomment the following block to use the GL option.
+
+***************
+*** 270,276 ****
+# the standard module 'panel' to provide an interface to most features
+# of the Panel Library. This option requires that you also turn on the
+# GL option. It adds about 100K to the Python text size and about 160K
+! # to the unstripped binary size.
+#
+# Uncomment and edit the following block to use the Panel option.
+# - Edit the PANELDIR definition to point to the top-level directory
+--- 278,286 ----
+# the standard module 'panel' to provide an interface to most features
+# of the Panel Library. This option requires that you also turn on the
+# GL option. It adds about 100K to the Python text size and about 160K
+! # to the unstripped binary size. This requires Panel Library version 9.7
+! # (for lower versions you may have to remove some functionality -- send
+! # me the patches if you bothered to do this).
+#
+# Uncomment and edit the following block to use the Panel option.
+# - Edit the PANELDIR definition to point to the top-level directory
+***************
+*** 335,341 ****
+tupleobject.c typeobject.c
+
+CONFIGDEFS= $(STDW_USE) $(AM_USE) $(AUDIO_USE) $(GL_USE) $(PANEL_USE) \
+! '-DPYTHONPATH="$(PYTHONPATH)"'
+
+CONFIGINCLS= $(STDW_INCL)
+
+--- 345,351 ----
+tupleobject.c typeobject.c
+
+CONFIGDEFS= $(STDW_USE) $(AM_USE) $(AUDIO_USE) $(GL_USE) $(PANEL_USE) \
+! '-DPYTHONPATH="$(DEFPYTHONPATH)"'
+
+CONFIGINCLS= $(STDW_INCL)
+
+***************
+*** 480,486 ****
+# The rules for doing so are given here.
+
+# Build "glmodule.c", the GL interface.
+! # Ignore the messages emitted by the cgen script.
+# Also ignore the warnings emitted while compiling glmodule.c; it works.
+
+glmodule.c: cstubs cgen
+--- 490,499 ----
+# The rules for doing so are given here.
+
+# Build "glmodule.c", the GL interface.
+! # See important note at "GL Option" above.
+! # You may have to set and export PYTHONPATH for this to work.
+! # Ignore the messages emitted by the cgen script as long as its exit
+! # status is zero.
+# Also ignore the warnings emitted while compiling glmodule.c; it works.
+
+glmodule.c: cstubs cgen
+*** /usr/people/guido/python-dist/src/patchlevel.h Tue Feb 19 13:44:44 1991
+--- src/patchlevel.h Wed Feb 20 12:57:39 1991
+***************
+*** 1 ****
+! 1
+--- 1 ----
+! #define PATCHLEVEL 1
+*** /usr/people/guido/python-dist/lib/testall.py Wed Dec 26 15:40:20 1990
+--- lib/testall.py Wed Feb 20 12:59:22 1991
+***************
+*** 122,128 ****
+[4]
+from math import *
+[5]
+! from sys import modules, ps1, ps2
+[6]
+
+### compound_stmt: if_stmt | while_stmt | for_stmt | try_stmt | funcdef | classdef
+--- 122,128 ----
+[4]
+from math import *
+[5]
+! from sys import modules, path
+[6]
+
+### compound_stmt: if_stmt | while_stmt | for_stmt | try_stmt | funcdef | classdef
+***************
+*** 213,219 ****
+x = +1
+x = -1
+x = 1
+! c = sys.ps1[0]
+x = time.time()
+x = sys.modules['time'].time()
+a = '01234'
+--- 213,219 ----
+x = +1
+x = -1
+x = 1
+! c = sys.path[0]
+x = time.time()
+x = sys.modules['time'].time()
+a = '01234' \ No newline at end of file
diff --git a/shar/python-0.9.1-03-21.shar b/shar/python-0.9.1-03-21.shar
new file mode 100644
index 0000000..b2f6af5
--- /dev/null
+++ b/shar/python-0.9.1-03-21.shar
@@ -0,0 +1,2944 @@
+: This is a shell archive.
+: Extract with 'sh this_file'.
+:
+: Extract part 01 first since it makes all directories
+echo 'Start of pack.out, part 03 out of 21:'
+if test -s 'src/compile.c'
+then echo '*** I will not over-write existing file src/compile.c'
+else
+echo 'x - src/compile.c'
+sed 's/^X//' > 'src/compile.c' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/* Compile an expression node to intermediate code */
+X
+X/* XXX TO DO:
+X XXX Compute maximum needed stack sizes while compiling
+X XXX Generate simple jump for break/return outside 'try...finally'
+X XXX Include function name in code (and module names?)
+X*/
+X
+X#include "allobjects.h"
+X
+X#include "node.h"
+X#include "token.h"
+X#include "graminit.h"
+X#include "compile.h"
+X#include "opcode.h"
+X#include "structmember.h"
+X
+X#include <ctype.h>
+X
+X#define OFF(x) offsetof(codeobject, x)
+X
+Xstatic struct memberlist code_memberlist[] = {
+X {"co_code", T_OBJECT, OFF(co_code)},
+X {"co_consts", T_OBJECT, OFF(co_consts)},
+X {"co_names", T_OBJECT, OFF(co_names)},
+X {"co_filename", T_OBJECT, OFF(co_filename)},
+X {NULL} /* Sentinel */
+X};
+X
+Xstatic object *
+Xcode_getattr(co, name)
+X codeobject *co;
+X char *name;
+X{
+X return getmember((char *)co, code_memberlist, name);
+X}
+X
+Xstatic void
+Xcode_dealloc(co)
+X codeobject *co;
+X{
+X XDECREF(co->co_code);
+X XDECREF(co->co_consts);
+X XDECREF(co->co_names);
+X XDECREF(co->co_filename);
+X DEL(co);
+X}
+X
+Xtypeobject Codetype = {
+X OB_HEAD_INIT(&Typetype)
+X 0,
+X "code",
+X sizeof(codeobject),
+X 0,
+X code_dealloc, /*tp_dealloc*/
+X 0, /*tp_print*/
+X code_getattr, /*tp_getattr*/
+X 0, /*tp_setattr*/
+X 0, /*tp_compare*/
+X 0, /*tp_repr*/
+X 0, /*tp_as_number*/
+X 0, /*tp_as_sequence*/
+X 0, /*tp_as_mapping*/
+X};
+X
+Xstatic codeobject *newcodeobject PROTO((object *, object *, object *, char *));
+X
+Xstatic codeobject *
+Xnewcodeobject(code, consts, names, filename)
+X object *code;
+X object *consts;
+X object *names;
+X char *filename;
+X{
+X codeobject *co;
+X int i;
+X /* Check argument types */
+X if (code == NULL || !is_stringobject(code) ||
+X consts == NULL || !is_listobject(consts) ||
+X names == NULL || !is_listobject(names)) {
+X err_badcall();
+X return NULL;
+X }
+X /* Make sure the list of names contains only strings */
+X for (i = getlistsize(names); --i >= 0; ) {
+X object *v = getlistitem(names, i);
+X if (v == NULL || !is_stringobject(v)) {
+X err_badcall();
+X return NULL;
+X }
+X }
+X co = NEWOBJ(codeobject, &Codetype);
+X if (co != NULL) {
+X INCREF(code);
+X co->co_code = (stringobject *)code;
+X INCREF(consts);
+X co->co_consts = consts;
+X INCREF(names);
+X co->co_names = names;
+X if ((co->co_filename = newstringobject(filename)) == NULL) {
+X DECREF(co);
+X co = NULL;
+X }
+X }
+X return co;
+X}
+X
+X
+X/* Data structure used internally */
+Xstruct compiling {
+X object *c_code; /* string */
+X object *c_consts; /* list of objects */
+X object *c_names; /* list of strings (names) */
+X int c_nexti; /* index into c_code */
+X int c_errors; /* counts errors occurred */
+X int c_infunction; /* set when compiling a function */
+X int c_loops; /* counts nested loops */
+X char *c_filename; /* filename of current node */
+X};
+X
+X/* Prototypes */
+Xstatic int com_init PROTO((struct compiling *, char *));
+Xstatic void com_free PROTO((struct compiling *));
+Xstatic void com_done PROTO((struct compiling *));
+Xstatic void com_node PROTO((struct compiling *, struct _node *));
+Xstatic void com_addbyte PROTO((struct compiling *, int));
+Xstatic void com_addint PROTO((struct compiling *, int));
+Xstatic void com_addoparg PROTO((struct compiling *, int, int));
+Xstatic void com_addfwref PROTO((struct compiling *, int, int *));
+Xstatic void com_backpatch PROTO((struct compiling *, int));
+Xstatic int com_add PROTO((struct compiling *, object *, object *));
+Xstatic int com_addconst PROTO((struct compiling *, object *));
+Xstatic int com_addname PROTO((struct compiling *, object *));
+Xstatic void com_addopname PROTO((struct compiling *, int, node *));
+X
+Xstatic int
+Xcom_init(c, filename)
+X struct compiling *c;
+X char *filename;
+X{
+X if ((c->c_code = newsizedstringobject((char *)NULL, 0)) == NULL)
+X goto fail_3;
+X if ((c->c_consts = newlistobject(0)) == NULL)
+X goto fail_2;
+X if ((c->c_names = newlistobject(0)) == NULL)
+X goto fail_1;
+X c->c_nexti = 0;
+X c->c_errors = 0;
+X c->c_infunction = 0;
+X c->c_loops = 0;
+X c->c_filename = filename;
+X return 1;
+X
+X fail_1:
+X DECREF(c->c_consts);
+X fail_2:
+X DECREF(c->c_code);
+X fail_3:
+X return 0;
+X}
+X
+Xstatic void
+Xcom_free(c)
+X struct compiling *c;
+X{
+X XDECREF(c->c_code);
+X XDECREF(c->c_consts);
+X XDECREF(c->c_names);
+X}
+X
+Xstatic void
+Xcom_done(c)
+X struct compiling *c;
+X{
+X if (c->c_code != NULL)
+X resizestring(&c->c_code, c->c_nexti);
+X}
+X
+Xstatic void
+Xcom_addbyte(c, byte)
+X struct compiling *c;
+X int byte;
+X{
+X int len;
+X if (byte < 0 || byte > 255) {
+X fprintf(stderr, "XXX compiling bad byte: %d\n", byte);
+X abort();
+X err_setstr(SystemError, "com_addbyte: byte out of range");
+X c->c_errors++;
+X }
+X if (c->c_code == NULL)
+X return;
+X len = getstringsize(c->c_code);
+X if (c->c_nexti >= len) {
+X if (resizestring(&c->c_code, len+1000) != 0) {
+X c->c_errors++;
+X return;
+X }
+X }
+X getstringvalue(c->c_code)[c->c_nexti++] = byte;
+X}
+X
+Xstatic void
+Xcom_addint(c, x)
+X struct compiling *c;
+X int x;
+X{
+X com_addbyte(c, x & 0xff);
+X com_addbyte(c, x >> 8); /* XXX x should be positive */
+X}
+X
+Xstatic void
+Xcom_addoparg(c, op, arg)
+X struct compiling *c;
+X int op;
+X int arg;
+X{
+X com_addbyte(c, op);
+X com_addint(c, arg);
+X}
+X
+Xstatic void
+Xcom_addfwref(c, op, p_anchor)
+X struct compiling *c;
+X int op;
+X int *p_anchor;
+X{
+X /* Compile a forward reference for backpatching */
+X int here;
+X int anchor;
+X com_addbyte(c, op);
+X here = c->c_nexti;
+X anchor = *p_anchor;
+X *p_anchor = here;
+X com_addint(c, anchor == 0 ? 0 : here - anchor);
+X}
+X
+Xstatic void
+Xcom_backpatch(c, anchor)
+X struct compiling *c;
+X int anchor; /* Must be nonzero */
+X{
+X unsigned char *code = (unsigned char *) getstringvalue(c->c_code);
+X int target = c->c_nexti;
+X int lastanchor = 0;
+X int dist;
+X int prev;
+X for (;;) {
+X /* Make the JUMP instruction at anchor point to target */
+X prev = code[anchor] + (code[anchor+1] << 8);
+X dist = target - (anchor+2);
+X code[anchor] = dist & 0xff;
+X code[anchor+1] = dist >> 8;
+X if (!prev)
+X break;
+X lastanchor = anchor;
+X anchor -= prev;
+X }
+X}
+X
+X/* Handle constants and names uniformly */
+X
+Xstatic int
+Xcom_add(c, list, v)
+X struct compiling *c;
+X object *list;
+X object *v;
+X{
+X int n = getlistsize(list);
+X int i;
+X for (i = n; --i >= 0; ) {
+X object *w = getlistitem(list, i);
+X if (cmpobject(v, w) == 0)
+X return i;
+X }
+X if (addlistitem(list, v) != 0)
+X c->c_errors++;
+X return n;
+X}
+X
+Xstatic int
+Xcom_addconst(c, v)
+X struct compiling *c;
+X object *v;
+X{
+X return com_add(c, c->c_consts, v);
+X}
+X
+Xstatic int
+Xcom_addname(c, v)
+X struct compiling *c;
+X object *v;
+X{
+X return com_add(c, c->c_names, v);
+X}
+X
+Xstatic void
+Xcom_addopname(c, op, n)
+X struct compiling *c;
+X int op;
+X node *n;
+X{
+X object *v;
+X int i;
+X char *name;
+X if (TYPE(n) == STAR)
+X name = "*";
+X else {
+X REQ(n, NAME);
+X name = STR(n);
+X }
+X if ((v = newstringobject(name)) == NULL) {
+X c->c_errors++;
+X i = 255;
+X }
+X else {
+X i = com_addname(c, v);
+X DECREF(v);
+X }
+X com_addoparg(c, op, i);
+X}
+X
+Xstatic object *
+Xparsenumber(s)
+X char *s;
+X{
+X extern long strtol();
+X extern double atof();
+X char *end = s;
+X long x;
+X x = strtol(s, &end, 0);
+X if (*end == '\0')
+X return newintobject(x);
+X if (*end == '.' || *end == 'e' || *end == 'E')
+X return newfloatobject(atof(s));
+X err_setstr(RuntimeError, "bad number syntax");
+X return NULL;
+X}
+X
+Xstatic object *
+Xparsestr(s)
+X char *s;
+X{
+X object *v;
+X int len;
+X char *buf;
+X char *p;
+X int c;
+X if (*s != '\'') {
+X err_badcall();
+X return NULL;
+X }
+X s++;
+X len = strlen(s);
+X if (s[--len] != '\'') {
+X err_badcall();
+X return NULL;
+X }
+X if (strchr(s, '\\') == NULL)
+X return newsizedstringobject(s, len);
+X v = newsizedstringobject((char *)NULL, len);
+X p = buf = getstringvalue(v);
+X while (*s != '\0' && *s != '\'') {
+X if (*s != '\\') {
+X *p++ = *s++;
+X continue;
+X }
+X s++;
+X switch (*s++) {
+X /* XXX This assumes ASCII! */
+X case '\\': *p++ = '\\'; break;
+X case '\'': *p++ = '\''; break;
+X case 'b': *p++ = '\b'; break;
+X case 'f': *p++ = '\014'; break; /* FF */
+X case 't': *p++ = '\t'; break;
+X case 'n': *p++ = '\n'; break;
+X case 'r': *p++ = '\r'; break;
+X case 'v': *p++ = '\013'; break; /* VT */
+X case 'E': *p++ = '\033'; break; /* ESC, not C */
+X case 'a': *p++ = '\007'; break; /* BEL, not classic C */
+X case '0': case '1': case '2': case '3':
+X case '4': case '5': case '6': case '7':
+X c = s[-1] - '0';
+X if ('0' <= *s && *s <= '7') {
+X c = (c<<3) + *s++ - '0';
+X if ('0' <= *s && *s <= '7')
+X c = (c<<3) + *s++ - '0';
+X }
+X *p++ = c;
+X break;
+X case 'x':
+X if (isxdigit(*s)) {
+X sscanf(s, "%x", &c);
+X *p++ = c;
+X do {
+X s++;
+X } while (isxdigit(*s));
+X break;
+X }
+X /* FALLTHROUGH */
+X default: *p++ = '\\'; *p++ = s[-1]; break;
+X }
+X }
+X resizestring(&v, (int)(p - buf));
+X return v;
+X}
+X
+Xstatic void
+Xcom_list_constructor(c, n)
+X struct compiling *c;
+X node *n;
+X{
+X int len;
+X int i;
+X object *v, *w;
+X if (TYPE(n) != testlist)
+X REQ(n, exprlist);
+X /* exprlist: expr (',' expr)* [',']; likewise for testlist */
+X len = (NCH(n) + 1) / 2;
+X for (i = 0; i < NCH(n); i += 2)
+X com_node(c, CHILD(n, i));
+X com_addoparg(c, BUILD_LIST, len);
+X}
+X
+Xstatic void
+Xcom_atom(c, n)
+X struct compiling *c;
+X node *n;
+X{
+X node *ch;
+X object *v;
+X int i;
+X REQ(n, atom);
+X ch = CHILD(n, 0);
+X switch (TYPE(ch)) {
+X case LPAR:
+X if (TYPE(CHILD(n, 1)) == RPAR)
+X com_addoparg(c, BUILD_TUPLE, 0);
+X else
+X com_node(c, CHILD(n, 1));
+X break;
+X case LSQB:
+X if (TYPE(CHILD(n, 1)) == RSQB)
+X com_addoparg(c, BUILD_LIST, 0);
+X else
+X com_list_constructor(c, CHILD(n, 1));
+X break;
+X case LBRACE:
+X com_addoparg(c, BUILD_MAP, 0);
+X break;
+X case BACKQUOTE:
+X com_node(c, CHILD(n, 1));
+X com_addbyte(c, UNARY_CONVERT);
+X break;
+X case NUMBER:
+X if ((v = parsenumber(STR(ch))) == NULL) {
+X c->c_errors++;
+X i = 255;
+X }
+X else {
+X i = com_addconst(c, v);
+X DECREF(v);
+X }
+X com_addoparg(c, LOAD_CONST, i);
+X break;
+X case STRING:
+X if ((v = parsestr(STR(ch))) == NULL) {
+X c->c_errors++;
+X i = 255;
+X }
+X else {
+X i = com_addconst(c, v);
+X DECREF(v);
+X }
+X com_addoparg(c, LOAD_CONST, i);
+X break;
+X case NAME:
+X com_addopname(c, LOAD_NAME, ch);
+X break;
+X default:
+X fprintf(stderr, "node type %d\n", TYPE(ch));
+X err_setstr(SystemError, "com_atom: unexpected node type");
+X c->c_errors++;
+X }
+X}
+X
+Xstatic void
+Xcom_slice(c, n, op)
+X struct compiling *c;
+X node *n;
+X int op;
+X{
+X if (NCH(n) == 1) {
+X com_addbyte(c, op);
+X }
+X else if (NCH(n) == 2) {
+X if (TYPE(CHILD(n, 0)) != COLON) {
+X com_node(c, CHILD(n, 0));
+X com_addbyte(c, op+1);
+X }
+X else {
+X com_node(c, CHILD(n, 1));
+X com_addbyte(c, op+2);
+X }
+X }
+X else {
+X com_node(c, CHILD(n, 0));
+X com_node(c, CHILD(n, 2));
+X com_addbyte(c, op+3);
+X }
+X}
+X
+Xstatic void
+Xcom_apply_subscript(c, n)
+X struct compiling *c;
+X node *n;
+X{
+X REQ(n, subscript);
+X if (NCH(n) == 1 && TYPE(CHILD(n, 0)) != COLON) {
+X /* It's a single subscript */
+X com_node(c, CHILD(n, 0));
+X com_addbyte(c, BINARY_SUBSCR);
+X }
+X else {
+X /* It's a slice: [expr] ':' [expr] */
+X com_slice(c, n, SLICE);
+X }
+X}
+X
+Xstatic void
+Xcom_call_function(c, n)
+X struct compiling *c;
+X node *n; /* EITHER testlist OR ')' */
+X{
+X if (TYPE(n) == RPAR) {
+X com_addbyte(c, UNARY_CALL);
+X }
+X else {
+X com_node(c, n);
+X com_addbyte(c, BINARY_CALL);
+X }
+X}
+X
+Xstatic void
+Xcom_select_member(c, n)
+X struct compiling *c;
+X node *n;
+X{
+X com_addopname(c, LOAD_ATTR, n);
+X}
+X
+Xstatic void
+Xcom_apply_trailer(c, n)
+X struct compiling *c;
+X node *n;
+X{
+X REQ(n, trailer);
+X switch (TYPE(CHILD(n, 0))) {
+X case LPAR:
+X com_call_function(c, CHILD(n, 1));
+X break;
+X case DOT:
+X com_select_member(c, CHILD(n, 1));
+X break;
+X case LSQB:
+X com_apply_subscript(c, CHILD(n, 1));
+X break;
+X default:
+X err_setstr(SystemError,
+X "com_apply_trailer: unknown trailer type");
+X c->c_errors++;
+X }
+X}
+X
+Xstatic void
+Xcom_factor(c, n)
+X struct compiling *c;
+X node *n;
+X{
+X int i;
+X REQ(n, factor);
+X if (TYPE(CHILD(n, 0)) == PLUS) {
+X com_factor(c, CHILD(n, 1));
+X com_addbyte(c, UNARY_POSITIVE);
+X }
+X else if (TYPE(CHILD(n, 0)) == MINUS) {
+X com_factor(c, CHILD(n, 1));
+X com_addbyte(c, UNARY_NEGATIVE);
+X }
+X else {
+X com_atom(c, CHILD(n, 0));
+X for (i = 1; i < NCH(n); i++)
+X com_apply_trailer(c, CHILD(n, i));
+X }
+X}
+X
+Xstatic void
+Xcom_term(c, n)
+X struct compiling *c;
+X node *n;
+X{
+X int i;
+X int op;
+X REQ(n, term);
+X com_factor(c, CHILD(n, 0));
+X for (i = 2; i < NCH(n); i += 2) {
+X com_factor(c, CHILD(n, i));
+X switch (TYPE(CHILD(n, i-1))) {
+X case STAR:
+X op = BINARY_MULTIPLY;
+X break;
+X case SLASH:
+X op = BINARY_DIVIDE;
+X break;
+X case PERCENT:
+X op = BINARY_MODULO;
+X break;
+X default:
+X err_setstr(SystemError,
+X "com_term: term operator not *, / or %");
+X c->c_errors++;
+X op = 255;
+X }
+X com_addbyte(c, op);
+X }
+X}
+X
+Xstatic void
+Xcom_expr(c, n)
+X struct compiling *c;
+X node *n;
+X{
+X int i;
+X int op;
+X REQ(n, expr);
+X com_term(c, CHILD(n, 0));
+X for (i = 2; i < NCH(n); i += 2) {
+X com_term(c, CHILD(n, i));
+X switch (TYPE(CHILD(n, i-1))) {
+X case PLUS:
+X op = BINARY_ADD;
+X break;
+X case MINUS:
+X op = BINARY_SUBTRACT;
+X break;
+X default:
+X err_setstr(SystemError,
+X "com_expr: expr operator not + or -");
+X c->c_errors++;
+X op = 255;
+X }
+X com_addbyte(c, op);
+X }
+X}
+X
+Xstatic enum cmp_op
+Xcmp_type(n)
+X node *n;
+X{
+X REQ(n, comp_op);
+X /* comp_op: '<' | '>' | '=' | '>' '=' | '<' '=' | '<' '>'
+X | 'in' | 'not' 'in' | 'is' | 'is' not' */
+X if (NCH(n) == 1) {
+X n = CHILD(n, 0);
+X switch (TYPE(n)) {
+X case LESS: return LT;
+X case GREATER: return GT;
+X case EQUAL: return EQ;
+X case NAME: if (strcmp(STR(n), "in") == 0) return IN;
+X if (strcmp(STR(n), "is") == 0) return IS;
+X }
+X }
+X else if (NCH(n) == 2) {
+X int t2 = TYPE(CHILD(n, 1));
+X switch (TYPE(CHILD(n, 0))) {
+X case LESS: if (t2 == EQUAL) return LE;
+X if (t2 == GREATER) return NE;
+X break;
+X case GREATER: if (t2 == EQUAL) return GE;
+X break;
+X case NAME: if (strcmp(STR(CHILD(n, 1)), "in") == 0)
+X return NOT_IN;
+X if (strcmp(STR(CHILD(n, 0)), "is") == 0)
+X return IS_NOT;
+X }
+X }
+X return BAD;
+X}
+X
+Xstatic void
+Xcom_comparison(c, n)
+X struct compiling *c;
+X node *n;
+X{
+X int i;
+X enum cmp_op op;
+X int anchor;
+X REQ(n, comparison); /* comparison: expr (comp_op expr)* */
+X com_expr(c, CHILD(n, 0));
+X if (NCH(n) == 1)
+X return;
+X
+X /****************************************************************
+X The following code is generated for all but the last
+X comparison in a chain:
+X
+X label: on stack: opcode: jump to:
+X
+X a <code to load b>
+X a, b DUP_TOP
+X a, b, b ROT_THREE
+X b, a, b COMPARE_OP
+X b, 0-or-1 JUMP_IF_FALSE L1
+X b, 1 POP_TOP
+X b
+X
+X We are now ready to repeat this sequence for the next
+X comparison in the chain.
+X
+X For the last we generate:
+X
+X b <code to load c>
+X b, c COMPARE_OP
+X 0-or-1
+X
+X If there were any jumps to L1 (i.e., there was more than one
+X comparison), we generate:
+X
+X 0-or-1 JUMP_FORWARD L2
+X L1: b, 0 ROT_TWO
+X 0, b POP_TOP
+X 0
+X L2:
+X ****************************************************************/
+X
+X anchor = 0;
+X
+X for (i = 2; i < NCH(n); i += 2) {
+X com_expr(c, CHILD(n, i));
+X if (i+2 < NCH(n)) {
+X com_addbyte(c, DUP_TOP);
+X com_addbyte(c, ROT_THREE);
+X }
+X op = cmp_type(CHILD(n, i-1));
+X if (op == BAD) {
+X err_setstr(SystemError,
+X "com_comparison: unknown comparison op");
+X c->c_errors++;
+X }
+X com_addoparg(c, COMPARE_OP, op);
+X if (i+2 < NCH(n)) {
+X com_addfwref(c, JUMP_IF_FALSE, &anchor);
+X com_addbyte(c, POP_TOP);
+X }
+X }
+X
+X if (anchor) {
+X int anchor2 = 0;
+X com_addfwref(c, JUMP_FORWARD, &anchor2);
+X com_backpatch(c, anchor);
+X com_addbyte(c, ROT_TWO);
+X com_addbyte(c, POP_TOP);
+X com_backpatch(c, anchor2);
+X }
+X}
+X
+Xstatic void
+Xcom_not_test(c, n)
+X struct compiling *c;
+X node *n;
+X{
+X REQ(n, not_test); /* 'not' not_test | comparison */
+X if (NCH(n) == 1) {
+X com_comparison(c, CHILD(n, 0));
+X }
+X else {
+X com_not_test(c, CHILD(n, 1));
+X com_addbyte(c, UNARY_NOT);
+X }
+X}
+X
+Xstatic void
+Xcom_and_test(c, n)
+X struct compiling *c;
+X node *n;
+X{
+X int i;
+X int anchor;
+X REQ(n, and_test); /* not_test ('and' not_test)* */
+X anchor = 0;
+X i = 0;
+X for (;;) {
+X com_not_test(c, CHILD(n, i));
+X if ((i += 2) >= NCH(n))
+X break;
+X com_addfwref(c, JUMP_IF_FALSE, &anchor);
+X com_addbyte(c, POP_TOP);
+X }
+X if (anchor)
+X com_backpatch(c, anchor);
+X}
+X
+Xstatic void
+Xcom_test(c, n)
+X struct compiling *c;
+X node *n;
+X{
+X int i;
+X int anchor;
+X REQ(n, test); /* and_test ('and' and_test)* */
+X anchor = 0;
+X i = 0;
+X for (;;) {
+X com_and_test(c, CHILD(n, i));
+X if ((i += 2) >= NCH(n))
+X break;
+X com_addfwref(c, JUMP_IF_TRUE, &anchor);
+X com_addbyte(c, POP_TOP);
+X }
+X if (anchor)
+X com_backpatch(c, anchor);
+X}
+X
+Xstatic void
+Xcom_list(c, n)
+X struct compiling *c;
+X node *n;
+X{
+X /* exprlist: expr (',' expr)* [',']; likewise for testlist */
+X if (NCH(n) == 1) {
+X com_node(c, CHILD(n, 0));
+X }
+X else {
+X int i;
+X int len;
+X len = (NCH(n) + 1) / 2;
+X for (i = 0; i < NCH(n); i += 2)
+X com_node(c, CHILD(n, i));
+X com_addoparg(c, BUILD_TUPLE, len);
+X }
+X}
+X
+X
+X/* Begin of assignment compilation */
+X
+Xstatic void com_assign_name PROTO((struct compiling *, node *, int));
+Xstatic void com_assign PROTO((struct compiling *, node *, int));
+X
+Xstatic void
+Xcom_assign_attr(c, n, assigning)
+X struct compiling *c;
+X node *n;
+X int assigning;
+X{
+X com_addopname(c, assigning ? STORE_ATTR : DELETE_ATTR, n);
+X}
+X
+Xstatic void
+Xcom_assign_slice(c, n, assigning)
+X struct compiling *c;
+X node *n;
+X int assigning;
+X{
+X com_slice(c, n, assigning ? STORE_SLICE : DELETE_SLICE);
+X}
+X
+Xstatic void
+Xcom_assign_subscript(c, n, assigning)
+X struct compiling *c;
+X node *n;
+X int assigning;
+X{
+X com_node(c, n);
+X com_addbyte(c, assigning ? STORE_SUBSCR : DELETE_SUBSCR);
+X}
+X
+Xstatic void
+Xcom_assign_trailer(c, n, assigning)
+X struct compiling *c;
+X node *n;
+X int assigning;
+X{
+X char *name;
+X REQ(n, trailer);
+X switch (TYPE(CHILD(n, 0))) {
+X case LPAR: /* '(' [exprlist] ')' */
+X err_setstr(TypeError, "can't assign to function call");
+X c->c_errors++;
+X break;
+X case DOT: /* '.' NAME */
+X com_assign_attr(c, CHILD(n, 1), assigning);
+X break;
+X case LSQB: /* '[' subscript ']' */
+X n = CHILD(n, 1);
+X REQ(n, subscript); /* subscript: expr | [expr] ':' [expr] */
+X if (NCH(n) > 1 || TYPE(CHILD(n, 0)) == COLON)
+X com_assign_slice(c, n, assigning);
+X else
+X com_assign_subscript(c, CHILD(n, 0), assigning);
+X break;
+X default:
+X err_setstr(TypeError, "unknown trailer type");
+X c->c_errors++;
+X }
+X}
+X
+Xstatic void
+Xcom_assign_tuple(c, n, assigning)
+X struct compiling *c;
+X node *n;
+X int assigning;
+X{
+X int i;
+X if (TYPE(n) != testlist)
+X REQ(n, exprlist);
+X if (assigning)
+X com_addoparg(c, UNPACK_TUPLE, (NCH(n)+1)/2);
+X for (i = 0; i < NCH(n); i += 2)
+X com_assign(c, CHILD(n, i), assigning);
+X}
+X
+Xstatic void
+Xcom_assign_list(c, n, assigning)
+X struct compiling *c;
+X node *n;
+X int assigning;
+X{
+X int i;
+X if (assigning)
+X com_addoparg(c, UNPACK_LIST, (NCH(n)+1)/2);
+X for (i = 0; i < NCH(n); i += 2)
+X com_assign(c, CHILD(n, i), assigning);
+X}
+X
+Xstatic void
+Xcom_assign_name(c, n, assigning)
+X struct compiling *c;
+X node *n;
+X int assigning;
+X{
+X REQ(n, NAME);
+X com_addopname(c, assigning ? STORE_NAME : DELETE_NAME, n);
+X}
+X
+Xstatic void
+Xcom_assign(c, n, assigning)
+X struct compiling *c;
+X node *n;
+X int assigning;
+X{
+X /* Loop to avoid trivial recursion */
+X for (;;) {
+X switch (TYPE(n)) {
+X
+X case exprlist:
+X case testlist:
+X if (NCH(n) > 1) {
+X com_assign_tuple(c, n, assigning);
+X return;
+X }
+X n = CHILD(n, 0);
+X break;
+X
+X case test:
+X case and_test:
+X case not_test:
+X if (NCH(n) > 1) {
+X err_setstr(TypeError,
+X "can't assign to operator");
+X c->c_errors++;
+X return;
+X }
+X n = CHILD(n, 0);
+X break;
+X
+X case comparison:
+X if (NCH(n) > 1) {
+X err_setstr(TypeError,
+X "can't assign to operator");
+X c->c_errors++;
+X return;
+X }
+X n = CHILD(n, 0);
+X break;
+X
+X case expr:
+X if (NCH(n) > 1) {
+X err_setstr(TypeError,
+X "can't assign to operator");
+X c->c_errors++;
+X return;
+X }
+X n = CHILD(n, 0);
+X break;
+X
+X case term:
+X if (NCH(n) > 1) {
+X err_setstr(TypeError,
+X "can't assign to operator");
+X c->c_errors++;
+X return;
+X }
+X n = CHILD(n, 0);
+X break;
+X
+X case factor: /* ('+'|'-') factor | atom trailer* */
+X if (TYPE(CHILD(n, 0)) != atom) { /* '+' | '-' */
+X err_setstr(TypeError,
+X "can't assign to operator");
+X c->c_errors++;
+X return;
+X }
+X if (NCH(n) > 1) { /* trailer present */
+X int i;
+X com_node(c, CHILD(n, 0));
+X for (i = 1; i+1 < NCH(n); i++) {
+X com_apply_trailer(c, CHILD(n, i));
+X } /* NB i is still alive */
+X com_assign_trailer(c,
+X CHILD(n, i), assigning);
+X return;
+X }
+X n = CHILD(n, 0);
+X break;
+X
+X case atom:
+X switch (TYPE(CHILD(n, 0))) {
+X case LPAR:
+X n = CHILD(n, 1);
+X if (TYPE(n) == RPAR) {
+X /* XXX Should allow () = () ??? */
+X err_setstr(TypeError,
+X "can't assign to ()");
+X c->c_errors++;
+X return;
+X }
+X break;
+X case LSQB:
+X n = CHILD(n, 1);
+X if (TYPE(n) == RSQB) {
+X err_setstr(TypeError,
+X "can't assign to []");
+X c->c_errors++;
+X return;
+X }
+X com_assign_list(c, n, assigning);
+X return;
+X case NAME:
+X com_assign_name(c, CHILD(n, 0), assigning);
+X return;
+X default:
+X err_setstr(TypeError,
+X "can't assign to constant");
+X c->c_errors++;
+X return;
+X }
+X break;
+X
+X default:
+X fprintf(stderr, "node type %d\n", TYPE(n));
+X err_setstr(SystemError, "com_assign: bad node");
+X c->c_errors++;
+X return;
+X
+X }
+X }
+X}
+X
+Xstatic void
+Xcom_expr_stmt(c, n)
+X struct compiling *c;
+X node *n;
+X{
+X REQ(n, expr_stmt); /* exprlist ('=' exprlist)* NEWLINE */
+X com_node(c, CHILD(n, NCH(n)-2));
+X if (NCH(n) == 2) {
+X com_addbyte(c, PRINT_EXPR);
+X }
+X else {
+X int i;
+X for (i = 0; i < NCH(n)-3; i+=2) {
+X if (i+2 < NCH(n)-3)
+X com_addbyte(c, DUP_TOP);
+X com_assign(c, CHILD(n, i), 1/*assign*/);
+X }
+X }
+X}
+X
+Xstatic void
+Xcom_print_stmt(c, n)
+X struct compiling *c;
+X node *n;
+X{
+X int i;
+X REQ(n, print_stmt); /* 'print' (test ',')* [test] NEWLINE */
+X for (i = 1; i+1 < NCH(n); i += 2) {
+X com_node(c, CHILD(n, i));
+X com_addbyte(c, PRINT_ITEM);
+X }
+X if (TYPE(CHILD(n, NCH(n)-2)) != COMMA)
+X com_addbyte(c, PRINT_NEWLINE);
+X /* XXX Alternatively, LOAD_CONST '\n' and then PRINT_ITEM */
+X}
+X
+Xstatic void
+Xcom_return_stmt(c, n)
+X struct compiling *c;
+X node *n;
+X{
+X REQ(n, return_stmt); /* 'return' [testlist] NEWLINE */
+X if (!c->c_infunction) {
+X err_setstr(TypeError, "'return' outside function");
+X c->c_errors++;
+X }
+X if (NCH(n) == 2)
+X com_addoparg(c, LOAD_CONST, com_addconst(c, None));
+X else
+X com_node(c, CHILD(n, 1));
+X com_addbyte(c, RETURN_VALUE);
+X}
+X
+Xstatic void
+Xcom_raise_stmt(c, n)
+X struct compiling *c;
+X node *n;
+X{
+X REQ(n, raise_stmt); /* 'raise' expr [',' expr] NEWLINE */
+X com_node(c, CHILD(n, 1));
+X if (NCH(n) > 3)
+X com_node(c, CHILD(n, 3));
+X else
+X com_addoparg(c, LOAD_CONST, com_addconst(c, None));
+X com_addbyte(c, RAISE_EXCEPTION);
+X}
+X
+Xstatic void
+Xcom_import_stmt(c, n)
+X struct compiling *c;
+X node *n;
+X{
+X int i;
+X REQ(n, import_stmt);
+X /* 'import' NAME (',' NAME)* NEWLINE |
+X 'from' NAME 'import' ('*' | NAME (',' NAME)*) NEWLINE */
+X if (STR(CHILD(n, 0))[0] == 'f') {
+X /* 'from' NAME 'import' ... */
+X REQ(CHILD(n, 1), NAME);
+X com_addopname(c, IMPORT_NAME, CHILD(n, 1));
+X for (i = 3; i < NCH(n); i += 2)
+X com_addopname(c, IMPORT_FROM, CHILD(n, i));
+X com_addbyte(c, POP_TOP);
+X }
+X else {
+X /* 'import' ... */
+X for (i = 1; i < NCH(n); i += 2) {
+X com_addopname(c, IMPORT_NAME, CHILD(n, i));
+X com_addopname(c, STORE_NAME, CHILD(n, i));
+X }
+X }
+X}
+X
+Xstatic void
+Xcom_if_stmt(c, n)
+X struct compiling *c;
+X node *n;
+X{
+X int i;
+X int anchor = 0;
+X REQ(n, if_stmt);
+X /*'if' test ':' suite ('elif' test ':' suite)* ['else' ':' suite] */
+X for (i = 0; i+3 < NCH(n); i+=4) {
+X int a = 0;
+X node *ch = CHILD(n, i+1);
+X if (i > 0)
+X com_addoparg(c, SET_LINENO, ch->n_lineno);
+X com_node(c, CHILD(n, i+1));
+X com_addfwref(c, JUMP_IF_FALSE, &a);
+X com_addbyte(c, POP_TOP);
+X com_node(c, CHILD(n, i+3));
+X com_addfwref(c, JUMP_FORWARD, &anchor);
+X com_backpatch(c, a);
+X com_addbyte(c, POP_TOP);
+X }
+X if (i+2 < NCH(n))
+X com_node(c, CHILD(n, i+2));
+X com_backpatch(c, anchor);
+X}
+X
+Xstatic void
+Xcom_while_stmt(c, n)
+X struct compiling *c;
+X node *n;
+X{
+X int break_anchor = 0;
+X int anchor = 0;
+X int begin;
+X REQ(n, while_stmt); /* 'while' test ':' suite ['else' ':' suite] */
+X com_addfwref(c, SETUP_LOOP, &break_anchor);
+X begin = c->c_nexti;
+X com_addoparg(c, SET_LINENO, n->n_lineno);
+X com_node(c, CHILD(n, 1));
+X com_addfwref(c, JUMP_IF_FALSE, &anchor);
+X com_addbyte(c, POP_TOP);
+X c->c_loops++;
+X com_node(c, CHILD(n, 3));
+X c->c_loops--;
+X com_addoparg(c, JUMP_ABSOLUTE, begin);
+X com_backpatch(c, anchor);
+X com_addbyte(c, POP_TOP);
+X com_addbyte(c, POP_BLOCK);
+X if (NCH(n) > 4)
+X com_node(c, CHILD(n, 6));
+X com_backpatch(c, break_anchor);
+X}
+X
+Xstatic void
+Xcom_for_stmt(c, n)
+X struct compiling *c;
+X node *n;
+X{
+X object *v;
+X int break_anchor = 0;
+X int anchor = 0;
+X int begin;
+X REQ(n, for_stmt);
+X /* 'for' exprlist 'in' exprlist ':' suite ['else' ':' suite] */
+X com_addfwref(c, SETUP_LOOP, &break_anchor);
+X com_node(c, CHILD(n, 3));
+X v = newintobject(0L);
+X if (v == NULL)
+X c->c_errors++;
+X com_addoparg(c, LOAD_CONST, com_addconst(c, v));
+X XDECREF(v);
+X begin = c->c_nexti;
+X com_addoparg(c, SET_LINENO, n->n_lineno);
+X com_addfwref(c, FOR_LOOP, &anchor);
+X com_assign(c, CHILD(n, 1), 1/*assigning*/);
+X c->c_loops++;
+X com_node(c, CHILD(n, 5));
+X c->c_loops--;
+X com_addoparg(c, JUMP_ABSOLUTE, begin);
+X com_backpatch(c, anchor);
+X com_addbyte(c, POP_BLOCK);
+X if (NCH(n) > 8)
+X com_node(c, CHILD(n, 8));
+X com_backpatch(c, break_anchor);
+X}
+X
+X/* Although 'execpt' and 'finally' clauses can be combined
+X syntactically, they are compiled separately. In fact,
+X try: S
+X except E1: S1
+X except E2: S2
+X ...
+X finally: Sf
+X is equivalent to
+X try:
+X try: S
+X except E1: S1
+X except E2: S2
+X ...
+X finally: Sf
+X meaning that the 'finally' clause is entered even if things
+X go wrong again in an exception handler. Note that this is
+X not the case for exception handlers: at most one is entered.
+X
+X Code generated for "try: S finally: Sf" is as follows:
+X
+X SETUP_FINALLY L
+X <code for S>
+X POP_BLOCK
+X LOAD_CONST <nil>
+X L: <code for Sf>
+X END_FINALLY
+X
+X The special instructions use the block stack. Each block
+X stack entry contains the instruction that created it (here
+X SETUP_FINALLY), the level of the value stack at the time the
+X block stack entry was created, and a label (here L).
+X
+X SETUP_FINALLY:
+X Pushes the current value stack level and the label
+X onto the block stack.
+X POP_BLOCK:
+X Pops en entry from the block stack, and pops the value
+X stack until its level is the same as indicated on the
+X block stack. (The label is ignored.)
+X END_FINALLY:
+X Pops a variable number of entries from the *value* stack
+X and re-raises the exception they specify. The number of
+X entries popped depends on the (pseudo) exception type.
+X
+X The block stack is unwound when an exception is raised:
+X when a SETUP_FINALLY entry is found, the exception is pushed
+X onto the value stack (and the exception condition is cleared),
+X and the interpreter jumps to the label gotten from the block
+X stack.
+X
+X Code generated for "try: S except E1, V1: S1 except E2, V2: S2 ...":
+X (The contents of the value stack is shown in [], with the top
+X at the right; 'tb' is trace-back info, 'val' the exception's
+X associated value, and 'exc' the exception.)
+X
+X Value stack Label Instruction Argument
+X [] SETUP_EXCEPT L1
+X [] <code for S>
+X [] POP_BLOCK
+X [] JUMP_FORWARD L0
+X
+X [tb, val, exc] L1: DUP )
+X [tb, val, exc, exc] <evaluate E1> )
+X [tb, val, exc, exc, E1] COMPARE_OP EXC_MATCH ) only if E1
+X [tb, val, exc, 1-or-0] JUMP_IF_FALSE L2 )
+X [tb, val, exc, 1] POP )
+X [tb, val, exc] POP
+X [tb, val] <assign to V1> (or POP if no V1)
+X [tb] POP
+X [] <code for S1>
+X JUMP_FORWARD L0
+X
+X [tb, val, exc, 0] L2: POP
+X [tb, val, exc] DUP
+X .............................etc.......................
+X
+X [tb, val, exc, 0] Ln+1: POP
+X [tb, val, exc] END_FINALLY # re-raise exception
+X
+X [] L0: <next statement>
+X
+X Of course, parts are not generated if Vi or Ei is not present.
+X*/
+X
+Xstatic void
+Xcom_try_stmt(c, n)
+X struct compiling *c;
+X node *n;
+X{
+X int finally_anchor = 0;
+X int except_anchor = 0;
+X REQ(n, try_stmt);
+X /* 'try' ':' suite (except_clause ':' suite)* ['finally' ':' suite] */
+X
+X if (NCH(n) > 3 && TYPE(CHILD(n, NCH(n)-3)) != except_clause) {
+X /* Have a 'finally' clause */
+X com_addfwref(c, SETUP_FINALLY, &finally_anchor);
+X }
+X if (NCH(n) > 3 && TYPE(CHILD(n, 3)) == except_clause) {
+X /* Have an 'except' clause */
+X com_addfwref(c, SETUP_EXCEPT, &except_anchor);
+X }
+X com_node(c, CHILD(n, 2));
+X if (except_anchor) {
+X int end_anchor = 0;
+X int i;
+X node *ch;
+X com_addbyte(c, POP_BLOCK);
+X com_addfwref(c, JUMP_FORWARD, &end_anchor);
+X com_backpatch(c, except_anchor);
+X for (i = 3;
+X i < NCH(n) && TYPE(ch = CHILD(n, i)) == except_clause;
+X i += 3) {
+X /* except_clause: 'except' [expr [',' expr]] */
+X if (except_anchor == 0) {
+X err_setstr(TypeError,
+X "default 'except:' must be last");
+X c->c_errors++;
+X break;
+X }
+X except_anchor = 0;
+X com_addoparg(c, SET_LINENO, ch->n_lineno);
+X if (NCH(ch) > 1) {
+X com_addbyte(c, DUP_TOP);
+X com_node(c, CHILD(ch, 1));
+X com_addoparg(c, COMPARE_OP, EXC_MATCH);
+X com_addfwref(c, JUMP_IF_FALSE, &except_anchor);
+X com_addbyte(c, POP_TOP);
+X }
+X com_addbyte(c, POP_TOP);
+X if (NCH(ch) > 3)
+X com_assign(c, CHILD(ch, 3), 1/*assigning*/);
+X else
+X com_addbyte(c, POP_TOP);
+X com_addbyte(c, POP_TOP);
+X com_node(c, CHILD(n, i+2));
+X com_addfwref(c, JUMP_FORWARD, &end_anchor);
+X if (except_anchor) {
+X com_backpatch(c, except_anchor);
+X com_addbyte(c, POP_TOP);
+X }
+X }
+X com_addbyte(c, END_FINALLY);
+X com_backpatch(c, end_anchor);
+X }
+X if (finally_anchor) {
+X node *ch;
+X com_addbyte(c, POP_BLOCK);
+X com_addoparg(c, LOAD_CONST, com_addconst(c, None));
+X com_backpatch(c, finally_anchor);
+X ch = CHILD(n, NCH(n)-1);
+X com_addoparg(c, SET_LINENO, ch->n_lineno);
+X com_node(c, ch);
+X com_addbyte(c, END_FINALLY);
+X }
+X}
+X
+Xstatic void
+Xcom_suite(c, n)
+X struct compiling *c;
+X node *n;
+X{
+X REQ(n, suite);
+X /* simple_stmt | NEWLINE INDENT NEWLINE* (stmt NEWLINE*)+ DEDENT */
+X if (NCH(n) == 1) {
+X com_node(c, CHILD(n, 0));
+X }
+X else {
+X int i;
+X for (i = 0; i < NCH(n); i++) {
+X node *ch = CHILD(n, i);
+X if (TYPE(ch) == stmt)
+X com_node(c, ch);
+X }
+X }
+X}
+X
+Xstatic void
+Xcom_funcdef(c, n)
+X struct compiling *c;
+X node *n;
+X{
+X object *v;
+X REQ(n, funcdef); /* funcdef: 'def' NAME parameters ':' suite */
+X v = (object *)compile(n, c->c_filename);
+X if (v == NULL)
+X c->c_errors++;
+X else {
+X int i = com_addconst(c, v);
+X com_addoparg(c, LOAD_CONST, i);
+X com_addbyte(c, BUILD_FUNCTION);
+X com_addopname(c, STORE_NAME, CHILD(n, 1));
+X DECREF(v);
+X }
+X}
+X
+Xstatic void
+Xcom_bases(c, n)
+X struct compiling *c;
+X node *n;
+X{
+X int i, nbases;
+X REQ(n, baselist);
+X /*
+X baselist: atom arguments (',' atom arguments)*
+X arguments: '(' [testlist] ')'
+X */
+X for (i = 0; i < NCH(n); i += 3)
+X com_node(c, CHILD(n, i));
+X com_addoparg(c, BUILD_TUPLE, (NCH(n)+1) / 3);
+X}
+X
+Xstatic void
+Xcom_classdef(c, n)
+X struct compiling *c;
+X node *n;
+X{
+X object *v;
+X REQ(n, classdef);
+X /*
+X classdef: 'class' NAME parameters ['=' baselist] ':' suite
+X baselist: atom arguments (',' atom arguments)*
+X arguments: '(' [testlist] ')'
+X */
+X if (NCH(n) == 7)
+X com_bases(c, CHILD(n, 4));
+X else
+X com_addoparg(c, LOAD_CONST, com_addconst(c, None));
+X v = (object *)compile(n, c->c_filename);
+X if (v == NULL)
+X c->c_errors++;
+X else {
+X int i = com_addconst(c, v);
+X com_addoparg(c, LOAD_CONST, i);
+X com_addbyte(c, BUILD_FUNCTION);
+X com_addbyte(c, UNARY_CALL);
+X com_addbyte(c, BUILD_CLASS);
+X com_addopname(c, STORE_NAME, CHILD(n, 1));
+X DECREF(v);
+X }
+X}
+X
+Xstatic void
+Xcom_node(c, n)
+X struct compiling *c;
+X node *n;
+X{
+X switch (TYPE(n)) {
+X
+X /* Definition nodes */
+X
+X case funcdef:
+X com_funcdef(c, n);
+X break;
+X case classdef:
+X com_classdef(c, n);
+X break;
+X
+X /* Trivial parse tree nodes */
+X
+X case stmt:
+X case flow_stmt:
+X com_node(c, CHILD(n, 0));
+X break;
+X
+X case simple_stmt:
+X case compound_stmt:
+X com_addoparg(c, SET_LINENO, n->n_lineno);
+X com_node(c, CHILD(n, 0));
+X break;
+X
+X /* Statement nodes */
+X
+X case expr_stmt:
+X com_expr_stmt(c, n);
+X break;
+X case print_stmt:
+X com_print_stmt(c, n);
+X break;
+X case del_stmt: /* 'del' exprlist NEWLINE */
+X com_assign(c, CHILD(n, 1), 0/*delete*/);
+X break;
+X case pass_stmt:
+X break;
+X case break_stmt:
+X if (c->c_loops == 0) {
+X err_setstr(TypeError, "'break' outside loop");
+X c->c_errors++;
+X }
+X com_addbyte(c, BREAK_LOOP);
+X break;
+X case return_stmt:
+X com_return_stmt(c, n);
+X break;
+X case raise_stmt:
+X com_raise_stmt(c, n);
+X break;
+X case import_stmt:
+X com_import_stmt(c, n);
+X break;
+X case if_stmt:
+X com_if_stmt(c, n);
+X break;
+X case while_stmt:
+X com_while_stmt(c, n);
+X break;
+X case for_stmt:
+X com_for_stmt(c, n);
+X break;
+X case try_stmt:
+X com_try_stmt(c, n);
+X break;
+X case suite:
+X com_suite(c, n);
+X break;
+X
+X /* Expression nodes */
+X
+X case testlist:
+X com_list(c, n);
+X break;
+X case test:
+X com_test(c, n);
+X break;
+X case and_test:
+X com_and_test(c, n);
+X break;
+X case not_test:
+X com_not_test(c, n);
+X break;
+X case comparison:
+X com_comparison(c, n);
+X break;
+X case exprlist:
+X com_list(c, n);
+X break;
+X case expr:
+X com_expr(c, n);
+X break;
+X case term:
+X com_term(c, n);
+X break;
+X case factor:
+X com_factor(c, n);
+X break;
+X case atom:
+X com_atom(c, n);
+X break;
+X
+X default:
+X fprintf(stderr, "node type %d\n", TYPE(n));
+X err_setstr(SystemError, "com_node: unexpected node type");
+X c->c_errors++;
+X }
+X}
+X
+Xstatic void com_fplist PROTO((struct compiling *, node *));
+X
+Xstatic void
+Xcom_fpdef(c, n)
+X struct compiling *c;
+X node *n;
+X{
+X REQ(n, fpdef); /* fpdef: NAME | '(' fplist ')' */
+X if (TYPE(CHILD(n, 0)) == LPAR)
+X com_fplist(c, CHILD(n, 1));
+X else
+X com_addopname(c, STORE_NAME, CHILD(n, 0));
+X}
+X
+Xstatic void
+Xcom_fplist(c, n)
+X struct compiling *c;
+X node *n;
+X{
+X REQ(n, fplist); /* fplist: fpdef (',' fpdef)* */
+X if (NCH(n) == 1) {
+X com_fpdef(c, CHILD(n, 0));
+X }
+X else {
+X int i;
+X com_addoparg(c, UNPACK_TUPLE, (NCH(n)+1)/2);
+X for (i = 0; i < NCH(n); i += 2)
+X com_fpdef(c, CHILD(n, i));
+X }
+X}
+X
+Xstatic void
+Xcom_file_input(c, n)
+X struct compiling *c;
+X node *n;
+X{
+X int i;
+X REQ(n, file_input); /* (NEWLINE | stmt)* ENDMARKER */
+X for (i = 0; i < NCH(n); i++) {
+X node *ch = CHILD(n, i);
+X if (TYPE(ch) != ENDMARKER && TYPE(ch) != NEWLINE)
+X com_node(c, ch);
+X }
+X}
+X
+X/* Top-level compile-node interface */
+X
+Xstatic void
+Xcompile_funcdef(c, n)
+X struct compiling *c;
+X node *n;
+X{
+X node *ch;
+X REQ(n, funcdef); /* funcdef: 'def' NAME parameters ':' suite */
+X ch = CHILD(n, 2); /* parameters: '(' [fplist] ')' */
+X ch = CHILD(ch, 1); /* ')' | fplist */
+X if (TYPE(ch) == RPAR)
+X com_addbyte(c, REFUSE_ARGS);
+X else {
+X com_addbyte(c, REQUIRE_ARGS);
+X com_fplist(c, ch);
+X }
+X c->c_infunction = 1;
+X com_node(c, CHILD(n, 4));
+X c->c_infunction = 0;
+X com_addoparg(c, LOAD_CONST, com_addconst(c, None));
+X com_addbyte(c, RETURN_VALUE);
+X}
+X
+Xstatic void
+Xcompile_node(c, n)
+X struct compiling *c;
+X node *n;
+X{
+X com_addoparg(c, SET_LINENO, n->n_lineno);
+X
+X switch (TYPE(n)) {
+X
+X case single_input: /* One interactive command */
+X /* NEWLINE | simple_stmt | compound_stmt NEWLINE */
+X com_addbyte(c, REFUSE_ARGS);
+X n = CHILD(n, 0);
+X if (TYPE(n) != NEWLINE)
+X com_node(c, n);
+X com_addoparg(c, LOAD_CONST, com_addconst(c, None));
+X com_addbyte(c, RETURN_VALUE);
+X break;
+X
+X case file_input: /* A whole file, or built-in function exec() */
+X com_addbyte(c, REFUSE_ARGS);
+X com_file_input(c, n);
+X com_addoparg(c, LOAD_CONST, com_addconst(c, None));
+X com_addbyte(c, RETURN_VALUE);
+X break;
+X
+X case expr_input: /* Built-in function eval() */
+X com_addbyte(c, REFUSE_ARGS);
+X com_node(c, CHILD(n, 0));
+X com_addbyte(c, RETURN_VALUE);
+X break;
+X
+X case eval_input: /* Built-in function input() */
+X com_addbyte(c, REFUSE_ARGS);
+X com_node(c, CHILD(n, 0));
+X com_addbyte(c, RETURN_VALUE);
+X break;
+X
+X case funcdef: /* A function definition */
+X compile_funcdef(c, n);
+X break;
+X
+X case classdef: /* A class definition */
+X /* 'class' NAME parameters ['=' baselist] ':' suite */
+X com_addbyte(c, REFUSE_ARGS);
+X com_node(c, CHILD(n, NCH(n)-1));
+X com_addbyte(c, LOAD_LOCALS);
+X com_addbyte(c, RETURN_VALUE);
+X break;
+X
+X default:
+X fprintf(stderr, "node type %d\n", TYPE(n));
+X err_setstr(SystemError, "compile_node: unexpected node type");
+X c->c_errors++;
+X }
+X}
+X
+Xcodeobject *
+Xcompile(n, filename)
+X node *n;
+X char *filename;
+X{
+X struct compiling sc;
+X codeobject *co;
+X if (!com_init(&sc, filename))
+X return NULL;
+X compile_node(&sc, n);
+X com_done(&sc);
+X if (sc.c_errors == 0)
+X co = newcodeobject(sc.c_code, sc.c_consts, sc.c_names, filename);
+X else
+X co = NULL;
+X com_free(&sc);
+X return co;
+X}
+EOF
+fi
+if test -s 'src/graminit.c'
+then echo '*** I will not over-write existing file src/graminit.c'
+else
+echo 'x - src/graminit.c'
+sed 's/^X//' > 'src/graminit.c' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X#include "pgenheaders.h"
+X#include "grammar.h"
+Xstatic arc arcs_0_0[3] = {
+X {2, 1},
+X {3, 1},
+X {4, 2},
+X};
+Xstatic arc arcs_0_1[1] = {
+X {0, 1},
+X};
+Xstatic arc arcs_0_2[1] = {
+X {2, 1},
+X};
+Xstatic state states_0[3] = {
+X {3, arcs_0_0},
+X {1, arcs_0_1},
+X {1, arcs_0_2},
+X};
+Xstatic arc arcs_1_0[3] = {
+X {2, 0},
+X {6, 0},
+X {7, 1},
+X};
+Xstatic arc arcs_1_1[1] = {
+X {0, 1},
+X};
+Xstatic state states_1[2] = {
+X {3, arcs_1_0},
+X {1, arcs_1_1},
+X};
+Xstatic arc arcs_2_0[1] = {
+X {9, 1},
+X};
+Xstatic arc arcs_2_1[1] = {
+X {2, 2},
+X};
+Xstatic arc arcs_2_2[1] = {
+X {0, 2},
+X};
+Xstatic state states_2[3] = {
+X {1, arcs_2_0},
+X {1, arcs_2_1},
+X {1, arcs_2_2},
+X};
+Xstatic arc arcs_3_0[1] = {
+X {9, 1},
+X};
+Xstatic arc arcs_3_1[1] = {
+X {7, 2},
+X};
+Xstatic arc arcs_3_2[1] = {
+X {0, 2},
+X};
+Xstatic state states_3[3] = {
+X {1, arcs_3_0},
+X {1, arcs_3_1},
+X {1, arcs_3_2},
+X};
+Xstatic arc arcs_4_0[1] = {
+X {12, 1},
+X};
+Xstatic arc arcs_4_1[1] = {
+X {13, 2},
+X};
+Xstatic arc arcs_4_2[1] = {
+X {14, 3},
+X};
+Xstatic arc arcs_4_3[1] = {
+X {15, 4},
+X};
+Xstatic arc arcs_4_4[1] = {
+X {16, 5},
+X};
+Xstatic arc arcs_4_5[1] = {
+X {0, 5},
+X};
+Xstatic state states_4[6] = {
+X {1, arcs_4_0},
+X {1, arcs_4_1},
+X {1, arcs_4_2},
+X {1, arcs_4_3},
+X {1, arcs_4_4},
+X {1, arcs_4_5},
+X};
+Xstatic arc arcs_5_0[1] = {
+X {17, 1},
+X};
+Xstatic arc arcs_5_1[2] = {
+X {18, 2},
+X {19, 3},
+X};
+Xstatic arc arcs_5_2[1] = {
+X {19, 3},
+X};
+Xstatic arc arcs_5_3[1] = {
+X {0, 3},
+X};
+Xstatic state states_5[4] = {
+X {1, arcs_5_0},
+X {2, arcs_5_1},
+X {1, arcs_5_2},
+X {1, arcs_5_3},
+X};
+Xstatic arc arcs_6_0[1] = {
+X {20, 1},
+X};
+Xstatic arc arcs_6_1[2] = {
+X {21, 0},
+X {0, 1},
+X};
+Xstatic state states_6[2] = {
+X {1, arcs_6_0},
+X {2, arcs_6_1},
+X};
+Xstatic arc arcs_7_0[2] = {
+X {13, 1},
+X {17, 2},
+X};
+Xstatic arc arcs_7_1[1] = {
+X {0, 1},
+X};
+Xstatic arc arcs_7_2[1] = {
+X {18, 3},
+X};
+Xstatic arc arcs_7_3[1] = {
+X {19, 1},
+X};
+Xstatic state states_7[4] = {
+X {2, arcs_7_0},
+X {1, arcs_7_1},
+X {1, arcs_7_2},
+X {1, arcs_7_3},
+X};
+Xstatic arc arcs_8_0[2] = {
+X {3, 1},
+X {4, 1},
+X};
+Xstatic arc arcs_8_1[1] = {
+X {0, 1},
+X};
+Xstatic state states_8[2] = {
+X {2, arcs_8_0},
+X {1, arcs_8_1},
+X};
+Xstatic arc arcs_9_0[6] = {
+X {22, 1},
+X {23, 1},
+X {24, 1},
+X {25, 1},
+X {26, 1},
+X {27, 1},
+X};
+Xstatic arc arcs_9_1[1] = {
+X {0, 1},
+X};
+Xstatic state states_9[2] = {
+X {6, arcs_9_0},
+X {1, arcs_9_1},
+X};
+Xstatic arc arcs_10_0[1] = {
+X {28, 1},
+X};
+Xstatic arc arcs_10_1[2] = {
+X {29, 0},
+X {2, 2},
+X};
+Xstatic arc arcs_10_2[1] = {
+X {0, 2},
+X};
+Xstatic state states_10[3] = {
+X {1, arcs_10_0},
+X {2, arcs_10_1},
+X {1, arcs_10_2},
+X};
+Xstatic arc arcs_11_0[1] = {
+X {30, 1},
+X};
+Xstatic arc arcs_11_1[2] = {
+X {31, 2},
+X {2, 3},
+X};
+Xstatic arc arcs_11_2[2] = {
+X {21, 1},
+X {2, 3},
+X};
+Xstatic arc arcs_11_3[1] = {
+X {0, 3},
+X};
+Xstatic state states_11[4] = {
+X {1, arcs_11_0},
+X {2, arcs_11_1},
+X {2, arcs_11_2},
+X {1, arcs_11_3},
+X};
+Xstatic arc arcs_12_0[1] = {
+X {32, 1},
+X};
+Xstatic arc arcs_12_1[1] = {
+X {28, 2},
+X};
+Xstatic arc arcs_12_2[1] = {
+X {2, 3},
+X};
+Xstatic arc arcs_12_3[1] = {
+X {0, 3},
+X};
+Xstatic state states_12[4] = {
+X {1, arcs_12_0},
+X {1, arcs_12_1},
+X {1, arcs_12_2},
+X {1, arcs_12_3},
+X};
+Xstatic arc arcs_13_0[1] = {
+X {33, 1},
+X};
+Xstatic arc arcs_13_1[1] = {
+X {2, 2},
+X};
+Xstatic arc arcs_13_2[1] = {
+X {0, 2},
+X};
+Xstatic state states_13[3] = {
+X {1, arcs_13_0},
+X {1, arcs_13_1},
+X {1, arcs_13_2},
+X};
+Xstatic arc arcs_14_0[3] = {
+X {34, 1},
+X {35, 1},
+X {36, 1},
+X};
+Xstatic arc arcs_14_1[1] = {
+X {0, 1},
+X};
+Xstatic state states_14[2] = {
+X {3, arcs_14_0},
+X {1, arcs_14_1},
+X};
+Xstatic arc arcs_15_0[1] = {
+X {37, 1},
+X};
+Xstatic arc arcs_15_1[1] = {
+X {2, 2},
+X};
+Xstatic arc arcs_15_2[1] = {
+X {0, 2},
+X};
+Xstatic state states_15[3] = {
+X {1, arcs_15_0},
+X {1, arcs_15_1},
+X {1, arcs_15_2},
+X};
+Xstatic arc arcs_16_0[1] = {
+X {38, 1},
+X};
+Xstatic arc arcs_16_1[2] = {
+X {9, 2},
+X {2, 3},
+X};
+Xstatic arc arcs_16_2[1] = {
+X {2, 3},
+X};
+Xstatic arc arcs_16_3[1] = {
+X {0, 3},
+X};
+Xstatic state states_16[4] = {
+X {1, arcs_16_0},
+X {2, arcs_16_1},
+X {1, arcs_16_2},
+X {1, arcs_16_3},
+X};
+Xstatic arc arcs_17_0[1] = {
+X {39, 1},
+X};
+Xstatic arc arcs_17_1[1] = {
+X {40, 2},
+X};
+Xstatic arc arcs_17_2[2] = {
+X {21, 3},
+X {2, 4},
+X};
+Xstatic arc arcs_17_3[1] = {
+X {40, 5},
+X};
+Xstatic arc arcs_17_4[1] = {
+X {0, 4},
+X};
+Xstatic arc arcs_17_5[1] = {
+X {2, 4},
+X};
+Xstatic state states_17[6] = {
+X {1, arcs_17_0},
+X {1, arcs_17_1},
+X {2, arcs_17_2},
+X {1, arcs_17_3},
+X {1, arcs_17_4},
+X {1, arcs_17_5},
+X};
+Xstatic arc arcs_18_0[2] = {
+X {41, 1},
+X {42, 2},
+X};
+Xstatic arc arcs_18_1[1] = {
+X {13, 3},
+X};
+Xstatic arc arcs_18_2[1] = {
+X {13, 4},
+X};
+Xstatic arc arcs_18_3[2] = {
+X {21, 1},
+X {2, 5},
+X};
+Xstatic arc arcs_18_4[1] = {
+X {41, 6},
+X};
+Xstatic arc arcs_18_5[1] = {
+X {0, 5},
+X};
+Xstatic arc arcs_18_6[2] = {
+X {43, 7},
+X {13, 8},
+X};
+Xstatic arc arcs_18_7[1] = {
+X {2, 5},
+X};
+Xstatic arc arcs_18_8[2] = {
+X {21, 9},
+X {2, 5},
+X};
+Xstatic arc arcs_18_9[1] = {
+X {13, 8},
+X};
+Xstatic state states_18[10] = {
+X {2, arcs_18_0},
+X {1, arcs_18_1},
+X {1, arcs_18_2},
+X {2, arcs_18_3},
+X {1, arcs_18_4},
+X {1, arcs_18_5},
+X {2, arcs_18_6},
+X {1, arcs_18_7},
+X {2, arcs_18_8},
+X {1, arcs_18_9},
+X};
+Xstatic arc arcs_19_0[6] = {
+X {44, 1},
+X {45, 1},
+X {46, 1},
+X {47, 1},
+X {11, 1},
+X {48, 1},
+X};
+Xstatic arc arcs_19_1[1] = {
+X {0, 1},
+X};
+Xstatic state states_19[2] = {
+X {6, arcs_19_0},
+X {1, arcs_19_1},
+X};
+Xstatic arc arcs_20_0[1] = {
+X {49, 1},
+X};
+Xstatic arc arcs_20_1[1] = {
+X {31, 2},
+X};
+Xstatic arc arcs_20_2[1] = {
+X {15, 3},
+X};
+Xstatic arc arcs_20_3[1] = {
+X {16, 4},
+X};
+Xstatic arc arcs_20_4[3] = {
+X {50, 1},
+X {51, 5},
+X {0, 4},
+X};
+Xstatic arc arcs_20_5[1] = {
+X {15, 6},
+X};
+Xstatic arc arcs_20_6[1] = {
+X {16, 7},
+X};
+Xstatic arc arcs_20_7[1] = {
+X {0, 7},
+X};
+Xstatic state states_20[8] = {
+X {1, arcs_20_0},
+X {1, arcs_20_1},
+X {1, arcs_20_2},
+X {1, arcs_20_3},
+X {3, arcs_20_4},
+X {1, arcs_20_5},
+X {1, arcs_20_6},
+X {1, arcs_20_7},
+X};
+Xstatic arc arcs_21_0[1] = {
+X {52, 1},
+X};
+Xstatic arc arcs_21_1[1] = {
+X {31, 2},
+X};
+Xstatic arc arcs_21_2[1] = {
+X {15, 3},
+X};
+Xstatic arc arcs_21_3[1] = {
+X {16, 4},
+X};
+Xstatic arc arcs_21_4[2] = {
+X {51, 5},
+X {0, 4},
+X};
+Xstatic arc arcs_21_5[1] = {
+X {15, 6},
+X};
+Xstatic arc arcs_21_6[1] = {
+X {16, 7},
+X};
+Xstatic arc arcs_21_7[1] = {
+X {0, 7},
+X};
+Xstatic state states_21[8] = {
+X {1, arcs_21_0},
+X {1, arcs_21_1},
+X {1, arcs_21_2},
+X {1, arcs_21_3},
+X {2, arcs_21_4},
+X {1, arcs_21_5},
+X {1, arcs_21_6},
+X {1, arcs_21_7},
+X};
+Xstatic arc arcs_22_0[1] = {
+X {53, 1},
+X};
+Xstatic arc arcs_22_1[1] = {
+X {28, 2},
+X};
+Xstatic arc arcs_22_2[1] = {
+X {54, 3},
+X};
+Xstatic arc arcs_22_3[1] = {
+X {28, 4},
+X};
+Xstatic arc arcs_22_4[1] = {
+X {15, 5},
+X};
+Xstatic arc arcs_22_5[1] = {
+X {16, 6},
+X};
+Xstatic arc arcs_22_6[2] = {
+X {51, 7},
+X {0, 6},
+X};
+Xstatic arc arcs_22_7[1] = {
+X {15, 8},
+X};
+Xstatic arc arcs_22_8[1] = {
+X {16, 9},
+X};
+Xstatic arc arcs_22_9[1] = {
+X {0, 9},
+X};
+Xstatic state states_22[10] = {
+X {1, arcs_22_0},
+X {1, arcs_22_1},
+X {1, arcs_22_2},
+X {1, arcs_22_3},
+X {1, arcs_22_4},
+X {1, arcs_22_5},
+X {2, arcs_22_6},
+X {1, arcs_22_7},
+X {1, arcs_22_8},
+X {1, arcs_22_9},
+X};
+Xstatic arc arcs_23_0[1] = {
+X {55, 1},
+X};
+Xstatic arc arcs_23_1[1] = {
+X {15, 2},
+X};
+Xstatic arc arcs_23_2[1] = {
+X {16, 3},
+X};
+Xstatic arc arcs_23_3[3] = {
+X {56, 1},
+X {57, 4},
+X {0, 3},
+X};
+Xstatic arc arcs_23_4[1] = {
+X {15, 5},
+X};
+Xstatic arc arcs_23_5[1] = {
+X {16, 6},
+X};
+Xstatic arc arcs_23_6[1] = {
+X {0, 6},
+X};
+Xstatic state states_23[7] = {
+X {1, arcs_23_0},
+X {1, arcs_23_1},
+X {1, arcs_23_2},
+X {3, arcs_23_3},
+X {1, arcs_23_4},
+X {1, arcs_23_5},
+X {1, arcs_23_6},
+X};
+Xstatic arc arcs_24_0[1] = {
+X {58, 1},
+X};
+Xstatic arc arcs_24_1[2] = {
+X {40, 2},
+X {0, 1},
+X};
+Xstatic arc arcs_24_2[2] = {
+X {21, 3},
+X {0, 2},
+X};
+Xstatic arc arcs_24_3[1] = {
+X {40, 4},
+X};
+Xstatic arc arcs_24_4[1] = {
+X {0, 4},
+X};
+Xstatic state states_24[5] = {
+X {1, arcs_24_0},
+X {2, arcs_24_1},
+X {2, arcs_24_2},
+X {1, arcs_24_3},
+X {1, arcs_24_4},
+X};
+Xstatic arc arcs_25_0[2] = {
+X {3, 1},
+X {2, 2},
+X};
+Xstatic arc arcs_25_1[1] = {
+X {0, 1},
+X};
+Xstatic arc arcs_25_2[1] = {
+X {59, 3},
+X};
+Xstatic arc arcs_25_3[2] = {
+X {2, 3},
+X {6, 4},
+X};
+Xstatic arc arcs_25_4[3] = {
+X {6, 4},
+X {2, 4},
+X {60, 1},
+X};
+Xstatic state states_25[5] = {
+X {2, arcs_25_0},
+X {1, arcs_25_1},
+X {1, arcs_25_2},
+X {2, arcs_25_3},
+X {3, arcs_25_4},
+X};
+Xstatic arc arcs_26_0[1] = {
+X {61, 1},
+X};
+Xstatic arc arcs_26_1[2] = {
+X {62, 0},
+X {0, 1},
+X};
+Xstatic state states_26[2] = {
+X {1, arcs_26_0},
+X {2, arcs_26_1},
+X};
+Xstatic arc arcs_27_0[1] = {
+X {63, 1},
+X};
+Xstatic arc arcs_27_1[2] = {
+X {64, 0},
+X {0, 1},
+X};
+Xstatic state states_27[2] = {
+X {1, arcs_27_0},
+X {2, arcs_27_1},
+X};
+Xstatic arc arcs_28_0[2] = {
+X {65, 1},
+X {66, 2},
+X};
+Xstatic arc arcs_28_1[1] = {
+X {63, 2},
+X};
+Xstatic arc arcs_28_2[1] = {
+X {0, 2},
+X};
+Xstatic state states_28[3] = {
+X {2, arcs_28_0},
+X {1, arcs_28_1},
+X {1, arcs_28_2},
+X};
+Xstatic arc arcs_29_0[1] = {
+X {40, 1},
+X};
+Xstatic arc arcs_29_1[2] = {
+X {67, 0},
+X {0, 1},
+X};
+Xstatic state states_29[2] = {
+X {1, arcs_29_0},
+X {2, arcs_29_1},
+X};
+Xstatic arc arcs_30_0[6] = {
+X {68, 1},
+X {69, 2},
+X {29, 3},
+X {54, 3},
+X {65, 4},
+X {70, 5},
+X};
+Xstatic arc arcs_30_1[3] = {
+X {29, 3},
+X {69, 3},
+X {0, 1},
+X};
+Xstatic arc arcs_30_2[2] = {
+X {29, 3},
+X {0, 2},
+X};
+Xstatic arc arcs_30_3[1] = {
+X {0, 3},
+X};
+Xstatic arc arcs_30_4[1] = {
+X {54, 3},
+X};
+Xstatic arc arcs_30_5[2] = {
+X {65, 3},
+X {0, 5},
+X};
+Xstatic state states_30[6] = {
+X {6, arcs_30_0},
+X {3, arcs_30_1},
+X {2, arcs_30_2},
+X {1, arcs_30_3},
+X {1, arcs_30_4},
+X {2, arcs_30_5},
+X};
+Xstatic arc arcs_31_0[1] = {
+X {71, 1},
+X};
+Xstatic arc arcs_31_1[3] = {
+X {72, 0},
+X {73, 0},
+X {0, 1},
+X};
+Xstatic state states_31[2] = {
+X {1, arcs_31_0},
+X {3, arcs_31_1},
+X};
+Xstatic arc arcs_32_0[1] = {
+X {74, 1},
+X};
+Xstatic arc arcs_32_1[4] = {
+X {43, 0},
+X {75, 0},
+X {76, 0},
+X {0, 1},
+X};
+Xstatic state states_32[2] = {
+X {1, arcs_32_0},
+X {4, arcs_32_1},
+X};
+Xstatic arc arcs_33_0[3] = {
+X {72, 1},
+X {73, 1},
+X {77, 2},
+X};
+Xstatic arc arcs_33_1[1] = {
+X {74, 3},
+X};
+Xstatic arc arcs_33_2[2] = {
+X {78, 2},
+X {0, 2},
+X};
+Xstatic arc arcs_33_3[1] = {
+X {0, 3},
+X};
+Xstatic state states_33[4] = {
+X {3, arcs_33_0},
+X {1, arcs_33_1},
+X {2, arcs_33_2},
+X {1, arcs_33_3},
+X};
+Xstatic arc arcs_34_0[7] = {
+X {17, 1},
+X {79, 2},
+X {81, 3},
+X {83, 4},
+X {13, 5},
+X {84, 5},
+X {85, 5},
+X};
+Xstatic arc arcs_34_1[2] = {
+X {9, 6},
+X {19, 5},
+X};
+Xstatic arc arcs_34_2[2] = {
+X {9, 7},
+X {80, 5},
+X};
+Xstatic arc arcs_34_3[1] = {
+X {82, 5},
+X};
+Xstatic arc arcs_34_4[1] = {
+X {9, 8},
+X};
+Xstatic arc arcs_34_5[1] = {
+X {0, 5},
+X};
+Xstatic arc arcs_34_6[1] = {
+X {19, 5},
+X};
+Xstatic arc arcs_34_7[1] = {
+X {80, 5},
+X};
+Xstatic arc arcs_34_8[1] = {
+X {83, 5},
+X};
+Xstatic state states_34[9] = {
+X {7, arcs_34_0},
+X {2, arcs_34_1},
+X {2, arcs_34_2},
+X {1, arcs_34_3},
+X {1, arcs_34_4},
+X {1, arcs_34_5},
+X {1, arcs_34_6},
+X {1, arcs_34_7},
+X {1, arcs_34_8},
+X};
+Xstatic arc arcs_35_0[3] = {
+X {17, 1},
+X {79, 2},
+X {87, 3},
+X};
+Xstatic arc arcs_35_1[2] = {
+X {9, 4},
+X {19, 5},
+X};
+Xstatic arc arcs_35_2[1] = {
+X {86, 6},
+X};
+Xstatic arc arcs_35_3[1] = {
+X {13, 5},
+X};
+Xstatic arc arcs_35_4[1] = {
+X {19, 5},
+X};
+Xstatic arc arcs_35_5[1] = {
+X {0, 5},
+X};
+Xstatic arc arcs_35_6[1] = {
+X {80, 5},
+X};
+Xstatic state states_35[7] = {
+X {3, arcs_35_0},
+X {2, arcs_35_1},
+X {1, arcs_35_2},
+X {1, arcs_35_3},
+X {1, arcs_35_4},
+X {1, arcs_35_5},
+X {1, arcs_35_6},
+X};
+Xstatic arc arcs_36_0[2] = {
+X {40, 1},
+X {15, 2},
+X};
+Xstatic arc arcs_36_1[2] = {
+X {15, 2},
+X {0, 1},
+X};
+Xstatic arc arcs_36_2[2] = {
+X {40, 3},
+X {0, 2},
+X};
+Xstatic arc arcs_36_3[1] = {
+X {0, 3},
+X};
+Xstatic state states_36[4] = {
+X {2, arcs_36_0},
+X {2, arcs_36_1},
+X {2, arcs_36_2},
+X {1, arcs_36_3},
+X};
+Xstatic arc arcs_37_0[1] = {
+X {40, 1},
+X};
+Xstatic arc arcs_37_1[2] = {
+X {21, 2},
+X {0, 1},
+X};
+Xstatic arc arcs_37_2[2] = {
+X {40, 1},
+X {0, 2},
+X};
+Xstatic state states_37[3] = {
+X {1, arcs_37_0},
+X {2, arcs_37_1},
+X {2, arcs_37_2},
+X};
+Xstatic arc arcs_38_0[1] = {
+X {31, 1},
+X};
+Xstatic arc arcs_38_1[2] = {
+X {21, 2},
+X {0, 1},
+X};
+Xstatic arc arcs_38_2[2] = {
+X {31, 1},
+X {0, 2},
+X};
+Xstatic state states_38[3] = {
+X {1, arcs_38_0},
+X {2, arcs_38_1},
+X {2, arcs_38_2},
+X};
+Xstatic arc arcs_39_0[1] = {
+X {88, 1},
+X};
+Xstatic arc arcs_39_1[1] = {
+X {13, 2},
+X};
+Xstatic arc arcs_39_2[1] = {
+X {14, 3},
+X};
+Xstatic arc arcs_39_3[2] = {
+X {29, 4},
+X {15, 5},
+X};
+Xstatic arc arcs_39_4[1] = {
+X {89, 6},
+X};
+Xstatic arc arcs_39_5[1] = {
+X {16, 7},
+X};
+Xstatic arc arcs_39_6[1] = {
+X {15, 5},
+X};
+Xstatic arc arcs_39_7[1] = {
+X {0, 7},
+X};
+Xstatic state states_39[8] = {
+X {1, arcs_39_0},
+X {1, arcs_39_1},
+X {1, arcs_39_2},
+X {2, arcs_39_3},
+X {1, arcs_39_4},
+X {1, arcs_39_5},
+X {1, arcs_39_6},
+X {1, arcs_39_7},
+X};
+Xstatic arc arcs_40_0[1] = {
+X {77, 1},
+X};
+Xstatic arc arcs_40_1[1] = {
+X {90, 2},
+X};
+Xstatic arc arcs_40_2[2] = {
+X {21, 0},
+X {0, 2},
+X};
+Xstatic state states_40[3] = {
+X {1, arcs_40_0},
+X {1, arcs_40_1},
+X {2, arcs_40_2},
+X};
+Xstatic arc arcs_41_0[1] = {
+X {17, 1},
+X};
+Xstatic arc arcs_41_1[2] = {
+X {9, 2},
+X {19, 3},
+X};
+Xstatic arc arcs_41_2[1] = {
+X {19, 3},
+X};
+Xstatic arc arcs_41_3[1] = {
+X {0, 3},
+X};
+Xstatic state states_41[4] = {
+X {1, arcs_41_0},
+X {2, arcs_41_1},
+X {1, arcs_41_2},
+X {1, arcs_41_3},
+X};
+Xstatic dfa dfas[42] = {
+X {256, "single_input", 0, 3, states_0,
+X "\004\060\002\100\343\006\262\000\000\203\072\001"},
+X {257, "file_input", 0, 2, states_1,
+X "\204\060\002\100\343\006\262\000\000\203\072\001"},
+X {258, "expr_input", 0, 3, states_2,
+X "\000\040\002\000\000\000\000\000\002\203\072\000"},
+X {259, "eval_input", 0, 3, states_3,
+X "\000\040\002\000\000\000\000\000\002\203\072\000"},
+X {260, "funcdef", 0, 6, states_4,
+X "\000\020\000\000\000\000\000\000\000\000\000\000"},
+X {261, "parameters", 0, 4, states_5,
+X "\000\000\002\000\000\000\000\000\000\000\000\000"},
+X {262, "fplist", 0, 2, states_6,
+X "\000\040\002\000\000\000\000\000\000\000\000\000"},
+X {263, "fpdef", 0, 4, states_7,
+X "\000\040\002\000\000\000\000\000\000\000\000\000"},
+X {264, "stmt", 0, 2, states_8,
+X "\000\060\002\100\343\006\262\000\000\203\072\001"},
+X {265, "simple_stmt", 0, 2, states_9,
+X "\000\040\002\100\343\006\000\000\000\203\072\000"},
+X {266, "expr_stmt", 0, 3, states_10,
+X "\000\040\002\000\000\000\000\000\000\203\072\000"},
+X {267, "print_stmt", 0, 4, states_11,
+X "\000\000\000\100\000\000\000\000\000\000\000\000"},
+X {268, "del_stmt", 0, 4, states_12,
+X "\000\000\000\000\001\000\000\000\000\000\000\000"},
+X {269, "pass_stmt", 0, 3, states_13,
+X "\000\000\000\000\002\000\000\000\000\000\000\000"},
+X {270, "flow_stmt", 0, 2, states_14,
+X "\000\000\000\000\340\000\000\000\000\000\000\000"},
+X {271, "break_stmt", 0, 3, states_15,
+X "\000\000\000\000\040\000\000\000\000\000\000\000"},
+X {272, "return_stmt", 0, 4, states_16,
+X "\000\000\000\000\100\000\000\000\000\000\000\000"},
+X {273, "raise_stmt", 0, 6, states_17,
+X "\000\000\000\000\200\000\000\000\000\000\000\000"},
+X {274, "import_stmt", 0, 10, states_18,
+X "\000\000\000\000\000\006\000\000\000\000\000\000"},
+X {275, "compound_stmt", 0, 2, states_19,
+X "\000\020\000\000\000\000\262\000\000\000\000\001"},
+X {276, "if_stmt", 0, 8, states_20,
+X "\000\000\000\000\000\000\002\000\000\000\000\000"},
+X {277, "while_stmt", 0, 8, states_21,
+X "\000\000\000\000\000\000\020\000\000\000\000\000"},
+X {278, "for_stmt", 0, 10, states_22,
+X "\000\000\000\000\000\000\040\000\000\000\000\000"},
+X {279, "try_stmt", 0, 7, states_23,
+X "\000\000\000\000\000\000\200\000\000\000\000\000"},
+X {280, "except_clause", 0, 5, states_24,
+X "\000\000\000\000\000\000\000\004\000\000\000\000"},
+X {281, "suite", 0, 5, states_25,
+X "\004\040\002\100\343\006\000\000\000\203\072\000"},
+X {282, "test", 0, 2, states_26,
+X "\000\040\002\000\000\000\000\000\002\203\072\000"},
+X {283, "and_test", 0, 2, states_27,
+X "\000\040\002\000\000\000\000\000\002\203\072\000"},
+X {284, "not_test", 0, 3, states_28,
+X "\000\040\002\000\000\000\000\000\002\203\072\000"},
+X {285, "comparison", 0, 2, states_29,
+X "\000\040\002\000\000\000\000\000\000\203\072\000"},
+X {286, "comp_op", 0, 6, states_30,
+X "\000\000\000\040\000\000\100\000\162\000\000\000"},
+X {287, "expr", 0, 2, states_31,
+X "\000\040\002\000\000\000\000\000\000\203\072\000"},
+X {288, "term", 0, 2, states_32,
+X "\000\040\002\000\000\000\000\000\000\203\072\000"},
+X {289, "factor", 0, 4, states_33,
+X "\000\040\002\000\000\000\000\000\000\203\072\000"},
+X {290, "atom", 0, 9, states_34,
+X "\000\040\002\000\000\000\000\000\000\200\072\000"},
+X {291, "trailer", 0, 7, states_35,
+X "\000\000\002\000\000\000\000\000\000\200\200\000"},
+X {292, "subscript", 0, 4, states_36,
+X "\000\240\002\000\000\000\000\000\000\203\072\000"},
+X {293, "exprlist", 0, 3, states_37,
+X "\000\040\002\000\000\000\000\000\000\203\072\000"},
+X {294, "testlist", 0, 3, states_38,
+X "\000\040\002\000\000\000\000\000\002\203\072\000"},
+X {295, "classdef", 0, 8, states_39,
+X "\000\000\000\000\000\000\000\000\000\000\000\001"},
+X {296, "baselist", 0, 3, states_40,
+X "\000\040\002\000\000\000\000\000\000\200\072\000"},
+X {297, "arguments", 0, 4, states_41,
+X "\000\000\002\000\000\000\000\000\000\000\000\000"},
+X};
+Xstatic label labels[91] = {
+X {0, "EMPTY"},
+X {256, 0},
+X {4, 0},
+X {265, 0},
+X {275, 0},
+X {257, 0},
+X {264, 0},
+X {0, 0},
+X {258, 0},
+X {294, 0},
+X {259, 0},
+X {260, 0},
+X {1, "def"},
+X {1, 0},
+X {261, 0},
+X {11, 0},
+X {281, 0},
+X {7, 0},
+X {262, 0},
+X {8, 0},
+X {263, 0},
+X {12, 0},
+X {266, 0},
+X {267, 0},
+X {269, 0},
+X {268, 0},
+X {270, 0},
+X {274, 0},
+X {293, 0},
+X {22, 0},
+X {1, "print"},
+X {282, 0},
+X {1, "del"},
+X {1, "pass"},
+X {271, 0},
+X {272, 0},
+X {273, 0},
+X {1, "break"},
+X {1, "return"},
+X {1, "raise"},
+X {287, 0},
+X {1, "import"},
+X {1, "from"},
+X {16, 0},
+X {276, 0},
+X {277, 0},
+X {278, 0},
+X {279, 0},
+X {295, 0},
+X {1, "if"},
+X {1, "elif"},
+X {1, "else"},
+X {1, "while"},
+X {1, "for"},
+X {1, "in"},
+X {1, "try"},
+X {280, 0},
+X {1, "finally"},
+X {1, "except"},
+X {5, 0},
+X {6, 0},
+X {283, 0},
+X {1, "or"},
+X {284, 0},
+X {1, "and"},
+X {1, "not"},
+X {285, 0},
+X {286, 0},
+X {20, 0},
+X {21, 0},
+X {1, "is"},
+X {288, 0},
+X {14, 0},
+X {15, 0},
+X {289, 0},
+X {17, 0},
+X {24, 0},
+X {290, 0},
+X {291, 0},
+X {9, 0},
+X {10, 0},
+X {26, 0},
+X {27, 0},
+X {25, 0},
+X {2, 0},
+X {3, 0},
+X {292, 0},
+X {23, 0},
+X {1, "class"},
+X {296, 0},
+X {297, 0},
+X};
+Xgrammar gram = {
+X 42,
+X dfas,
+X {91, labels},
+X 256
+X};
+EOF
+fi
+if test -s 'src/objimpl.h'
+then echo '*** I will not over-write existing file src/objimpl.h'
+else
+echo 'x - src/objimpl.h'
+sed 's/^X//' > 'src/objimpl.h' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/*
+X123456789-123456789-123456789-123456789-123456789-123456789-123456789-12
+X
+XAdditional macros for modules that implement new object types.
+XYou must first include "object.h".
+X
+XNEWOBJ(type, typeobj) allocates memory for a new object of the given
+Xtype; here 'type' must be the C structure type used to represent the
+Xobject and 'typeobj' the address of the corresponding type object.
+XReference count and type pointer are filled in; the rest of the bytes of
+Xthe object are *undefined*! The resulting expression type is 'type *'.
+XThe size of the object is actually determined by the tp_basicsize field
+Xof the type object.
+X
+XNEWVAROBJ(type, typeobj, n) is similar but allocates a variable-size
+Xobject with n extra items. The size is computer as tp_basicsize plus
+Xn * tp_itemsize. This fills in the ob_size field as well.
+X*/
+X
+Xextern object *newobject PROTO((typeobject *));
+Xextern varobject *newvarobject PROTO((typeobject *, unsigned int));
+X
+X#define NEWOBJ(type, typeobj) ((type *) newobject(typeobj))
+X#define NEWVAROBJ(type, typeobj, n) ((type *) newvarobject(typeobj, n))
+X
+Xextern int StopPrint; /* Set when printing is interrupted */
+EOF
+fi
+echo 'Part 03 out of 21 of pack.out complete.'
+exit 0
diff --git a/shar/python-0.9.1-04-21.shar b/shar/python-0.9.1-04-21.shar
new file mode 100644
index 0000000..5f1cbee
--- /dev/null
+++ b/shar/python-0.9.1-04-21.shar
@@ -0,0 +1,2755 @@
+: This is a shell archive.
+: Extract with 'sh this_file'.
+:
+: Extract part 01 first since it makes all directories
+echo 'Start of pack.out, part 04 out of 21:'
+if test -s 'demo/sgi/gl_panel/flying/freeze.s'
+then echo '*** I will not over-write existing file demo/sgi/gl_panel/flying/freeze.s'
+else
+echo 'x - demo/sgi/gl_panel/flying/freeze.s'
+sed 's/^X//' > 'demo/sgi/gl_panel/flying/freeze.s' << 'EOF'
+X;;; This file was automatically generated by the panel editor.
+X;;; If you read it into gnu emacs, it will automagically format itself.
+X
+X(panel (prop help creator:user-panel-help)
+X(prop user-panel #t)
+X(label "frames per second")
+X(al (pnl_toggle_button (name "freeze")
+X(prop help creator:user-act-help)
+X(label "freeze")
+X(x 0.25)
+X(y 4.3)
+X(w 1.45)
+X(h 0.6)
+X(labeltype 16)
+X(downfunc move-then-resize)
+X)
+X(pnl_scale_chart (name "mystrip")
+X(prop help creator:user-act-help)
+X(x 0.25)
+X(y 0.25)
+X(downfunc move-then-resize)
+X)
+X)
+X)
+X;;; Local Variables:
+X;;; mode: scheme
+X;;; eval: (save-excursion (goto-char (point-min)) (kill-line 3))
+X;;; eval: (save-excursion (goto-char (point-min)) (replace-regexp "[ \n]*)" ")"))
+X;;; eval: (indent-region (point-min) (point-max) nil)
+X;;; eval: (progn (kill-line -3) (delete-backward-char 1) (save-buffer))
+X;;; End:
+EOF
+fi
+if test -s 'src/cstubs'
+then echo '*** I will not over-write existing file src/cstubs'
+else
+echo 'x - src/cstubs'
+sed 's/^X//' > 'src/cstubs' << 'EOF'
+X/*
+XInput used to generate the Python module "glmodule.c".
+XThe stub generator is a Python script called "cgen".
+X
+XEach definition must be contained on one line:
+X
+X<returntype> <name> <type> <arg> <type> <arg>
+X
+X<returntype> can be: void, short, long (XXX maybe others?)
+X
+X<type> can be: char, string, short, float, long, or double
+X string indicates a null terminated string;
+X if <type> is char and <arg> begins with a *, the * is stripped
+X and <type> is changed into string
+X
+X<arg> has the form <mode> or <mode>[<subscript>]
+X where <mode> can be
+X s: arg is sent
+X r: arg is received (arg is a pointer)
+X and <subscript> can be (N and I are numbers):
+X N
+X argI
+X retval
+X N*argI
+X N*retval
+X*/
+X
+X#include <gl.h>
+X#include <device.h>
+X
+X#include "allobjects.h"
+X#include "import.h"
+X#include "modsupport.h"
+X#include "cgensupport.h"
+X
+X/*
+XSome stubs are too complicated for the stub generator.
+XWe can include manually written versions of them here.
+XA line starting with '%' gives the name of the function so the stub
+Xgenerator can include it in the table of functions.
+X*/
+X
+X/*
+Xvarray -- an array of v.. calls.
+XThe argument is an array (maybe list or tuple) of points.
+XEach point must be a tuple or list of coordinates (x, y, z).
+XThe points may be 2- or 3-dimensional but must all have the
+Xsame dimension. Float and int values may be mixed however.
+XThe points are always converted to 3D double precision points
+Xby assuming z=0.0 if necessary (as indicated in the man page),
+Xand for each point v3d() is called.
+X*/
+X
+X% varray
+X
+Xstatic object *
+Xgl_varray(self, args)
+X object *self;
+X object *args;
+X{
+X object *v, *w;
+X int i, n, width;
+X double vec[3];
+X object * (*getitem) FPROTO((object *, int));
+X
+X if (!getiobjectarg(args, 1, 0, &v))
+X return NULL;
+X
+X if (is_listobject(v)) {
+X n = getlistsize(v);
+X getitem = getlistitem;
+X }
+X else if (is_tupleobject(v)) {
+X n = gettuplesize(v);
+X getitem = gettupleitem;
+X }
+X else {
+X err_badarg();
+X return NULL;
+X }
+X
+X if (n == 0) {
+X INCREF(None);
+X return None;
+X }
+X if (n > 0)
+X w = (*getitem)(v, 0);
+X
+X width = 0;
+X if (w == NULL) {
+X }
+X else if (is_listobject(w)) {
+X width = getlistsize(w);
+X }
+X else if (is_tupleobject(w)) {
+X width = gettuplesize(w);
+X }
+X
+X switch (width) {
+X case 2:
+X vec[2] = 0.0;
+X /* Fall through */
+X case 3:
+X break;
+X default:
+X err_badarg();
+X return NULL;
+X }
+X
+X for (i = 0; i < n; i++) {
+X w = (*getitem)(v, i);
+X if (!getidoublearray(w, 1, 0, width, vec))
+X return NULL;
+X v3d(vec);
+X }
+X
+X INCREF(None);
+X return None;
+X}
+X
+X/*
+Xvnarray, nvarray -- an array of n3f and v3f calls.
+XThe argument is an array (list or tuple) of pairs of points and normals.
+XEach pair is a tuple (NOT a list) of a point and a normal for that point.
+XEach point or normal must be a tuple (NOT a list) of coordinates (x, y, z).
+XThree coordinates must be given. Float and int values may be mixed.
+XFor each pair, n3f() is called for the normal, and then v3f() is called
+Xfor the vector.
+X
+Xvnarray and nvarray differ only in the order of the vector and normal in
+Xthe pair: vnarray expects (v, n) while nvarray expects (n, v).
+X*/
+X
+Xstatic object *gen_nvarray(); /* Forward */
+X
+X% nvarray
+X
+Xstatic object *
+Xgl_nvarray(self, args)
+X object *self;
+X object *args;
+X{
+X return gen_nvarray(args, 0);
+X}
+X
+X% vnarray
+X
+Xstatic object *
+Xgl_vnarray(self, args)
+X object *self;
+X object *args;
+X{
+X return gen_nvarray(args, 1);
+X}
+X
+X/* Generic, internal version of {nv,nv}array: inorm indicates the
+X argument order, 0: normal first, 1: vector first. */
+X
+Xstatic object *
+Xgen_nvarray(args, inorm)
+X object *args;
+X int inorm;
+X{
+X object *v, *w, *wnorm, *wvec;
+X int i, n;
+X float norm[3], vec[3];
+X object * (*getitem) FPROTO((object *, int));
+X
+X if (!getiobjectarg(args, 1, 0, &v))
+X return NULL;
+X
+X if (is_listobject(v)) {
+X n = getlistsize(v);
+X getitem = getlistitem;
+X }
+X else if (is_tupleobject(v)) {
+X n = gettuplesize(v);
+X getitem = gettupleitem;
+X }
+X else {
+X err_badarg();
+X return NULL;
+X }
+X
+X for (i = 0; i < n; i++) {
+X w = (*getitem)(v, i);
+X if (!is_tupleobject(w) || gettuplesize(w) != 2) {
+X err_badarg();
+X return NULL;
+X }
+X wnorm = gettupleitem(w, inorm);
+X wvec = gettupleitem(w, 1 - inorm);
+X if (!getifloatarray(wnorm, 1, 0, 3, norm) ||
+X !getifloatarray(wvec, 1, 0, 3, vec))
+X return NULL;
+X n3f(norm);
+X v3f(vec);
+X }
+X
+X INCREF(None);
+X return None;
+X}
+X
+X/* nurbssurface(s_knots[], t_knots[], ctl[][], s_order, t_order, type).
+X The dimensions of ctl[] are computed as follows:
+X [len(s_knots) - s_order], [len(t_knots) - t_order]
+X*/
+X
+X% nurbssurface
+X
+Xstatic object *
+Xgl_nurbssurface(self, args)
+X object *self;
+X object *args;
+X{
+X long arg1 ;
+X double * arg2 ;
+X long arg3 ;
+X double * arg4 ;
+X double *arg5 ;
+X long arg6 ;
+X long arg7 ;
+X long arg8 ;
+X long ncoords;
+X long s_byte_stride, t_byte_stride;
+X long s_nctl, t_nctl;
+X long s, t;
+X object *v, *w, *pt;
+X double *pnext;
+X if (!getilongarraysize(args, 6, 0, &arg1))
+X return NULL;
+X if ((arg2 = NEW(double, arg1 )) == NULL) {
+X return err_nomem();
+X }
+X if (!getidoublearray(args, 6, 0, arg1 , arg2))
+X return NULL;
+X if (!getilongarraysize(args, 6, 1, &arg3))
+X return NULL;
+X if ((arg4 = NEW(double, arg3 )) == NULL) {
+X return err_nomem();
+X }
+X if (!getidoublearray(args, 6, 1, arg3 , arg4))
+X return NULL;
+X if (!getilongarg(args, 6, 3, &arg6))
+X return NULL;
+X if (!getilongarg(args, 6, 4, &arg7))
+X return NULL;
+X if (!getilongarg(args, 6, 5, &arg8))
+X return NULL;
+X if (arg8 == N_XYZ)
+X ncoords = 3;
+X else if (arg8 == N_XYZW)
+X ncoords = 4;
+X else {
+X err_badarg();
+X return NULL;
+X }
+X s_nctl = arg1 - arg6;
+X t_nctl = arg3 - arg7;
+X if (!getiobjectarg(args, 6, 2, &v))
+X return NULL;
+X if (!is_listobject(v) || getlistsize(v) != s_nctl) {
+X err_badarg();
+X return NULL;
+X }
+X if ((arg5 = NEW(double, s_nctl*t_nctl*ncoords )) == NULL) {
+X return err_nomem();
+X }
+X pnext = arg5;
+X for (s = 0; s < s_nctl; s++) {
+X w = getlistitem(v, s);
+X if (w == NULL || !is_listobject(w) ||
+X getlistsize(w) != t_nctl) {
+X err_badarg();
+X return NULL;
+X }
+X for (t = 0; t < t_nctl; t++) {
+X pt = getlistitem(w, t);
+X if (!getidoublearray(pt, 1, 0, ncoords, pnext))
+X return NULL;
+X pnext += ncoords;
+X }
+X }
+X s_byte_stride = sizeof(double) * ncoords;
+X t_byte_stride = s_byte_stride * s_nctl;
+X nurbssurface( arg1 , arg2 , arg3 , arg4 ,
+X s_byte_stride , t_byte_stride , arg5 , arg6 , arg7 , arg8 );
+X DEL(arg2);
+X DEL(arg4);
+X DEL(arg5);
+X INCREF(None);
+X return None;
+X}
+X
+X/* nurbscurve(knots, ctlpoints, order, type).
+X The length of ctlpoints is len(knots)-order. */
+X
+X%nurbscurve
+X
+Xstatic object *
+Xgl_nurbscurve(self, args)
+X object *self;
+X object *args;
+X{
+X long arg1 ;
+X double * arg2 ;
+X long arg3 ;
+X double * arg4 ;
+X long arg5 ;
+X long arg6 ;
+X int ncoords, npoints;
+X int i;
+X object *v;
+X double *pnext;
+X if (!getilongarraysize(args, 4, 0, &arg1))
+X return NULL;
+X if ((arg2 = NEW(double, arg1 )) == NULL) {
+X return err_nomem();
+X }
+X if (!getidoublearray(args, 4, 0, arg1 , arg2))
+X return NULL;
+X if (!getilongarg(args, 4, 2, &arg5))
+X return NULL;
+X if (!getilongarg(args, 4, 3, &arg6))
+X return NULL;
+X if (arg6 == N_ST)
+X ncoords = 2;
+X else if (arg6 == N_STW)
+X ncoords = 3;
+X else {
+X err_badarg();
+X return NULL;
+X }
+X npoints = arg1 - arg5;
+X if (!getiobjectarg(args, 4, 1, &v))
+X return NULL;
+X if (!is_listobject(v) || getlistsize(v) != npoints) {
+X err_badarg();
+X return NULL;
+X }
+X if ((arg4 = NEW(double, npoints*ncoords )) == NULL) {
+X return err_nomem();
+X }
+X pnext = arg4;
+X for (i = 0; i < npoints; i++) {
+X if (!getidoublearray(getlistitem(v, i), 1, 0, ncoords, pnext))
+X return NULL;
+X pnext += ncoords;
+X }
+X arg3 = (sizeof(double)) * ncoords;
+X nurbscurve( arg1 , arg2 , arg3 , arg4 , arg5 , arg6 );
+X DEL(arg2);
+X DEL(arg4);
+X INCREF(None);
+X return None;
+X}
+X
+X/* pwlcurve(points, type).
+X Points is a list of points. Type must be N_ST. */
+X
+X%pwlcurve
+X
+Xstatic object *
+Xgl_pwlcurve(self, args)
+X object *self;
+X object *args;
+X{
+X object *v;
+X long type;
+X double *data, *pnext;
+X long npoints, ncoords;
+X int i;
+X if (!getiobjectarg(args, 2, 0, &v))
+X return NULL;
+X if (!getilongarg(args, 2, 1, &type))
+X return NULL;
+X if (!is_listobject(v)) {
+X err_badarg();
+X return NULL;
+X }
+X npoints = getlistsize(v);
+X if (type == N_ST)
+X ncoords = 2;
+X else {
+X err_badarg();
+X return NULL;
+X }
+X if ((data = NEW(double, npoints*ncoords)) == NULL) {
+X return err_nomem();
+X }
+X pnext = data;
+X for (i = 0; i < npoints; i++) {
+X if (!getidoublearray(getlistitem(v, i), 1, 0, ncoords, pnext))
+X return NULL;
+X pnext += ncoords;
+X }
+X pwlcurve(npoints, data, sizeof(double)*ncoords, type);
+X DEL(data);
+X INCREF(None);
+X return None;
+X}
+X
+X
+X/* Picking and Selecting */
+X
+Xstatic short *pickbuffer = NULL;
+Xstatic long pickbuffersize;
+X
+Xstatic object *
+Xpick_select(args, func)
+X object *args;
+X void (*func)();
+X{
+X if (!getilongarg(args, 1, 0, &pickbuffersize))
+X return NULL;
+X if (pickbuffer != NULL) {
+X err_setstr(RuntimeError,
+X "pick/gselect: already picking/selecting");
+X return NULL;
+X }
+X if ((pickbuffer = NEW(short, pickbuffersize)) == NULL) {
+X return err_nomem();
+X }
+X (*func)(pickbuffer, pickbuffersize);
+X INCREF(None);
+X return None;
+X}
+X
+Xstatic object *
+Xendpick_select(args, func)
+X object *args;
+X long (*func)();
+X{
+X object *v, *w;
+X int i, nhits, n;
+X if (!getnoarg(args))
+X return NULL;
+X if (pickbuffer == NULL) {
+X err_setstr(RuntimeError,
+X "endpick/endselect: not in pick/select mode");
+X return NULL;
+X }
+X nhits = (*func)(pickbuffer);
+X if (nhits < 0) {
+X nhits = -nhits; /* How to report buffer overflow otherwise? */
+X }
+X /* Scan the buffer to see how many integers */
+X n = 0;
+X for (; nhits > 0; nhits--) {
+X n += 1 + pickbuffer[n];
+X }
+X v = newlistobject(n);
+X if (v == NULL)
+X return NULL;
+X /* XXX Could do it nicer and interpret the data structure here,
+X returning a list of lists. But this can be done in Python... */
+X for (i = 0; i < n; i++) {
+X w = newintobject((long)pickbuffer[i]);
+X if (w == NULL) {
+X DECREF(v);
+X return NULL;
+X }
+X setlistitem(v, i, w);
+X }
+X DEL(pickbuffer);
+X pickbuffer = NULL;
+X return v;
+X}
+X
+Xextern void pick(), gselect();
+Xextern long endpick(), endselect();
+X
+X%pick
+Xstatic object *gl_pick(self, args) object *self, *args; {
+X return pick_select(args, pick);
+X}
+X
+X%endpick
+Xstatic object *gl_endpick(self, args) object *self, *args; {
+X return endpick_select(args, endpick);
+X}
+X
+X%gselect
+Xstatic object *gl_gselect(self, args) object *self, *args; {
+X return pick_select(args, gselect);
+X}
+X
+X%endselect
+Xstatic object *gl_endselect(self, args) object *self, *args; {
+X return endpick_select(args, endselect);
+X}
+X
+X
+X/* XXX The generator botches this one. Here's a quick hack to fix it. */
+X
+X% getmatrix float r[16]
+X
+Xstatic object *
+Xgl_getmatrix(self, args)
+X object *self;
+X object *args;
+X{
+X float arg1 [ 16 ] ;
+X object *v, *w;
+X int i;
+X getmatrix( arg1 );
+X v = newlistobject(16);
+X if (v == NULL) {
+X return err_nomem();
+X }
+X for (i = 0; i < 16; i++) {
+X w = mknewfloatobject(arg1[i]);
+X if (w == NULL) {
+X DECREF(v);
+X return NULL;
+X }
+X setlistitem(v, i, w);
+X }
+X return v;
+X}
+X
+X/* End of manually written stubs */
+X
+X%%
+X
+Xlong getshade
+Xvoid devport short s long s
+Xvoid rdr2i long s long s
+Xvoid rectfs short s short s short s short s
+Xvoid rects short s short s short s short s
+Xvoid rmv2i long s long s
+Xvoid noport
+Xvoid popviewport
+Xvoid clear
+Xvoid clearhitcode
+Xvoid closeobj
+Xvoid cursoff
+Xvoid curson
+Xvoid doublebuffer
+Xvoid finish
+Xvoid gconfig
+Xvoid ginit
+Xvoid greset
+Xvoid multimap
+Xvoid onemap
+Xvoid popattributes
+Xvoid popmatrix
+Xvoid pushattributes
+Xvoid pushmatrix
+Xvoid pushviewport
+Xvoid qreset
+Xvoid RGBmode
+Xvoid singlebuffer
+Xvoid swapbuffers
+Xvoid gsync
+Xvoid tpon
+Xvoid tpoff
+Xvoid clkon
+Xvoid clkoff
+Xvoid ringbell
+X#void callfunc
+Xvoid gbegin
+Xvoid textinit
+Xvoid initnames
+Xvoid pclos
+Xvoid popname
+Xvoid spclos
+Xvoid zclear
+Xvoid screenspace
+Xvoid reshapeviewport
+Xvoid winpush
+Xvoid winpop
+Xvoid foreground
+Xvoid endfullscrn
+Xvoid endpupmode
+Xvoid fullscrn
+Xvoid pupmode
+Xvoid winconstraints
+Xvoid pagecolor short s
+Xvoid textcolor short s
+Xvoid color short s
+Xvoid curveit short s
+Xvoid font short s
+Xvoid linewidth short s
+Xvoid setlinestyle short s
+Xvoid setmap short s
+Xvoid swapinterval short s
+Xvoid writemask short s
+Xvoid textwritemask short s
+Xvoid qdevice short s
+Xvoid unqdevice short s
+Xvoid curvebasis short s
+Xvoid curveprecision short s
+Xvoid loadname short s
+Xvoid passthrough short s
+Xvoid pushname short s
+Xvoid setmonitor short s
+Xvoid setshade short s
+Xvoid setpattern short s
+Xvoid pagewritemask short s
+X#
+Xvoid callobj long s
+Xvoid delobj long s
+Xvoid editobj long s
+Xvoid makeobj long s
+Xvoid maketag long s
+Xvoid chunksize long s
+Xvoid compactify long s
+Xvoid deltag long s
+Xvoid lsrepeat long s
+Xvoid objinsert long s
+Xvoid objreplace long s
+Xvoid winclose long s
+Xvoid blanktime long s
+Xvoid freepup long s
+X# This is not in the library!?
+X###void pupcolor long s
+X#
+Xvoid backbuffer long s
+Xvoid frontbuffer long s
+Xvoid lsbackup long s
+Xvoid resetls long s
+Xvoid lampon long s
+Xvoid lampoff long s
+Xvoid setbell long s
+Xvoid blankscreen long s
+Xvoid depthcue long s
+Xvoid zbuffer long s
+Xvoid backface long s
+X#
+Xvoid cmov2i long s long s
+Xvoid draw2i long s long s
+Xvoid move2i long s long s
+Xvoid pnt2i long s long s
+Xvoid patchbasis long s long s
+Xvoid patchprecision long s long s
+Xvoid pdr2i long s long s
+Xvoid pmv2i long s long s
+Xvoid rpdr2i long s long s
+Xvoid rpmv2i long s long s
+Xvoid xfpt2i long s long s
+Xvoid objdelete long s long s
+Xvoid patchcurves long s long s
+Xvoid minsize long s long s
+Xvoid maxsize long s long s
+Xvoid keepaspect long s long s
+Xvoid prefsize long s long s
+Xvoid stepunit long s long s
+Xvoid fudge long s long s
+Xvoid winmove long s long s
+X#
+Xvoid attachcursor short s short s
+Xvoid deflinestyle short s short s
+Xvoid noise short s short s
+Xvoid picksize short s short s
+Xvoid qenter short s short s
+Xvoid setdepth short s short s
+Xvoid cmov2s short s short s
+Xvoid draw2s short s short s
+Xvoid move2s short s short s
+Xvoid pdr2s short s short s
+Xvoid pmv2s short s short s
+Xvoid pnt2s short s short s
+Xvoid rdr2s short s short s
+Xvoid rmv2s short s short s
+Xvoid rpdr2s short s short s
+Xvoid rpmv2s short s short s
+Xvoid xfpt2s short s short s
+X#
+Xvoid cmov2 float s float s
+Xvoid draw2 float s float s
+Xvoid move2 float s float s
+Xvoid pnt2 float s float s
+Xvoid pdr2 float s float s
+Xvoid pmv2 float s float s
+Xvoid rdr2 float s float s
+Xvoid rmv2 float s float s
+Xvoid rpdr2 float s float s
+Xvoid rpmv2 float s float s
+Xvoid xfpt2 float s float s
+X#
+Xvoid loadmatrix float s[16]
+Xvoid multmatrix float s[16]
+Xvoid crv float s[16]
+Xvoid rcrv float s[16]
+X#
+X# Methods that have strings.
+X#
+Xvoid addtopup long s char *s long s
+Xvoid charstr char *s
+Xvoid getport char *s
+Xlong strwidth char *s
+Xlong winopen char *s
+Xvoid wintitle char *s
+X#
+X# Methods that have 1 long (# of elements) and an array
+X#
+Xvoid polf long s float s[3*arg1]
+Xvoid polf2 long s float s[2*arg1]
+Xvoid poly long s float s[3*arg1]
+Xvoid poly2 long s float s[2*arg1]
+Xvoid crvn long s float s[3*arg1]
+Xvoid rcrvn long s float s[4*arg1]
+X#
+Xvoid polf2i long s long s[2*arg1]
+Xvoid polfi long s long s[3*arg1]
+Xvoid poly2i long s long s[2*arg1]
+Xvoid polyi long s long s[3*arg1]
+X#
+Xvoid polf2s long s short s[2*arg1]
+Xvoid polfs long s short s[3*arg1]
+Xvoid polys long s short s[3*arg1]
+Xvoid poly2s long s short s[2*arg1]
+X#
+Xvoid defcursor short s short s[16]
+Xvoid writepixels short s short s[arg1]
+Xvoid defbasis long s float s[16]
+Xvoid gewrite short s short s[arg1]
+X#
+Xvoid rotate short s char s
+X# This is not in the library!?
+X###void setbutton short s char s
+Xvoid rot float s char s
+X#
+Xvoid circfi long s long s long s
+Xvoid circi long s long s long s
+Xvoid cmovi long s long s long s
+Xvoid drawi long s long s long s
+Xvoid movei long s long s long s
+Xvoid pnti long s long s long s
+Xvoid newtag long s long s long s
+Xvoid pdri long s long s long s
+Xvoid pmvi long s long s long s
+Xvoid rdri long s long s long s
+Xvoid rmvi long s long s long s
+Xvoid rpdri long s long s long s
+Xvoid rpmvi long s long s long s
+Xvoid xfpti long s long s long s
+X#
+Xvoid circ float s float s float s
+Xvoid circf float s float s float s
+Xvoid cmov float s float s float s
+Xvoid draw float s float s float s
+Xvoid move float s float s float s
+Xvoid pnt float s float s float s
+Xvoid scale float s float s float s
+Xvoid translate float s float s float s
+Xvoid pdr float s float s float s
+Xvoid pmv float s float s float s
+Xvoid rdr float s float s float s
+Xvoid rmv float s float s float s
+Xvoid rpdr float s float s float s
+Xvoid rpmv float s float s float s
+Xvoid xfpt float s float s float s
+X#
+Xvoid RGBcolor short s short s short s
+Xvoid RGBwritemask short s short s short s
+Xvoid setcursor short s short s short s
+Xvoid tie short s short s short s
+Xvoid circfs short s short s short s
+Xvoid circs short s short s short s
+Xvoid cmovs short s short s short s
+Xvoid draws short s short s short s
+Xvoid moves short s short s short s
+Xvoid pdrs short s short s short s
+Xvoid pmvs short s short s short s
+Xvoid pnts short s short s short s
+Xvoid rdrs short s short s short s
+Xvoid rmvs short s short s short s
+Xvoid rpdrs short s short s short s
+Xvoid rpmvs short s short s short s
+Xvoid xfpts short s short s short s
+Xvoid curorigin short s short s short s
+Xvoid cyclemap short s short s short s
+X#
+Xvoid patch float s[16] float s[16] float s[16]
+Xvoid splf long s float s[3*arg1] short s[arg1]
+Xvoid splf2 long s float s[2*arg1] short s[arg1]
+Xvoid splfi long s long s[3*arg1] short s[arg1]
+Xvoid splf2i long s long s[2*arg1] short s[arg1]
+Xvoid splfs long s short s[3*arg1] short s[arg1]
+Xvoid splf2s long s short s[2*arg1] short s[arg1]
+Xvoid defpattern short s short s short s[arg2*arg2/16]
+X#
+Xvoid rpatch float s[16] float s[16] float s[16] float s[16]
+X#
+X# routines that send 4 floats
+X#
+Xvoid ortho2 float s float s float s float s
+Xvoid rect float s float s float s float s
+Xvoid rectf float s float s float s float s
+Xvoid xfpt4 float s float s float s float s
+X#
+Xvoid textport short s short s short s short s
+Xvoid mapcolor short s short s short s short s
+Xvoid scrmask short s short s short s short s
+Xvoid setvaluator short s short s short s short s
+Xvoid viewport short s short s short s short s
+Xvoid shaderange short s short s short s short s
+Xvoid xfpt4s short s short s short s short s
+Xvoid rectfi long s long s long s long s
+Xvoid recti long s long s long s long s
+Xvoid xfpt4i long s long s long s long s
+Xvoid prefposition long s long s long s long s
+X#
+Xvoid arc float s float s float s short s short s
+Xvoid arcf float s float s float s short s short s
+Xvoid arcfi long s long s long s short s short s
+Xvoid arci long s long s long s short s short s
+X#
+Xvoid bbox2 short s short s float s float s float s float s
+Xvoid bbox2i short s short s long s long s long s long s
+Xvoid bbox2s short s short s short s short s short s short s
+Xvoid blink short s short s short s short s short s
+Xvoid ortho float s float s float s float s float s float s
+Xvoid window float s float s float s float s float s float s
+Xvoid lookat float s float s float s float s float s float s short s
+X#
+Xvoid perspective short s float s float s float s
+Xvoid polarview float s short s short s short s
+X# XXX getichararray not supported
+X#void writeRGB short s char s[arg1] char s[arg1] char s[arg1]
+X#
+Xvoid arcfs short s short s short s short s short s
+Xvoid arcs short s short s short s short s short s
+Xvoid rectcopy short s short s short s short s short s short s
+Xvoid RGBcursor short s short s short s short s short s short s short s
+X#
+Xlong getbutton short s
+Xlong getcmmode
+Xlong getlsbackup
+Xlong getresetls
+Xlong getdcm
+Xlong getzbuffer
+Xlong ismex
+Xlong isobj long s
+Xlong isqueued short s
+Xlong istag long s
+X#
+Xlong genobj
+Xlong gentag
+Xlong getbuffer
+Xlong getcolor
+Xlong getdisplaymode
+Xlong getfont
+Xlong getheight
+Xlong gethitcode
+Xlong getlstyle
+Xlong getlwidth
+Xlong getmap
+Xlong getplanes
+Xlong getwritemask
+Xlong qtest
+Xlong getlsrepeat
+Xlong getmonitor
+Xlong getopenobj
+Xlong getpattern
+Xlong winget
+Xlong winattach
+Xlong getothermonitor
+Xlong newpup
+X#
+Xlong getvaluator short s
+Xvoid winset long s
+Xlong dopup long s
+Xvoid getdepth short r short r
+Xvoid getcpos short r short r
+Xvoid getsize long r long r
+Xvoid getorigin long r long r
+Xvoid getviewport short r short r short r short r
+Xvoid gettp short r short r short r short r
+Xvoid getgpos float r float r float r float r
+Xvoid winposition long s long s long s long s
+Xvoid gRGBcolor short r short r short r
+Xvoid gRGBmask short r short r short r
+Xvoid getscrmask short r short r short r short r
+Xvoid gRGBcursor short r short r short r short r short r short r short r short r long *
+Xvoid getmcolor short s short r short r short r
+Xvoid mapw long s short s short s float r float r float r float r float r float r
+Xvoid mapw2 long s short s short s float r float r
+Xvoid defrasterfont short s short s short s Fontchar s[arg3] short s short s[4*arg5]
+Xlong qread short r
+Xvoid getcursor short r short r short r long r
+X#
+X# For these we receive arrays of stuff
+X#
+Xvoid getdev long s short s[arg1] short r[arg1]
+X#XXX not generated correctly yet
+X#void getmatrix float r[16]
+Xlong readpixels short s short r[retval]
+Xlong readRGB short s char r[retval] char r[retval] char r[retval]
+Xlong blkqread short s short r[arg1]
+X#
+X# New 4D routines
+X#
+Xvoid cmode
+Xvoid concave long s
+Xvoid curstype long s
+Xvoid drawmode long s
+Xvoid gammaramp short s[256] short s[256] short s[256]
+Xlong getbackface
+Xlong getdescender
+Xlong getdrawmode
+Xlong getmmode
+Xlong getsm
+Xlong getvideo long s
+Xvoid imakebackground
+Xvoid lmbind short s short s
+Xvoid lmdef long s long s long s float s[arg3]
+Xvoid mmode long s
+Xvoid normal float s[3]
+Xvoid overlay long s
+Xvoid RGBrange short s short s short s short s short s short s short s short s
+Xvoid setvideo long s long s
+Xvoid shademodel long s
+Xvoid underlay long s
+X#
+X# New Personal Iris/GT Routines
+X#
+Xvoid bgnclosedline
+Xvoid bgnline
+Xvoid bgnpoint
+Xvoid bgnpolygon
+Xvoid bgnsurface
+Xvoid bgntmesh
+Xvoid bgntrim
+Xvoid endclosedline
+Xvoid endline
+Xvoid endpoint
+Xvoid endpolygon
+Xvoid endsurface
+Xvoid endtmesh
+Xvoid endtrim
+Xvoid blendfunction long s long s
+Xvoid c3f float s[3]
+Xvoid c3i long s[3]
+Xvoid c3s short s[3]
+Xvoid c4f float s[4]
+Xvoid c4i long s[4]
+Xvoid c4s short s[4]
+Xvoid colorf float s
+Xvoid cpack long s
+Xvoid czclear long s long s
+Xvoid dglclose long s
+Xlong dglopen char *s long s
+Xlong getgdesc long s
+Xvoid getnurbsproperty long s float r
+Xvoid glcompat long s long s
+Xvoid iconsize long s long s
+Xvoid icontitle char *s
+Xvoid lRGBrange short s short s short s short s short s short s long s long s
+Xvoid linesmooth long s
+Xvoid lmcolor long s
+Xvoid logicop long s
+Xlong lrectread short s short s short s short s long r[retval]
+Xvoid lrectwrite short s short s short s short s long s[(arg2-arg1+1)*(arg4-arg3+1)]
+Xlong rectread short s short s short s short s short r[retval]
+Xvoid rectwrite short s short s short s short s short s[(arg2-arg1+1)*(arg4-arg3+1)]
+Xvoid lsetdepth long s long s
+Xvoid lshaderange short s short s long s long s
+Xvoid n3f float s[3]
+Xvoid noborder
+Xvoid pntsmooth long s
+Xvoid readsource long s
+Xvoid rectzoom float s float s
+Xvoid sbox float s float s float s float s
+Xvoid sboxi long s long s long s long s
+Xvoid sboxs short s short s short s short s
+Xvoid sboxf float s float s float s float s
+Xvoid sboxfi long s long s long s long s
+Xvoid sboxfs short s short s short s short s
+Xvoid setnurbsproperty long s float s
+Xvoid setpup long s long s long s
+Xvoid smoothline long s
+Xvoid subpixel long s
+Xvoid swaptmesh
+Xlong swinopen long s
+Xvoid v2f float s[2]
+Xvoid v2i long s[2]
+Xvoid v2s short s[2]
+Xvoid v3f float s[3]
+Xvoid v3i long s[3]
+Xvoid v3s short s[3]
+Xvoid v4f float s[4]
+Xvoid v4i long s[4]
+Xvoid v4s short s[4]
+Xvoid videocmd long s
+Xlong windepth long s
+Xvoid wmpack long s
+Xvoid zdraw long s
+Xvoid zfunction long s
+Xvoid zsource long s
+Xvoid zwritemask long s
+X#
+X# uses doubles
+X#
+Xvoid v2d double s[2]
+Xvoid v3d double s[3]
+Xvoid v4d double s[4]
+EOF
+fi
+if test -s 'src/stdwinmodule.c'
+then echo '*** I will not over-write existing file src/stdwinmodule.c'
+else
+echo 'x - src/stdwinmodule.c'
+sed 's/^X//' > 'src/stdwinmodule.c' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/* Stdwin module */
+X
+X/* Stdwin itself is a module, not a separate object type.
+X Object types defined here:
+X wp: a window
+X dp: a drawing structure (only one can exist at a time)
+X mp: a menu
+X tp: a textedit block
+X*/
+X
+X/* Rules for translating C stdwin function calls into Python stwin:
+X - All names drop their initial letter 'w'
+X - Functions with a window as first parameter are methods of window objects
+X - There is no equivalent for wclose(); just delete the window object
+X (all references to it!) (XXX maybe this is a bad idea)
+X - w.begindrawing() returns a drawing object
+X - There is no equivalent for wenddrawing(win); just delete the drawing
+X object (all references to it!) (XXX maybe this is a bad idea)
+X - Functions that may only be used inside wbegindrawing / wendddrawing
+X are methods of the drawing object; this includes the text measurement
+X functions (which however have doubles as module functions).
+X - Methods of the drawing object drop an initial 'draw' from their name
+X if they have it, e.g., wdrawline() --> d.line()
+X - The obvious type conversions: int --> intobject; string --> stringobject
+X - A text parameter followed by a length parameter is only a text (string)
+X parameter in Python
+X - A point or other pair of horizontal and vertical coordinates is always
+X a pair of integers in Python
+X - Two points forming a rectangle or endpoints of a line segment are a
+X pair of points in Python
+X - The arguments to d.elarc() are three points.
+X - The functions wgetclip() and wsetclip() are translated into
+X stdwin.getcutbuffer() and stdwin.setcutbuffer(); 'clip' is really
+X a bad word for what these functions do (clipping has a different
+X meaning in the drawing world), while cutbuffer is standard X jargon.
+X XXX This must change again in the light of changes to stdwin!
+X - For textedit, similar rules hold, but they are less strict.
+X XXX more?
+X*/
+X
+X#include "allobjects.h"
+X
+X#include "modsupport.h"
+X
+X#include "stdwin.h"
+X
+X/* Window and menu object types declared here because of forward references */
+X
+Xtypedef struct {
+X OB_HEAD
+X object *w_title;
+X WINDOW *w_win;
+X object *w_attr; /* Attributes dictionary */
+X} windowobject;
+X
+Xextern typeobject Windowtype; /* Really static, forward */
+X
+X#define is_windowobject(wp) ((wp)->ob_type == &Windowtype)
+X
+Xtypedef struct {
+X OB_HEAD
+X MENU *m_menu;
+X int m_id;
+X object *m_attr; /* Attributes dictionary */
+X} menuobject;
+X
+Xextern typeobject Menutype; /* Really static, forward */
+X
+X#define is_menuobject(mp) ((mp)->ob_type == &Menutype)
+X
+X
+X/* Strongly stdwin-specific argument handlers */
+X
+Xstatic int
+Xgetmousedetail(v, ep)
+X object *v;
+X EVENT *ep;
+X{
+X if (v == NULL || !is_tupleobject(v) || gettuplesize(v) != 4)
+X return err_badarg();
+X return getintintarg(gettupleitem(v, 0),
+X &ep->u.where.h, &ep->u.where.v) &&
+X getintarg(gettupleitem(v, 1), &ep->u.where.clicks) &&
+X getintarg(gettupleitem(v, 2), &ep->u.where.button) &&
+X getintarg(gettupleitem(v, 3), &ep->u.where.mask);
+X}
+X
+Xstatic int
+Xgetmenudetail(v, ep)
+X object *v;
+X EVENT *ep;
+X{
+X object *mp;
+X if (v == NULL || !is_tupleobject(v) || gettuplesize(v) != 2)
+X return err_badarg();
+X mp = gettupleitem(v, 0);
+X if (mp == NULL || !is_menuobject(mp))
+X return err_badarg();
+X ep->u.m.id = ((menuobject *)mp) -> m_id;
+X return getintarg(gettupleitem(v, 1), &ep->u.m.item);
+X}
+X
+Xstatic int
+Xgeteventarg(v, ep)
+X object *v;
+X EVENT *ep;
+X{
+X object *wp, *detail;
+X int a[4];
+X if (v == NULL || !is_tupleobject(v) || gettuplesize(v) != 3)
+X return err_badarg();
+X if (!getintarg(gettupleitem(v, 0), &ep->type))
+X return 0;
+X wp = gettupleitem(v, 1);
+X if (wp == None)
+X ep->window = NULL;
+X else if (wp == NULL || !is_windowobject(wp))
+X return err_badarg();
+X else
+X ep->window = ((windowobject *)wp) -> w_win;
+X detail = gettupleitem(v, 2);
+X switch (ep->type) {
+X case WE_CHAR:
+X if (!is_stringobject(detail) || getstringsize(detail) != 1)
+X return err_badarg();
+X ep->u.character = getstringvalue(detail)[0];
+X return 1;
+X case WE_COMMAND:
+X return getintarg(detail, &ep->u.command);
+X case WE_DRAW:
+X if (!getrectarg(detail, a))
+X return 0;
+X ep->u.area.left = a[0];
+X ep->u.area.top = a[1];
+X ep->u.area.right = a[2];
+X ep->u.area.bottom = a[3];
+X return 1;
+X case WE_MOUSE_DOWN:
+X case WE_MOUSE_UP:
+X case WE_MOUSE_MOVE:
+X return getmousedetail(detail, ep);
+X case WE_MENU:
+X return getmenudetail(detail, ep);
+X default:
+X return 1;
+X }
+X}
+X
+X
+X/* Return construction tools */
+X
+Xstatic object *
+Xmakepoint(a, b)
+X int a, b;
+X{
+X object *v;
+X object *w;
+X if ((v = newtupleobject(2)) == NULL)
+X return NULL;
+X if ((w = newintobject((long)a)) == NULL ||
+X settupleitem(v, 0, w) != 0 ||
+X (w = newintobject((long)b)) == NULL ||
+X settupleitem(v, 1, w) != 0) {
+X DECREF(v);
+X return NULL;
+X }
+X return v;
+X}
+X
+Xstatic object *
+Xmakerect(a, b, c, d)
+X int a, b, c, d;
+X{
+X object *v;
+X object *w;
+X if ((v = newtupleobject(2)) == NULL)
+X return NULL;
+X if ((w = makepoint(a, b)) == NULL ||
+X settupleitem(v, 0, w) != 0 ||
+X (w = makepoint(c, d)) == NULL ||
+X settupleitem(v, 1, w) != 0) {
+X DECREF(v);
+X return NULL;
+X }
+X return v;
+X}
+X
+Xstatic object *
+Xmakemouse(hor, ver, clicks, button, mask)
+X int hor, ver, clicks, button, mask;
+X{
+X object *v;
+X object *w;
+X if ((v = newtupleobject(4)) == NULL)
+X return NULL;
+X if ((w = makepoint(hor, ver)) == NULL ||
+X settupleitem(v, 0, w) != 0 ||
+X (w = newintobject((long)clicks)) == NULL ||
+X settupleitem(v, 1, w) != 0 ||
+X (w = newintobject((long)button)) == NULL ||
+X settupleitem(v, 2, w) != 0 ||
+X (w = newintobject((long)mask)) == NULL ||
+X settupleitem(v, 3, w) != 0) {
+X DECREF(v);
+X return NULL;
+X }
+X return v;
+X}
+X
+Xstatic object *
+Xmakemenu(mp, item)
+X object *mp;
+X int item;
+X{
+X object *v;
+X object *w;
+X if ((v = newtupleobject(2)) == NULL)
+X return NULL;
+X INCREF(mp);
+X if (settupleitem(v, 0, mp) != 0 ||
+X (w = newintobject((long)item)) == NULL ||
+X settupleitem(v, 1, w) != 0) {
+X DECREF(v);
+X return NULL;
+X }
+X return v;
+X}
+X
+X
+X/* Drawing objects */
+X
+Xtypedef struct {
+X OB_HEAD
+X windowobject *d_ref;
+X} drawingobject;
+X
+Xstatic drawingobject *Drawing; /* Set to current drawing object, or NULL */
+X
+X/* Drawing methods */
+X
+Xstatic void
+Xdrawing_dealloc(dp)
+X drawingobject *dp;
+X{
+X wenddrawing(dp->d_ref->w_win);
+X Drawing = NULL;
+X DECREF(dp->d_ref);
+X free((char *)dp);
+X}
+X
+Xstatic object *
+Xdrawing_generic(dp, args, func)
+X drawingobject *dp;
+X object *args;
+X void (*func) FPROTO((int, int, int, int));
+X{
+X int a[4];
+X if (!getrectarg(args, a))
+X return NULL;
+X (*func)(a[0], a[1], a[2], a[3]);
+X INCREF(None);
+X return None;
+X}
+X
+Xstatic object *
+Xdrawing_line(dp, args)
+X drawingobject *dp;
+X object *args;
+X{
+X drawing_generic(dp, args, wdrawline);
+X}
+X
+Xstatic object *
+Xdrawing_xorline(dp, args)
+X drawingobject *dp;
+X object *args;
+X{
+X drawing_generic(dp, args, wxorline);
+X}
+X
+Xstatic object *
+Xdrawing_circle(dp, args)
+X drawingobject *dp;
+X object *args;
+X{
+X int a[3];
+X if (!getpointintarg(args, a))
+X return NULL;
+X wdrawcircle(a[0], a[1], a[2]);
+X INCREF(None);
+X return None;
+X}
+X
+Xstatic object *
+Xdrawing_elarc(dp, args)
+X drawingobject *dp;
+X object *args;
+X{
+X int a[6];
+X if (!get3pointarg(args, a))
+X return NULL;
+X wdrawelarc(a[0], a[1], a[2], a[3], a[4], a[5]);
+X INCREF(None);
+X return None;
+X}
+X
+Xstatic object *
+Xdrawing_box(dp, args)
+X drawingobject *dp;
+X object *args;
+X{
+X drawing_generic(dp, args, wdrawbox);
+X}
+X
+Xstatic object *
+Xdrawing_erase(dp, args)
+X drawingobject *dp;
+X object *args;
+X{
+X drawing_generic(dp, args, werase);
+X}
+X
+Xstatic object *
+Xdrawing_paint(dp, args)
+X drawingobject *dp;
+X object *args;
+X{
+X drawing_generic(dp, args, wpaint);
+X}
+X
+Xstatic object *
+Xdrawing_invert(dp, args)
+X drawingobject *dp;
+X object *args;
+X{
+X drawing_generic(dp, args, winvert);
+X}
+X
+Xstatic object *
+Xdrawing_cliprect(dp, args)
+X drawingobject *dp;
+X object *args;
+X{
+X drawing_generic(dp, args, wcliprect);
+X}
+X
+Xstatic object *
+Xdrawing_noclip(dp, args)
+X drawingobject *dp;
+X object *args;
+X{
+X if (!getnoarg(args))
+X return NULL;
+X wnoclip();
+X INCREF(None);
+X return None;
+X}
+X
+Xstatic object *
+Xdrawing_shade(dp, args)
+X drawingobject *dp;
+X object *args;
+X{
+X int a[5];
+X if (!getrectintarg(args, a))
+X return NULL;
+X wshade(a[0], a[1], a[2], a[3], a[4]);
+X INCREF(None);
+X return None;
+X}
+X
+Xstatic object *
+Xdrawing_text(dp, args)
+X drawingobject *dp;
+X object *args;
+X{
+X int a[2];
+X object *s;
+X if (!getpointstrarg(args, a, &s))
+X return NULL;
+X wdrawtext(a[0], a[1], getstringvalue(s), (int)getstringsize(s));
+X INCREF(None);
+X return None;
+X}
+X
+X/* The following four are also used as stdwin functions */
+X
+Xstatic object *
+Xdrawing_lineheight(dp, args)
+X drawingobject *dp;
+X object *args;
+X{
+X if (!getnoarg(args))
+X return NULL;
+X return newintobject((long)wlineheight());
+X}
+X
+Xstatic object *
+Xdrawing_baseline(dp, args)
+X drawingobject *dp;
+X object *args;
+X{
+X if (!getnoarg(args))
+X return NULL;
+X return newintobject((long)wbaseline());
+X}
+X
+Xstatic object *
+Xdrawing_textwidth(dp, args)
+X drawingobject *dp;
+X object *args;
+X{
+X object *s;
+X if (!getstrarg(args, &s))
+X return NULL;
+X return newintobject(
+X (long)wtextwidth(getstringvalue(s), (int)getstringsize(s)));
+X}
+X
+Xstatic object *
+Xdrawing_textbreak(dp, args)
+X drawingobject *dp;
+X object *args;
+X{
+X object *s;
+X int a;
+X if (!getstrintarg(args, &s, &a))
+X return NULL;
+X return newintobject(
+X (long)wtextbreak(getstringvalue(s), (int)getstringsize(s), a));
+X}
+X
+Xstatic struct methodlist drawing_methods[] = {
+X {"box", drawing_box},
+X {"circle", drawing_circle},
+X {"cliprect", drawing_cliprect},
+X {"elarc", drawing_elarc},
+X {"erase", drawing_erase},
+X {"invert", drawing_invert},
+X {"line", drawing_line},
+X {"noclip", drawing_noclip},
+X {"paint", drawing_paint},
+X {"shade", drawing_shade},
+X {"text", drawing_text},
+X {"xorline", drawing_xorline},
+X
+X /* Text measuring methods: */
+X {"baseline", drawing_baseline},
+X {"lineheight", drawing_lineheight},
+X {"textbreak", drawing_textbreak},
+X {"textwidth", drawing_textwidth},
+X {NULL, NULL} /* sentinel */
+X};
+X
+Xstatic object *
+Xdrawing_getattr(wp, name)
+X drawingobject *wp;
+X char *name;
+X{
+X return findmethod(drawing_methods, (object *)wp, name);
+X}
+X
+Xstatic typeobject Drawingtype = {
+X OB_HEAD_INIT(&Typetype)
+X 0, /*ob_size*/
+X "drawing", /*tp_name*/
+X sizeof(drawingobject), /*tp_size*/
+X 0, /*tp_itemsize*/
+X /* methods */
+X drawing_dealloc, /*tp_dealloc*/
+X 0, /*tp_print*/
+X drawing_getattr, /*tp_getattr*/
+X 0, /*tp_setattr*/
+X 0, /*tp_compare*/
+X 0, /*tp_repr*/
+X};
+X
+X
+X/* Text(edit) objects */
+X
+Xtypedef struct {
+X OB_HEAD
+X TEXTEDIT *t_text;
+X windowobject *t_ref;
+X object *t_attr; /* Attributes dictionary */
+X} textobject;
+X
+Xextern typeobject Texttype; /* Really static, forward */
+X
+Xstatic textobject *
+Xnewtextobject(wp, left, top, right, bottom)
+X windowobject *wp;
+X int left, top, right, bottom;
+X{
+X textobject *tp;
+X tp = NEWOBJ(textobject, &Texttype);
+X if (tp == NULL)
+X return NULL;
+X tp->t_attr = NULL;
+X INCREF(wp);
+X tp->t_ref = wp;
+X tp->t_text = tecreate(wp->w_win, left, top, right, bottom);
+X if (tp->t_text == NULL) {
+X DECREF(tp);
+X return (textobject *) err_nomem();
+X }
+X return tp;
+X}
+X
+X/* Text(edit) methods */
+X
+Xstatic void
+Xtext_dealloc(tp)
+X textobject *tp;
+X{
+X if (tp->t_text != NULL)
+X tefree(tp->t_text);
+X if (tp->t_attr != NULL)
+X DECREF(tp->t_attr);
+X DECREF(tp->t_ref);
+X DEL(tp);
+X}
+X
+Xstatic object *
+Xtext_arrow(self, args)
+X textobject *self;
+X object *args;
+X{
+X int code;
+X if (!getintarg(args, &code))
+X return NULL;
+X tearrow(self->t_text, code);
+X INCREF(None);
+X return None;
+X}
+X
+Xstatic object *
+Xtext_draw(self, args)
+X textobject *self;
+X object *args;
+X{
+X register TEXTEDIT *tp = self->t_text;
+X int a[4];
+X int left, top, right, bottom;
+X if (!getrectarg(args, a))
+X return NULL;
+X if (Drawing != NULL) {
+X err_setstr(RuntimeError, "not drawing");
+X return NULL;
+X }
+X /* Clip to text area and ignore if area is empty */
+X left = tegetleft(tp);
+X top = tegettop(tp);
+X right = tegetright(tp);
+X bottom = tegetbottom(tp);
+X if (a[0] < left) a[0] = left;
+X if (a[1] < top) a[1] = top;
+X if (a[2] > right) a[2] = right;
+X if (a[3] > bottom) a[3] = bottom;
+X if (a[0] < a[2] && a[1] < a[3]) {
+X /* Hide/show focus around draw call; these are undocumented,
+X but required here to get the highlighting correct.
+X The call to werase is also required for this reason.
+X Finally, this forces us to require (above) that we are NOT
+X already drawing. */
+X tehidefocus(tp);
+X wbegindrawing(self->t_ref->w_win);
+X werase(a[0], a[1], a[2], a[3]);
+X tedrawnew(tp, a[0], a[1], a[2], a[3]);
+X wenddrawing(self->t_ref->w_win);
+X teshowfocus(tp);
+X }
+X INCREF(None);
+X return None;
+X}
+X
+Xstatic object *
+Xtext_event(self, args)
+X textobject *self;
+X object *args;
+X{
+X register TEXTEDIT *tp = self->t_text;
+X EVENT e;
+X if (!geteventarg(args, &e))
+X return NULL;
+X if (e.type == WE_MOUSE_DOWN) {
+X /* Cheat at the margins */
+X int width, height;
+X wgetdocsize(e.window, &width, &height);
+X if (e.u.where.h < 0 && tegetleft(tp) == 0)
+X e.u.where.h = 0;
+X else if (e.u.where.h > width && tegetright(tp) == width)
+X e.u.where.h = width;
+X if (e.u.where.v < 0 && tegettop(tp) == 0)
+X e.u.where.v = 0;
+X else if (e.u.where.v > height && tegetright(tp) == height)
+X e.u.where.v = height;
+X }
+X return newintobject((long) teevent(tp, &e));
+X}
+X
+Xstatic object *
+Xtext_getfocus(self, args)
+X textobject *self;
+X object *args;
+X{
+X if (!getnoarg(args))
+X return NULL;
+X return makepoint(tegetfoc1(self->t_text), tegetfoc2(self->t_text));
+X}
+X
+Xstatic object *
+Xtext_getfocustext(self, args)
+X textobject *self;
+X object *args;
+X{
+X int f1, f2;
+X char *text;
+X if (!getnoarg(args))
+X return NULL;
+X f1 = tegetfoc1(self->t_text);
+X f2 = tegetfoc2(self->t_text);
+X text = tegettext(self->t_text);
+X return newsizedstringobject(text + f1, f2-f1);
+X}
+X
+Xstatic object *
+Xtext_getrect(self, args)
+X textobject *self;
+X object *args;
+X{
+X if (!getnoarg(args))
+X return NULL;
+X return makerect(tegetleft(self->t_text),
+X tegettop(self->t_text),
+X tegetright(self->t_text),
+X tegetbottom(self->t_text));
+X}
+X
+Xstatic object *
+Xtext_gettext(self, args)
+X textobject *self;
+X object *args;
+X{
+X if (!getnoarg(args))
+X return NULL;
+X return newsizedstringobject(tegettext(self->t_text),
+X tegetlen(self->t_text));
+X}
+X
+Xstatic object *
+Xtext_move(self, args)
+X textobject *self;
+X object *args;
+X{
+X int a[4];
+X if (!getrectarg(args, a))
+X return NULL;
+X temovenew(self->t_text, a[0], a[1], a[2], a[3]);
+X INCREF(None);
+X return None;
+X}
+X
+Xstatic object *
+Xtext_setfocus(self, args)
+X textobject *self;
+X object *args;
+X{
+X int a[2];
+X if (!getpointarg(args, a))
+X return NULL;
+X tesetfocus(self->t_text, a[0], a[1]);
+X INCREF(None);
+X return None;
+X}
+X
+Xstatic object *
+Xtext_replace(self, args)
+X textobject *self;
+X object *args;
+X{
+X object *text;
+X if (!getstrarg(args, &text))
+X return NULL;
+X tereplace(self->t_text, getstringvalue(text));
+X INCREF(None);
+X return None;
+X}
+X
+Xstatic struct methodlist text_methods[] = {
+X "arrow", text_arrow,
+X "draw", text_draw,
+X "event", text_event,
+X "getfocus", text_getfocus,
+X "getfocustext", text_getfocustext,
+X "getrect", text_getrect,
+X "gettext", text_gettext,
+X "move", text_move,
+X "replace", text_replace,
+X "setfocus", text_setfocus,
+X {NULL, NULL} /* sentinel */
+X};
+X
+Xstatic object *
+Xtext_getattr(tp, name)
+X textobject *tp;
+X char *name;
+X{
+X if (tp->t_attr != NULL) {
+X object *v = dictlookup(tp->t_attr, name);
+X if (v != NULL) {
+X INCREF(v);
+X return v;
+X }
+X }
+X return findmethod(text_methods, (object *)tp, name);
+X}
+X
+Xstatic int
+Xtext_setattr(tp, name, v)
+X textobject *tp;
+X char *name;
+X object *v;
+X{
+X if (tp->t_attr == NULL) {
+X tp->t_attr = newdictobject();
+X if (tp->t_attr == NULL)
+X return -1;
+X }
+X if (v == NULL)
+X return dictremove(tp->t_attr, name);
+X else
+X return dictinsert(tp->t_attr, name, v);
+X}
+X
+Xstatic typeobject Texttype = {
+X OB_HEAD_INIT(&Typetype)
+X 0, /*ob_size*/
+X "textedit", /*tp_name*/
+X sizeof(textobject), /*tp_size*/
+X 0, /*tp_itemsize*/
+X /* methods */
+X text_dealloc, /*tp_dealloc*/
+X 0, /*tp_print*/
+X text_getattr, /*tp_getattr*/
+X text_setattr, /*tp_setattr*/
+X 0, /*tp_compare*/
+X 0, /*tp_repr*/
+X};
+X
+X
+X/* Menu objects */
+X
+X#define IDOFFSET 10 /* Menu IDs we use start here */
+X#define MAXNMENU 20 /* Max #menus we allow */
+Xstatic menuobject *menulist[MAXNMENU];
+X
+Xstatic menuobject *
+Xnewmenuobject(title)
+X object *title;
+X{
+X int id;
+X MENU *menu;
+X menuobject *mp;
+X for (id = 0; id < MAXNMENU; id++) {
+X if (menulist[id] == NULL)
+X break;
+X }
+X if (id >= MAXNMENU)
+X return (menuobject *) err_nomem();
+X menu = wmenucreate(id + IDOFFSET, getstringvalue(title));
+X if (menu == NULL)
+X return (menuobject *) err_nomem();
+X mp = NEWOBJ(menuobject, &Menutype);
+X if (mp != NULL) {
+X mp->m_menu = menu;
+X mp->m_id = id + IDOFFSET;
+X mp->m_attr = NULL;
+X menulist[id] = mp;
+X }
+X else
+X wmenudelete(menu);
+X return mp;
+X}
+X
+X/* Menu methods */
+X
+Xstatic void
+Xmenu_dealloc(mp)
+X menuobject *mp;
+X{
+X
+X int id = mp->m_id - IDOFFSET;
+X if (id >= 0 && id < MAXNMENU && menulist[id] == mp) {
+X menulist[id] = NULL;
+X }
+X wmenudelete(mp->m_menu);
+X if (mp->m_attr != NULL)
+X DECREF(mp->m_attr);
+X DEL(mp);
+X}
+X
+Xstatic object *
+Xmenu_additem(self, args)
+X menuobject *self;
+X object *args;
+X{
+X object *text;
+X int shortcut;
+X if (is_tupleobject(args)) {
+X object *v;
+X if (!getstrstrarg(args, &text, &v))
+X return NULL;
+X if (getstringsize(v) != 1) {
+X err_badarg();
+X return NULL;
+X }
+X shortcut = *getstringvalue(v) & 0xff;
+X }
+X else {
+X if (!getstrarg(args, &text))
+X return NULL;
+X shortcut = -1;
+X }
+X wmenuadditem(self->m_menu, getstringvalue(text), shortcut);
+X INCREF(None);
+X return None;
+X}
+X
+Xstatic object *
+Xmenu_setitem(self, args)
+X menuobject *self;
+X object *args;
+X{
+X int index;
+X object *text;
+X if (!getintstrarg(args, &index, &text))
+X return NULL;
+X wmenusetitem(self->m_menu, index, getstringvalue(text));
+X INCREF(None);
+X return None;
+X}
+X
+Xstatic object *
+Xmenu_enable(self, args)
+X menuobject *self;
+X object *args;
+X{
+X int index;
+X int flag;
+X if (!getintintarg(args, &index, &flag))
+X return NULL;
+X wmenuenable(self->m_menu, index, flag);
+X INCREF(None);
+X return None;
+X}
+X
+Xstatic object *
+Xmenu_check(self, args)
+X menuobject *self;
+X object *args;
+X{
+X int index;
+X int flag;
+X if (!getintintarg(args, &index, &flag))
+X return NULL;
+X wmenucheck(self->m_menu, index, flag);
+X INCREF(None);
+X return None;
+X}
+X
+Xstatic struct methodlist menu_methods[] = {
+X "additem", menu_additem,
+X "setitem", menu_setitem,
+X "enable", menu_enable,
+X "check", menu_check,
+X {NULL, NULL} /* sentinel */
+X};
+X
+Xstatic object *
+Xmenu_getattr(mp, name)
+X menuobject *mp;
+X char *name;
+X{
+X if (mp->m_attr != NULL) {
+X object *v = dictlookup(mp->m_attr, name);
+X if (v != NULL) {
+X INCREF(v);
+X return v;
+X }
+X }
+X return findmethod(menu_methods, (object *)mp, name);
+X}
+X
+Xstatic int
+Xmenu_setattr(mp, name, v)
+X menuobject *mp;
+X char *name;
+X object *v;
+X{
+X if (mp->m_attr == NULL) {
+X mp->m_attr = newdictobject();
+X if (mp->m_attr == NULL)
+X return -1;
+X }
+X if (v == NULL)
+X return dictremove(mp->m_attr, name);
+X else
+X return dictinsert(mp->m_attr, name, v);
+X}
+X
+Xstatic typeobject Menutype = {
+X OB_HEAD_INIT(&Typetype)
+X 0, /*ob_size*/
+X "menu", /*tp_name*/
+X sizeof(menuobject), /*tp_size*/
+X 0, /*tp_itemsize*/
+X /* methods */
+X menu_dealloc, /*tp_dealloc*/
+X 0, /*tp_print*/
+X menu_getattr, /*tp_getattr*/
+X menu_setattr, /*tp_setattr*/
+X 0, /*tp_compare*/
+X 0, /*tp_repr*/
+X};
+X
+X
+X/* Windows */
+X
+X#define MAXNWIN 50
+Xstatic windowobject *windowlist[MAXNWIN];
+X
+X/* Window methods */
+X
+Xstatic void
+Xwindow_dealloc(wp)
+X windowobject *wp;
+X{
+X if (wp->w_win != NULL) {
+X int tag = wgettag(wp->w_win);
+X if (tag >= 0 && tag < MAXNWIN)
+X windowlist[tag] = NULL;
+X else
+X fprintf(stderr, "XXX help! tag %d in window_dealloc\n",
+X tag);
+X wclose(wp->w_win);
+X }
+X DECREF(wp->w_title);
+X if (wp->w_attr != NULL)
+X DECREF(wp->w_attr);
+X free((char *)wp);
+X}
+X
+Xstatic void
+Xwindow_print(wp, fp, flags)
+X windowobject *wp;
+X FILE *fp;
+X int flags;
+X{
+X fprintf(fp, "<window titled '%s'>", getstringvalue(wp->w_title));
+X}
+X
+Xstatic object *
+Xwindow_begindrawing(wp, args)
+X windowobject *wp;
+X object *args;
+X{
+X drawingobject *dp;
+X if (!getnoarg(args))
+X return NULL;
+X if (Drawing != NULL) {
+X err_setstr(RuntimeError, "already drawing");
+X return NULL;
+X }
+X dp = NEWOBJ(drawingobject, &Drawingtype);
+X if (dp == NULL)
+X return NULL;
+X Drawing = dp;
+X INCREF(wp);
+X dp->d_ref = wp;
+X wbegindrawing(wp->w_win);
+X return (object *)dp;
+X}
+X
+Xstatic object *
+Xwindow_change(wp, args)
+X windowobject *wp;
+X object *args;
+X{
+X int a[4];
+X if (!getrectarg(args, a))
+X return NULL;
+X wchange(wp->w_win, a[0], a[1], a[2], a[3]);
+X INCREF(None);
+X return None;
+X}
+X
+Xstatic object *
+Xwindow_gettitle(wp, args)
+X windowobject *wp;
+X object *args;
+X{
+X if (!getnoarg(args))
+X return NULL;
+X INCREF(wp->w_title);
+X return wp->w_title;
+X}
+X
+Xstatic object *
+Xwindow_getwinsize(wp, args)
+X windowobject *wp;
+X object *args;
+X{
+X int width, height;
+X if (!getnoarg(args))
+X return NULL;
+X wgetwinsize(wp->w_win, &width, &height);
+X return makepoint(width, height);
+X}
+X
+Xstatic object *
+Xwindow_getdocsize(wp, args)
+X windowobject *wp;
+X object *args;
+X{
+X int width, height;
+X if (!getnoarg(args))
+X return NULL;
+X wgetdocsize(wp->w_win, &width, &height);
+X return makepoint(width, height);
+X}
+X
+Xstatic object *
+Xwindow_getorigin(wp, args)
+X windowobject *wp;
+X object *args;
+X{
+X int width, height;
+X if (!getnoarg(args))
+X return NULL;
+X wgetorigin(wp->w_win, &width, &height);
+X return makepoint(width, height);
+X}
+X
+Xstatic object *
+Xwindow_scroll(wp, args)
+X windowobject *wp;
+X object *args;
+X{
+X int a[6];
+X if (!getrectpointarg(args, a))
+X return NULL;
+X wscroll(wp->w_win, a[0], a[1], a[2], a[3], a[4], a[5]);
+X INCREF(None);
+X return None;
+X}
+X
+Xstatic object *
+Xwindow_setdocsize(wp, args)
+X windowobject *wp;
+X object *args;
+X{
+X int a[2];
+X if (!getpointarg(args, a))
+X return NULL;
+X wsetdocsize(wp->w_win, a[0], a[1]);
+X INCREF(None);
+X return None;
+X}
+X
+Xstatic object *
+Xwindow_setorigin(wp, args)
+X windowobject *wp;
+X object *args;
+X{
+X int a[2];
+X if (!getpointarg(args, a))
+X return NULL;
+X wsetorigin(wp->w_win, a[0], a[1]);
+X INCREF(None);
+X return None;
+X}
+X
+Xstatic object *
+Xwindow_settitle(wp, args)
+X windowobject *wp;
+X object *args;
+X{
+X object *title;
+X if (!getstrarg(args, &title))
+X return NULL;
+X DECREF(wp->w_title);
+X INCREF(title);
+X wp->w_title = title;
+X wsettitle(wp->w_win, getstringvalue(title));
+X INCREF(None);
+X return None;
+X}
+X
+Xstatic object *
+Xwindow_show(wp, args)
+X windowobject *wp;
+X object *args;
+X{
+X int a[4];
+X if (!getrectarg(args, a))
+X return NULL;
+X wshow(wp->w_win, a[0], a[1], a[2], a[3]);
+X INCREF(None);
+X return None;
+X}
+X
+Xstatic object *
+Xwindow_settimer(wp, args)
+X windowobject *wp;
+X object *args;
+X{
+X int a;
+X if (!getintarg(args, &a))
+X return NULL;
+X wsettimer(wp->w_win, a);
+X INCREF(None);
+X return None;
+X}
+X
+Xstatic object *
+Xwindow_menucreate(self, args)
+X windowobject *self;
+X object *args;
+X{
+X menuobject *mp;
+X object *title;
+X if (!getstrarg(args, &title))
+X return NULL;
+X wmenusetdeflocal(1);
+X mp = newmenuobject(title);
+X if (mp == NULL)
+X return NULL;
+X wmenuattach(self->w_win, mp->m_menu);
+X return (object *)mp;
+X}
+X
+Xstatic object *
+Xwindow_textcreate(self, args)
+X windowobject *self;
+X object *args;
+X{
+X textobject *tp;
+X int a[4];
+X if (!getrectarg(args, a))
+X return NULL;
+X return (object *)
+X newtextobject(self, a[0], a[1], a[2], a[3]);
+X}
+X
+Xstatic object *
+Xwindow_setselection(self, args)
+X windowobject *self;
+X object *args;
+X{
+X int sel;
+X object *str;
+X int ok;
+X if (!getintstrarg(args, &sel, &str))
+X return NULL;
+X ok = wsetselection(self->w_win, sel,
+X getstringvalue(str), (int)getstringsize(str));
+X return newintobject(ok);
+X}
+X
+Xstatic object *
+Xwindow_setwincursor(self, args)
+X windowobject *self;
+X object *args;
+X{
+X object *str;
+X CURSOR *c;
+X if (!getstrarg(args, &str))
+X return NULL;
+X c = wfetchcursor(getstringvalue(str));
+X if (c == NULL) {
+X err_setstr(RuntimeError, "no such cursor");
+X return NULL;
+X }
+X wsetwincursor(self->w_win, c);
+X INCREF(None);
+X return None;
+X}
+X
+Xstatic struct methodlist window_methods[] = {
+X {"begindrawing",window_begindrawing},
+X {"change", window_change},
+X {"getdocsize", window_getdocsize},
+X {"getorigin", window_getorigin},
+X {"gettitle", window_gettitle},
+X {"getwinsize", window_getwinsize},
+X {"menucreate", window_menucreate},
+X {"scroll", window_scroll},
+X {"setwincursor",window_setwincursor},
+X {"setdocsize", window_setdocsize},
+X {"setorigin", window_setorigin},
+X {"setselection",window_setselection},
+X {"settimer", window_settimer},
+X {"settitle", window_settitle},
+X {"show", window_show},
+X {"textcreate", window_textcreate},
+X {NULL, NULL} /* sentinel */
+X};
+X
+Xstatic object *
+Xwindow_getattr(wp, name)
+X windowobject *wp;
+X char *name;
+X{
+X if (wp->w_attr != NULL) {
+X object *v = dictlookup(wp->w_attr, name);
+X if (v != NULL) {
+X INCREF(v);
+X return v;
+X }
+X }
+X return findmethod(window_methods, (object *)wp, name);
+X}
+X
+Xstatic int
+Xwindow_setattr(wp, name, v)
+X windowobject *wp;
+X char *name;
+X object *v;
+X{
+X if (wp->w_attr == NULL) {
+X wp->w_attr = newdictobject();
+X if (wp->w_attr == NULL)
+X return -1;
+X }
+X if (v == NULL)
+X return dictremove(wp->w_attr, name);
+X else
+X return dictinsert(wp->w_attr, name, v);
+X}
+X
+Xstatic typeobject Windowtype = {
+X OB_HEAD_INIT(&Typetype)
+X 0, /*ob_size*/
+X "window", /*tp_name*/
+X sizeof(windowobject), /*tp_size*/
+X 0, /*tp_itemsize*/
+X /* methods */
+X window_dealloc, /*tp_dealloc*/
+X window_print, /*tp_print*/
+X window_getattr, /*tp_getattr*/
+X window_setattr, /*tp_setattr*/
+X 0, /*tp_compare*/
+X 0, /*tp_repr*/
+X};
+X
+X/* Stdwin methods */
+X
+Xstatic object *
+Xstdwin_open(sw, args)
+X object *sw;
+X object *args;
+X{
+X int tag;
+X object *title;
+X windowobject *wp;
+X if (!getstrarg(args, &title))
+X return NULL;
+X for (tag = 0; tag < MAXNWIN; tag++) {
+X if (windowlist[tag] == NULL)
+X break;
+X }
+X if (tag >= MAXNWIN)
+X return err_nomem();
+X wp = NEWOBJ(windowobject, &Windowtype);
+X if (wp == NULL)
+X return NULL;
+X INCREF(title);
+X wp->w_title = title;
+X wp->w_win = wopen(getstringvalue(title), (void (*)()) NULL);
+X wp->w_attr = NULL;
+X if (wp->w_win == NULL) {
+X DECREF(wp);
+X return NULL;
+X }
+X windowlist[tag] = wp;
+X wsettag(wp->w_win, tag);
+X return (object *)wp;
+X}
+X
+Xstatic object *
+Xstdwin_get_poll_event(poll, args)
+X int poll;
+X object *args;
+X{
+X EVENT e;
+X object *v, *w;
+X if (!getnoarg(args))
+X return NULL;
+X if (Drawing != NULL) {
+X err_setstr(RuntimeError, "cannot getevent() while drawing");
+X return NULL;
+X }
+X/* again: */
+X if (poll) {
+X if (!wpollevent(&e)) {
+X INCREF(None);
+X return None;
+X }
+X }
+X else
+X wgetevent(&e);
+X if (e.type == WE_COMMAND && e.u.command == WC_CANCEL) {
+X /* Turn keyboard interrupts into exceptions */
+X err_set(KeyboardInterrupt);
+X return NULL;
+X }
+X/*
+X if (e.window == NULL && (e.type == WE_COMMAND || e.type == WE_CHAR))
+X goto again;
+X*/
+X if (e.type == WE_COMMAND && e.u.command == WC_CLOSE) {
+X /* Turn WC_CLOSE commands into WE_CLOSE events */
+X e.type = WE_CLOSE;
+X }
+X v = newtupleobject(3);
+X if (v == NULL)
+X return NULL;
+X if ((w = newintobject((long)e.type)) == NULL) {
+X DECREF(v);
+X return NULL;
+X }
+X settupleitem(v, 0, w);
+X if (e.window == NULL)
+X w = None;
+X else {
+X int tag = wgettag(e.window);
+X if (tag < 0 || tag >= MAXNWIN || windowlist[tag] == NULL)
+X w = None;
+X else
+X w = (object *)windowlist[tag];
+X#ifdef sgi
+X /* XXX Trap for unexplained weird bug */
+X if ((long)w == (long)0x80000001) {
+X err_setstr(SystemError,
+X "bad pointer in stdwin.getevent()");
+X return NULL;
+X }
+X#endif
+X }
+X INCREF(w);
+X settupleitem(v, 1, w);
+X switch (e.type) {
+X case WE_CHAR:
+X {
+X char c[1];
+X c[0] = e.u.character;
+X w = newsizedstringobject(c, 1);
+X }
+X break;
+X case WE_COMMAND:
+X w = newintobject((long)e.u.command);
+X break;
+X case WE_DRAW:
+X w = makerect(e.u.area.left, e.u.area.top,
+X e.u.area.right, e.u.area.bottom);
+X break;
+X case WE_MOUSE_DOWN:
+X case WE_MOUSE_MOVE:
+X case WE_MOUSE_UP:
+X w = makemouse(e.u.where.h, e.u.where.v,
+X e.u.where.clicks,
+X e.u.where.button,
+X e.u.where.mask);
+X break;
+X case WE_MENU:
+X if (e.u.m.id >= IDOFFSET && e.u.m.id < IDOFFSET+MAXNMENU &&
+X menulist[e.u.m.id - IDOFFSET] != NULL)
+X w = (object *)menulist[e.u.m.id - IDOFFSET];
+X else
+X w = None;
+X w = makemenu(w, e.u.m.item);
+X break;
+X case WE_LOST_SEL:
+X w = newintobject((long)e.u.sel);
+X break;
+X default:
+X w = None;
+X INCREF(w);
+X break;
+X }
+X if (w == NULL) {
+X DECREF(v);
+X return NULL;
+X }
+X settupleitem(v, 2, w);
+X return v;
+X}
+X
+Xstatic object *
+Xstdwin_getevent(sw, args)
+X object *sw;
+X object *args;
+X{
+X return stdwin_get_poll_event(0, args);
+X}
+X
+Xstatic object *
+Xstdwin_pollevent(sw, args)
+X object *sw;
+X object *args;
+X{
+X return stdwin_get_poll_event(1, args);
+X}
+X
+Xstatic object *
+Xstdwin_setdefwinpos(sw, args)
+X object *sw;
+X object *args;
+X{
+X int a[2];
+X if (!getpointarg(args, a))
+X return NULL;
+X wsetdefwinpos(a[0], a[1]);
+X INCREF(None);
+X return None;
+X}
+X
+Xstatic object *
+Xstdwin_setdefwinsize(sw, args)
+X object *sw;
+X object *args;
+X{
+X int a[2];
+X if (!getpointarg(args, a))
+X return NULL;
+X wsetdefwinsize(a[0], a[1]);
+X INCREF(None);
+X return None;
+X}
+X
+Xstatic object *
+Xstdwin_getdefwinpos(wp, args)
+X windowobject *wp;
+X object *args;
+X{
+X int h, v;
+X if (!getnoarg(args))
+X return NULL;
+X wgetdefwinpos(&h, &v);
+X return makepoint(h, v);
+X}
+X
+Xstatic object *
+Xstdwin_getdefwinsize(wp, args)
+X windowobject *wp;
+X object *args;
+X{
+X int width, height;
+X if (!getnoarg(args))
+X return NULL;
+X wgetdefwinsize(&width, &height);
+X return makepoint(width, height);
+X}
+X
+Xstatic object *
+Xstdwin_menucreate(self, args)
+X object *self;
+X object *args;
+X{
+X object *title;
+X if (!getstrarg(args, &title))
+X return NULL;
+X wmenusetdeflocal(0);
+X return (object *)newmenuobject(title);
+X}
+X
+Xstatic object *
+Xstdwin_askfile(self, args)
+X object *self;
+X object *args;
+X{
+X object *prompt, *dflt;
+X int new, ret;
+X char buf[256];
+X if (!getstrstrintarg(args, &prompt, &dflt, &new))
+X return NULL;
+X strncpy(buf, getstringvalue(dflt), sizeof buf);
+X buf[sizeof buf - 1] = '\0';
+X ret = waskfile(getstringvalue(prompt), buf, sizeof buf, new);
+X if (!ret) {
+X err_set(KeyboardInterrupt);
+X return NULL;
+X }
+X return newstringobject(buf);
+X}
+X
+Xstatic object *
+Xstdwin_askync(self, args)
+X object *self;
+X object *args;
+X{
+X object *prompt;
+X int new, ret;
+X if (!getstrintarg(args, &prompt, &new))
+X return NULL;
+X ret = waskync(getstringvalue(prompt), new);
+X if (ret < 0) {
+X err_set(KeyboardInterrupt);
+X return NULL;
+X }
+X return newintobject((long)ret);
+X}
+X
+Xstatic object *
+Xstdwin_askstr(self, args)
+X object *self;
+X object *args;
+X{
+X object *prompt, *dflt;
+X int ret;
+X char buf[256];
+X if (!getstrstrarg(args, &prompt, &dflt))
+X return NULL;
+X strncpy(buf, getstringvalue(dflt), sizeof buf);
+X buf[sizeof buf - 1] = '\0';
+X ret = waskstr(getstringvalue(prompt), buf, sizeof buf);
+X if (!ret) {
+X err_set(KeyboardInterrupt);
+X return NULL;
+X }
+X return newstringobject(buf);
+X}
+X
+Xstatic object *
+Xstdwin_message(self, args)
+X object *self;
+X object *args;
+X{
+X object *msg;
+X if (!getstrarg(args, &msg))
+X return NULL;
+X wmessage(getstringvalue(msg));
+X INCREF(None);
+X return None;
+X}
+X
+Xstatic object *
+Xstdwin_fleep(self, args)
+X object *self;
+X object *args;
+X{
+X if (!getnoarg(args))
+X return NULL;
+X wfleep();
+X INCREF(None);
+X return None;
+X}
+X
+Xstatic object *
+Xstdwin_setcutbuffer(self, args)
+X object *self;
+X object *args;
+X{
+X int i;
+X object *str;
+X if (!getintstrarg(args, &i, &str))
+X return NULL;
+X wsetcutbuffer(i, getstringvalue(str), getstringsize(str));
+X INCREF(None);
+X return None;
+X}
+X
+Xstatic object *
+Xstdwin_getcutbuffer(self, args)
+X object *self;
+X object *args;
+X{
+X int i;
+X char *str;
+X int len;
+X if (!getintarg(args, &i))
+X return NULL;
+X str = wgetcutbuffer(i, &len);
+X if (str == NULL) {
+X str = "";
+X len = 0;
+X }
+X return newsizedstringobject(str, len);
+X}
+X
+Xstatic object *
+Xstdwin_rotatecutbuffers(self, args)
+X object *self;
+X object *args;
+X{
+X int i;
+X if (!getintarg(args, &i))
+X return NULL;
+X wrotatecutbuffers(i);
+X INCREF(None);
+X return None;
+X}
+X
+Xstatic object *
+Xstdwin_getselection(self, args)
+X object *self;
+X object *args;
+X{
+X int sel;
+X char *data;
+X int len;
+X if (!getintarg(args, &sel))
+X return NULL;
+X data = wgetselection(sel, &len);
+X if (data == NULL) {
+X data = "";
+X len = 0;
+X }
+X return newsizedstringobject(data, len);
+X}
+X
+Xstatic object *
+Xstdwin_resetselection(self, args)
+X object *self;
+X object *args;
+X{
+X int sel;
+X if (!getintarg(args, &sel))
+X return NULL;
+X wresetselection(sel);
+X INCREF(None);
+X return None;
+X}
+X
+Xstatic struct methodlist stdwin_methods[] = {
+X {"askfile", stdwin_askfile},
+X {"askstr", stdwin_askstr},
+X {"askync", stdwin_askync},
+X {"fleep", stdwin_fleep},
+X {"getselection", stdwin_getselection},
+X {"getcutbuffer", stdwin_getcutbuffer},
+X {"getdefwinpos", stdwin_getdefwinpos},
+X {"getdefwinsize", stdwin_getdefwinsize},
+X {"getevent", stdwin_getevent},
+X {"menucreate", stdwin_menucreate},
+X {"message", stdwin_message},
+X {"open", stdwin_open},
+X {"pollevent", stdwin_pollevent},
+X {"resetselection", stdwin_resetselection},
+X {"rotatecutbuffers", stdwin_rotatecutbuffers},
+X {"setcutbuffer", stdwin_setcutbuffer},
+X {"setdefwinpos", stdwin_setdefwinpos},
+X {"setdefwinsize", stdwin_setdefwinsize},
+X
+X /* Text measuring methods borrow code from drawing objects: */
+X {"baseline", drawing_baseline},
+X {"lineheight", drawing_lineheight},
+X {"textbreak", drawing_textbreak},
+X {"textwidth", drawing_textwidth},
+X {NULL, NULL} /* sentinel */
+X};
+X
+Xvoid
+Xinitstdwin()
+X{
+X static int inited;
+X if (!inited) {
+X winit();
+X inited = 1;
+X }
+X initmodule("stdwin", stdwin_methods);
+X}
+EOF
+fi
+echo 'Part 04 out of 21 of pack.out complete.'
+exit 0
diff --git a/shar/python-0.9.1-05-21.shar b/shar/python-0.9.1-05-21.shar
new file mode 100644
index 0000000..2d7f035
--- /dev/null
+++ b/shar/python-0.9.1-05-21.shar
@@ -0,0 +1,2528 @@
+: This is a shell archive.
+: Extract with 'sh this_file'.
+:
+: Extract part 01 first since it makes all directories
+echo 'Start of pack.out, part 05 out of 21:'
+if test -s 'demo/sgi/audio_stdwin/README'
+then echo '*** I will not over-write existing file demo/sgi/audio_stdwin/README'
+else
+echo 'x - demo/sgi/audio_stdwin/README'
+sed 's/^X//' > 'demo/sgi/audio_stdwin/README' << 'EOF'
+XThree programs that provide a user interface based upon STDWIN to the
+Xaudio device of the SGI 4D/25. These scripts also demonstrate the power
+Xof a set of window interface classes implemented in Python that simplify
+Xthe construction of all sorts of buttons, etc.
+X
+Xjukebox Browses a directory full of sound samples and lets you
+X play selected ones. (Probably not fully functional, it
+X requires a conversion program.)
+X
+Xrec A tape recorder that lets you record a sound sample,
+X play it back, and save it to a file. Various options to
+X set sampling rate, volume etc. When idle it doubles
+X as a VU meter.
+X
+Xvumeter A VU meter that displays a history of the volume of
+X sound recently sampled from the microphone.
+EOF
+fi
+if test -s 'src/panelmodule.c'
+then echo '*** I will not over-write existing file src/panelmodule.c'
+else
+echo 'x - src/panelmodule.c'
+sed 's/^X//' > 'src/panelmodule.c' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/* Panel module.
+X Interface to the NASA Ames "panel library" for the SGI Graphics Library
+X by David Tristram.
+X
+X NOTE: the panel library dumps core if you don't create a window before
+X calling pnl.mkpanel(). A call to gl.winopen() suffices.
+X If you don't want a window to be created, call gl.noport() before
+X gl.winopen().
+X*/
+X
+X#include <gl.h>
+X#include <device.h>
+X#include <panel.h>
+X
+X#include "allobjects.h"
+X#include "import.h"
+X#include "modsupport.h"
+X#include "cgensupport.h"
+X
+X
+X/* The offsetof() macro calculates the offset of a structure member
+X in its structure. Unfortunately this cannot be written down portably,
+X hence it is standardized by ANSI C. For pre-ANSI C compilers,
+X we give a version here that works usually (but watch out!): */
+X
+X#ifndef offsetof
+X#define offsetof(type, member) ( (int) & ((type*)0) -> member )
+X#endif
+X
+X
+X/* Panel objects */
+X
+Xtypedef struct {
+X OB_HEAD
+X Panel *ob_panel;
+X object *ob_paneldict;
+X} panelobject;
+X
+Xextern typeobject Paneltype; /* Really static, forward */
+X
+X#define is_panelobject(v) ((v)->ob_type == &Paneltype)
+X
+X
+X/* Actuator objects */
+X
+Xtypedef struct {
+X OB_HEAD
+X Actuator *ob_actuator;
+X} actuatorobject;
+X
+Xextern typeobject Actuatortype; /* Really static, forward */
+X
+X#define is_actuatorobject(v) ((v)->ob_type == &Actuatortype)
+X
+Xstatic object *newactuatorobject(); /* Forward */
+X
+X
+X/* Since we allow different types of members than the functions from
+X structmember.c, the memberlist stuff is replicated here.
+X (Historically, it originated in this file and later became a generic
+X feature.) */
+X
+X/* An array of memberlist structures defines the name, type and offset
+X of selected members of a C structure. These can be read by
+X panel_getmember() and set by panel_setmember() (except if their
+X READONLY flag is set). The array must be terminated with an entry
+X whose name pointer is NULL. */
+X
+Xstruct memberlist {
+X char *name;
+X int type;
+X int offset;
+X int readonly;
+X};
+X
+X/* Types */
+X#define T_SHORT 0
+X#define T_DEVICE T_SHORT
+X#define T_LONG 1
+X#define T_INT T_LONG
+X#define T_BOOL T_LONG
+X#define T_FLOAT 2
+X#define T_COORD T_FLOAT
+X#define T_STRING 3
+X#define T_FUNC 4
+X#define T_ACTUATOR 5
+X
+X/* Readonly flag */
+X#define READONLY 1
+X#define RO READONLY /* Shorthand */
+X
+Xstatic object *
+Xpanel_getmember(addr, mlist, name)
+X char *addr;
+X struct memberlist *mlist;
+X char *name;
+X{
+X object *v;
+X register struct memberlist *l;
+X
+X for (l = mlist; l->name != NULL; l++) {
+X if (strcmp(l->name, name) == 0) {
+X addr += l->offset;
+X switch (l->type) {
+X case T_SHORT:
+X v = newintobject((long) *(short*)addr);
+X break;
+X case T_LONG:
+X v = newintobject(*(long*)addr);
+X break;
+X case T_FLOAT:
+X v = newfloatobject(*(float*)addr);
+X break;
+X case T_STRING:
+X if (*(char**)addr == NULL) {
+X INCREF(None);
+X v = None;
+X }
+X else
+X v = newstringobject(*(char**)addr);
+X break;
+X case T_ACTUATOR:
+X v = newactuatorobject(*(Actuator**)addr);
+X break;
+X default:
+X err_badarg();
+X v = NULL;
+X }
+X return v;
+X }
+X }
+X err_setstr(NameError, name);
+X return NULL;
+X}
+X
+X/* Attempt to set a member. Return: 0 if OK; 1 if not found; -1 if error */
+X
+Xstatic int
+Xpanel_setmember(addr, mlist, name, v)
+X char *addr;
+X struct memberlist *mlist;
+X char *name;
+X object *v;
+X{
+X register struct memberlist *l;
+X
+X for (l = mlist; l->name != NULL; l++) {
+X if (strcmp(l->name, name) == 0) {
+X if (l->readonly) {
+X err_setstr(TypeError, "read-only member");
+X return -1;
+X }
+X addr += l->offset;
+X switch (l->type) {
+X case T_SHORT:
+X if (!is_intobject(v)) {
+X err_setstr(TypeError, "int expected");
+X return -1;
+X }
+X *(short*)addr = getintvalue(v);
+X break;
+X case T_LONG:
+X if (!is_intobject(v)) {
+X err_setstr(TypeError, "int expected");
+X return -1;
+X }
+X *(long*)addr = getintvalue(v);
+X break;
+X case T_FLOAT:
+X if (is_intobject(v))
+X *(float*)addr = getintvalue(v);
+X else if (is_floatobject(v))
+X *(float*)addr = getfloatvalue(v);
+X else {
+X err_setstr(TypeError,"float expected");
+X return -1;
+X }
+X break;
+X case T_STRING:
+X /* XXX Should free(*(char**)addr) here
+X but it's dangerous since we don't know
+X if we set the label ourselves */
+X if (v == None)
+X *(char**)addr = NULL;
+X else if (!is_stringobject(v)) {
+X err_setstr(TypeError,
+X "string expected");
+X return -1;
+X }
+X else
+X *(char**)addr =
+X strdup(getstringvalue(v));
+X break;
+X case T_ACTUATOR:
+X if (v == None)
+X *(Actuator**)addr = NULL;
+X else if (!is_actuatorobject(v)) {
+X err_setstr(TypeError,
+X "actuator expected");
+X return -1;
+X }
+X else
+X *(Actuator**)addr =
+X ((actuatorobject *)v)->ob_actuator;
+X break;
+X default:
+X err_setstr(SystemError, "unknown member type");
+X return -1;
+X }
+X return 0; /* Found it */
+X }
+X }
+X
+X return 1; /* Not found */
+X}
+X
+X
+X/* Panel object methods */
+X
+Xstatic object *
+Xpanel_addpanel(self, args)
+X panelobject *self;
+X object *args;
+X{
+X if (!getnoarg(args))
+X return NULL;
+X pnl_addpanel(self->ob_panel);
+X INCREF(None);
+X return None;
+X}
+X
+Xstatic object *
+Xpanel_endgroup(self, args)
+X panelobject *self;
+X object *args;
+X{
+X if (!getnoarg(args))
+X return NULL;
+X pnl_endgroup(self->ob_panel);
+X INCREF(None);
+X return None;
+X}
+X
+Xstatic object *
+Xpanel_fixpanel(self, args)
+X panelobject *self;
+X object *args;
+X{
+X if (!getnoarg(args))
+X return NULL;
+X pnl_fixpanel(self->ob_panel);
+X INCREF(None);
+X return None;
+X}
+X
+Xstatic object *
+Xpanel_strwidth(self, args)
+X panelobject *self;
+X object *args;
+X{
+X object *v;
+X double width;
+X if (!getstrarg(args, &v))
+X return NULL;
+X width = pnl_strwidth(self->ob_panel, getstringvalue(v));
+X return newfloatobject(width);
+X}
+X
+Xstatic struct methodlist panel_methods[] = {
+X {"addpanel", panel_addpanel},
+X {"endgroup", panel_endgroup},
+X {"fixpanel", panel_fixpanel},
+X {"strwidth", panel_strwidth},
+X {NULL, NULL} /* sentinel */
+X};
+X
+Xstatic object *
+Xnewpanelobject()
+X{
+X panelobject *p;
+X p = NEWOBJ(panelobject, &Paneltype);
+X if (p == NULL)
+X return NULL;
+X p->ob_panel = pnl_mkpanel();
+X if ((p->ob_paneldict = newdictobject()) == NULL) {
+X DECREF(p);
+X return NULL;
+X }
+X return (object *)p;
+X}
+X
+Xstatic void
+Xpanel_dealloc(p)
+X panelobject *p;
+X{
+X pnl_delpanel(p->ob_panel);
+X if (p->ob_paneldict != NULL)
+X DECREF(p->ob_paneldict);
+X DEL(p);
+X}
+X
+X
+X/* Table of panel members */
+X
+X#define PANOFF(member) offsetof(Panel, member)
+X
+Xstatic struct memberlist panel_memberlist[] = {
+X {"id", T_SHORT, PANOFF(id), READONLY},
+X {"a", T_ACTUATOR, PANOFF(a), READONLY},
+X {"al", T_ACTUATOR, PANOFF(al), READONLY},
+X {"lastgroup", T_ACTUATOR, PANOFF(lastgroup), READONLY},
+X
+X {"active", T_BOOL, PANOFF(active)},
+X {"selectable", T_BOOL, PANOFF(selectable)},
+X
+X {"x", T_LONG, PANOFF(x)},
+X {"y", T_LONG, PANOFF(y)},
+X {"w", T_LONG, PANOFF(w)},
+X {"h", T_LONG, PANOFF(h)},
+X
+X {"minx", T_COORD, PANOFF(minx)},
+X {"maxx", T_COORD, PANOFF(maxx)},
+X {"miny", T_COORD, PANOFF(miny)},
+X {"maxy", T_COORD, PANOFF(maxy)},
+X
+X {"cw", T_COORD, PANOFF(cw)},
+X {"ch", T_COORD, PANOFF(ch)},
+X
+X {"gid", T_LONG, PANOFF(gid), READONLY},
+X {"usergid", T_LONG, PANOFF(usergid), READONLY},
+X
+X {"vobj", T_LONG, PANOFF(vobj), READONLY},
+X {"ppu", T_FLOAT, PANOFF(ppu)},
+X
+X {"label", T_STRING, PANOFF(label)},
+X
+X /* Panel callbacks are not supported */
+X
+X {"visible", T_BOOL, PANOFF(visible)},
+X {"somedirty", T_INT, PANOFF(somedirty)},
+X {"dirtycnt", T_INT, PANOFF(dirtycnt)},
+X
+X /* T_PANEL is not supported */
+X /*
+X {"next", T_PANEL, PANOFF(next), READONLY},
+X */
+X
+X {NULL, 0, 0} /* Sentinel */
+X};
+X
+Xstatic object *
+Xpanel_getattr(p, name)
+X panelobject *p;
+X char *name;
+X{
+X object *v;
+X
+X v = dictlookup(p->ob_paneldict, name);
+X if (v != NULL) {
+X INCREF(v);
+X return v;
+X }
+X
+X v = findmethod(panel_methods, (object *)p, name);
+X if (v != NULL)
+X return v;
+X err_clear();
+X return panel_getmember((char *)p->ob_panel, panel_memberlist, name);
+X}
+X
+Xstatic int
+Xpanel_setattr(p, name, v)
+X panelobject *p;
+X char *name;
+X object *v;
+X{
+X int err;
+X
+X /* We don't allow deletion of attributes */
+X if (v == NULL) {
+X err_setstr(TypeError, "read-only panel attribute");
+X return -1;
+X }
+X err = panel_setmember((char *)p->ob_panel, panel_memberlist, name, v);
+X if (err != 1)
+X return err;
+X return dictinsert(p->ob_paneldict, name, v);
+X}
+X
+Xstatic typeobject Paneltype = {
+X OB_HEAD_INIT(&Typetype)
+X 0, /*ob_size*/
+X "panel", /*tp_name*/
+X sizeof(panelobject), /*tp_size*/
+X 0, /*tp_itemsize*/
+X /* methods */
+X panel_dealloc, /*tp_dealloc*/
+X 0, /*tp_print*/
+X panel_getattr, /*tp_getattr*/
+X panel_setattr, /*tp_setattr*/
+X 0, /*tp_compare*/
+X 0, /*tp_repr*/
+X};
+X
+X
+X/* Descriptions of actuator-specific data members */
+X
+Xstruct memberlist slider_spec[] = {
+X {"mode", T_INT, offsetof(Slider, mode)},
+X {"finefactor", T_FLOAT, offsetof(Slider, finefactor)},
+X {"differentialfactor",
+X T_FLOAT, offsetof(Slider, differentialfactor)},
+X {"valsave", T_FLOAT, offsetof(Slider, valsave), RO},
+X {"wsave", T_COORD, offsetof(Slider, wsave)},
+X {"bh", T_COORD, offsetof(Slider, bh)},
+X {NULL}
+X};
+X
+X#define palette_spec slider_spec
+X
+Xstruct memberlist puck_spec[] = {
+X /* Actuators already have members x and y, so the Puck's x and y
+X have different names */
+X {"puck_x", T_FLOAT, offsetof(Puck, x)},
+X {"puck_y", T_FLOAT, offsetof(Puck, y)},
+X {NULL}
+X};
+X
+Xstruct memberlist dial_spec[] = {
+X {"mode", T_INT, offsetof(Dial, mode)},
+X {"finefactor", T_FLOAT, offsetof(Dial, finefactor)},
+X {"valsave", T_FLOAT, offsetof(Dial, valsave), RO},
+X {"wsave", T_COORD, offsetof(Dial, wsave)},
+X {"winds", T_FLOAT, offsetof(Dial, winds)},
+X {NULL}
+X};
+X
+Xstruct memberlist slideroid_spec[] = {
+X {"mode", T_INT, offsetof(Slideroid, mode)},
+X {"finemode", T_BOOL, offsetof(Slideroid, finemode)},
+X {"resetmode", T_BOOL, offsetof(Slideroid, resetmode)},
+X /* XXX Can't do resettarget (pointer to float) */
+X /* XXX This makes resetval pretty useless... */
+X /*
+X {"resetval", T_FLOAT, offsetof(Slideroid, resetval)},
+X */
+X {"valsave", T_FLOAT, offsetof(Slideroid, valsave), RO},
+X {"wsave", T_COORD, offsetof(Slideroid, wsave)},
+X {NULL}
+X};
+X
+Xstruct memberlist stripchart_spec[] = {
+X {"firstpt", T_INT, offsetof(Stripchart, firstpt), RO},
+X {"lastpt", T_INT, offsetof(Stripchart, lastpt), RO},
+X {"Bind_Low", T_BOOL, offsetof(Stripchart, Bind_Low)},
+X {"Bind_High", T_BOOL, offsetof(Stripchart, Bind_High)},
+X /* XXX Can't do y (array of floats) */
+X {"lowlabel", T_ACTUATOR, offsetof(Stripchart, lowlabel), RO},
+X {"highlabel", T_ACTUATOR, offsetof(Stripchart, highlabel), RO},
+X {NULL}
+X};
+X
+Xstruct memberlist typein_spec[] = {
+X /* Note: these should be readonly after the actuator is added
+X to a panel */
+X {"str", T_STRING, offsetof(Typein, str)},
+X {"len", T_INT, offsetof(Typein, len)},
+X {NULL}
+X};
+X
+Xstruct memberlist typeout_spec[] = {
+X {"mode", T_INT, offsetof(Typeout, mode)},
+X /* XXX The buffer is managed by the actuator; but how do we
+X add text? */
+X {"buf", T_STRING, offsetof(Typeout, buf), READONLY},
+X {"delimstr", T_STRING, offsetof(Typeout, delimstr)},
+X {"start", T_INT, offsetof(Typeout, start)},
+X {"dot", T_INT, offsetof(Typeout, dot)},
+X {"mark", T_INT, offsetof(Typeout, mark)},
+X {"col", T_INT, offsetof(Typeout, col)},
+X {"lin", T_INT, offsetof(Typeout, lin)},
+X {"len", T_INT, offsetof(Typeout, len)},
+X {"size", T_INT, offsetof(Typeout, size)},
+X {NULL}
+X};
+X
+Xstruct memberlist mouse_spec[] = {
+X /* Actuators already have members x and y, so the Mouse's x and y
+X have different names */
+X {"mouse_x", T_FLOAT, offsetof(Mouse, x)},
+X {"mouse_y", T_FLOAT, offsetof(Mouse, y)},
+X {NULL}
+X};
+X
+X#define MULOFF(member) offsetof(Multislider, member)
+X
+Xstruct memberlist multislider_spec[] = {
+X {"mode", T_INT, MULOFF(mode)},
+X {"n", T_INT, MULOFF(n)},
+X {"finefactor", T_FLOAT, MULOFF(finefactor)},
+X {"wsave", T_COORD, MULOFF(wsave)},
+X {"sa", T_ACTUATOR, MULOFF(sa)},
+X {"bh", T_COORD, MULOFF(bh)},
+X {"clrx", T_COORD, MULOFF(clrx)},
+X {"clry", T_COORD, MULOFF(clry)},
+X {"clrw", T_COORD, MULOFF(clrw)},
+X {"clrh", T_COORD, MULOFF(clrh)},
+X /* XXX acttype? */
+X {NULL}
+X};
+X
+X/* XXX Still to do:
+X Frame
+X Icon
+X Cycle
+X Scroll
+X Menu
+X*/
+X
+X/* List of known actuator initializer functions */
+X
+Xstruct {
+X char *name;
+X void (*func)();
+X struct memberlist *spec;
+X} initializerlist[] = {
+X {"analog_bar", pnl_analog_bar},
+X {"analog_meter", pnl_analog_meter},
+X {"button", pnl_button},
+X {"cycle", pnl_cycle},
+X /* Doesn't exist: */
+X/* {"dhslider", pnl_dhslider, slider_spec}, */
+X {"dial", pnl_dial, dial_spec},
+X {"down_arrow_button", pnl_down_arrow_button},
+X {"down_double_arrow_button", pnl_down_double_arrow_button},
+X {"dvslider", pnl_dvslider, slider_spec},
+X {"filled_hslider", pnl_filled_hslider, slider_spec},
+X {"filled_slider", pnl_filled_slider, slider_spec},
+X {"filled_vslider", pnl_filled_vslider, slider_spec},
+X {"floating_puck", pnl_floating_puck, puck_spec},
+X {"frame", pnl_frame},
+X {"graphframe", pnl_graphframe},
+X {"hmultislider", pnl_hmultislider, multislider_spec},
+X {"hmultislider_bar", pnl_hmultislider_bar},
+X {"hmultislider_open_bar", pnl_hmultislider_open_bar},
+X {"hpalette", pnl_hpalette, palette_spec},
+X {"hslider", pnl_hslider, slider_spec},
+X {"icon", pnl_icon},
+X {"icon_menu", pnl_icon_menu},
+X {"label", pnl_label},
+X {"left_arrow_button", pnl_left_arrow_button},
+X {"left_double_arrow_button", pnl_left_double_arrow_button},
+X {"menu", pnl_menu},
+X {"menu_item", pnl_menu_item},
+X {"meter", pnl_meter},
+X {"mouse", pnl_mouse, mouse_spec},
+X {"multislider", pnl_multislider, multislider_spec},
+X {"multislider_bar", pnl_multislider_bar},
+X {"multislider_open_bar", pnl_multislider_open_bar},
+X {"palette", pnl_palette, palette_spec},
+X {"puck", pnl_puck, puck_spec},
+X {"radio_button", pnl_radio_button},
+X {"radio_check_button", pnl_radio_check_button},
+X {"right_arrow_button", pnl_right_arrow_button},
+X {"right_double_arrow_button", pnl_right_double_arrow_button},
+X {"rubber_puck", pnl_rubber_puck, puck_spec},
+X {"scale_chart", pnl_scale_chart, stripchart_spec},
+X {"scroll", pnl_scroll},
+X {"signal", pnl_signal},
+X {"slider", pnl_slider, slider_spec},
+X {"slideroid", pnl_slideroid, slideroid_spec},
+X {"strip_chart", pnl_strip_chart, stripchart_spec},
+X {"sub_menu", pnl_sub_menu},
+X {"toggle_button", pnl_toggle_button},
+X {"typein", pnl_typein, typein_spec},
+X {"typeout", pnl_typeout, typeout_spec},
+X {"up_arrow_button", pnl_up_arrow_button},
+X {"up_double_arrow_button", pnl_up_double_arrow_button},
+X {"viewframe", pnl_viewframe},
+X {"vmultislider", pnl_vmultislider, multislider_spec},
+X {"vmultislider_bar", pnl_vmultislider_bar},
+X {"vmultislider_open_bar", pnl_vmultislider_open_bar},
+X {"vpalette", pnl_vpalette, palette_spec},
+X {"vslider", pnl_vslider, slider_spec},
+X {"wide_button", pnl_wide_button},
+X {NULL, NULL} /* Sentinel */
+X};
+X
+X
+X/* Pseudo downfunc etc. */
+X
+Xstatic Actuator *down_pend, *active_pend, *up_pend;
+X
+Xstatic void
+Xdownfunc(a)
+X Actuator *a;
+X{
+X if (down_pend == NULL)
+X down_pend = a;
+X}
+X
+Xstatic void
+Xactivefunc(a)
+X Actuator *a;
+X{
+X if (active_pend == NULL)
+X active_pend = a;
+X}
+X
+Xstatic void
+Xupfunc(a)
+X Actuator *a;
+X{
+X if (up_pend == NULL)
+X up_pend = a;
+X}
+X
+X
+X/* Lay-out for the user data */
+X
+Xstruct userdata {
+X object *dict; /* Dictionary object for additional attributes */
+X struct memberlist *spec; /* Actuator-specific members */
+X};
+X
+X
+X/* Create a new actuator; the actuator type is given as a string */
+X
+Xstatic Actuator *
+Xmakeactuator(name)
+X char *name;
+X{
+X Actuator *act;
+X void (*initializer)() = NULL;
+X int i;
+X struct userdata *u;
+X for (i = 0; initializerlist[i].name != NULL; i++) {
+X if (strcmp(initializerlist[i].name, name) == 0) {
+X initializer = initializerlist[i].func;
+X break;
+X }
+X }
+X if (initializerlist[i].name == NULL) {
+X err_badarg();
+X return NULL;
+X }
+X u = NEW(struct userdata, 1);
+X if (u == NULL) {
+X err_nomem();
+X return NULL;
+X }
+X u->dict = NULL;
+X u->spec = initializerlist[i].spec;
+X act = pnl_mkact(initializer);
+X act->u = (char *)u;
+X act->downfunc = downfunc;
+X act->activefunc = activefunc;
+X act->upfunc = upfunc;
+X return act;
+X}
+X
+X
+X/* Actuator objects methods */
+X
+Xstatic object *
+Xactuator_addact(self, args)
+X actuatorobject *self;
+X object *args;
+X{
+X Panel *p;
+X if (!is_panelobject(args)) {
+X err_badarg();
+X return NULL;
+X }
+X p = ((panelobject *)args) -> ob_panel;
+X pnl_addact(self->ob_actuator, p);
+X INCREF(None);
+X return None;
+X}
+X
+Xstatic object *
+Xactuator_addsubact(self, args)
+X actuatorobject *self;
+X object *args;
+X{
+X Actuator *a;
+X if (!is_actuatorobject(args)) {
+X err_badarg();
+X return NULL;
+X }
+X a = ((actuatorobject *)args) -> ob_actuator;
+X pnl_addsubact(self->ob_actuator, a);
+X INCREF(None);
+X return None;
+X}
+X
+Xstatic object *
+Xactuator_delact(self, args)
+X actuatorobject *self;
+X object *args;
+X{
+X Panel *p;
+X if (!getnoarg(args))
+X return NULL;
+X pnl_delact(self->ob_actuator);
+X INCREF(None);
+X return None;
+X}
+X
+Xstatic object *
+Xactuator_fixact(self, args)
+X actuatorobject *self;
+X object *args;
+X{
+X Panel *p;
+X if (!getnoarg(args))
+X return NULL;
+X pnl_fixact(self->ob_actuator);
+X INCREF(None);
+X return None;
+X}
+X
+Xstatic object *
+Xactuator_tprint(self, args)
+X actuatorobject *self;
+X object *args;
+X{
+X object *str;
+X if (self->ob_actuator->type != PNL_TYPEOUT) {
+X err_setstr(TypeError, "tprint for non-typeout panel");
+X return NULL;
+X }
+X if (!getstrarg(args, &str))
+X return NULL;
+X tprint(self->ob_actuator, getstringvalue(str));
+X /* XXX Can't turn tprint's errors into exceptions, sorry */
+X INCREF(None);
+X return None;
+X}
+X
+Xstatic struct methodlist actuator_methods[] = {
+X {"addact", actuator_addact},
+X {"addsubact", actuator_addsubact},
+X {"delact", actuator_delact},
+X {"fixact", actuator_fixact},
+X {"tprint", actuator_tprint},
+X {NULL, NULL} /* sentinel */
+X};
+X
+Xstatic object *
+Xnewactuatorobject(act)
+X Actuator *act;
+X{
+X actuatorobject *a;
+X if (act == NULL) {
+X INCREF(None);
+X return None;
+X }
+X a = NEWOBJ(actuatorobject, &Actuatortype);
+X if (a == NULL)
+X return NULL;
+X a->ob_actuator = act;
+X return (object *)a;
+X}
+X
+Xstatic void
+Xactuator_dealloc(a)
+X actuatorobject *a;
+X{
+X /* Do NOT delete the actuator; most actuator objects are created
+X to hold a temporary reference to an actuator, like one gotten
+X from pnl_dopanel(). */
+X
+X DEL(a);
+X}
+X
+X
+X/* Table of actuator members */
+X
+X#define ACTOFF(member) offsetof(Actuator, member)
+X
+Xstruct memberlist act_memberlist[] = {
+X {"id", T_SHORT, ACTOFF(id), READONLY},
+X
+X /* T_PANEL is not defined */
+X /*
+X {"p", T_PANEL, ACTOFF(p), READONLY},
+X */
+X
+X {"pa", T_ACTUATOR, ACTOFF(pa), READONLY},
+X {"ca", T_ACTUATOR, ACTOFF(ca), READONLY},
+X {"al", T_ACTUATOR, ACTOFF(al), READONLY},
+X {"na", T_INT, ACTOFF(na), READONLY},
+X {"type", T_INT, ACTOFF(type), READONLY},
+X {"active", T_BOOL, ACTOFF(active)},
+X
+X {"x", T_COORD, ACTOFF(x)},
+X {"y", T_COORD, ACTOFF(y)},
+X {"w", T_COORD, ACTOFF(w)},
+X {"h", T_COORD, ACTOFF(h)},
+X
+X {"lx", T_COORD, ACTOFF(lx)},
+X {"ly", T_COORD, ACTOFF(ly)},
+X {"lw", T_COORD, ACTOFF(lw)},
+X {"lh", T_COORD, ACTOFF(lh)},
+X {"ld", T_COORD, ACTOFF(ld)},
+X
+X {"val", T_FLOAT, ACTOFF(val)},
+X {"extval", T_FLOAT, ACTOFF(extval)},
+X {"initval", T_FLOAT, ACTOFF(initval)},
+X {"maxval", T_FLOAT, ACTOFF(maxval)},
+X {"minval", T_FLOAT, ACTOFF(minval)},
+X {"scalefactor", T_FLOAT, ACTOFF(scalefactor)},
+X
+X {"label", T_STRING, ACTOFF(label)},
+X {"key", T_DEVICE, ACTOFF(key)},
+X {"labeltype", T_INT, ACTOFF(labeltype)},
+X
+X /* Internal callbacks are not supported;
+X user callbacks are treated special! */
+X
+X {"dirtycnt", T_INT, ACTOFF(dirtycnt)},
+X
+X /* members u and data are accessed differently */
+X
+X {"automatic", T_BOOL, ACTOFF(automatic)},
+X {"selectable", T_BOOL, ACTOFF(selectable)},
+X {"visible", T_BOOL, ACTOFF(visible)},
+X {"beveled", T_BOOL, ACTOFF(beveled)},
+X
+X {"group", T_ACTUATOR, ACTOFF(group), READONLY},
+X {"next", T_ACTUATOR, ACTOFF(next), READONLY},
+X
+X {NULL, 0, 0} /* Sentinel */
+X};
+X
+X
+X/* Potential name conflicts between attributes are solved as follows.
+X - Actuator-specific attributes always override generic attributes.
+X - When reading, the dictionary has overrides everything else;
+X when writing, everything else overrides the dictionary.
+X - When reading, methods are tried last.
+X*/
+X
+Xstatic object *
+Xactuator_getattr(a, name)
+X actuatorobject *a;
+X char *name;
+X{
+X Actuator *act = a->ob_actuator;
+X struct userdata *u = (struct userdata *) act->u;
+X object *v;
+X
+X if (u != NULL) {
+X /* 1. Try the dictionary */
+X if (u->dict != NULL) {
+X v = dictlookup(u->dict, name);
+X if (v != NULL) {
+X INCREF(v);
+X return v;
+X }
+X }
+X
+X /* 2. Try actuator-specific attributes */
+X if (u->spec != NULL) {
+X v = panel_getmember(act->data, u->spec, name);
+X if (v != NULL)
+X return v;
+X err_clear();
+X }
+X }
+X
+X /* 3. Try generic actuator attributes */
+X v = panel_getmember((char *)act, act_memberlist, name);
+X if (v != NULL)
+X return v;
+X
+X /* 4. Try methods */
+X err_clear();
+X return findmethod(actuator_methods, (object *)a, name);
+X}
+X
+Xstatic int
+Xactuator_setattr(a, name, v)
+X actuatorobject *a;
+X char *name;
+X object *v;
+X{
+X Actuator *act = a->ob_actuator;
+X struct userdata *u = (struct userdata *) act->u;
+X int err;
+X
+X /* 0. We don't allow deletion of attributes */
+X if (v == NULL) {
+X err_setstr(TypeError, "read-only actuator attribute");
+X return -1;
+X }
+X
+X /* 1. Try actuator-specific attributes */
+X if (u != NULL && u->spec != NULL) {
+X err = panel_setmember(act->data, u->spec, name, v);
+X if (err != 1)
+X return err;
+X }
+X
+X /* 2. Try generic actuator attributes */
+X err = panel_setmember((char *)act, act_memberlist, name, v);
+X if (err != 1)
+X return err;
+X
+X /* 3. Try the dictionary */
+X if (u != NULL) {
+X if (u->dict == NULL && (u->dict = newdictobject()) == NULL)
+X return NULL;
+X return dictinsert(u->dict, name, v);
+X }
+X
+X err_setstr(NameError, name);
+X return -1;
+X}
+X
+Xstatic int
+Xactuator_compare(v, w)
+X actuatorobject *v, *w;
+X{
+X long i = (long)v->ob_actuator;
+X long j = (long)w->ob_actuator;
+X return (i < j) ? -1 : (i > j) ? 1 : 0;
+X}
+X
+Xstatic typeobject Actuatortype = {
+X OB_HEAD_INIT(&Typetype)
+X 0, /*ob_size*/
+X "actuator", /*tp_name*/
+X sizeof(actuatorobject), /*tp_size*/
+X 0, /*tp_itemsize*/
+X /* methods */
+X actuator_dealloc, /*tp_dealloc*/
+X 0, /*tp_print*/
+X actuator_getattr, /*tp_getattr*/
+X actuator_setattr, /*tp_setattr*/
+X actuator_compare, /*tp_compare*/
+X 0, /*tp_repr*/
+X};
+X
+X
+X/* The panel module itself */
+X
+Xstatic object *
+Xmodule_mkpanel(self, args)
+X object *self;
+X object *args;
+X{
+X if (!getnoarg(args))
+X return NULL;
+X return newpanelobject();
+X}
+X
+Xstatic object *
+Xmodule_mkact(self, args)
+X object *self;
+X object *args;
+X{
+X object *v;
+X Actuator *a;
+X if (!getstrarg(args, &v))
+X return NULL;
+X a = makeactuator(getstringvalue(v));
+X if (a == NULL)
+X return NULL;
+X return newactuatorobject(a);
+X}
+X
+Xstatic object *
+Xmodule_dopanel(self, args)
+X object *self;
+X object *args;
+X{
+X Actuator *a;
+X object *v, *w;
+X if (!getnoarg(args))
+X return NULL;
+X a = pnl_dopanel();
+X v = newtupleobject(4);
+X if (v == NULL)
+X return NULL;
+X settupleitem(v, 0, newactuatorobject(a));
+X settupleitem(v, 1, newactuatorobject(down_pend));
+X settupleitem(v, 2, newactuatorobject(active_pend));
+X settupleitem(v, 3, newactuatorobject(up_pend));
+X down_pend = active_pend = up_pend = NULL;
+X return v;
+X}
+X
+Xstatic object *
+Xmodule_drawpanel(self, args)
+X object *self;
+X object *args;
+X{
+X if (!getnoarg(args))
+X return NULL;
+X pnl_drawpanel();
+X INCREF(None);
+X return None;
+X}
+X
+Xstatic object *
+Xmodule_needredraw(self, args)
+X object *self;
+X object *args;
+X{
+X if (!getnoarg(args))
+X return NULL;
+X pnl_needredraw();
+X INCREF(None);
+X return None;
+X}
+X
+Xstatic object *
+Xmodule_userredraw(self, args)
+X object *self;
+X object *args;
+X{
+X short wid;
+X if (!getnoarg(args))
+X return NULL;
+X wid = pnl_userredraw();
+X return newintobject((long)wid);
+X}
+X
+Xstatic object *
+Xmodule_block(self, args)
+X object *self;
+X object *args;
+X{
+X int flag;
+X if (!getintarg(args, &flag))
+X return NULL;
+X pnl_block = flag;
+X INCREF(None);
+X return None;
+X}
+X
+Xstatic struct methodlist module_methods[] = {
+X {"block", module_block},
+X {"dopanel", module_dopanel},
+X {"drawpanel", module_drawpanel},
+X {"mkpanel", module_mkpanel},
+X {"mkact", module_mkact},
+X {"needredraw", module_needredraw},
+X {"userredraw", module_userredraw},
+X {NULL, NULL} /* sentinel */
+X};
+X
+Xvoid
+Xinitpanel()
+X{
+X /* Setting pnl_block to 1 would greatly reduce the CPU usage
+X of an idle application. Unfortunately it also breaks our
+X little hacks to get callback functions in Python called.
+X So we clear pnl_block here. You can set/clear pnl_block
+X from Python using pnl.block(flag). It works if you have
+X no upfuncs. */
+X pnl_block = 0;
+X initmodule("pnl", module_methods);
+X}
+EOF
+fi
+if test -s 'src/regexp.c'
+then echo '*** I will not over-write existing file src/regexp.c'
+else
+echo 'x - src/regexp.c'
+sed 's/^X//' > 'src/regexp.c' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/*
+X * regcomp and regexec -- regsub and regerror are elsewhere
+X *
+X * Copyright (c) 1986 by University of Toronto.
+X * Written by Henry Spencer. Not derived from licensed software.
+X#ifdef MULTILINE
+X * Changed by Guido van Rossum, CWI, Amsterdam
+X * for multi-line support.
+X#endif
+X *
+X * Permission is granted to anyone to use this software for any
+X * purpose on any computer system, and to redistribute it freely,
+X * subject to the following restrictions:
+X *
+X * 1. The author is not responsible for the consequences of use of
+X * this software, no matter how awful, even if they arise
+X * from defects in it.
+X *
+X * 2. The origin of this software must not be misrepresented, either
+X * by explicit claim or by omission.
+X *
+X * 3. Altered versions must be plainly marked as such, and must not
+X * be misrepresented as being the original software.
+X *
+X * Beware that some of this code is subtly aware of the way operator
+X * precedence is structured in regular expressions. Serious changes in
+X * regular-expression syntax might require a total rethink.
+X */
+X#include <stdio.h>
+X#include "PROTO.h"
+X#include "malloc.h"
+X#undef ANY /* Conflicting identifier defined in malloc.h */
+X#include <string.h> /* XXX Remove if not found */
+X#include "regexp.h"
+X#include "regmagic.h"
+X
+X#ifdef MULTILINE
+X/*
+X * Defining MULTILINE turns on the following changes in the semantics:
+X * 1. The '.' operator matches all characters except a newline.
+X * 2. The '^' operator matches at the beginning of the string or after
+X * a newline. (Anchored matches are retried after each newline.)
+X * 3. The '$' operator matches at the end of the string or before
+X * a newline.
+X * 4. A '\' followed by an 'n' matches a newline. (This is an
+X * unfortunate exception to the rule that '\' followed by a
+X * character matches that character...)
+X *
+X * Also, there is a new function reglexec(prog, string, offset)
+X * which searches for a match starting at 'string+offset';
+X * it differs from regexec(prog, string+offset) in assuming
+X * that the line begins at 'string'.
+X */
+X#endif
+X
+X/*
+X * The "internal use only" fields in regexp.h are present to pass info from
+X * compile to execute that permits the execute phase to run lots faster on
+X * simple cases. They are:
+X *
+X * regstart char that must begin a match; '\0' if none obvious
+X * reganch is the match anchored (at beginning-of-line only)?
+X * regmust string (pointer into program) that match must include, or NULL
+X * regmlen length of regmust string
+X *
+X * Regstart and reganch permit very fast decisions on suitable starting points
+X * for a match, cutting down the work a lot. Regmust permits fast rejection
+X * of lines that cannot possibly match. The regmust tests are costly enough
+X * that regcomp() supplies a regmust only if the r.e. contains something
+X * potentially expensive (at present, the only such thing detected is * or +
+X * at the start of the r.e., which can involve a lot of backup). Regmlen is
+X * supplied because the test in regexec() needs it and regcomp() is computing
+X * it anyway.
+X */
+X
+X/*
+X * Structure for regexp "program". This is essentially a linear encoding
+X * of a nondeterministic finite-state machine (aka syntax charts or
+X * "railroad normal form" in parsing technology). Each node is an opcode
+X * plus a "next" pointer, possibly plus an operand. "Next" pointers of
+X * all nodes except BRANCH implement concatenation; a "next" pointer with
+X * a BRANCH on both ends of it is connecting two alternatives. (Here we
+X * have one of the subtle syntax dependencies: an individual BRANCH (as
+X * opposed to a collection of them) is never concatenated with anything
+X * because of operator precedence.) The operand of some types of node is
+X * a literal string; for others, it is a node leading into a sub-FSM. In
+X * particular, the operand of a BRANCH node is the first node of the branch.
+X * (NB this is *not* a tree structure: the tail of the branch connects
+X * to the thing following the set of BRANCHes.) The opcodes are:
+X */
+X
+X/* definition number opnd? meaning */
+X#define END 0 /* no End of program. */
+X#define BOL 1 /* no Match "" at beginning of line. */
+X#define EOL 2 /* no Match "" at end of line. */
+X#define ANY 3 /* no Match any one character. */
+X#define ANYOF 4 /* str Match any character in this string. */
+X#define ANYBUT 5 /* str Match any character not in this string. */
+X#define BRANCH 6 /* node Match this alternative, or the next... */
+X#define BACK 7 /* no Match "", "next" ptr points backward. */
+X#define EXACTLY 8 /* str Match this string. */
+X#define NOTHING 9 /* no Match empty string. */
+X#define STAR 10 /* node Match this (simple) thing 0 or more times. */
+X#define PLUS 11 /* node Match this (simple) thing 1 or more times. */
+X#define OPEN 20 /* no Mark this point in input as start of #n. */
+X /* OPEN+1 is number 1, etc. */
+X#define CLOSE 30 /* no Analogous to OPEN. */
+X
+X/*
+X * Opcode notes:
+X *
+X * BRANCH The set of branches constituting a single choice are hooked
+X * together with their "next" pointers, since precedence prevents
+X * anything being concatenated to any individual branch. The
+X * "next" pointer of the last BRANCH in a choice points to the
+X * thing following the whole choice. This is also where the
+X * final "next" pointer of each individual branch points; each
+X * branch starts with the operand node of a BRANCH node.
+X *
+X * BACK Normal "next" pointers all implicitly point forward; BACK
+X * exists to make loop structures possible.
+X *
+X * STAR,PLUS '?', and complex '*' and '+', are implemented as circular
+X * BRANCH structures using BACK. Simple cases (one character
+X * per match) are implemented with STAR and PLUS for speed
+X * and to minimize recursive plunges.
+X *
+X * OPEN,CLOSE ...are numbered at compile time.
+X */
+X
+X/*
+X * A node is one char of opcode followed by two chars of "next" pointer.
+X * "Next" pointers are stored as two 8-bit pieces, high order first. The
+X * value is a positive offset from the opcode of the node containing it.
+X * An operand, if any, simply follows the node. (Note that much of the
+X * code generation knows about this implicit relationship.)
+X *
+X * Using two bytes for the "next" pointer is vast overkill for most things,
+X * but allows patterns to get big without disasters.
+X */
+X#define OP(p) (*(p))
+X#define NEXT(p) (((*((p)+1)&0377)<<8) + (*((p)+2)&0377))
+X#define OPERAND(p) ((p) + 3)
+X
+X/*
+X * See regmagic.h for one further detail of program structure.
+X */
+X
+X
+X/*
+X * Utility definitions.
+X */
+X#ifndef CHARBITS
+X#define UCHARAT(p) ((int)*(unsigned char *)(p))
+X#else
+X#define UCHARAT(p) ((int)*(p)&CHARBITS)
+X#endif
+X
+X#define FAIL(m) { regerror(m); return(NULL); }
+X#define ISMULT(c) ((c) == '*' || (c) == '+' || (c) == '?')
+X#define META "^$.[()|?+*\\"
+X
+X/*
+X * Flags to be passed up and down.
+X */
+X#define HASWIDTH 01 /* Known never to match null string. */
+X#define SIMPLE 02 /* Simple enough to be STAR/PLUS operand. */
+X#define SPSTART 04 /* Starts with * or +. */
+X#define WORST 0 /* Worst case. */
+X
+X/*
+X * Global work variables for regcomp().
+X */
+Xstatic char *regparse; /* Input-scan pointer. */
+Xstatic int regnpar; /* () count. */
+Xstatic char regdummy;
+Xstatic char *regcode; /* Code-emit pointer; &regdummy = don't. */
+Xstatic long regsize; /* Code size. */
+X#ifdef MULTILINE
+Xstatic int regnl; /* '\n' detected. */
+X#endif
+X
+X/*
+X * Forward declarations for regcomp()'s friends.
+X */
+X#ifndef STATIC
+X#define STATIC static
+X#endif
+XSTATIC char *reg();
+XSTATIC char *regbranch();
+XSTATIC char *regpiece();
+XSTATIC char *regatom();
+XSTATIC char *regnode();
+XSTATIC char *regnext();
+XSTATIC void regc();
+XSTATIC void reginsert();
+XSTATIC void regtail();
+XSTATIC void regoptail();
+X#ifdef STRCSPN
+XSTATIC int strcspn();
+X#endif
+X
+X/*
+X - regcomp - compile a regular expression into internal code
+X *
+X * We can't allocate space until we know how big the compiled form will be,
+X * but we can't compile it (and thus know how big it is) until we've got a
+X * place to put the code. So we cheat: we compile it twice, once with code
+X * generation turned off and size counting turned on, and once "for real".
+X * This also means that we don't allocate space until we are sure that the
+X * thing really will compile successfully, and we never have to move the
+X * code and thus invalidate pointers into it. (Note that it has to be in
+X * one piece because free() must be able to free it all.)
+X *
+X * Beware that the optimization-preparation code in here knows about some
+X * of the structure of the compiled regexp.
+X */
+Xregexp *
+Xregcomp(exp)
+Xchar *exp;
+X{
+X register regexp *r;
+X register char *scan;
+X register char *longest;
+X register int len;
+X int flags;
+X
+X if (exp == NULL)
+X FAIL("NULL argument");
+X
+X /* First pass: determine size, legality. */
+X regparse = exp;
+X regnpar = 1;
+X regsize = 0L;
+X regcode = &regdummy;
+X#ifdef MULTILINE
+X regnl = 0;
+X#endif
+X regc(MAGIC);
+X if (reg(0, &flags) == NULL)
+X return(NULL);
+X
+X /* Small enough for pointer-storage convention? */
+X if (regsize >= 32767L) /* Probably could be 65535L. */
+X FAIL("regexp too big");
+X
+X /* Allocate space. */
+X r = (regexp *)malloc(sizeof(regexp) + (unsigned)regsize);
+X if (r == NULL)
+X FAIL("out of space");
+X
+X /* Second pass: emit code. */
+X regparse = exp;
+X regnpar = 1;
+X regcode = r->program;
+X regc(MAGIC);
+X if (reg(0, &flags) == NULL)
+X return(NULL);
+X
+X /* Dig out information for optimizations. */
+X r->regstart = '\0'; /* Worst-case defaults. */
+X r->reganch = 0;
+X r->regmust = NULL;
+X r->regmlen = 0;
+X scan = r->program+1; /* First BRANCH. */
+X if (OP(regnext(scan)) == END) { /* Only one top-level choice. */
+X scan = OPERAND(scan);
+X
+X /* Starting-point info. */
+X if (OP(scan) == EXACTLY)
+X r->regstart = *OPERAND(scan);
+X else if (OP(scan) == BOL)
+X r->reganch++;
+X
+X /*
+X * If there's something expensive in the r.e., find the
+X * longest literal string that must appear and make it the
+X * regmust. Resolve ties in favor of later strings, since
+X * the regstart check works with the beginning of the r.e.
+X * and avoiding duplication strengthens checking. Not a
+X * strong reason, but sufficient in the absence of others.
+X */
+X#ifdef MULTILINE
+X if ((flags&SPSTART) && !regnl) {
+X#else
+X if (flags&SPSTART) {
+X#endif
+X longest = NULL;
+X len = 0;
+X for (; scan != NULL; scan = regnext(scan))
+X if (OP(scan) == EXACTLY && strlen(OPERAND(scan)) >= len) {
+X longest = OPERAND(scan);
+X len = strlen(OPERAND(scan));
+X }
+X r->regmust = longest;
+X r->regmlen = len;
+X }
+X }
+X
+X return(r);
+X}
+X
+X/*
+X - reg - regular expression, i.e. main body or parenthesized thing
+X *
+X * Caller must absorb opening parenthesis.
+X *
+X * Combining parenthesis handling with the base level of regular expression
+X * is a trifle forced, but the need to tie the tails of the branches to what
+X * follows makes it hard to avoid.
+X */
+Xstatic char *
+Xreg(paren, flagp)
+Xint paren; /* Parenthesized? */
+Xint *flagp;
+X{
+X register char *ret;
+X register char *br;
+X register char *ender;
+X register int parno;
+X int flags;
+X
+X *flagp = HASWIDTH; /* Tentatively. */
+X
+X /* Make an OPEN node, if parenthesized. */
+X if (paren) {
+X if (regnpar >= NSUBEXP)
+X FAIL("too many ()");
+X parno = regnpar;
+X regnpar++;
+X ret = regnode(OPEN+parno);
+X } else
+X ret = NULL;
+X
+X /* Pick up the branches, linking them together. */
+X br = regbranch(&flags);
+X if (br == NULL)
+X return(NULL);
+X if (ret != NULL)
+X regtail(ret, br); /* OPEN -> first. */
+X else
+X ret = br;
+X if (!(flags&HASWIDTH))
+X *flagp &= ~HASWIDTH;
+X *flagp |= flags&SPSTART;
+X while (*regparse == '|') {
+X regparse++;
+X br = regbranch(&flags);
+X if (br == NULL)
+X return(NULL);
+X regtail(ret, br); /* BRANCH -> BRANCH. */
+X if (!(flags&HASWIDTH))
+X *flagp &= ~HASWIDTH;
+X *flagp |= flags&SPSTART;
+X }
+X
+X /* Make a closing node, and hook it on the end. */
+X ender = regnode((paren) ? CLOSE+parno : END);
+X regtail(ret, ender);
+X
+X /* Hook the tails of the branches to the closing node. */
+X for (br = ret; br != NULL; br = regnext(br))
+X regoptail(br, ender);
+X
+X /* Check for proper termination. */
+X if (paren && *regparse++ != ')') {
+X FAIL("unmatched ()");
+X } else if (!paren && *regparse != '\0') {
+X if (*regparse == ')') {
+X FAIL("unmatched ()");
+X } else
+X FAIL("junk on end"); /* "Can't happen". */
+X /* NOTREACHED */
+X }
+X
+X return(ret);
+X}
+X
+X/*
+X - regbranch - one alternative of an | operator
+X *
+X * Implements the concatenation operator.
+X */
+Xstatic char *
+Xregbranch(flagp)
+Xint *flagp;
+X{
+X register char *ret;
+X register char *chain;
+X register char *latest;
+X int flags;
+X
+X *flagp = WORST; /* Tentatively. */
+X
+X ret = regnode(BRANCH);
+X chain = NULL;
+X while (*regparse != '\0' && *regparse != '|' && *regparse != ')') {
+X latest = regpiece(&flags);
+X if (latest == NULL)
+X return(NULL);
+X *flagp |= flags&HASWIDTH;
+X if (chain == NULL) /* First piece. */
+X *flagp |= flags&SPSTART;
+X else
+X regtail(chain, latest);
+X chain = latest;
+X }
+X if (chain == NULL) /* Loop ran zero times. */
+X (void) regnode(NOTHING);
+X
+X return(ret);
+X}
+X
+X/*
+X - regpiece - something followed by possible [*+?]
+X *
+X * Note that the branching code sequences used for ? and the general cases
+X * of * and + are somewhat optimized: they use the same NOTHING node as
+X * both the endmarker for their branch list and the body of the last branch.
+X * It might seem that this node could be dispensed with entirely, but the
+X * endmarker role is not redundant.
+X */
+Xstatic char *
+Xregpiece(flagp)
+Xint *flagp;
+X{
+X register char *ret;
+X register char op;
+X register char *next;
+X int flags;
+X
+X ret = regatom(&flags);
+X if (ret == NULL)
+X return(NULL);
+X
+X op = *regparse;
+X if (!ISMULT(op)) {
+X *flagp = flags;
+X return(ret);
+X }
+X
+X if (!(flags&HASWIDTH) && op != '?')
+X FAIL("*+ operand could be empty");
+X *flagp = (op != '+') ? (WORST|SPSTART) : (WORST|HASWIDTH);
+X
+X if (op == '*' && (flags&SIMPLE))
+X reginsert(STAR, ret);
+X else if (op == '*') {
+X /* Emit x* as (x&|), where & means "self". */
+X reginsert(BRANCH, ret); /* Either x */
+X regoptail(ret, regnode(BACK)); /* and loop */
+X regoptail(ret, ret); /* back */
+X regtail(ret, regnode(BRANCH)); /* or */
+X regtail(ret, regnode(NOTHING)); /* null. */
+X } else if (op == '+' && (flags&SIMPLE))
+X reginsert(PLUS, ret);
+X else if (op == '+') {
+X /* Emit x+ as x(&|), where & means "self". */
+X next = regnode(BRANCH); /* Either */
+X regtail(ret, next);
+X regtail(regnode(BACK), ret); /* loop back */
+X regtail(next, regnode(BRANCH)); /* or */
+X regtail(ret, regnode(NOTHING)); /* null. */
+X } else if (op == '?') {
+X /* Emit x? as (x|) */
+X reginsert(BRANCH, ret); /* Either x */
+X regtail(ret, regnode(BRANCH)); /* or */
+X next = regnode(NOTHING); /* null. */
+X regtail(ret, next);
+X regoptail(ret, next);
+X }
+X regparse++;
+X if (ISMULT(*regparse))
+X FAIL("nested *?+");
+X
+X return(ret);
+X}
+X
+X/*
+X - regatom - the lowest level
+X *
+X * Optimization: gobbles an entire sequence of ordinary characters so that
+X * it can turn them into a single node, which is smaller to store and
+X * faster to run. Backslashed characters are exceptions, each becoming a
+X * separate node; the code is simpler that way and it's not worth fixing.
+X */
+Xstatic char *
+Xregatom(flagp)
+Xint *flagp;
+X{
+X register char *ret;
+X int flags;
+X
+X *flagp = WORST; /* Tentatively. */
+X
+X switch (*regparse++) {
+X case '^':
+X ret = regnode(BOL);
+X break;
+X case '$':
+X ret = regnode(EOL);
+X break;
+X case '.':
+X ret = regnode(ANY);
+X *flagp |= HASWIDTH|SIMPLE;
+X break;
+X case '[': {
+X register int class;
+X register int classend;
+X
+X if (*regparse == '^') { /* Complement of range. */
+X ret = regnode(ANYBUT);
+X regparse++;
+X } else
+X ret = regnode(ANYOF);
+X if (*regparse == ']' || *regparse == '-')
+X regc(*regparse++);
+X while (*regparse != '\0' && *regparse != ']') {
+X if (*regparse == '-') {
+X regparse++;
+X if (*regparse == ']' || *regparse == '\0')
+X regc('-');
+X else {
+X class = UCHARAT(regparse-2)+1;
+X classend = UCHARAT(regparse);
+X if (class > classend+1)
+X FAIL("invalid [] range");
+X for (; class <= classend; class++)
+X regc(class);
+X regparse++;
+X }
+X } else
+X regc(*regparse++);
+X }
+X regc('\0');
+X if (*regparse != ']')
+X FAIL("unmatched []");
+X regparse++;
+X *flagp |= HASWIDTH|SIMPLE;
+X }
+X break;
+X case '(':
+X ret = reg(1, &flags);
+X if (ret == NULL)
+X return(NULL);
+X *flagp |= flags&(HASWIDTH|SPSTART);
+X break;
+X case '\0':
+X case '|':
+X case ')':
+X FAIL("internal urp"); /* Supposed to be caught earlier. */
+X break;
+X case '?':
+X case '+':
+X case '*':
+X FAIL("?+* follows nothing");
+X break;
+X case '\\':
+X if (*regparse == '\0')
+X FAIL("trailing \\");
+X ret = regnode(EXACTLY);
+X#ifdef MULTILINE
+X if (*regparse == 'n') {
+X regc('\n');
+X regparse++;
+X regnl++;
+X }
+X else
+X#endif
+X regc(*regparse++);
+X regc('\0');
+X *flagp |= HASWIDTH|SIMPLE;
+X break;
+X default: {
+X register int len;
+X register char ender;
+X
+X regparse--;
+X len = strcspn(regparse, META);
+X if (len <= 0)
+X FAIL("internal disaster");
+X ender = *(regparse+len);
+X if (len > 1 && ISMULT(ender))
+X len--; /* Back off clear of ?+* operand. */
+X *flagp |= HASWIDTH;
+X if (len == 1)
+X *flagp |= SIMPLE;
+X ret = regnode(EXACTLY);
+X while (len > 0) {
+X#ifdef MULTILINE
+X if (*regparse == '\n')
+X regnl++;
+X#endif
+X regc(*regparse++);
+X len--;
+X }
+X regc('\0');
+X }
+X break;
+X }
+X
+X return(ret);
+X}
+X
+X/*
+X - regnode - emit a node
+X */
+Xstatic char * /* Location. */
+Xregnode(op)
+Xchar op;
+X{
+X register char *ret;
+X register char *ptr;
+X
+X ret = regcode;
+X if (ret == &regdummy) {
+X regsize += 3;
+X return(ret);
+X }
+X
+X ptr = ret;
+X *ptr++ = op;
+X *ptr++ = '\0'; /* Null "next" pointer. */
+X *ptr++ = '\0';
+X regcode = ptr;
+X
+X return(ret);
+X}
+X
+X/*
+X - regc - emit (if appropriate) a byte of code
+X */
+Xstatic void
+Xregc(b)
+Xchar b;
+X{
+X if (regcode != &regdummy)
+X *regcode++ = b;
+X else
+X regsize++;
+X}
+X
+X/*
+X - reginsert - insert an operator in front of already-emitted operand
+X *
+X * Means relocating the operand.
+X */
+Xstatic void
+Xreginsert(op, opnd)
+Xchar op;
+Xchar *opnd;
+X{
+X register char *src;
+X register char *dst;
+X register char *place;
+X
+X if (regcode == &regdummy) {
+X regsize += 3;
+X return;
+X }
+X
+X src = regcode;
+X regcode += 3;
+X dst = regcode;
+X while (src > opnd)
+X *--dst = *--src;
+X
+X place = opnd; /* Op node, where operand used to be. */
+X *place++ = op;
+X *place++ = '\0';
+X *place++ = '\0';
+X}
+X
+X/*
+X - regtail - set the next-pointer at the end of a node chain
+X */
+Xstatic void
+Xregtail(p, val)
+Xchar *p;
+Xchar *val;
+X{
+X register char *scan;
+X register char *temp;
+X register int offset;
+X
+X if (p == &regdummy)
+X return;
+X
+X /* Find last node. */
+X scan = p;
+X for (;;) {
+X temp = regnext(scan);
+X if (temp == NULL)
+X break;
+X scan = temp;
+X }
+X
+X if (OP(scan) == BACK)
+X offset = scan - val;
+X else
+X offset = val - scan;
+X *(scan+1) = (offset>>8)&0377;
+X *(scan+2) = offset&0377;
+X}
+X
+X/*
+X - regoptail - regtail on operand of first argument; nop if operandless
+X */
+Xstatic void
+Xregoptail(p, val)
+Xchar *p;
+Xchar *val;
+X{
+X /* "Operandless" and "op != BRANCH" are synonymous in practice. */
+X if (p == NULL || p == &regdummy || OP(p) != BRANCH)
+X return;
+X regtail(OPERAND(p), val);
+X}
+X
+X/*
+X * regexec and friends
+X */
+X
+X/*
+X * Global work variables for regexec().
+X */
+Xstatic char *reginput; /* String-input pointer. */
+Xstatic char *regbol; /* Beginning of input, for ^ check. */
+Xstatic char **regstartp; /* Pointer to startp array. */
+Xstatic char **regendp; /* Ditto for endp. */
+X
+X/*
+X * Forwards.
+X */
+XSTATIC int regtry();
+XSTATIC int regmatch();
+XSTATIC int regrepeat();
+X
+X#ifdef DEBUG
+Xint regnarrate = 0;
+Xvoid regdump();
+XSTATIC char *regprop();
+X#endif
+X
+X/*
+X - regexec - match a regexp against a string
+X */
+Xint
+Xregexec(prog, string)
+Xregister regexp *prog;
+Xregister char *string;
+X{
+X register char *s;
+X extern char *strchr();
+X
+X /* Be paranoid... */
+X if (prog == NULL || string == NULL) {
+X regerror("NULL parameter");
+X return(0);
+X }
+X
+X#ifdef MULTILINE
+X /* Check for \n in string, and if so, call the more general routine. */
+X if (strchr(string, '\n') != NULL)
+X return reglexec(prog, string, 0);
+X#endif
+X
+X /* Check validity of program. */
+X if (UCHARAT(prog->program) != MAGIC) {
+X regerror("corrupted program");
+X return(0);
+X }
+X
+X /* If there is a "must appear" string, look for it. */
+X if (prog->regmust != NULL) {
+X s = string;
+X while ((s = strchr(s, prog->regmust[0])) != NULL) {
+X if (strncmp(s, prog->regmust, prog->regmlen) == 0)
+X break; /* Found it. */
+X s++;
+X }
+X if (s == NULL) /* Not present. */
+X return(0);
+X }
+X
+X /* Mark beginning of line for ^ . */
+X regbol = string;
+X
+X /* Simplest case: anchored match need be tried only once. */
+X if (prog->reganch)
+X return(regtry(prog, string));
+X
+X /* Messy cases: unanchored match. */
+X s = string;
+X if (prog->regstart != '\0')
+X /* We know what char it must start with. */
+X while ((s = strchr(s, prog->regstart)) != NULL) {
+X if (regtry(prog, s))
+X return(1);
+X s++;
+X }
+X else
+X /* We don't -- general case. */
+X do {
+X if (regtry(prog, s))
+X return(1);
+X } while (*s++ != '\0');
+X
+X /* Failure. */
+X return(0);
+X}
+X
+X#ifdef MULTILINE
+X/*
+X - reglexec - match a regexp against a long string buffer, starting at offset
+X */
+Xint
+Xreglexec(prog, string, offset)
+Xregister regexp *prog;
+Xregister char *string;
+X{
+X register char *s;
+X extern char *strchr();
+X
+X /* Be paranoid... */
+X if (prog == NULL || string == NULL) {
+X regerror("NULL parameter");
+X return(0);
+X }
+X
+X /* Check validity of program. */
+X if (UCHARAT(prog->program) != MAGIC) {
+X regerror("corrupted program");
+X return(0);
+X }
+X
+X /* (Don't look for "must appear" string -- string can be long.) */
+X
+X /* Mark beginning of line for ^ . */
+X regbol = string;
+X
+X /* Apply offset.
+X Assume 0 <= offset <= strlen(string), but don't check,
+X as string can be long. */
+X s= string + offset;
+X
+X /* Anchored match need be tried only at line starts. */
+X if (prog->reganch) {
+X while (!regtry(prog, s)) {
+X s = strchr(s, '\n');
+X if (s == NULL)
+X return(0);
+X s++;
+X }
+X return(1);
+X }
+X
+X /* Messy cases: unanchored match. */
+X if (prog->regstart != '\0')
+X /* We know what char it must start with. */
+X while ((s = strchr(s, prog->regstart)) != NULL) {
+X if (regtry(prog, s))
+X return(1);
+X s++;
+X }
+X else
+X /* We don't -- general case. */
+X do {
+X if (regtry(prog, s))
+X return(1);
+X } while (*s++ != '\0');
+X
+X /* Failure. */
+X return(0);
+X}
+X#endif
+X
+X/*
+X - regtry - try match at specific point
+X */
+Xstatic int /* 0 failure, 1 success */
+Xregtry(prog, string)
+Xregexp *prog;
+Xchar *string;
+X{
+X register int i;
+X register char **sp;
+X register char **ep;
+X
+X reginput = string;
+X regstartp = prog->startp;
+X regendp = prog->endp;
+X
+X sp = prog->startp;
+X ep = prog->endp;
+X for (i = NSUBEXP; i > 0; i--) {
+X *sp++ = NULL;
+X *ep++ = NULL;
+X }
+X if (regmatch(prog->program + 1)) {
+X prog->startp[0] = string;
+X prog->endp[0] = reginput;
+X return(1);
+X } else
+X return(0);
+X}
+X
+X/*
+X - regmatch - main matching routine
+X *
+X * Conceptually the strategy is simple: check to see whether the current
+X * node matches, call self recursively to see whether the rest matches,
+X * and then act accordingly. In practice we make some effort to avoid
+X * recursion, in particular by going through "ordinary" nodes (that don't
+X * need to know whether the rest of the match failed) by a loop instead of
+X * by recursion.
+X */
+Xstatic int /* 0 failure, 1 success */
+Xregmatch(prog)
+Xchar *prog;
+X{
+X register char *scan; /* Current node. */
+X char *next; /* Next node. */
+X extern char *strchr();
+X
+X scan = prog;
+X#ifdef DEBUG
+X if (scan != NULL && regnarrate)
+X fprintf(stderr, "%s(\n", regprop(scan));
+X#endif
+X while (scan != NULL) {
+X#ifdef DEBUG
+X if (regnarrate)
+X fprintf(stderr, "%s...\n", regprop(scan));
+X#endif
+X next = regnext(scan);
+X
+X switch (OP(scan)) {
+X case BOL:
+X#ifdef MULTILINE
+X if (!(reginput == regbol ||
+X reginput > regbol && *(reginput-1) == '\n'))
+X#else
+X if (reginput != regbol)
+X#endif
+X return(0);
+X break;
+X case EOL:
+X#ifdef MULTILINE
+X if (*reginput != '\0' && *reginput != '\n')
+X#else
+X if (*reginput != '\0')
+X#endif
+X return(0);
+X break;
+X case ANY:
+X#ifdef MULTILINE
+X if (*reginput == '\0' || *reginput == '\n')
+X#else
+X if (*reginput == '\0')
+X#endif
+X return(0);
+X reginput++;
+X break;
+X case EXACTLY: {
+X register int len;
+X register char *opnd;
+X
+X opnd = OPERAND(scan);
+X /* Inline the first character, for speed. */
+X if (*opnd != *reginput)
+X return(0);
+X len = strlen(opnd);
+X if (len > 1 && strncmp(opnd, reginput, len) != 0)
+X return(0);
+X reginput += len;
+X }
+X break;
+X case ANYOF:
+X if (*reginput == '\0' || strchr(OPERAND(scan), *reginput) == NULL)
+X return(0);
+X reginput++;
+X break;
+X case ANYBUT:
+X#ifdef MULTILINE
+X if (*reginput == '\0' || *reginput == '\n' ||
+X strchr(OPERAND(scan), *reginput) != NULL)
+X#else
+X if (*reginput == '\0' || strchr(OPERAND(scan), *reginput) != NULL)
+X#endif
+X return(0);
+X reginput++;
+X break;
+X case NOTHING:
+X break;
+X case BACK:
+X break;
+X case OPEN+1:
+X case OPEN+2:
+X case OPEN+3:
+X case OPEN+4:
+X case OPEN+5:
+X case OPEN+6:
+X case OPEN+7:
+X case OPEN+8:
+X case OPEN+9: {
+X register int no;
+X register char *save;
+X
+X no = OP(scan) - OPEN;
+X save = reginput;
+X
+X if (regmatch(next)) {
+X /*
+X * Don't set startp if some later
+X * invocation of the same parentheses
+X * already has.
+X */
+X if (regstartp[no] == NULL)
+X regstartp[no] = save;
+X return(1);
+X } else
+X return(0);
+X }
+X break;
+X case CLOSE+1:
+X case CLOSE+2:
+X case CLOSE+3:
+X case CLOSE+4:
+X case CLOSE+5:
+X case CLOSE+6:
+X case CLOSE+7:
+X case CLOSE+8:
+X case CLOSE+9: {
+X register int no;
+X register char *save;
+X
+X no = OP(scan) - CLOSE;
+X save = reginput;
+X
+X if (regmatch(next)) {
+X /*
+X * Don't set endp if some later
+X * invocation of the same parentheses
+X * already has.
+X */
+X if (regendp[no] == NULL)
+X regendp[no] = save;
+X return(1);
+X } else
+X return(0);
+X }
+X break;
+X case BRANCH: {
+X register char *save;
+X
+X if (OP(next) != BRANCH) /* No choice. */
+X next = OPERAND(scan); /* Avoid recursion. */
+X else {
+X do {
+X save = reginput;
+X if (regmatch(OPERAND(scan)))
+X return(1);
+X reginput = save;
+X scan = regnext(scan);
+X } while (scan != NULL && OP(scan) == BRANCH);
+X return(0);
+X /* NOTREACHED */
+X }
+X }
+X break;
+X case STAR:
+X case PLUS: {
+X register char nextch;
+X register int no;
+X register char *save;
+X register int min;
+X
+X /*
+X * Lookahead to avoid useless match attempts
+X * when we know what character comes next.
+X */
+X nextch = '\0';
+X if (OP(next) == EXACTLY)
+X nextch = *OPERAND(next);
+X min = (OP(scan) == STAR) ? 0 : 1;
+X save = reginput;
+X no = regrepeat(OPERAND(scan));
+X while (no >= min) {
+X /* If it could work, try it. */
+X if (nextch == '\0' || *reginput == nextch)
+X if (regmatch(next))
+X return(1);
+X /* Couldn't or didn't -- back up. */
+X no--;
+X reginput = save + no;
+X }
+X return(0);
+X }
+X break;
+X case END:
+X return(1); /* Success! */
+X break;
+X default:
+X regerror("memory corruption");
+X return(0);
+X break;
+X }
+X
+X scan = next;
+X }
+X
+X /*
+X * We get here only if there's trouble -- normally "case END" is
+X * the terminating point.
+X */
+X regerror("corrupted pointers");
+X return(0);
+X}
+X
+X/*
+X - regrepeat - repeatedly match something simple, report how many
+X */
+Xstatic int
+Xregrepeat(p)
+Xchar *p;
+X{
+X register int count = 0;
+X register char *scan;
+X register char *opnd;
+X#ifdef MULTILINE
+X register char *eol;
+X#endif
+X
+X scan = reginput;
+X opnd = OPERAND(p);
+X switch (OP(p)) {
+X case ANY:
+X#ifdef MULTILINE
+X if ((eol = strchr(scan, '\n')) != NULL) {
+X count += eol - scan;
+X scan = eol;
+X break;
+X }
+X#endif
+X count = strlen(scan);
+X scan += count;
+X break;
+X case EXACTLY:
+X while (*opnd == *scan) {
+X count++;
+X scan++;
+X }
+X break;
+X case ANYOF:
+X while (*scan != '\0' && strchr(opnd, *scan) != NULL) {
+X count++;
+X scan++;
+X }
+X break;
+X case ANYBUT:
+X#ifdef MULTILINE
+X while (*scan != '\0' && *scan != '\n' &&
+X strchr(opnd, *scan) == NULL) {
+X#else
+X while (*scan != '\0' && strchr(opnd, *scan) == NULL) {
+X#endif
+X count++;
+X scan++;
+X }
+X break;
+X default: /* Oh dear. Called inappropriately. */
+X regerror("internal foulup");
+X count = 0; /* Best compromise. */
+X break;
+X }
+X reginput = scan;
+X
+X return(count);
+X}
+X
+X/*
+X - regnext - dig the "next" pointer out of a node
+X */
+Xstatic char *
+Xregnext(p)
+Xregister char *p;
+X{
+X register int offset;
+X
+X if (p == &regdummy)
+X return(NULL);
+X
+X offset = NEXT(p);
+X if (offset == 0)
+X return(NULL);
+X
+X if (OP(p) == BACK)
+X return(p-offset);
+X else
+X return(p+offset);
+X}
+X
+X#ifdef DEBUG
+X
+XSTATIC char *regprop();
+X
+X/*
+X - regdump - dump a regexp onto stdout in vaguely comprehensible form
+X */
+Xvoid
+Xregdump(r)
+Xregexp *r;
+X{
+X register char *s;
+X register char op = EXACTLY; /* Arbitrary non-END op. */
+X register char *next;
+X extern char *strchr();
+X
+X
+X s = r->program + 1;
+X while (op != END) { /* While that wasn't END last time... */
+X op = OP(s);
+X printf("%2d%s", (int)(s-r->program), regprop(s)); /* Where, what. */
+X next = regnext(s);
+X if (next == NULL) /* Next ptr. */
+X printf("(0)");
+X else
+X printf("(%d)", (int)((s-r->program)+(next-s)));
+X s += 3;
+X if (op == ANYOF || op == ANYBUT || op == EXACTLY) {
+X /* Literal string, where present. */
+X while (*s != '\0') {
+X#ifdef MULTILINE
+X if (*s == '\n')
+X printf("\\n");
+X else
+X#endif
+X putchar(*s);
+X s++;
+X }
+X s++;
+X }
+X putchar('\n');
+X }
+X
+X /* Header fields of interest. */
+X if (r->regstart != '\0')
+X printf("start `%c' ", r->regstart);
+X if (r->reganch)
+X printf("anchored ");
+X if (r->regmust != NULL)
+X printf("must have \"%s\"", r->regmust);
+X printf("\n");
+X}
+X
+X/*
+X - regprop - printable representation of opcode
+X */
+Xstatic char *
+Xregprop(op)
+Xchar *op;
+X{
+X register char *p;
+X static char buf[50];
+X
+X (void) strcpy(buf, ":");
+X
+X switch (OP(op)) {
+X case BOL:
+X p = "BOL";
+X break;
+X case EOL:
+X p = "EOL";
+X break;
+X case ANY:
+X p = "ANY";
+X break;
+X case ANYOF:
+X p = "ANYOF";
+X break;
+X case ANYBUT:
+X p = "ANYBUT";
+X break;
+X case BRANCH:
+X p = "BRANCH";
+X break;
+X case EXACTLY:
+X p = "EXACTLY";
+X break;
+X case NOTHING:
+X p = "NOTHING";
+X break;
+X case BACK:
+X p = "BACK";
+X break;
+X case END:
+X p = "END";
+X break;
+X case OPEN+1:
+X case OPEN+2:
+X case OPEN+3:
+X case OPEN+4:
+X case OPEN+5:
+X case OPEN+6:
+X case OPEN+7:
+X case OPEN+8:
+X case OPEN+9:
+X sprintf(buf+strlen(buf), "OPEN%d", (int)(OP(op)-OPEN));
+X p = NULL;
+X break;
+X case CLOSE+1:
+X case CLOSE+2:
+X case CLOSE+3:
+X case CLOSE+4:
+X case CLOSE+5:
+X case CLOSE+6:
+X case CLOSE+7:
+X case CLOSE+8:
+X case CLOSE+9:
+X sprintf(buf+strlen(buf), "CLOSE%d", (int)(OP(op)-CLOSE));
+X p = NULL;
+X break;
+X case STAR:
+X p = "STAR";
+X break;
+X case PLUS:
+X p = "PLUS";
+X break;
+X default:
+X regerror("corrupted opcode");
+X break;
+X }
+X if (p != NULL)
+X (void) strcat(buf, p);
+X return(buf);
+X}
+X#endif
+X
+X/*
+X * The following is provided for those people who do not have strcspn() in
+X * their C libraries. They should get off their butts and do something
+X * about it; at least one public-domain implementation of those (highly
+X * useful) string routines has been published on Usenet.
+X */
+X#ifdef STRCSPN
+X/*
+X * strcspn - find length of initial segment of s1 consisting entirely
+X * of characters not from s2
+X */
+X
+Xstatic int
+Xstrcspn(s1, s2)
+Xchar *s1;
+Xchar *s2;
+X{
+X register char *scan1;
+X register char *scan2;
+X register int count;
+X
+X count = 0;
+X for (scan1 = s1; *scan1 != '\0'; scan1++) {
+X for (scan2 = s2; *scan2 != '\0';) /* ++ moved down. */
+X if (*scan1 == *scan2++)
+X return(count);
+X count++;
+X }
+X return(count);
+X}
+X#endif
+EOF
+fi
+echo 'Part 05 out of 21 of pack.out complete.'
+exit 0
diff --git a/shar/python-0.9.1-06-21.shar b/shar/python-0.9.1-06-21.shar
new file mode 100644
index 0000000..2d2194b
--- /dev/null
+++ b/shar/python-0.9.1-06-21.shar
@@ -0,0 +1,2510 @@
+: This is a shell archive.
+: Extract with 'sh this_file'.
+:
+: Extract part 01 first since it makes all directories
+echo 'Start of pack.out, part 06 out of 21:'
+if test -s 'doc/Makefile'
+then echo '*** I will not over-write existing file doc/Makefile'
+else
+echo 'x - doc/Makefile'
+sed 's/^X//' > 'doc/Makefile' << 'EOF'
+X# Makefile for Python documentation.
+X
+XLATEX= latex
+XDVIPS= dvips
+XTEXPREVIEW= xdvi
+X
+XPRINT= lpr
+X
+Xtut: tut.dvi
+X $(TEXPREVIEW) tut
+X
+Xtut.dvi tut.ps: tut.toc tut.tex myformat.sty
+X
+Xmod: mod.dvi
+X $(TEXPREVIEW) mod
+X
+Xmod.dvi mod.ps: mod.toc mod.tex mod1.tex mod2.tex mod3.tex myformat.sty
+X
+XALL= tut.ps mod.ps
+X
+Xall: $(ALL)
+X
+Xprint: $(ALL)
+X $(PRINT) $(ALL)
+X
+Xclean:
+X rm -f *.dvi *.aux *.toc *.log *.ps core [#@,]* *~
+X
+X.SUFFIXES: # Remove default suffixes
+X
+X.SUFFIXES: .tex .aux .toc .dvi .ps
+X
+X.tex.aux:
+X $(LATEX) $*
+X
+X.tex.toc:
+X $(LATEX) $*
+X
+X.tex.dvi:
+X $(LATEX) $*
+X
+X.dvi.ps:
+X $(DVIPS) $* >$*.ps
+X
+X.tex.ps:
+X $(LATEX) $*
+X $(DVIPS) $* >$*.ps
+EOF
+fi
+if test -s 'doc/mod2.tex'
+then echo '*** I will not over-write existing file doc/mod2.tex'
+else
+echo 'x - doc/mod2.tex'
+sed 's/^X//' > 'doc/mod2.tex' << 'EOF'
+X\section{Built-in Modules}
+X
+XThe modules described in this section are built into the interpreter.
+XThey must be imported using
+X{\tt import}.
+XSome modules are not always available; it is a configuration option to
+Xprovide them.
+XDetails are listed with the descriptions, but the best way to see if
+Xa module exists in a particular implementation is to attempt to import
+Xit.
+X
+X\subsection{Built-in Module {\tt sys}}
+X
+XThis module provides access to some variables used or maintained by the
+Xinterpreter and to functions that interact strongly with the interpreter.
+XIt is always available.
+X\begin{description}
+X\funcitem{argv}
+XThe list of command line arguments passed to a {\Python} script.
+X{\tt sys.argv[0]}
+Xis the script name.
+XIf no script name was passed to the {\Python} interpreter,
+X{\tt sys.argv}
+Xis empty.
+X\funcitem{exit}{n}
+XExits from {\Python} with numeric exit status
+X{\tt n}.
+XThis closes all open files and performs other cleanup-actions required by
+Xthe interpreter (but
+X{\em finally clauses}
+Xof
+X{\tt try}
+Xstatements are not executed!).
+X\funcitem{modules}
+XGives the list of modules that have already been loaded.
+XThis can be manipulated to force reloading of modules and other tricks.
+X\funcitem{path}
+XA list of strings that specifies the search path for modules.
+XInitialized from the environment variable {\tt PYTHONPATH}, or an
+Xinstallation-dependent default.
+X\funcitem{ps1,~ps2}
+XStrings specifying the primary and secondary prompt of the interpreter.
+XThese are only defined if the interpreter is in interactive mode.
+XTheir initial values in this case are
+X{\tt '>>> '}
+Xand
+X{\tt '... '}.
+X\funcitem{stdin, stdout, stderr}
+X%.br
+XFile objects corresponding to the interpreter's standard input, output
+Xand error streams.
+X{\tt sys.stdin}
+Xis used for all interpreter input except for scripts but including calls
+Xto
+X{\tt input()}
+Xand
+X{\tt raw\_input()}.
+X{\tt sys.stdout}
+Xis used for the output of
+X{\tt print} and expression statements
+Xand for the prompts of
+X{\tt input()}
+Xand
+X{\tt raw\_input()}.
+XThe interpreter's own prompts and its error messages are written to
+Xstderr.
+XAssigning to
+X{\tt sys.stderr}
+Xhas no effect on the interpreter; it can be used to write error messages
+Xto stderr using
+X{\tt print}.
+X\end{description}
+X
+X\subsection{Built-in Module {\tt math}}
+X
+XThis module is always available.
+XIt provides access to the mathematical functions defined by the C
+Xstandard.
+XThey are:
+X{\tt acos(x)},
+X{\tt asin(x)},
+X{\tt atan(x)},
+X{\tt atan2(x,y)},
+X{\tt ceil(x)},
+X{\tt cos(x)},
+X{\tt cosh(x)},
+X{\tt exp(x)},
+X{\tt fabs(x)},
+X{\tt floor(x)},
+X%{\tt fmod(...)} XXX not yet
+X%{\tt frexp(...)} XXX not yet
+X%{\tt ldexp(...)} XXX not yet
+X{\tt log(x)},
+X{\tt log10(x)},
+X%{\tt modf(...)} XXX not yet
+X{\tt pow(x,y)},
+X{\tt sin(x)},
+X{\tt sinh(x)},
+X{\tt sqrt(x)},
+X{\tt tan(x)},
+X{\tt tanh(x)}.
+X
+XIt also defines two mathematical constants:
+X{\tt pi}
+Xand
+X{\tt e}.
+X
+X\subsection{Built-in Module {\tt time}}
+X
+XThis module provides various time-related functions.
+XIt is always available.
+XFunctions are:
+X\begin{description}
+X\funcitem{sleep}{secs}
+XSuspends execution for the given number of seconds.
+X\funcitem{time}{}
+XReturns the time in seconds since the Epoch (Thursday January 1,
+X00:00:00, 1970 UCT on \UNIX\ machines).
+X\end{description}
+X
+X\noindent
+XIn some versions (Amoeba, Mac) the following functions also exist:
+X\begin{description}
+X\funcitem{millisleep}{msecs}
+XSuspends execution for the given number of milliseconds.
+X\funcitem{millitimer}{}
+XReturns the number of milliseconds of real time elapsed since some point
+Xin the past that is fixed per execution of the python interpreter (but
+Xmay change in each following run).
+X\end{description}
+X
+X\noindent
+XThe granularity of the milliseconds functions may be more than a
+Xmillisecond (100 msecs on Amoeba, 1/60 sec on the Mac).
+X
+X\subsection{Built-in Module {\tt regexp}}
+X
+XThis module provides a regular expression matching operation.
+XIt is always available.
+X
+XThe module defines a function and an exception:
+X
+X\begin{description}
+X
+X\funcitem{compile}{pattern}
+X
+XCompile a regular expression given as a string into a regular
+Xexpression object.
+XThe string must be an egrep-style regular expression;
+Xthis means that the characters
+X{\tt '(' ')' '*' '+' '?'\ '|' }\verb='^' '$'=
+Xare special.
+X(It is implemented using Henry Spencer's regular expression matching
+Xfunctions.)
+X
+Xexcitem{error}{regexp.error}
+X
+XException raised when a string passed to {\tt compile()} is not a
+Xvalid regular expression (e.g., unmatched parentheses) or when some other
+Xerror occurs during compilation or matching
+X(``no match found'' is not an error).
+X
+X\end{description}
+X
+XCompiled regular expression objects support a single method:
+X
+X\begin{description}
+X
+X\funcitem{exec}{str}
+X
+XFind the first occurrence of the compiled regular expression in the
+Xstring {\tt str}.
+XThe return value is a tuple of pairs specifying where a match was
+Xfound and where matches were found for subpatterns specified with
+X{\tt '('} and {\tt ')'} in the pattern.
+XIf no match is found, an empty tuple is returned; otherwise the first
+Xitem of the tuple is a pair of slice indices into the search string
+Xgiving the match found.
+XIf there were any subpatterns in the pattern, the returned tuple has an
+Xadditional item for each subpattern, giving the slice indices into the
+Xsearch string where that subpattern was found.
+X
+X\end{description}
+X
+XFor example:
+X\bcode\begin{verbatim}
+X>>> import regexp
+X>>> r = regexp.compile('--(.*)--')
+X>>> s = 'a--b--c'
+X>>> r.exec(s)
+X((1, 6), (3, 4))
+X>>> s[1:6] # The entire match
+X'--b--'
+X>>> s[3:4] # The subpattern
+X'b'
+X>>>
+X\end{verbatim}\ecode
+X
+X\subsection{Built-in Module {\tt posix}}
+X
+XThis module provides access to operating system functionality that is
+Xstandardized by the C Standard and the POSIX standard (a thinly diguised
+X{\UNIX} interface).
+XIt is available in all {\Python} versions except on the Macintosh.
+XErrors are reported exceptions.
+XIt defines the following items:
+X\begin{description}
+X\funcitem{chdir}{path}
+XChanges the current directory to
+X{\tt path}.
+X\funcitem{chmod}{path, mode}
+XChange the mode of
+X{\tt path}
+Xto the numeric
+X{\tt mode}.
+X\funcitem{environ}
+XA dictionary representing the string environment at the time
+Xthe interpreter was started.
+X(Modifying this dictionary does not affect the string environment of the
+Xinterpreter.)
+XFor example,
+X{\tt posix.environ['HOME']}
+Xis the pathname of your home directory, equivalent to
+X{\tt getenv("HOME")}
+Xin C.
+X\excitem{error}{posix.error}
+X%.br
+XThe exception raised when an POSIX function returns an error.
+XThe value accompanying this exception is a pair containing the numeric
+Xerror code from
+X{\tt errno}
+Xand the corresponding string, as would be printed by the C function
+X{\tt perror()}.
+X\funcitem{getcwd}{}
+XReturns a string representing the current working directory.
+X\funcitem{link}{src, dst}
+XCreates a hard link pointing to
+X{\tt src}
+Xnamed
+X{\tt dst}.
+X\funcitem{listdir}{path}
+XReturns a list containing the names of the entries in the
+Xdirectory.
+XThe list is in arbitrary order.
+XIt includes the special entries
+X{\tt '.'}
+Xand
+X{\tt '..'}
+Xif they are present in the directory.
+X\funcitem{mkdir}{path, mode}
+XCreates a directory named
+X{\tt path}
+Xwith numeric mode
+X{\tt mode}.
+X\funcitem{rename}{src, dst}
+XRenames the file or directory
+X{\tt src}
+Xto
+X{\tt dst}.
+X\funcitem{rmdir}{path}
+XRemoves the directory
+X{\tt path}.
+X\funcitem{stat}{path}
+XPerforms a
+X{\em stat}
+Xsystem call on the given path.
+XThe return value is a tuple of at least 10 integers giving the most
+Ximportant (and portable) members of the
+X{\em stat}
+Xstructure, in the order
+X{\tt st\_mode},
+X{\tt st\_ino},
+X{\tt st\_dev},
+X{\tt st\_nlink},
+X{\tt st\_uid},
+X{\tt st\_gid},
+X{\tt st\_size},
+X{\tt st\_atime},
+X{\tt st\_mtime},
+X{\tt st\_ctime}.
+XMore items may be added at the end by some implementations.
+X\funcitem{system}{command}
+XExecutes the command (a string) in a subshell.
+XThis is implemented by calling the Standard C function
+X{\tt system()},
+Xand has the same limitations.
+XChanges to
+X{\tt posix.environ},
+X{\tt sys.stdin}
+Xetc. are not reflected in the environment of the executed command.
+XThe return value is the exit status of the process as returned by
+XStandard C
+X{\tt system()}.
+X\funcitem{umask}{mask}
+XSets the current numeric umask and returns the previous umask.
+X\funcitem{unlink}{path}
+XUnlinks the file
+X{\tt path}.
+X\funcitem{utimes(path, }{atime, mtime)}
+X%.br
+XSets the access and modified time of the file to the given values.
+X(The second argument is a tuple of two items.)
+X\end{description}
+X
+XThe following functions are only available on systems that support
+Xsymbolic links:
+X\begin{description}
+X\funcitem{lstat}{path}
+XLike
+X{\tt stat()},
+Xbut does not follow symbolic links.
+X\funcitem{readlink}{path}
+XReturns a string representing the path to which the symbolic link
+Xpoints.
+X\funcitem{symlink}{src, dst}
+XCreates a symbolic link pointing to
+X{\tt src}
+Xnamed
+X{\tt dst}.
+X\end{description}
+X
+X\subsection{Built-in Module {\tt stdwin}}
+X
+XThis module defines several new object types and functions that
+Xprovide access to the functionality of the Standard Window System
+XInterface, STDWIN [CWI report CR-R8817].
+XIt is available on systems to which STDWIN has been ported (which is
+Xmost systems).
+XIt is only available if the {\tt DISPLAY} environment variable is set
+Xor an explicit `{\tt -display \it displayname}' argument is passed to
+Xthe interpreter.
+X
+XFunctions have names that usually resemble their C STDWIN counterparts
+Xwith the initial `w' dropped.
+XPoints are represented by pairs of integers; rectangles
+Xby pairs of points.
+XFor a complete description of STDWIN please refer to the documentation
+Xof STDWIN for C programmers (aforementioned CWI report).
+X\subsubsection{Functions Defined in Module {\tt stdwin}}
+X
+XThe following functions are defined in the {\tt stdwin} module:
+X\begin{description}
+X\funcitem{open}{title}
+X%.br
+XOpens a new window whose initial title is given by the string argument.
+XReturns a window object; window object methods are described below.%
+X\footnote{
+XThe {\Python} version of STDWIN does not support draw procedures; all
+Xdrawing requests are reported as draw events.
+X}
+X\funcitem{getevent}{}
+X%.br
+XWaits for and returns the next event.
+XAn event is returned as a triple: the first element is the event
+Xtype, a small integer; the second element is the window object to which
+Xthe event applies, or
+X{\tt None}
+Xif it applies to no window in particular;
+Xthe third element is type-dependent.
+XNames for event types and command codes are defined in the standard
+Xmodule
+X{\tt stdwinevent}.
+X\funcitem{setdefwinpos}{h, v}
+X%.br
+XSets the default window position.
+X\funcitem{setdefwinsize}{width, height}
+X%.br
+XSets the default window size.
+X\funcitem{menucreate}{title}
+X%.br
+XCreates a menu object referring to a global menu (a menu that appears in
+Xall windows).
+XMethods of menu objects are described below.
+X\funcitem{fleep}{}
+X%.br
+XCauses a beep or bell (or perhaps a `visual bell' or flash, hence the
+Xname).
+X\funcitem{message}{string}
+X%.br
+XDisplays a dialog box containing the string.
+XThe user must click OK before the function returns.
+X\funcitem{askync}{prompt, default}
+X%.br
+XDisplays a dialog that prompts the user to answer a question with yes or
+Xno.
+XThe function returns 0 for no, 1 for yes.
+XIf the user hits the Return key, the default (which must be 0 or 1) is
+Xreturned.
+XIf the user cancels the dialog, the
+X{\tt KeyboardInterrupt}
+Xexception is raised.
+X\funcitem{askstr}{prompt, default}
+X%.br
+XDisplays a dialog that prompts the user for a string.
+XIf the user hits the Return key, the default string is returned.
+XIf the user cancels the dialog, the
+X{\tt KeyboardInterrupt}
+Xexception is raised.
+X\funcitem{askfile}{prompt, default, new}
+X%.br
+XAsks the user to specify a filename.
+XIf
+X{\tt new}
+Xis zero it must be an existing file; otherwise, it must be a new file.
+XIf the user cancels the dialog, the
+X{\tt KeyboardInterrupt}
+Xexception is raised.
+X\funcitem{setcutbuffer}{i, string}
+X%.br
+XStores the string in the system's cut buffer number
+X{\tt i},
+Xwhere it can be found (for pasting) by other applications.
+XOn X11, there are 8 cut buffers (numbered 0..7).
+XCut buffer number 0 is the `clipboard' on the Macintosh.
+X\funcitem{getcutbuffer}{i}
+X%.br
+XReturns the contents of the system's cut buffer number
+X{\tt i}.
+X\funcitem{rotatebutbuffers}{n}
+X%.br
+XOn X11, this rotates the 8 cut buffers by
+X{\tt n}.
+XIgnored on the Macintosh.
+X\funcitem{getselection}{i}
+X%.br
+XReturns X11 selection number
+X{\tt i.}
+XSelections are not cut buffers.
+XSelection numbers are defined in module
+X{\tt stdwinevents}.
+XSelection {\tt WS\_PRIMARY} is the
+X{\em primary}
+Xselection (used by
+Xxterm,
+Xfor instance);
+Xselection {\tt WS\_SECONDARY} is the
+X{\em secondary}
+Xselection; selection {\tt WS\_CLIPBOARD} is the
+X{\em clipboard}
+Xselection (used by
+Xxclipboard).
+XOn the Macintosh, this always returns an empty string.
+X\funcitem{resetselection}{i}
+X%.br
+XResets selection number
+X{\tt i},
+Xif this process owns it.
+X(See window method
+X{\tt setselection()}).
+X\funcitem{baseline}{}
+X%.br
+XReturn the baseline of the current font (defined by STDWIN as the
+Xvertical distance between the baseline and the top of the
+Xcharacters).%
+X\footnote{
+XThere is no way yet to set the current font.
+XThis will change in a future version.
+X}
+X\funcitem{lineheight}{}
+X%.br
+XReturn the total line height of the current font.
+X\funcitem{textbreak}{str, width}
+X%.br
+XReturn the number of characters of the string that fit into a space of
+X{\tt width}
+Xbits wide when drawn in the curent font.
+X\funcitem{textwidth}{str}
+X%.br
+XReturn the width in bits of the string when drawn in the current font.
+X\end{description}
+X
+X\subsubsection{Window Object Methods}
+X
+XWindow objects are created by
+X{\tt stdwin.open()}.
+XThere is no explicit function to close a window; windows are closed when
+Xthey are garbage-collected.
+XWindow objects have the following methods:
+X\begin{description}
+X\funcitem{begindrawing}{}
+XReturns a drawing object, whose methods (described below) allow drawing
+Xin the window.
+X\funcitem{change}{rect}
+XInvalidates the given rectangle; this may cause a draw event.
+X\funcitem{gettitle}{}
+XReturns the window's title string.
+X\funcitem{getdocsize}{}
+X\begin{sloppypar}
+XReturns a pair of integers giving the size of the document as set by
+X{\tt setdocsize()}.
+X\end{sloppypar}
+X\funcitem{getorigin}{}
+XReturns a pair of integers giving the origin of the window with respect
+Xto the document.
+X\funcitem{getwinsize}{}
+XReturns a pair of integers giving the size of the window.
+X\funcitem{menucreate}{title}
+XCreates a menu object referring to a local menu (a menu that appears
+Xonly in this window).
+XMethods menu objects are described below.
+X\funcitem{scroll}{rect,~point}
+XScrolls the given rectangle by the vector given by the point.
+X\funcitem{setwincursor}{name}
+X\begin{sloppypar}
+XSets the window cursor to a cursor of the given name.
+XIt raises the
+X{\tt Runtime\-Error}
+Xexception if no cursor of the given name exists.
+XSuitable names are
+X{\tt 'ibeam'},
+X{\tt 'arrow'},
+X{\tt 'cross'},
+X{\tt 'watch'}
+Xand
+X{\tt 'plus'}.
+XOn X11, there are many more (see
+X{\tt <X11/cursorfont.h>}).
+X\end{sloppypar}
+X\funcitem{setdocsize}{point}
+XSets the size of the drawing document.
+X\funcitem{setorigin}{point}
+XMoves the origin of the window to the given point in the document.
+X\funcitem{setselection}{i, str}
+XAttempts to set X11 selection number
+X{\tt i}
+Xto the string
+X{\tt str}.
+X(See stdwin method
+X{\tt getselection()}
+Xfor the meaning of
+X{\tt i}.)
+XReturns true if it succeeds.
+XIf it succeeds, the window ``owns'' the selection until
+X(a) another applications takes ownership of the selection; or
+X(b) the window is deleted; or
+X(c) the application clears ownership by calling
+X{\tt stdwin.resetselection(i)}.
+XWhen another application takes ownership of the selection, a
+X{\tt WE\_LOST\_SEL}
+Xevent is received for no particular window and with the selection number
+Xas detail.
+XIgnored on the Macintosh.
+X\funcitem{settitle}{title}
+XSets the window's title string.
+X\funcitem{settimer}{dsecs}
+XSchedules a timer event for the window in
+X{\tt dsecs/10}
+Xseconds.
+X\funcitem{show}{rect}
+XTries to ensure that the given rectangle of the document is visible in
+Xthe window.
+X\funcitem{textcreate}{rect}
+XCreates a text-edit object in the document at the given rectangle.
+XMethods of text-edit objects are described below.
+X\end{description}
+X
+X\subsubsection{Drawing Object Methods}
+X
+XDrawing objects are created exclusively by the window method
+X{\tt begindrawing()}.
+XOnly one drawing object can exist at any given time; the drawing object
+Xmust be deleted to finish drawing.
+XNo drawing object may exist when
+X{\tt stdwin.getevent()}
+Xis called.
+XDrawing objects have the following methods:
+X\begin{description}
+X\funcitem{box}{rect}
+XDraws a box around a rectangle.
+X\funcitem{circle}{center, radius}
+X%.br
+XDraws a circle with given center point and radius.
+X\funcitem{elarc(center, (rh, rv), }{a1, a2)}
+X%.br
+XDraws an elliptical arc with given center point.
+X{\tt (rh, rv)}
+Xgives the half sizes of the horizontal and vertical radii.
+X{\tt (a1, a2)}
+Xgives the angles (in degrees) of the begin and end points.
+X0 degrees is at 3 o'clock, 90 degrees is at 12 o'clock.
+X\funcitem{erase}{rect}
+XErases a rectangle.
+X\funcitem{invert}{rect}
+XInverts a rectangle.
+X\funcitem{line}{p1, p2}
+XDraws a line from point
+X{\tt p1}
+Xto
+X{\tt p2}.
+X\funcitem{paint}{rect}
+XFills a rectangle.
+X\funcitem{text}{p, str}
+XDraws a string starting at point p (the point specifies the
+Xtop left coordinate of the string).
+X\funcitem{shade}{rect, percent}
+X%.br
+XFills a rectangle with a shading pattern that is about
+X{\tt percent}
+Xpercent filled.
+X\funcitem{xorline}{p1, p2}
+XDraws a line in XOR mode.
+X\funcitem{baseline(), lineheight(), textbreak(), textwidth}{}
+X%.br
+XThese functions are similar to the corresponding functions described
+Xabove for the
+X{\tt stdwin}
+Xmodule, but use the current font of the window instead of the (global)
+Xdefault font.
+X\end{description}
+X
+X\subsubsection{Menu Object Methods}
+X
+XA menu object represents a menu.
+XThe menu is destroyed when the menu object is deleted.
+XThe following methods are defined:
+X\begin{description}
+X\funcitem{additem}{text, shortcut}
+X%.br
+XAdds a menu item with given text.
+XThe shortcut must be a string of length 1, or omitted (to specify no
+Xshortcut).
+X\funcitem{setitem}{i, text}
+XSets the text of item number
+X{\tt i}.
+X\funcitem{enable}{i, flag}
+XEnables or disables item
+X{\tt i}.
+X\funcitem{check}{i, flag}
+XSets or clears the
+X{\em check mark}
+Xfor item
+X{\tt i}.
+X\end{description}
+X
+X\subsubsection{Text-edit Object Methods}
+X
+XA text-edit object represents a text-edit block.
+XFor semantics, see the STDWIN documentation for C programmers.
+XThe following methods exist:
+X\begin{description}
+X\funcitem{arrow}{code}
+XPasses an arrow event to the text-edit block.
+XThe
+X{\tt code}
+Xmust be one of
+X{\tt WC\_LEFT},
+X{\tt WC\_RIGHT},
+X{\tt WC\_UP}
+Xor
+X{\tt WC\_DOWN}
+X(see module
+X{\tt stdwinevents}).
+X\funcitem{draw}{rect}
+XPasses a draw event to the text-edit block.
+XThe rectangle specifies the redraw area.
+X\funcitem{event}{type, window, detail}
+X%.br
+XPasses an event gotten from
+X{\tt stdwin.getevent()}
+Xto the text-edit block.
+XReturns true if the event was handled.
+X\funcitem{getfocus}{}
+XReturns 2 integers representing the start and end positions of the
+Xfocus, usable as slice indices on the string returned by
+X{\tt getfocustext()}.
+X\funcitem{getfocustext}{}
+XReturns the text in the focus.
+X\funcitem{getrect}{}
+XReturns a rectangle giving the actual position of the text-edit block.
+X(The bottom coordinate may differ from the initial position because
+Xthe block automatically shrinks or grows to fit.)
+X\funcitem{gettext}{}
+XReturns the entire text buffer.
+X\funcitem{move}{rect}
+XSpecifies a new position for the text-edit block in the document.
+X\funcitem{replace}{str}
+XReplaces the focus by the given string.
+XThe new focus is an insert point at the end of the string.
+X\funcitem{setfocus}{i,~j}
+XSpecifies the new focus.
+XOut-of-bounds values are silently clipped.
+X\end{description}
+X
+X\subsubsection{Example}
+X
+XHere is a simple example of using STDWIN in Python.
+XIt creates a window and draws the string ``Hello world'' in the top
+Xleft corner of the window.
+XThe window will be correctly redrawn when covered and re-exposed.
+XThe program quits when the close icon or menu item is requested.
+X\bcode\begin{verbatim}
+Ximport stdwin
+Xfrom stdwinevents import *
+X
+Xdef main():
+X mywin = stdwin.open('Hello')
+X #
+X while 1:
+X (type, win, detail) = stdwin.getevent()
+X if type = WE_DRAW:
+X draw = win.begindrawing()
+X draw.text((0, 0), 'Hello, world')
+X del draw
+X elif type = WE_CLOSE:
+X break
+X
+Xmain()
+X\end{verbatim}\ecode
+X
+X\subsection{Built-in Module {\tt amoeba}}
+X
+XThis module provides some object types and operations useful for
+XAmoeba applications.
+XIt is only available on systems that support Amoeba operations.
+XRPC errors and other Amoeba errors are reported as the exception
+X{\tt amoeba.error = 'amoeba.error'}.
+XThe module
+X{\tt amoeba}
+Xdefines the following items:
+X\begin{description}
+X\funcitem{name\_append}{path,~cap}
+X%.br
+XStores a capability in the Amoeba directory tree.
+XArguments are the pathname (a string) and the capability (a capability
+Xobject as returned by
+X{\tt name\_lookup()}).
+X\funcitem{name\_delete}{path}
+X%.br
+XDeletes a capability from the Amoeba directory tree.
+XArgument is the pathname.
+X\funcitem{name\_lookup}{path}
+X%.br
+XLooks up a capability.
+XArgument is the pathname.
+XReturns a
+X{\em capability}
+Xobject, to which various interesting operations apply, described below.
+X\funcitem{name\_replace}{path,~cap}
+X%.br
+XReplaces a capability in the Amoeba directory tree.
+XArguments are the pathname and the new capability.
+X(This differs from
+X{\tt name\_append()}
+Xin the behavior when the pathname already exists:
+X{\tt name\_append()}
+Xfinds this an error while
+X{\tt name\_replace()}
+Xallows it, as its name suggests.)
+X\funcitem{capv}
+XA table representing the capability environment at the time the
+Xinterpreter was started.
+X(Alas, modifying this table does not affect the capability environment
+Xof the interpreter.)
+XFor example,
+X{\tt amoeba.capv['ROOT']}
+Xis the capability of your root directory, similar to
+X{\tt getcap("ROOT")}
+Xin C.
+X\excitem{error}{amoeba.error}
+X%.br
+XThe exception raised when an Amoeba function returns an error.
+XThe value accompanying this exception is a pair containing the numeric
+Xerror code and the corresponding string, as returned by the C function
+X{\tt err\_why()}.
+X\funcitem{timeout}{msecs}
+X%.br
+XSets the transaction timeout, in milliseconds.
+XReturns the previous timeout.
+XInitially, the timeout is set to 2 seconds by the {\Python} interpreter.
+X\end{description}
+X
+X\subsubsection{Capability Operations}
+X
+XCapabilities are written in a convenient ASCII format, also used by the
+XAmoeba utilities
+X{\em c2a}(U)
+Xand
+X{\em a2c}(U).
+XFor example:
+X\bcode\begin{verbatim}
+X>>> amoeba.name_lookup('/profile/cap')
+Xaa:1c:95:52:6a:fa/14(ff)/8e:ba:5b:8:11:1a
+X>>>
+X\end{verbatim}\ecode
+XThe following methods are defined for capability objects.
+X\begin{description}
+X\funcitem{dir\_list}{}
+XReturns a list of the names of the entries in an Amoeba directory.
+X\funcitem{b\_read}{offset, maxsize}
+X%.br
+XReads (at most)
+X{\tt maxsize}
+Xbytes from a bullet file at offset
+X{\tt offset.}
+XThe data is returned as a string.
+XEOF is reported as an empty string.
+X\funcitem{b\_size}{}
+XReturns the size of a bullet file.
+X\funcitem{dir\_append(), dir\_delete(), dir\_lookup(), dir\_replace}{}
+X%.br
+X\itembreak
+XLike the corresponding
+X{\tt name\_*}
+Xfunctions, but with a path relative to the capability.
+X(For paths beginning with a slash the capability is ignored, since this
+Xis the defined semantics for Amoeba.)
+X\funcitem{std\_info}{}
+XReturns the standard info string of the object.
+X\funcitem{tod\_gettime}{}
+XReturns the time (in seconds since the Epoch, in UCT, as for POSIX) from
+Xa time server.
+X\funcitem{tod\_settime}{t}
+XSets the time kept by a time server.
+X\end{description}
+X
+X\subsection{Built-in Module {\tt audio}}
+X
+XThis module provides rudimentary access to the audio I/O device
+X{\tt /dev/audio}
+Xon the Silicon Graphics Personal IRIS; see audio(7).
+XIt supports the following operations:
+X\begin{description}
+X\funcitem{setoutgain}{n}
+XSets the output gain (0-255).
+X\funcitem{getoutgain}{}
+XReturns the output gain.
+X\funcitem{setrate}{n}
+XSets the sampling rate: 1=32K/sec, 2=16K/sec, 3=8K/sec.
+X\funcitem{setduration}{n}
+XSets the `sound duration' in units of 1/100 seconds.
+X\funcitem{read}{n}
+XReads a chunk of
+X{\tt n}
+Xsampled bytes from the audio input (line in or microphone).
+XThe chunk is returned as a string of length n.
+XEach byte encodes one sample as a signed 8-bit quantity using linear
+Xencoding.
+XThis string can be converted to numbers using {\tt chr2num()} described
+Xbelow.
+X\funcitem{write}{buf}
+XWrites a chunk of samples to the audio output (speaker).
+X\end{description}
+X
+XThese operations support asynchronous audio I/O:
+X\begin{description}
+X\funcitem{start\_recording}{n}
+X%.br
+XStarts a second thread (a process with shared memory) that begins reading
+X{\tt n}
+Xbytes from the audio device.
+XThe main thread immediately continues.
+X\funcitem{wait\_recording}{}
+X%.br
+XWaits for the second thread to finish and returns the data read.
+X\funcitem{stop\_recording}{}
+X%.br
+XMakes the second thread stop reading as soon as possible.
+XReturns the data read so far.
+X\funcitem{poll\_recording}{}
+X%.br
+XReturns true if the second thread has finished reading (so
+X{\tt wait\_recording()} would return the data without delay).
+X\item[{\tt start\_playing(chunk)}, {\tt wait\_playing()},
+X{\tt stop\_playing()}, {\tt poll\_playing()}]
+X%.br
+X\begin{sloppypar}
+XSimilar but for output.
+X{\tt stop\_playing()}
+Xreturns a lower bound for the number of bytes actually played (not very
+Xaccurate).
+X\end{sloppypar}
+X\end{description}
+X
+XThe following operations do not affect the audio device but are
+Ximplemented in C for efficiency:
+X\begin{description}
+X\funcitem{amplify}{buf, f1, f2}
+X%.br
+XAmplifies a chunk of samples by a variable factor changing from
+X{\tt f1}/256 to {\tt f2}/256.
+XNegative factors are allowed.
+XResulting values that are to large to fit in a byte are clipped.
+X\funcitem{reverse}{buf}
+X%.br
+XReturns a chunk of samples backwards.
+X\funcitem{add}{buf1, buf2}
+X%.br
+XBytewise adds two chunks of samples.
+XBytes that exceed the range are clipped.
+XIf one buffer shorter, it is assumed to be padded with zeros.
+X\funcitem{chr2num}{buf}
+X%.br
+XConverts a string of sampled bytes as returned by {\tt read()} into
+Xa list containing the numeric values of the samples.
+X\funcitem{num2chr}{list}
+X%.br
+X\begin{sloppypar}
+XConverts a list as returned by
+X{\tt chr2num()}
+Xback to a buffer acceptable by
+X{\tt write()}.
+X\end{sloppypar}
+X\end{description}
+X
+X\subsection{Built-in Module {\tt gl}}
+X
+XThis module provides access to the Silicon Graphics
+X{\em Graphics Library}.
+XIt is available only on Silicon Graphics machines.
+X
+X{\bf Warning:}
+XSome illegal calls to the GL library cause the {\Python} interpreter to dump
+Xcore.
+XIn particular, the use of most GL calls is unsafe before the first
+Xwindow is opened.
+X
+XThe module is too large to document here in its entirety, but the
+Xfollowing should help you to get started.
+XThe parameter conventions for the C functions are translated to {\Python} as
+Xfollows:
+X
+X\begin{itemize}
+X\item
+XAll (short, long, unsigned) int values are represented by {\Python}
+Xintegers.
+X\item
+XAll float and double values are represented by {\Python} floating point
+Xnumbers.
+XIn most cases, {\Python} integers are also allowed.
+X\item
+XAll arrays are represented by one-dimensional {\Python} lists.
+XIn most cases, tuples are also allowed.
+X\item
+X\begin{sloppypar}
+XAll string and character arguments are represented by {\Python} strings,
+Xfor instance,
+X{\tt winopen('Hi~There!')}
+Xand
+X{\tt rotate(900,~'z')}.
+X\end{sloppypar}
+X\item
+XAll (short, long, unsigned) integer arguments or return values that are
+Xonly used to specify the length of an array argument are omitted.
+XFor example, the C call
+X\bcode\begin{verbatim}
+Xlmdef(deftype, index, np, props)
+X\end{verbatim}\ecode
+Xis translated to {\Python} as
+X\bcode\begin{verbatim}
+Xlmdef(deftype, index, props)
+X\end{verbatim}\ecode
+X\item
+XOutput arguments are omitted from the argument list; they are
+Xtransmitted as function return values instead.
+XIf more than one value must be returned, the return value is a tuple.
+XIf the C function has both a regular return value (that is not omitted
+Xbecause of the previous rule) and an output argument, the return value
+Xcomes first in the tuple.
+XExamples: the C call
+X\bcode\begin{verbatim}
+Xgetmcolor(i, &red, &green, &blue)
+X\end{verbatim}\ecode
+Xis translated to {\Python} as
+X\bcode\begin{verbatim}
+Xred, green, blue = getmcolor(i)
+X\end{verbatim}\ecode
+X\end{itemize}
+X
+XThe following functions are non-standard or have special argument
+Xconventions:
+X\begin{description}
+X\funcitem{varray}{}
+XEquivalent to but faster than a number of
+X{\tt v3d()}
+Xcalls.
+XThe argument is a list (or tuple) of points.
+XEach point must be a tuple of coordinates (x, y, z) or (x, y).
+XThe points may be 2- or 3-dimensional but must all have the
+Xsame dimension.
+XFloat and int values may be mixed however.
+XThe points are always converted to 3D double precision points
+Xby assuming z=0.0 if necessary (as indicated in the man page),
+Xand for each point
+X{\tt v3d()}
+Xis called.
+X\funcitem{nvarray}{}
+XEquivalent to but faster than a number of
+X{\tt n3f}
+Xand
+X{\tt v3f}
+Xcalls.
+XThe argument is an array (list or tuple) of pairs of normals and points.
+XEach pair is a tuple of a point and a normal for that point.
+XEach point or normal must be a tuple of coordinates (x, y, z).
+XThree coordinates must be given.
+XFloat and int values may be mixed.
+XFor each pair,
+X{\tt n3f()}
+Xis called for the normal, and then
+X{\tt v3f()}
+Xis called for the point.
+X\funcitem{vnarray}{}
+XSimilar to
+X{\tt nvarray()}
+Xbut the pairs have the point first and the normal second.
+X\funcitem{nurbssurface}{s\_k[], t\_k[], ctl[][], s\_ord, t\_ord, type}
+X%.br
+X\itembreak
+XDefines a nurbs surface.
+XThe dimensions of
+X{\tt ctl[][]}
+Xare computed as follows:
+X{\tt [len(s\_k)~-~s\_ord]},
+X{\tt [len(t\_k)~-~t\_ord]}.
+X\funcitem{nurbscurve}{knots, ctlpoints, order, type}
+X%.br
+XDefines a nurbs curve.
+XThe length of ctlpoints is
+X{\tt len(knots)~-~order}.
+X\funcitem{pwlcurve}{points, type}
+X%.br
+XDefines a piecewise-linear curve.
+X{\tt points}
+Xis a list of points.
+X{\tt type}
+Xmust be
+X{\tt N\_ST}.
+X\funcitem{pick(n), select}{n}
+X%.br
+XThe only argument to these functions specifies the desired size of the
+Xpick or select buffer.
+X\funcitem{endpick(), endselect}{}
+X%.br
+XThese functions have no arguments.
+XThey return a list of integers representing the used part of the
+Xpick/select buffer.
+XNo method is provided to detect buffer overrun.
+X\end{description}
+X
+XHere is a tiny but complete example GL program in {\Python}:
+X\bcode\begin{verbatim}
+Ximport gl, GL, time
+X
+Xdef main():
+X gl.foreground()
+X gl.prefposition(500, 900, 500, 900)
+X w = gl.winopen('CrissCross')
+X gl.ortho2(0.0, 400.0, 0.0, 400.0)
+X gl.color(GL.WHITE)
+X gl.clear()
+X gl.color(GL.RED)
+X gl.bgnline()
+X gl.v2f(0.0, 0.0)
+X gl.v2f(400.0, 400.0)
+X gl.endline()
+X gl.bgnline()
+X gl.v2f(400.0, 0.0)
+X gl.v2f(0.0, 400.0)
+X gl.endline()
+X time.sleep(5)
+X
+Xmain()
+X\end{verbatim}\ecode
+X
+X\subsection{Built-in Module {\tt pnl}}
+X
+XThis module provides access to the
+X{\em Panel Library}
+Xbuilt by NASA Ames (to get it, send e-mail to
+XAll access to it should be done through the standard module
+X{\tt panel},
+Xwhich transparantly exports most functions from
+X{\tt pnl}
+Xbut redefines
+X{\tt pnl.dopanel()}.
+X
+X{\bf Warning:}
+Xthe {\Python} interpreter will dump core if you don't create a GL window
+Xbefore calling
+X{\tt pnl.mkpanel()}.
+X
+XThe module is too large to document here in its entirety.
+EOF
+fi
+if test -s 'src/sc_interpr.c'
+then echo '*** I will not over-write existing file src/sc_interpr.c'
+else
+echo 'x - src/sc_interpr.c'
+sed 's/^X//' > 'src/sc_interpr.c' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X#if 0
+X#define STACK_TRACE
+X#define SCDEBUG
+X#endif
+X#include <stdio.h>
+X
+X#include <ailamoeba.h>
+X
+X#include "PROTO.h"
+X#include "sc_global.h"
+X#include "object.h"
+X#include "objimpl.h"
+X#include "stringobject.h"
+X#include "errors.h"
+X#include "sc_errors.h"
+X#include "stubcode.h"
+X#include "tupleobject.h"
+X#include "intobject.h"
+X#include "listobject.h"
+X
+Xtypedef struct s_loopstruct {
+X struct s_loopstruct *l_next; /* Make a list of it */
+X TscOperand l_label; /* Indentify the loop */
+X int l_index; /* The index of the list */
+X int l_size; /* The size of the list */
+X int l_retaddr; /* Addres to jump back */
+X int l_endaddr; /* Addres to jump to end */
+X object *l_list; /* The list to append to */
+X} TsLoop, *TpsLoop;
+X
+X
+X/*
+X** This file contains the Stubcode interpreter.
+X** All the instructions have there own function. The interpreter
+X** reads an instruction from the data and if needed also an operand.
+X** After this it calls the function that executes the instruction.
+X*/
+X
+Xstruct sc_ProcessBlock {
+X object **stack;
+X unsigned char *buffer, *data;
+X int sp, bp, pc, maxbufsize, datsize;
+X header hdr;
+X TpsLoop loops;
+X};
+X
+Xextern getcapability();
+X
+X/*
+X * Clean up the mess the loops make.
+X */
+X
+Xstatic void
+XxCleanUpLoops(sc_pb)
+X struct sc_ProcessBlock *sc_pb;
+X{
+X TpsLoop prev, this;
+X
+X if (sc_pb->loops == NULL)
+X return;
+X prev = sc_pb->loops;
+X this = sc_pb->loops->l_next;
+X while(this) {
+X free((char *)prev);
+X prev = this;
+X this = this->l_next;
+X }
+X free((char *)prev);
+X}
+X
+Xstatic int
+Xfindendloop(label, sc_pb)
+X TscOperand label;
+X struct sc_ProcessBlock *sc_pb;
+X{
+X TscOperand operand;
+X TscOpcode opcode;
+X int walk = sc_pb->pc, found = 0;
+X
+X while (!found && (walk < sc_pb->datsize)) {
+X memcpy(&opcode, &sc_pb->data[walk], sizeof(TscOpcode));
+X walk += sizeof(TscOpcode);
+X if (opcode & (FLAGS | OPERAND)) {
+X memcpy(&operand, &sc_pb->data[walk], sizeof(TscOperand));
+X walk += sizeof(TscOperand);
+X }
+X if (opcode == EndLoop)
+X if (operand == label) found = 1;
+X }
+X if (found)
+X return walk;
+X return -1;
+X}
+X
+Xstatic int
+Xfindloop(ret, label, sc_pb)
+X TpsLoop *ret;
+X TscOperand label;
+X struct sc_ProcessBlock *sc_pb;
+X{
+X TpsLoop walk;
+X
+X for (walk = sc_pb->loops; walk != NULL; walk = walk->l_next) {
+X if (walk->l_label == label) break;
+X }
+X if (walk == NULL) {
+X TpsLoop newloop;
+X
+X newloop = (TpsLoop)malloc(sizeof(TsLoop));
+X if (newloop == NULL) {
+X err_nomem();
+X return -1;
+X }
+X newloop->l_label = label;
+X newloop->l_index = 0;
+X newloop->l_retaddr = sc_pb->pc - (sizeof(TscOpcode) + sizeof(TscOperand));
+X /*
+X ** We need a correction because the pc points to
+X ** the instruction after the XXXLoop.
+X */
+X if ((newloop->l_endaddr = findendloop(label, sc_pb)) < 0) {
+X free((char *)newloop);
+X err_scerr(NoEndLoop);
+X return -1;
+X }
+X newloop->l_list = NULL;
+X newloop->l_next = sc_pb->loops;
+X sc_pb->loops = newloop;
+X *ret = newloop;
+X return 1;
+X }
+X *ret = walk;
+X return 0;
+X}
+X
+X#ifdef 0
+X
+Xstatic void
+Xremoveloop(this, sc_pb)
+X TpsLoop this;
+X struct sc_ProcessBlock *sc_pb;
+X{
+X TpsLoop walk, prev = NULL;
+X
+X for (walk = sc_pb->loops; walk != NULL; walk = walk->l_next) {
+X if (walk->l_label == this->l_label) {
+X if (prev != NULL) {
+X prev->l_next = walk->l_next;
+X } else {
+X loop = walk->l_next;
+X }
+X free((char *)this);
+X break;
+X }
+X prev = walk;
+X }
+X}
+X
+X#endif
+X
+Xstatic int
+Xinit(self, sc_pb)
+X object *self;
+X struct sc_ProcessBlock *sc_pb;
+X{
+Xobject *string;
+Xint datasize;
+X
+X string = gettupleitem(self, STUBC);
+X if (string == NULL)
+X return -1;
+X sc_pb->data = getstringvalue(string);
+X if (sc_pb->data == NULL)
+X return -1;
+X datasize = (int)getstringsize(string);
+X if (datasize == -1)
+X return -1;
+X sc_pb->stack = (object **)malloc(STKSIZE * sizeof(object *));
+X if (sc_pb->stack == NULL) {
+X err_nomem();
+X return -1;
+X }
+X sc_pb->bp = sc_pb->sp = sc_pb->pc = 0;
+X sc_pb->loops = NULL;
+X return datasize;
+X}
+X
+Xstatic void reinit(sc_pb)
+X struct sc_ProcessBlock *sc_pb;
+X{
+X int i;
+X
+X sc_pb->bp = 0;
+X for (i = 0; i < sc_pb->sp; i++) {
+X DECREF(sc_pb->stack[i]);
+X }
+X sc_pb->sp = 0;
+X}
+X
+Xstatic void UnInit(self, sc_pb)
+X object *self;
+X struct sc_ProcessBlock *sc_pb;
+X{
+X int i;
+X
+X free(sc_pb->buffer);
+X reinit(sc_pb);
+X free((char *)sc_pb->stack);
+X xCleanUpLoops(sc_pb);
+X}
+X
+Xstatic object *
+Xstacktop(sc_pb)
+X struct sc_ProcessBlock *sc_pb;
+X{
+X
+X if (sc_pb->sp == 0)
+X return err_scerr(StackUnderflow);
+X if (sc_pb->sp == (STKSIZE + 1))
+X return err_scerr(StackOverflow);
+X return sc_pb->stack[sc_pb->sp - 1];
+X}
+X
+X/*
+X * Push an object on the stack.
+X */
+Xstatic int
+XxPush(element, sc_pb)
+X object *element;
+X struct sc_ProcessBlock *sc_pb;
+X{
+X
+X if (sc_pb->sp >= STKSIZE) {
+X err_scerr(StackOverflow);
+X return -1;
+X }
+X if (element == NULL) {
+X err_scerr(ElementIsNull);
+X return -1;
+X }
+X INCREF(element);
+X#ifdef STACK_TRACE
+X printf("pushed :");
+X printobject(element, stdout, 0);
+X printf("\n");
+X#endif
+X sc_pb->stack[sc_pb->sp++] = element;
+X return 0;
+X}
+X
+X/*
+X * Perform the RPC.
+X */
+Xstatic int
+XxTrans(self,cmd, sc_pb)
+X object *self;
+X TscOperand cmd;
+X struct sc_ProcessBlock *sc_pb;
+X{
+X short ret;
+X capability cap;
+X object *capobj;
+X
+X if ((capobj = gettupleitem(self, CAP)) == NULL)
+X return -1;
+X if (getcapability(capobj, &cap) == -1)
+X return -1;
+X sc_pb->hdr.h_port = cap.cap_port;
+X sc_pb->hdr.h_priv = cap.cap_priv;
+X sc_pb->hdr.h_command = (command)cmd;
+X#ifdef SCDEBUG
+X printf("bp = %d maxbufsize = %d\n",sc_pb->bp, sc_pb->maxbufsize);
+X {
+X int i;
+X
+X for (i = 0; i < sc_pb->bp; i++) {
+X printf("%x ", sc_pb->buffer[i]);
+X }
+X }
+X printf("\n");
+X#endif
+X ret = trans(&sc_pb->hdr, sc_pb->buffer, (bufsize) sc_pb->bp,
+X &sc_pb->hdr, sc_pb->buffer, (bufsize)sc_pb->maxbufsize);
+X#ifdef SCDEBUG
+X printf("after Trans:ret = %d\n",ret);
+X {
+X int i;
+X
+X for (i = 0; i < ret; i++) {
+X printf("%x ", sc_pb->buffer[i]);
+X }
+X }
+X printf("\n");
+X#endif
+X if (ERR_STATUS(ret)) {
+X amoeba_error(ERR_CONVERT(ret));
+X return -1;
+X }
+X if (sc_pb->hdr.h_status != 0) {
+X object *v;
+X
+X if ((v = newintobject(sc_pb->hdr.h_status)) == NULL)
+X return -1;
+X err_scerrset(TransError, v, "Trans");
+X DECREF(v);
+X return -1;
+X }
+X reinit(sc_pb);
+X return 0;
+X}
+X
+X/*
+X * Test the tuple size.
+X */
+Xstatic int
+XxTTupleS(size, sc_pb)
+X TscOperand size;
+X struct sc_ProcessBlock *sc_pb;
+X{
+X object *tuple;
+X
+X if ((tuple = stacktop(sc_pb)) == NULL)
+X return -1;
+X if (!is_tupleobject(tuple))
+X return err_scerrset(TypeFailure, tuple, "TTupleS");
+X if (gettuplesize(tuple) != (unsigned int)size)
+X return err_scerrset(SizeError, tuple, "TTupleS");
+X return 0;
+X}
+X
+X/*
+X * Unpack a tuple
+X */
+Xstatic int
+XxUnpack(size, sc_pb)
+X TscOperand size;
+X struct sc_ProcessBlock *sc_pb;
+X{
+X object *tuple, *element;
+X int i;
+X
+X if (size < (TscOperand)2) {
+X element = newintobject(size);
+X if (element == NULL)
+X return -1;
+X return err_scerrset(SizeError, element, "Unpack");
+X }
+X if ((tuple = stacktop(sc_pb)) == NULL)
+X return -1;
+X INCREF(tuple);
+X if (xPop((TscOperand) 1, sc_pb) != 0) {
+X DECREF(tuple);
+X return -1;
+X }
+X for (i = 0; i < (int)size; i++) {
+X if ((element = gettupleitem(tuple, i)) == NULL) {
+X DECREF(tuple);
+X return -1;
+X }
+X if (xPush(element, sc_pb) != 0) {
+X DECREF(tuple);
+X return -1;
+X }
+X }
+X DECREF(tuple);
+X return 0;
+X}
+X
+X/*
+X * Marshal the Ailword to a headerfiels.
+X */
+Xstatic int
+XxAilword(headerfield, sc_pb)
+X TscOperand headerfield;
+X struct sc_ProcessBlock *sc_pb;
+X{
+X
+X switch(headerfield) {
+X
+X case H_EXTRA:
+X sc_pb->hdr.h_extra = (uint16)_ailword;
+X return 0;
+X
+X case H_SIZE:
+X sc_pb->hdr.h_size = (bufsize)_ailword;
+X return 0;
+X
+X case H_OFFSET:
+X sc_pb->hdr.h_offset = (int32)_ailword;
+X return 0;
+X
+X default:
+X {
+X object *v;
+X
+X if ((v = newintobject(headerfield)) == NULL)
+X return -1;
+X return err_scerrset(FlagError, v, "Ailword");
+X }
+X }
+X}
+X
+Xstatic int
+XxStringS(sc_pb)
+X struct sc_ProcessBlock *sc_pb;
+X{
+X object *size, *string;
+X int s;
+X
+X if ((string = stacktop(sc_pb)) == NULL)
+X return -1;
+X if (!is_stringobject(string))
+X return err_scerrset(TypeFailure, string, "StringS");
+X if ((s = getstringsize(string)) < 0)
+X return -1;
+X if (xPop((TscOperand) 1, sc_pb) != 0)
+X return -1;
+X if ((size = newintobject(s)) == NULL)
+X return -1;
+X if (xPush(size, sc_pb) != 0) {
+X DECREF(size);
+X return -1;
+X }
+X DECREF(size);
+X return 0;
+X}
+X
+X/*
+X *
+X */
+Xstatic int
+XxListS(sc_pb)
+X struct sc_ProcessBlock *sc_pb;
+X{
+X object *size, *list;
+X int s;
+X
+X if ((list = stacktop(sc_pb)) == NULL)
+X return -1;
+X if (!is_listobject(list))
+X return err_scerrset(TypeFailure, list, "ListS");
+X if ((s = getlistsize(list)) < 0)
+X return -1;
+X if (xPop((TscOperand) 1, sc_pb) != 0)
+X return -1;
+X if ((size = newintobject(s)) == NULL)
+X return -1;
+X if (xPush(size, sc_pb) != 0) {
+X DECREF(size);
+X return -1;
+X }
+X DECREF(size);
+X return 0;
+X}
+X
+X/*
+X * Marshal a fixed string to the buffer.
+X */
+Xstatic int
+XxPutFS(size, sc_pb)
+X TscOperand size;
+X struct sc_ProcessBlock *sc_pb;
+X{
+X object *string;
+X char *str;
+X
+X if ((string = stacktop(sc_pb)) == NULL) {
+X return -1;
+X }
+X if (!is_stringobject(string))
+X return err_scerrset(TypeFailure, string, "PutFS");
+X if (getstringsize(string) != size)
+X return err_scerrset(SizeError, string, "PutFS");
+X if ((str = getstringvalue(string)) == NULL)
+X return -1;
+X if ((size + sc_pb->bp) > sc_pb->maxbufsize) {
+X err_scerr(BufferOverflow);
+X return -1;
+X }
+X memcpy(&sc_pb->buffer[sc_pb->bp], str, (int)size);
+X sc_pb->bp += size;
+X return xPop((TscOperand) 1, sc_pb);
+X}
+X
+X
+X/*
+X * Test the size of a string or list
+X */
+Xstatic int
+XxTStringSeq(size, sc_pb)
+X TscOperand size;
+X struct sc_ProcessBlock *sc_pb;
+X{
+X object *string;
+X
+X if ((string = stacktop(sc_pb)) == NULL)
+X return -1;
+X if (!is_stringobject(string))
+X return err_scerrset(TypeFailure, string, "TStringSeq");
+X if (getstringsize(string) != size)
+X return err_scerrset(SizeError, string, "TStringSeq");
+X return 0;
+X}
+X
+Xstatic int
+XxTStringSlt(size, sc_pb)
+X TscOperand size;
+X struct sc_ProcessBlock *sc_pb;
+X{
+X object *string;
+X
+X if ((string = stacktop(sc_pb)) == NULL)
+X return -1;
+X if (!is_stringobject(string))
+X return err_scerrset(TypeFailure, string, "TStringSlt");
+X if (getstringsize(string) > size)
+X return err_scerrset(SizeError, string, "TStringSlt");
+X return 0;
+X}
+X
+Xstatic int
+XxTListSeq(size, sc_pb)
+X TscOperand size;
+X struct sc_ProcessBlock *sc_pb;
+X{
+X object *list;
+X
+X if ((list = stacktop(sc_pb)) == NULL)
+X return -1;
+X if (!is_listobject(list))
+X return err_scerrset(TypeFailure, list, "TListSeq");
+X if (getlistsize(list) != size)
+X return err_scerrset(SizeError, list, "TListSeq");
+X return 0;
+X}
+X
+Xstatic int
+XxTListSlt(size, sc_pb)
+X TscOperand size;
+X struct sc_ProcessBlock *sc_pb;
+X{
+X object *list;
+X
+X if ((list = stacktop(sc_pb)) == NULL)
+X return -1;
+X if (!is_listobject(list))
+X return err_scerrset(TypeFailure, list, "TListSlt");
+X if (getlistsize(list) > size)
+X return err_scerrset(SizeError, list, "TListSlt");
+X return 0;
+X}
+X
+Xstatic int
+XxPutVS(sc_pb)
+X struct sc_ProcessBlock *sc_pb;
+X{
+X object *string;
+X char *str;
+X int size;
+X
+X if ((string = stacktop(sc_pb)) == NULL)
+X return -1;
+X if ((size = getstringsize(string)) < 0)
+X return (size == -1 ? -1 : err_scerrset(SizeError, string, "PutVS"));
+X if ((str = getstringvalue(string)) == NULL)
+X return -1;
+X if (sc_pb->bp + size > sc_pb->maxbufsize) {
+X err_scerr(BufferOverflow);
+X return -1;
+X }
+X memcpy(&sc_pb->buffer[sc_pb->bp], str, size);
+X sc_pb->bp += size;
+X return xPop((TscOperand) 1, sc_pb);
+X}
+X
+X/*
+X * The loop instructions.
+X */
+Xstatic int
+XxLoopPut(label, sc_pb)
+X TscOperand label;
+X struct sc_ProcessBlock *sc_pb;
+X{
+X TpsLoop this;
+X object *list, *element;
+X
+X if (findloop(&this, label, sc_pb) < 0)
+X return -1;
+X if ((list = stacktop(sc_pb)) == NULL)
+X return -1;
+X if (!is_listobject(list))
+X return err_scerrset(TypeFailure, list, "LoopPut");
+X if (this->l_index >= getlistsize(list)) {
+X sc_pb->pc = this->l_endaddr;
+X /*
+X ** Pop the list from the stack
+X */
+X return xPop((TscOperand)1, sc_pb);
+X }
+X if ((element = getlistitem(list, this->l_index)) == NULL)
+X return -1;
+X return xPush(element, sc_pb);
+X}
+X
+Xstatic int
+XxLoopGet(label, sc_pb)
+X TscOperand label;
+X struct sc_ProcessBlock *sc_pb;
+X{
+X TpsLoop this;
+X object *element, *integer;
+X int i;
+X
+X if ((i = findloop(&this, label, sc_pb)) < 0)
+X return -1;
+X else if (i == 1) {
+X /*
+X * It is the first time we enter LoopGet label
+X */
+X if ((this->l_list = newlistobject(0)) == NULL)
+X return -1;
+X if ((integer = stacktop(sc_pb)) == NULL)
+X return -1;
+X if (!is_intobject(integer))
+X return err_scerrset(TypeFailure, integer, "LoopGet");
+X this->l_size = getintvalue(integer);
+X if (xPop((TscOperand) 1, sc_pb) != 0)
+X return -1;
+X } else {
+X if ((element = stacktop(sc_pb)) == NULL)
+X return -1;
+X if (addlistitem(this->l_list, element) != 0)
+X return -1;
+X if (xPop((TscOperand) 1, sc_pb) != 0)
+X return -1;
+X }
+X if (this->l_index >= this->l_size) {
+X int ret;
+X
+X sc_pb->pc = this->l_endaddr;
+X ret = xPush(this->l_list, sc_pb);
+X DECREF(this->l_list);
+X return ret;
+X }
+X return 0;
+X}
+X
+Xstatic int
+XxEndLoop(label, sc_pb)
+X TscOperand label;
+X struct sc_ProcessBlock *sc_pb;
+X{
+X TpsLoop this;
+X
+X if (findloop(&this, label, sc_pb) < 0)
+X return -1;
+X this ->l_index += 1;
+X sc_pb->pc = this->l_retaddr;
+X return 0;
+X}
+X
+Xstatic int
+XxPutI(flags, sc_pb)
+X TscOperand flags;
+X struct sc_ProcessBlock *sc_pb;
+X{
+X object *integer;
+X
+X if ((integer = stacktop(sc_pb)) == NULL)
+X return -1;
+X if (!is_intobject(integer))
+X return err_scerrset(TypeFailure, integer, "PutI");
+X if (flags & ALL_FIELDS) {
+X long i;
+X
+X /*
+X * The integer must be marshalles in the header.
+X * No type casting according to the type flag because
+X * we have to cast to the headerfield types.
+X */
+X i = getintvalue(integer);
+X switch(flags & ALL_FIELDS) {
+X
+X case H_EXTRA:
+X sc_pb->hdr.h_extra = (uint16)i;
+X break;
+X
+X case H_SIZE:
+X sc_pb->hdr.h_size = (bufsize)i;
+X break;
+X
+X case H_OFFSET:
+X sc_pb->hdr.h_offset = (int32)i;
+X break;
+X
+X default:
+X if ((integer = newintobject(flags & ALL_FIELDS)) == NULL)
+X return -1;
+X err_scerrset(FlagError, integer, "Ailword");
+X DECREF(integer);
+X return -1;
+X }
+X } else {
+X long i;
+X
+X i = getintvalue(integer);
+X switch(flags & ALLTYPES) {
+X
+X case 0:
+X {
+X int16 x;
+X
+X x = (int16)i;
+X if ((sc_pb->bp + sizeof(int16)) > sc_pb->maxbufsize) {
+X err_scerr(BufferOverflow);
+X return -1;
+X }
+X memcpy(&sc_pb->buffer[sc_pb->bp], &x, sizeof(int16));
+X sc_pb->bp += sizeof(int16);
+X break;
+X }
+X
+X case NOSIGN:
+X {
+X uint16 x;
+X
+X x = (uint16)i;
+X if ((sc_pb->bp + sizeof(uint16)) > sc_pb->maxbufsize) {
+X err_scerr(BufferOverflow);
+X return -1;
+X }
+X memcpy(&sc_pb->buffer[sc_pb->bp], &x, sizeof(uint16));
+X sc_pb->bp += sizeof(uint16);
+X break;
+X }
+X
+X case INT32:
+X {
+X int32 x;
+X
+X x = (int32)i;
+X if ((sc_pb->bp + sizeof(int32)) > sc_pb->maxbufsize) {
+X err_scerr(BufferOverflow);
+X return -1;
+X }
+X memcpy(&sc_pb->buffer[sc_pb->bp], &x, sizeof(int32));
+X sc_pb->bp += sizeof(int32);
+X break;
+X }
+X
+X case INT32 | NOSIGN:
+X {
+X uint32 x;
+X
+X x = (uint32)i;
+X if ((sc_pb->bp + sizeof(uint32)) > sc_pb->maxbufsize) {
+X err_scerr(BufferOverflow);
+X return -1;
+X }
+X memcpy(&sc_pb->buffer[sc_pb->bp], &x, sizeof(uint32));
+X sc_pb->bp += sizeof(uint32);
+X break;
+X }
+X default:
+X {
+X object *x;
+X
+X if ((x = newintobject(flags)) == NULL)
+X return -1;
+X err_scerrset(FlagError, x, "PutI");
+X DECREF(x);
+X return -1;
+X }
+X }
+X }
+X return xPop((TscOperand)1, sc_pb);
+X}
+X
+Xstatic int
+XxPutC(sc_pb)
+X struct sc_ProcessBlock *sc_pb;
+X{
+X capability cap;
+X object *capobj;
+X
+X if ((capobj = stacktop(sc_pb)) == NULL)
+X return -1;
+X if (!is_capobj(capobj))
+X return err_scerrset(TypeFailure, capobj, "xPutC");
+X if (getcapability(capobj, &cap) != 0)
+X return -1;
+X if ((sc_pb->bp + CAPSIZE) > sc_pb->maxbufsize) {
+X err_scerr(BufferOverflow);
+X return -1;
+X }
+X memcpy(&sc_pb->buffer[sc_pb->bp], &cap, CAPSIZE);
+X sc_pb->bp += CAPSIZE;
+X return xPop((TscOperand) 1, sc_pb);
+X}
+X
+Xstatic int
+XxDup(n, sc_pb)
+X TscOperand n;
+X struct sc_ProcessBlock *sc_pb;
+X{
+X
+X if ((int)n > sc_pb->sp) {
+X object *i;
+X
+X if ((i = newintobject((long)n)) == NULL)
+X return -1;
+X err_scerrset(RangeError, i, "Dup");
+X DECREF(i);
+X return -1;
+X }
+X return xPush(sc_pb->stack[sc_pb->sp - n], sc_pb);
+X}
+X
+Xstatic int
+XxPop(n, sc_pb)
+X TscOperand n;
+X struct sc_ProcessBlock *sc_pb;
+X{
+X int i;
+X
+X if ((sc_pb->sp - (int)n) < 0) {
+X err_scerr(StackUnderflow);
+X return -1;
+X }
+X for (i = 0; i < (int)n; i++) {
+X sc_pb->sp--;
+X#ifdef STACK_TRACE
+X printf("popped :");
+X printobject(sc_pb->stack[sc_pb->sp], stdout, 0);
+X printf("\n");
+X#endif
+X DECREF(sc_pb->stack[sc_pb->sp]);
+X }
+X return 0;
+X}
+X
+Xstatic int
+XxAlign(n, sc_pb)
+X TscOperand n;
+X struct sc_ProcessBlock *sc_pb;
+X{
+X int align = sc_pb->bp % (int)n;
+X
+X#ifdef SCDEBUG
+X printf("Old bp = %d\n", sc_pb->bp);
+X#endif
+X sc_pb->bp += (align == 0) ? 0 : ((int)n - align);
+X#ifdef SCDEBUG
+X printf("New bp = %d\n", sc_pb->bp);
+X#endif
+X return 0;
+X}
+X
+Xstatic int
+XxPack(size, sc_pb)
+X TscOperand size;
+X struct sc_ProcessBlock *sc_pb;
+X{
+X object *element, *tuple;
+X int i, ret;
+X
+X if ((tuple = newtupleobject((int)size)) == NULL)
+X return -1;
+X for (i = 0; i < (int)size; i++) {
+X if ((element = stacktop(sc_pb)) == NULL)
+X return -1;
+X if (settupleitem(tuple, (int)size - i - 1, element) != 0)
+X return -1;
+X INCREF(element);
+X if (xPop((TscOperand) 1, sc_pb) != 0)
+X return -1;
+X }
+X ret = xPush(tuple, sc_pb);
+X DECREF(tuple);
+X return ret;
+X}
+X
+Xstatic int
+XxGetVS(sc_pb)
+X struct sc_ProcessBlock *sc_pb;
+X{
+X object *string, *integer;
+X int size;
+X
+X if ((integer = stacktop(sc_pb)) == NULL)
+X return -1;
+X if (!is_intobject(integer))
+X return err_scerrset(TypeFailure, integer, "GetVS");
+X size = getintvalue(integer);
+X if ((sc_pb->bp + size) > sc_pb->maxbufsize) {
+X err_scerr(BufferOverflow);
+X return -1;
+X }
+X if ((string = newsizedstringobject(&sc_pb->buffer[sc_pb->bp], size)) == NULL)
+X return -1;
+X sc_pb->bp += size;
+X if (xPop((TscOperand) 1, sc_pb) != 0)
+X return -1;
+X if (xPush(string, sc_pb) != 0) {
+X return -1;
+X }
+X DECREF(string);
+X return 0;
+X}
+X
+Xstatic int
+XxGetFS(size, sc_pb)
+X TscOperand size;
+X struct sc_ProcessBlock *sc_pb;
+X{
+X object *string;
+X
+X if ((sc_pb->bp + (int)size) > sc_pb->maxbufsize) {
+X err_scerr(BufferOverflow);
+X return -1;
+X }
+X if ((string = newsizedstringobject(&sc_pb->buffer[sc_pb->bp], (int)size)) == NULL)
+X return -1;
+X sc_pb->bp += (int)size;
+X if(xPush(string, sc_pb) != 0) {
+X return -1;
+X }
+X DECREF(string);
+X return 0;
+X}
+X
+Xstatic int
+XxGetI(flags, sc_pb)
+X TscOperand flags;
+X struct sc_ProcessBlock *sc_pb;
+X{
+X object *integer;
+X long i;
+X
+X if (flags & ALL_FIELDS) {
+X
+X switch(flags & ALL_FIELDS) {
+X
+X case H_EXTRA:
+X i = (long)sc_pb->hdr.h_extra;
+X break;
+X
+X case H_SIZE:
+X i = (long)sc_pb->hdr.h_size;
+X break;
+X
+X case H_OFFSET:
+X i = (long)sc_pb->hdr.h_offset;
+X break;
+X
+X default:
+X if ((integer = newintobject(flags & ALL_FIELDS)) == NULL)
+X return -1;
+X err_scerrset(FlagError, integer, "Ailword");
+X DECREF(integer);
+X return -1;
+X }
+X } else {
+X switch(flags & ALLTYPES) {
+X
+X case 0:
+X {
+X int16 x;
+X
+X if ((sc_pb->bp + sizeof(int16)) > sc_pb->maxbufsize) {
+X err_scerr(BufferOverflow);
+X return -1;
+X }
+X memcpy(&x, &sc_pb->buffer[sc_pb->bp], sizeof(int16));
+X sc_pb->bp += sizeof(int16);
+X i = (long)x;
+X break;
+X }
+X
+X case NOSIGN:
+X {
+X uint16 x;
+X
+X if ((sc_pb->bp + sizeof(uint16)) > sc_pb->maxbufsize) {
+X err_scerr(BufferOverflow);
+X return -1;
+X }
+X memcpy(&x, &sc_pb->buffer[sc_pb->bp], sizeof(uint16));
+X sc_pb->bp += sizeof(uint16);
+X i = (long)x;
+X break;
+X }
+X
+X case INT32:
+X {
+X int32 x;
+X
+X if ((sc_pb->bp + sizeof(int32)) > sc_pb->maxbufsize) {
+X err_scerr(BufferOverflow);
+X return -1;
+X }
+X memcpy(&x, &sc_pb->buffer[sc_pb->bp], sizeof(int32));
+X sc_pb->bp += sizeof(int32);
+X i = (long)x;
+X break;
+X }
+X
+X case INT32 | NOSIGN:
+X {
+X uint32 x;
+X
+X if ((sc_pb->bp + sizeof(uint32)) > sc_pb->maxbufsize) {
+X err_scerr(BufferOverflow);
+X return -1;
+X }
+X memcpy(&x, &sc_pb->buffer[sc_pb->bp], sizeof(uint32));
+X sc_pb->bp += sizeof(uint32);
+X i = (long)x;
+X break;
+X }
+X default:
+X {
+X if ((integer = newintobject(flags)) == NULL)
+X return -1;
+X err_scerrset(FlagError, integer, "GetI");
+X DECREF(integer);
+X return -1;
+X }
+X }
+X }
+X if ((integer = newintobject(i)) == NULL)
+X return -1;
+X if (xPush(integer, sc_pb) != 0) {
+X DECREF(integer);
+X return -1;
+X }
+X DECREF(integer);
+X return 0;
+X}
+X
+Xstatic int
+XxGetC(flags, sc_pb)
+X TscOperand flags;
+X struct sc_ProcessBlock *sc_pb;
+X{
+X extern object *newcapobject();
+X object *capobj;
+X capability cap;
+X
+X if ((int)flags != 0) {
+X switch ((int)flags) {
+X
+X case PSEUDOFIELD:
+X cap.cap_port = sc_pb->hdr.h_port;
+X cap.cap_priv = sc_pb->hdr.h_priv;
+X break;
+X }
+X } else {
+X if ((CAPSIZE + sc_pb->bp) > sc_pb->maxbufsize) {
+X err_scerr(BufferOverflow);
+X return -1;
+X }
+X memcpy(&cap, &sc_pb->buffer[sc_pb->bp], CAPSIZE);
+X }
+X if ((capobj = newcapobject(&cap)) == NULL)
+X return -1;
+X return xPush(capobj, sc_pb);
+X}
+X
+Xstatic int
+XxEqual(sc_pb)
+X struct sc_ProcessBlock *sc_pb;
+X{
+X object *int1, *int2;
+X
+X if (sc_pb->sp < 2) {
+X err_scerr(StackUnderflow);
+X return -1;
+X }
+X int1 = sc_pb->stack[sc_pb->sp - 1];
+X int2 = sc_pb->stack[sc_pb->sp - 2];
+X if ((int1 == NULL) || (int2 == NULL))
+X return -1;
+X if (!is_intobject(int1))
+X return err_scerrset(TypeFailure, int1, "Equal");
+X if (!is_intobject(int2))
+X return err_scerrset(TypeFailure, int2, "Equal");
+X if (getintvalue(int1) != getintvalue(int2)) {
+X object *tmptuple;
+X
+X if ((tmptuple = newtupleobject(2)) == NULL)
+X return -1;
+X INCREF(int1);
+X if (settupleitem(tmptuple, 0, int1) != 0) {
+X DECREF(tmptuple);
+X DECREF(int1);
+X return -1;
+X }
+X if (settupleitem(tmptuple, 1, int2) != 0) {
+X DECREF(tmptuple);
+X DECREF(int2);
+X return -1;
+X }
+X return err_scerrset(SizeError, tmptuple, "Equal");
+X }
+X return 0;
+X}
+X
+Xobject *
+Xsc_interpreter(self, args)
+X object *self, *args;
+X{
+XTscOpcode opcode;
+XTscOperand operand;
+Xint datasize, ret;
+Xobject *returnobject;
+Xstruct sc_ProcessBlock sc_pb;
+X
+X if ((datasize = init(self, &sc_pb)) < 0)
+X return NULL;
+X memcpy(&opcode, sc_pb.data, sizeof(TscOpcode));
+X sc_pb.datsize = datasize;
+X sc_pb.pc += sizeof(TscOpcode);
+X if (opcode != BufSize) {
+X free((char *)sc_pb.stack);
+X return err_scerr(NoBufSize);
+X }
+X memcpy(&operand, &sc_pb.data[sc_pb.pc], sizeof(TscOperand));
+X sc_pb.pc += sizeof(TscOperand);
+X sc_pb.buffer = (unsigned char *)malloc(operand);
+X sc_pb.maxbufsize = (int)operand;
+X if (sc_pb.buffer == NULL) {
+X free((char *)sc_pb.stack);
+X return err_nomem();
+X }
+X memcpy(&opcode, &sc_pb.data[sc_pb.pc], sizeof(TscOpcode));
+X if (opcode != NoArgs) {
+X if (xPush(args, &sc_pb) != 0) {
+X UnInit(self, &sc_pb);
+X return NULL;
+X }
+X }
+X while (sc_pb.pc < datasize) {
+X memcpy(&opcode, &sc_pb.data[sc_pb.pc], sizeof(TscOpcode));
+X sc_pb.pc += sizeof(TscOpcode);
+X if (opcode & (OPERAND | FLAGS)) {
+X memcpy(&operand, &sc_pb.data[sc_pb.pc], sizeof(TscOperand));
+X sc_pb.pc += sizeof(TscOperand);
+X }
+X#ifdef SCDEBUG
+X xPrintCode(opcode);
+X if ((opcode & FLAGS) && (opcode & OPERAND))
+X xPrintFlags(operand);
+X else if (opcode & OPERAND)
+X xPrintNum(operand);
+X printf("\n");
+X fflush(stdout);
+X#endif
+X#ifdef STACK_TRACE
+X {
+X register i;
+X
+X printf("Stack trace :\n");
+X for(i = 0; i < sc_pb.sp; i++) {
+X printobject(sc_pb.stack[i], stdout, 0);
+X printf("\n");
+X }
+X }
+X#endif
+X switch(opcode) {
+X
+X case NoArgs:
+X ret = 0;
+X if (args != NULL) {
+X err_scerrset(TypeFailure, args, "NoArgs");
+X ret = -1;
+X }
+X break;
+X
+X case BufSize:
+X UnInit(self, &sc_pb);
+X return err_scerr(TwoBufSize);
+X
+X case Trans:
+X ret = xTrans(self, operand, &sc_pb);
+X break;
+X
+X case TTupleS:
+X ret = xTTupleS(operand, &sc_pb);
+X break;
+X
+X case Unpack:
+X ret = xUnpack(operand, &sc_pb);
+X break;
+X
+X case AilWord:
+X ret = xAilword(operand, &sc_pb);
+X break;
+X
+X case StringS:
+X ret = xStringS(&sc_pb);
+X break;
+X
+X case ListS:
+X ret = xListS(&sc_pb);
+X break;
+X
+X case PutFS:
+X ret = xPutFS(operand, &sc_pb);
+X break;
+X
+X case TStringSeq:
+X ret = xTStringSeq(operand, &sc_pb);
+X break;
+X
+X case TStringSlt:
+X ret = xTStringSlt(operand, &sc_pb);
+X break;
+X
+X case PutVS:
+X ret = xPutVS(&sc_pb);
+X break;
+X
+X case TListSeq:
+X ret = xTListSeq(operand, &sc_pb);
+X break;
+X
+X case TListSlt:
+X
+ret = xTListSlt(operand, &sc_pb);
+X break;
+X
+X case LoopPut:
+X ret = xLoopPut(operand, &sc_pb);
+X break;
+X
+X case EndLoop:
+X ret = xEndLoop(operand, &sc_pb);
+X break;
+X
+X case PutI:
+X ret = xPutI(operand, &sc_pb);
+X break;
+X
+X case PutC:
+X ret = xPutC(&sc_pb);
+X break;
+X
+X case Dup:
+X ret = xDup(operand, &sc_pb);
+X break;
+X
+X case Pop:
+X ret = xPop(operand, &sc_pb);
+X break;
+X
+X case Align:
+X ret = xAlign(operand, &sc_pb);
+X break;
+X
+X case Pack:
+X ret = xPack(operand, &sc_pb);
+X break;
+X
+X case GetVS:
+X ret = xGetVS(&sc_pb);
+X break;
+X
+X case LoopGet:
+X ret = xLoopGet(operand, &sc_pb);
+X break;
+X
+X case GetFS:
+X ret = xGetFS(operand, &sc_pb);
+X break;
+X
+X case GetI:
+X ret = xGetI(operand, &sc_pb);
+X break;
+X
+X case GetC:
+X ret = xGetC(operand, &sc_pb);
+X break;
+X
+X case PushI:
+X {
+X object *element;
+X
+X element = newintobject((long)operand);
+X if (element == NULL) {
+X UnInit(self, &sc_pb);
+X return NULL;
+X }
+X ret = xPush(element, &sc_pb);
+X if (ret == 0)
+X DECREF(element);
+X }
+X break;
+X
+X case Equal:
+X ret = xEqual(&sc_pb);
+X break;
+X
+X default:
+X {
+X char errstr[256];
+X
+X UnInit(self, &sc_pb);
+X sprintf(errstr, "Unknow stubcode %d", opcode);
+X err_setstr(RuntimeError, errstr);
+X return NULL;
+X }
+X }
+X if (ret != 0) {
+X UnInit(self, &sc_pb);
+X return NULL;
+X }
+X }
+X if (sc_pb.sp > 0) {
+X INCREF(sc_pb.stack[sc_pb.sp - 1]);
+X returnobject = sc_pb.stack[sc_pb.sp - 1];
+X } else {
+X INCREF(None);
+X returnobject = None;
+X }
+X UnInit(self, &sc_pb);
+X return returnobject;
+X}
+EOF
+fi
+echo 'Part 06 out of 21 of pack.out complete.'
+exit 0
diff --git a/shar/python-0.9.1-07-21.shar b/shar/python-0.9.1-07-21.shar
new file mode 100644
index 0000000..e242423
--- /dev/null
+++ b/shar/python-0.9.1-07-21.shar
@@ -0,0 +1,2518 @@
+: This is a shell archive.
+: Extract with 'sh this_file'.
+:
+: Extract part 01 first since it makes all directories
+echo 'Start of pack.out, part 07 out of 21:'
+if test -s 'demo/sgi/gl/mclock.py'
+then echo '*** I will not over-write existing file demo/sgi/gl/mclock.py'
+else
+echo 'x - demo/sgi/gl/mclock.py'
+sed 's/^X//' > 'demo/sgi/gl/mclock.py' << 'EOF'
+X#! /ufs/guido/bin/sgi/python
+X
+X#############################################################################
+X# NOTA BENE: Before installing, fix TZDIFF to reflect your local time zone! #
+X#############################################################################
+X
+X# "M Clock"
+X#
+X# An implementation in software of an original design by Rob Juda.
+X# Clock implementation: Guido van Rossum.
+X# Alarm and Gong features: Sape Mullender.
+X#
+X# XXX TO DO:
+X# find out local time zone difference automatically
+X# add a date indicator
+X# allow multiple alarms
+X# allow the menu to change more parameters
+X
+Ximport sys
+X
+Xfrom gl import *
+Xfrom GL import *
+Xfrom DEVICE import *
+Ximport time
+Ximport getopt
+Ximport string
+Ximport path
+Xfrom math import pi
+Ximport math
+Ximport posix
+X
+XFULLC = 3600 # Full circle in 1/10-ths of a degree
+XMIDN = 900 # Angle of the 12 o'clock position
+XR, G, B = 0, 1, 2 # Indices of colors in RGB list
+X
+XHOUR = 3600 # Number of seconds per hour
+XMINUTE = 60 # Number of seconds per minute
+X
+Xclass struct(): pass # Class to define featureless structures
+XGl = struct() # Object to hold writable global variables
+X
+X# Default constants (used in multiple places)
+X
+XSCREENBG = 127, 156, 191
+XNPARTS = 9
+XTITLE = 'M Clock'
+XTZDIFF = -1*HOUR # <--- change this to reflect your local time zone
+X
+X# Default parameters
+X
+XGl.foreground = 0 # If set, run in the foreground
+XGl.fullscreen = 0 # If set, run on full screen
+XGl.tzdiff = TZDIFF # Seconds west of Greenwich (winter time)
+XGl.nparts = NPARTS # Number of parts each circle is divided in (>= 2)
+XGl.debug = 0 # If set, print debug output
+XGl.doublebuffer = 1 # If set, use double buffering
+XGl.update = 0 # Update interval; seconds hand is suppressed if > 1
+XGl.colorsubset = 0 # If set, display only a subset of the colors
+XGl.cyan = 0 # If set, display cyan overlay (big hand)
+XGl.magenta = 0 # If set, display magenta overlay (little hand)
+XGl.yellow = 0 # If set, display yellow overlay (fixed background)
+XGl.black = 0 # If set, display black overlay (hands)
+XGl.colormap = 0 # If set, use colormap mode instead of RGB mode
+XGl.warnings = 0 # If set, print warnings
+XGl.title = '- - ' # Window title (default set later)
+XGl.border = 1 # If set, use a window border (and title)
+XGl.bg = 0, 0, 0 # Background color R, G, B value
+XGl.iconic = 0 # Set in iconic state
+XGl.fg = 255, 0, 0 # Alarm background RGB (either normal or alarm)
+XGl.ox,Gl.oy = 0,0 # Window origin
+XGl.cx,Gl.cy = 0,0 # Window size
+XGl.alarm_set = 0 # Alarm on or off
+XGl.alarm_on = 0 # Alarm is ringing
+XGl.alarm_time = 0 # Alarm time in seconds after midnight
+XGl.alarm_hours = 0 # Alarm hour setting, 24 hour clock
+XGl.alarm_minutes = 0 # Alarm minutes setting
+XGl.alarm_rgb = 0,0,0 # Alarm display RGB colors
+XGl.alarm_cmd = '' # Command to execute when alarm goes off
+XGl.mouse2down = 0 # Mouse button state
+XGl.mouse3down = 0 # Mouse button state
+XGl.gong_cmd = '' # Command to execute when chimes go off
+XGl.gong_int = 3600 # Gong interval
+XGl.indices = R, G, B # Colors (permuted when alarm is on)
+X
+Xdef main():
+X #
+X sys.stdout = sys.stderr # All output is errors/warnings etc.
+X #
+X try:
+X args = getoptions()
+X except string.atoi_error, value:
+X usage(string.atoi_error, value)
+X except getopt.error, msg:
+X usage(getopt.error, msg)
+X #
+X if args:
+X realtime = 0
+X hours = string.atoi(args[0])
+X minutes = seconds = 0
+X if args[1:]: minutes = string.atoi(args[1])
+X if args[2:]: seconds = string.atoi(args[2])
+X localtime = ((hours*60)+minutes)*60+seconds
+X else:
+X realtime = 1
+X #
+X if Gl.title = '- - ':
+X if realtime:
+X Gl.title = TITLE
+X else:
+X title = ''
+X for arg in args: title = title + ' ' + arg
+X Gl.title = title[1:]
+X del title
+X #
+X wid = makewindow()
+X Gl.ox,Gl.oy = getorigin()
+X Gl.cx,Gl.cy = getsize()
+X initmenu()
+X clearall()
+X #
+X if not Gl.update:
+X Gl.update = 60
+X #
+X if Gl.update <= 1:
+X Gl.timernoise = 6
+X else:
+X Gl.timernoise = 60
+X noise(TIMER0, Gl.timernoise)
+X #
+X qdevice(WINSHUT)
+X qdevice(WINQUIT)
+X qdevice(ESCKEY)
+X if realtime:
+X qdevice(TIMER0)
+X qdevice(REDRAW)
+X qdevice(WINFREEZE)
+X qdevice(WINTHAW)
+X qdevice(MENUBUTTON) # MOUSE1
+X qdevice(MOUSE3) # Left button
+X qdevice(MOUSE2) # Middle button
+X unqdevice(INPUTCHANGE)
+X #
+X lasttime = 0
+X Gl.change = 1
+X while 1:
+X if realtime:
+X localtime = time.time() - Gl.tzdiff
+X if Gl.alarm_set:
+X if localtime%(24*HOUR) = Gl.alarm_time:
+X # Ring the alarm!
+X if Gl.debug:
+X print 'Rrrringg!'
+X Gl.alarm_on = 1
+X if Gl.alarm_cmd <> '':
+X d = posix.system(Gl.alarm_cmd+' '+`Gl.alarm_time/3600`+' '+`(Gl.alarm_time/60)%60` + ' &')
+X Gl.change = 1
+X clearall()
+X if Gl.alarm_on:
+X if (localtime - Gl.alarm_time) % (24*HOUR) > 300:
+X # More than 5 minutes away from alarm
+X Gl.alarm_on = 0
+X if Gl.debug:
+X print 'Alarm turned off'
+X Gl.change = 1
+X clearall()
+X Gl.indices = R, G, B
+X else:
+X if localtime % 2 = 0:
+X # Permute color indices
+X Gl.indices = Gl.indices[2:] + Gl.indices[:2]
+X Gl.change = 1
+X if Gl.gong_cmd <> '' and localtime%Gl.gong_int = 0:
+X d = posix.system(Gl.gong_cmd+' '+`(localtime/3600)%24`+' '+`(localtime/60)%60` + ' &')
+X if localtime/Gl.update <> lasttime/Gl.update:
+X if Gl.debug: print 'new time'
+X Gl.change = 1
+X if Gl.change:
+X if Gl.debug: print 'drawing'
+X doit(localtime)
+X lasttime = localtime
+X Gl.change = 0
+X dev, data = qread()
+X if Gl.debug and dev <> TIMER0:
+X print dev, data
+X if dev = TIMER0:
+X if Gl.debug > 1:
+X print dev, data
+X elif dev = MOUSE3:
+X mousex = getvaluator(MOUSEX)
+X mousey = getvaluator(MOUSEY)
+X if mouseclick(3, data, mousex, mousey):
+X Gl.change = 1
+X elif dev = MOUSE2:
+X mousex = getvaluator(MOUSEX)
+X mousey = getvaluator(MOUSEY)
+X if mouseclick(2, data, mousex, mousey):
+X Gl.change = 1
+X elif dev = MOUSEX:
+X mousex = data
+X if Gl.mouse2down:
+X mouse2track(mousex, mousey)
+X if Gl.mouse3down:
+X mouse3track(mousex, mousey)
+X elif dev = MOUSEY:
+X mousey = data
+X if Gl.mouse2down:
+X mouse2track(mousex, mousey)
+X if Gl.mouse3down:
+X mouse3track(mousex, mousey)
+X elif dev = REDRAW or dev = REDRAWICONIC:
+X if Gl.debug:
+X if dev = REDRAW: print 'REDRAW'
+X else: print 'REDRAWICONIC'
+X reshapeviewport()
+X Gl.ox,Gl.oy = getorigin()
+X Gl.cx,Gl.cy = getsize()
+X Gl.change = 1
+X clearall()
+X elif dev = MENUBUTTON:
+X if Gl.debug: print 'MENUBUTTON'
+X handlemenu()
+X elif dev = WINFREEZE:
+X if Gl.debug: print 'WINFREEZE'
+X Gl.iconic = 1
+X noise(TIMER0, 60*60) # Redraw every 60 seconds only
+X elif dev = WINTHAW:
+X if Gl.debug: print 'WINTHAW'
+X Gl.iconic = 0
+X noise(TIMER0, Gl.timernoise)
+X Gl.change = 1
+X elif dev = ESCKEY or dev = WINSHUT or dev = WINQUIT:
+X if Gl.debug: print 'Exit'
+X sys.exit(0)
+X
+Xdef getoptions():
+X optlist, args = getopt.getopt(sys.argv[1:], 'A:a:B:bc:dFfG:g:n:sT:t:u:wCMYK')
+X for optname, optarg in optlist:
+X if optname = '-A':
+X Gl.fg = eval(optarg) # Should be (r,g,b)
+X elif optname = '-a':
+X Gl.alarm_cmd = optarg
+X elif optname = '-B':
+X Gl.bg = eval(optarg) # Should be (r,g,b)
+X elif optname = '-b':
+X Gl.border = 0
+X elif optname = '-c':
+X Gl.colormap = string.atoi(optarg)
+X elif optname = '-d':
+X Gl.debug = Gl.debug + 1
+X Gl.warnings = 1
+X elif optname = '-F':
+X Gl.foreground = 1
+X elif optname = '-f':
+X Gl.fullscreen = 1
+X elif optname = '-G':
+X Gl.gong_int = 60*string.atoi(optarg)
+X elif optname = '-g':
+X Gl.gong_cmd = optarg
+X elif optname = '-n':
+X Gl.nparts = string.atoi(optarg)
+X elif optname = '-s':
+X Gl.doublebuffer = 0
+X elif optname = '-T':
+X Gl.title = optarg
+X elif optname = '-t':
+X Gl.tzdiff = string.atoi(optarg)
+X elif optname = '-u':
+X Gl.update = string.atoi(optarg)
+X elif optname = '-w':
+X Gl.warnings = 1
+X elif optname = '-C':
+X Gl.cyan = Gl.colorsubset = 1
+X elif optname = '-M':
+X Gl.magenta = Gl.colorsubset = 1
+X elif optname = '-Y':
+X Gl.yellow = Gl.colorsubset = 1
+X elif optname = '-K':
+X Gl.black = Gl.colorsubset = 1
+X else:
+X print 'Unsupported option', optname
+X return args
+X
+Xdef usage(exc, msg):
+X if sys.argv:
+X progname = path.basename(sys.argv[0])
+X else:
+X progname = 'mclock'
+X #
+X print progname + ':',
+X if exc = string.atoi_error:
+X print 'non-numeric argument:',
+X print msg
+X #
+X print 'usage:', progname, '[options] [hh [mm [ss]]]'
+X #
+X print '-A r,g,b : alarm background red,green,blue [255,0,0]'
+X print '-a cmd : shell command executed when alarm goes off'
+X print '-B r,g,b : background red,green,blue [0,0,0]'
+X print ' (-B SCREENBG uses the default screen background)'
+X print '-b : suppress window border and title'
+X print '-c cmapid : select explicit colormap'
+X print '-d : more debug output (implies -F, -w)'
+X print '-F : run in foreground'
+X print '-f : use full screen'
+X print '-G intrvl : interval between chimes in minutes [60]'
+X print '-g cmd : shell command executed when chimes go off'
+X print '-s : single buffer mode'
+X print '-w : print various warnings'
+X print '-n nparts : number of parts [' + `NPARTS` + ']'
+X print '-T title : alternate window title [\'' + TITLE + '\']'
+X print '-t tzdiff : time zone difference [' + `TZDIFF` + ']'
+X print '-u update : update interval [60]'
+X print '-CMYK : Cyan, Magenta, Yellow or blacK overlay only'
+X print 'if hh [mm [ss]] is specified, display that time statically'
+X print 'on machines with < 12 bitplanes, -c and -s are forced on'
+X #
+X sys.exit(2)
+X
+Xdef doit(localtime):
+X hands = makehands(localtime)
+X list = makelist(hands)
+X render(list, hands)
+X
+Xdef makehands(localtime):
+X localtime = localtime % (12*HOUR)
+X seconds_hand = MIDN + FULLC - (localtime*60) % FULLC
+X big_hand = (MIDN + FULLC - (localtime%HOUR)) % FULLC
+X little_hand = (MIDN + FULLC - ((localtime/12) % HOUR)) % FULLC
+X return little_hand, big_hand, seconds_hand
+X
+Xdef makelist(little_hand, big_hand, seconds_hand):
+X total = []
+X if Gl.cyan or not Gl.colorsubset:
+X total = total + makesublist(big_hand, Gl.indices[0])
+X if Gl.magenta or not Gl.colorsubset:
+X total = total + makesublist(little_hand, Gl.indices[1])
+X if Gl.yellow or not Gl.colorsubset:
+X total = total + makesublist(MIDN, Gl.indices[2])
+X total.sort()
+X return total
+X
+Xdef makesublist(first, icolor):
+X list = []
+X alpha = FULLC/Gl.nparts
+X a = first - alpha/2
+X for i in range(Gl.nparts):
+X angle = (a + i*alpha + FULLC) % FULLC
+X value = 255*(Gl.nparts-1-i)/(Gl.nparts-1)
+X list.append(angle, icolor, value)
+X list.sort()
+X a, icolor, value = list[0]
+X if a <> 0:
+X a, icolor, value = list[len(list)-1]
+X t = 0, icolor, value
+X list.insert(0, t)
+X return list
+X
+Xdef rgb_fg():
+X return Gl.fg
+X # Obsolete code:
+X if Gl.alarm_on:
+X return Gl.bg
+X else:
+X return Gl.fg
+X
+Xdef rgb_bg():
+X return Gl.bg
+X # Obsolete code:
+X if Gl.alarm_on:
+X return Gl.fg
+X else:
+X return Gl.bg
+X
+Xdef clearall():
+X Gl.c3i(rgb_bg())
+X clear()
+X if Gl.doublebuffer:
+X swapbuffers()
+X clear()
+X
+Xdef draw_alarm(color):
+X frontbuffer(TRUE)
+X Gl.c3i(color)
+X pushmatrix()
+X rotate(-((Gl.alarm_time/12)%3600), 'z')
+X bgnpolygon()
+X v2f( 0.00,1.00)
+X v2f( 0.04,1.05)
+X v2f(-0.04,1.05)
+X endpolygon()
+X popmatrix()
+X #
+X pushmatrix()
+X rotate(-((Gl.alarm_time)%3600), 'z')
+X bgnpolygon()
+X v2f( 0.00,1.05)
+X v2f( 0.07,1.10)
+X v2f(-0.07,1.10)
+X endpolygon()
+X popmatrix()
+X #
+X cmov2(-1.06, -1.06)
+X charstr(string.rjust(`Gl.alarm_time/3600`,2))
+X charstr(':')
+X charstr(string.zfill((Gl.alarm_time/60)%60,2))
+X frontbuffer(FALSE)
+X
+Xdef render(list, (little_hand, big_hand, seconds_hand)):
+X #
+X if Gl.colormap:
+X resetindex()
+X #
+X if not list:
+X Gl.c3i(255, 255, 255) # White
+X circf(0.0, 0.0, 1.0)
+X else:
+X list.append(3600, 0, 255) # Sentinel
+X #
+X rgb = [255, 255, 255]
+X a_prev = 0
+X for a, icolor, value in list:
+X if a <> a_prev:
+X [r, g, b] = rgb
+X if Gl.debug > 1:
+X print rgb, a_prev, a
+X Gl.c3i(r, g, b)
+X arcf(0.0, 0.0, 1.0, a_prev, a)
+X rgb[icolor] = value
+X a_prev = a
+X #
+X if Gl.black or not Gl.colorsubset:
+X #
+X # Draw the hands -- in black
+X #
+X Gl.c3i(0, 0, 0)
+X #
+X if Gl.update = 1 and not Gl.iconic:
+X # Seconds hand is only drawn if we update every second
+X pushmatrix()
+X rotate(seconds_hand, 'z')
+X bgnline()
+X v2f(0.0, 0.0)
+X v2f(1.0, 0.0)
+X endline()
+X popmatrix()
+X #
+X pushmatrix()
+X rotate(big_hand, 'z')
+X rectf(0.0, -0.01, 0.97, 0.01)
+X circf(0.0, 0.0, 0.01)
+X circf(0.97, 0.0, 0.01)
+X popmatrix()
+X #
+X pushmatrix()
+X rotate(little_hand, 'z')
+X rectf(0.04, -0.02, 0.63, 0.02)
+X circf(0.04, 0.0, 0.02)
+X circf(0.63, 0.0, 0.02)
+X popmatrix()
+X #
+X # Draw the alarm time, if set or being set
+X #
+X if Gl.alarm_set:
+X draw_alarm(rgb_fg())
+X #
+X if Gl.doublebuffer: swapbuffers()
+X
+Xdef makewindow():
+X #
+X if Gl.debug or Gl.foreground:
+X foreground()
+X #
+X if Gl.fullscreen:
+X # XXX Should find out true screen size using getgdesc()
+X prefposition(0, 1279, 0, 1023)
+X else:
+X keepaspect(1, 1)
+X minsize(64, 64)
+X #
+X if not Gl.border:
+X noborder()
+X wid = winopen(Gl.title)
+X #
+X if not Gl.fullscreen:
+X keepaspect(1, 1)
+X minsize(10, 10)
+X maxsize(2000, 2000)
+X iconsize(66, 66)
+X winconstraints()
+X #
+X nplanes = getplanes()
+X nmaps = getgdesc(GD_NMMAPS)
+X if Gl.warnings:
+X print nplanes, 'color planes,', nmaps, 'color maps'
+X #
+X if nplanes < 12 or Gl.colormap:
+X if not Gl.colormap:
+X Gl.colormap = nmaps - 1
+X if Gl.warnings:
+X print 'not enough color planes available',
+X print 'for RGB mode; forcing colormap mode'
+X print 'using color map number', Gl.colormap
+X if not Gl.colorsubset:
+X needed = 3
+X else:
+X needed = Gl.cyan + Gl.magenta + Gl.yellow
+X needed = needed*Gl.nparts
+X if Gl.bg <> (0, 0, 0):
+X needed = needed+1
+X if Gl.fg <> (0, 0, 0):
+X needed = needed+1
+X if Gl.doublebuffer:
+X if needed > available(nplanes/2):
+X Gl.doublebuffer = 0
+X if Gl.warnings:
+X print 'not enough colors available',
+X print 'for double buffer mode;',
+X print 'forcing single buffer mode'
+X else:
+X nplanes = nplanes/2
+X if needed > available(nplanes):
+X # Do this warning always
+X print 'still not enough colors available;',
+X print 'parts will be left white'
+X print '(needed', needed, 'but have only',
+X print available(nplanes), 'colors available)'
+X #
+X if Gl.doublebuffer:
+X doublebuffer()
+X gconfig()
+X #
+X if Gl.colormap:
+X Gl.c3i = pseudo_c3i
+X fixcolormap()
+X else:
+X Gl.c3i = c3i
+X RGBmode()
+X gconfig()
+X #
+X if Gl.fullscreen:
+X # XXX Should find out true screen size using getgdesc()
+X ortho2(-1.1*1.280, 1.1*1.280, -1.1*1.024, 1.1*1.024)
+X else:
+X ortho2(-1.1, 1.1, -1.1, 1.1)
+X #
+X return wid
+X
+Xdef available(nplanes):
+X return pow(2, nplanes) - 1 # Reserve one pixel for black
+X
+Xdef fixcolormap():
+X multimap()
+X gconfig()
+X nplanes = getplanes()
+X if Gl.warnings:
+X print 'multimap mode has', nplanes, 'color planes'
+X imap = Gl.colormap
+X Gl.startindex = pow(2, nplanes) - 1
+X Gl.stopindex = 1
+X setmap(imap)
+X mapcolor(0, 0, 0, 0) # Fixed entry for black
+X if Gl.bg <> (0, 0, 0):
+X r, g, b = Gl.bg
+X mapcolor(1, r, g, b) # Fixed entry for Gl.bg
+X Gl.stopindex = 2
+X if Gl.fg <> (0, 0, 0):
+X r, g, b = Gl.fg
+X mapcolor(2, r, g, b) # Fixed entry for Gl.fg
+X Gl.stopindex = 3
+X Gl.overflow_seen = 0
+X resetindex()
+X
+Xdef resetindex():
+X Gl.index = Gl.startindex
+X
+Xr0g0b0 = (0, 0, 0)
+X
+Xdef pseudo_c3i(rgb):
+X if rgb = r0g0b0:
+X index = 0
+X elif rgb = Gl.bg:
+X index = 1
+X elif rgb = Gl.fg:
+X index = 2
+X else:
+X index = definecolor(rgb)
+X color(index)
+X
+Xdef definecolor(rgb):
+X index = Gl.index
+X if index < Gl.stopindex:
+X if Gl.debug: print 'definecolor hard case', rgb
+X # First see if we already have this one...
+X for index in range(Gl.stopindex, Gl.startindex+1):
+X if rgb = getmcolor(index):
+X if Gl.debug: print 'return', index
+X return index
+X # Don't clobber reserverd colormap entries
+X if not Gl.overflow_seen:
+X # Shouldn't happen any more, hence no Gl.warnings test
+X print 'mclock: out of colormap entries'
+X Gl.overflow_seen = 1
+X return Gl.stopindex
+X r, g, b = rgb
+X if Gl.debug > 1: print 'mapcolor', (index, r, g, b)
+X mapcolor(index, r, g, b)
+X Gl.index = index - 1
+X return index
+X
+X# Compute n**i
+Xdef pow(n, i):
+X x = 1
+X for j in range(i): x = x*n
+X return x
+X
+Xdef mouseclick(mouse, updown, x, y):
+X if updown = 1:
+X # mouse button came down, start tracking
+X if Gl.debug:
+X print 'mouse', mouse, 'down at', x, y
+X if mouse = 2:
+X Gl.mouse2down = 1
+X mouse2track(x, y)
+X elif mouse = 3:
+X Gl.mouse3down = 1
+X mouse3track(x, y)
+X else:
+X print 'fatal error'
+X qdevice(MOUSEX)
+X qdevice(MOUSEY)
+X return 0
+X else:
+X # mouse button came up, stop tracking
+X if Gl.debug:
+X print 'mouse', mouse, 'up at', x, y
+X unqdevice(MOUSEX)
+X unqdevice(MOUSEY)
+X if mouse = 2:
+X mouse2track(x, y)
+X Gl.mouse2down = 0
+X elif mouse = 3:
+X mouse3track(x, y)
+X Gl.mouse3down = 0
+X else:
+X print 'fatal error'
+X Gl.alarm_set = 1
+X return 1
+X
+Xdef mouse3track(x, y):
+X # first compute polar coordinates from x and y
+X cx, cy = Gl.ox + Gl.cx/2, Gl.oy + Gl.cy/2
+X x, y = x - cx, y - cy
+X if (x, y) = (0, 0): return # would cause an exception
+X minutes = int(30.5 + 30.0*math.atan2(float(-x), float(-y))/pi)
+X if minutes = 60: minutes = 0
+X a,b = Gl.alarm_minutes/15, minutes/15
+X if (a,b) = (0,3):
+X # Moved backward through 12 o'clock:
+X Gl.alarm_hours = Gl.alarm_hours - 1
+X if Gl.alarm_hours < 0: Gl.alarm_hours = Gl.alarm_hours + 24
+X if (a,b) = (3,0):
+X # Moved forward through 12 o'clock:
+X Gl.alarm_hours = Gl.alarm_hours + 1
+X if Gl.alarm_hours >= 24: Gl.alarm_hours = Gl.alarm_hours - 24
+X Gl.alarm_minutes = minutes
+X seconds = Gl.alarm_hours * HOUR + Gl.alarm_minutes * MINUTE
+X if seconds <> Gl.alarm_time:
+X draw_alarm(rgb_bg())
+X Gl.alarm_time = seconds
+X draw_alarm(rgb_fg())
+X
+Xdef mouse2track(x, y):
+X # first compute polar coordinates from x and y
+X cx, cy = Gl.ox + Gl.cx/2, Gl.oy + Gl.cy/2
+X x, y = x - cx, y - cy
+X if (x, y) = (0, 0): return # would cause an exception
+X hours = int(6.5 - float(Gl.alarm_minutes)/60.0 + 6.0*math.atan2(float(-x), float(-y))/pi)
+X if hours = 12: hours = 0
+X if (Gl.alarm_hours,hours) = (0,11):
+X # Moved backward through midnight:
+X Gl.alarm_hours = 23
+X elif (Gl.alarm_hours,hours) = (12,11):
+X # Moved backward through noon:
+X Gl.alarm_hours = 11
+X elif (Gl.alarm_hours,hours) = (11,0):
+X # Moved forward through noon:
+X Gl.alarm_hours = 12
+X elif (Gl.alarm_hours,hours) = (23,0):
+X # Moved forward through midnight:
+X Gl.alarm_hours = 0
+X elif Gl.alarm_hours < 12:
+X Gl.alarm_hours = hours
+X else:
+X Gl.alarm_hours = hours + 12
+X seconds = Gl.alarm_hours * HOUR + Gl.alarm_minutes * MINUTE
+X if seconds <> Gl.alarm_time:
+X draw_alarm(rgb_bg())
+X Gl.alarm_time = seconds
+X draw_alarm(rgb_fg())
+X
+Xdef initmenu():
+X Gl.pup = pup = newpup()
+X addtopup(pup, 'M Clock%t|Alarm On/Off|Seconds Hand On/Off|Quit', 0)
+X
+Xdef handlemenu():
+X item = dopup(Gl.pup)
+X if item = 1:
+X # Toggle alarm
+X if Gl.alarm_set:
+X Gl.alarm_set = 0
+X Gl.alarm_on = 0
+X else:
+X Gl.alarm_set = 1
+X Gl.change = 1
+X clearall()
+X elif item = 2:
+X # Toggle Seconds Hand
+X if Gl.update = 1:
+X Gl.update = 60
+X Gl.timernoise = 60
+X else:
+X Gl.update = 1
+X Gl.timernoise = 6
+X Gl.change = 1
+X elif item = 3:
+X if Gl.debug: print 'Exit'
+X sys.exit(0)
+X
+Xmain()
+EOF
+chmod +x 'demo/sgi/gl/mclock.py'
+fi
+if test -s 'src/ceval.c'
+then echo '*** I will not over-write existing file src/ceval.c'
+else
+echo 'x - src/ceval.c'
+sed 's/^X//' > 'src/ceval.c' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/* Execute compiled code */
+X
+X#include "allobjects.h"
+X
+X#include "import.h"
+X#include "sysmodule.h"
+X#include "compile.h"
+X#include "frameobject.h"
+X#include "ceval.h"
+X#include "opcode.h"
+X#include "bltinmodule.h"
+X#include "traceback.h"
+X
+X#ifndef NDEBUG
+X#define TRACE
+X#endif
+X
+X#ifdef TRACE
+Xstatic int
+Xprtrace(v, str)
+X object *v;
+X char *str;
+X{
+X printf("%s ", str);
+X printobject(v, stdout, 0);
+X printf("\n");
+X}
+X#endif
+X
+Xstatic frameobject *current_frame;
+X
+Xobject *
+Xgetlocals()
+X{
+X if (current_frame == NULL)
+X return NULL;
+X else
+X return current_frame->f_locals;
+X}
+X
+Xobject *
+Xgetglobals()
+X{
+X if (current_frame == NULL)
+X return NULL;
+X else
+X return current_frame->f_globals;
+X}
+X
+Xvoid
+Xprinttraceback(fp)
+X FILE *fp;
+X{
+X object *v = tb_fetch();
+X if (v != NULL) {
+X fprintf(fp, "Stack backtrace (innermost last):\n");
+X tb_print(v, fp);
+X DECREF(v);
+X }
+X}
+X
+X
+X/* XXX Mixing "print ...," and direct file I/O on stdin/stdout
+X XXX has some bad consequences. The needspace flag should
+X XXX really be part of the file object. */
+X
+Xstatic int needspace;
+X
+Xvoid
+Xflushline()
+X{
+X FILE *fp = sysgetfile("stdout", stdout);
+X if (needspace) {
+X fprintf(fp, "\n");
+X needspace = 0;
+X }
+X}
+X
+X
+X/* Test a value used as condition, e.g., in a for or if statement */
+X
+Xstatic int
+Xtestbool(v)
+X object *v;
+X{
+X if (is_intobject(v))
+X return getintvalue(v) != 0;
+X if (is_floatobject(v))
+X return getfloatvalue(v) != 0.0;
+X if (v->ob_type->tp_as_sequence != NULL)
+X return (*v->ob_type->tp_as_sequence->sq_length)(v) != 0;
+X if (v->ob_type->tp_as_mapping != NULL)
+X return (*v->ob_type->tp_as_mapping->mp_length)(v) != 0;
+X if (v == None)
+X return 0;
+X /* All other objects are 'true' */
+X return 1;
+X}
+X
+Xstatic object *
+Xadd(v, w)
+X object *v, *w;
+X{
+X if (v->ob_type->tp_as_number != NULL)
+X v = (*v->ob_type->tp_as_number->nb_add)(v, w);
+X else if (v->ob_type->tp_as_sequence != NULL)
+X v = (*v->ob_type->tp_as_sequence->sq_concat)(v, w);
+X else {
+X err_setstr(TypeError, "+ not supported by operands");
+X return NULL;
+X }
+X return v;
+X}
+X
+Xstatic object *
+Xsub(v, w)
+X object *v, *w;
+X{
+X if (v->ob_type->tp_as_number != NULL)
+X return (*v->ob_type->tp_as_number->nb_subtract)(v, w);
+X err_setstr(TypeError, "bad operand type(s) for -");
+X return NULL;
+X}
+X
+Xstatic object *
+Xmul(v, w)
+X object *v, *w;
+X{
+X typeobject *tp;
+X if (is_intobject(v) && w->ob_type->tp_as_sequence != NULL) {
+X /* int*sequence -- swap v and w */
+X object *tmp = v;
+X v = w;
+X w = tmp;
+X }
+X tp = v->ob_type;
+X if (tp->tp_as_number != NULL)
+X return (*tp->tp_as_number->nb_multiply)(v, w);
+X if (tp->tp_as_sequence != NULL) {
+X if (!is_intobject(w)) {
+X err_setstr(TypeError,
+X "can't multiply sequence with non-int");
+X return NULL;
+X }
+X if (tp->tp_as_sequence->sq_repeat == NULL) {
+X err_setstr(TypeError, "sequence does not support *");
+X return NULL;
+X }
+X return (*tp->tp_as_sequence->sq_repeat)
+X (v, (int)getintvalue(w));
+X }
+X err_setstr(TypeError, "bad operand type(s) for *");
+X return NULL;
+X}
+X
+Xstatic object *
+Xdivide(v, w)
+X object *v, *w;
+X{
+X if (v->ob_type->tp_as_number != NULL)
+X return (*v->ob_type->tp_as_number->nb_divide)(v, w);
+X err_setstr(TypeError, "bad operand type(s) for /");
+X return NULL;
+X}
+X
+Xstatic object *
+Xrem(v, w)
+X object *v, *w;
+X{
+X if (v->ob_type->tp_as_number != NULL)
+X return (*v->ob_type->tp_as_number->nb_remainder)(v, w);
+X err_setstr(TypeError, "bad operand type(s) for %");
+X return NULL;
+X}
+X
+Xstatic object *
+Xneg(v)
+X object *v;
+X{
+X if (v->ob_type->tp_as_number != NULL)
+X return (*v->ob_type->tp_as_number->nb_negative)(v);
+X err_setstr(TypeError, "bad operand type(s) for unary -");
+X return NULL;
+X}
+X
+Xstatic object *
+Xpos(v)
+X object *v;
+X{
+X if (v->ob_type->tp_as_number != NULL)
+X return (*v->ob_type->tp_as_number->nb_positive)(v);
+X err_setstr(TypeError, "bad operand type(s) for unary +");
+X return NULL;
+X}
+X
+Xstatic object *
+Xnot(v)
+X object *v;
+X{
+X int outcome = testbool(v);
+X object *w = outcome == 0 ? True : False;
+X INCREF(w);
+X return w;
+X}
+X
+Xstatic object *
+Xcall_builtin(func, arg)
+X object *func;
+X object *arg;
+X{
+X if (is_methodobject(func)) {
+X method meth = getmethod(func);
+X object *self = getself(func);
+X return (*meth)(self, arg);
+X }
+X if (is_classobject(func)) {
+X if (arg != NULL) {
+X err_setstr(TypeError,
+X "classobject() allows no arguments");
+X return NULL;
+X }
+X return newclassmemberobject(func);
+X }
+X err_setstr(TypeError, "call of non-function");
+X return NULL;
+X}
+X
+Xstatic object *
+Xcall_function(func, arg)
+X object *func;
+X object *arg;
+X{
+X object *newarg = NULL;
+X object *newlocals, *newglobals;
+X object *co, *v;
+X
+X if (is_classmethodobject(func)) {
+X object *self = classmethodgetself(func);
+X func = classmethodgetfunc(func);
+X if (arg == NULL) {
+X arg = self;
+X }
+X else {
+X newarg = newtupleobject(2);
+X if (newarg == NULL)
+X return NULL;
+X INCREF(self);
+X INCREF(arg);
+X settupleitem(newarg, 0, self);
+X settupleitem(newarg, 1, arg);
+X arg = newarg;
+X }
+X }
+X else {
+X if (!is_funcobject(func)) {
+X err_setstr(TypeError, "call of non-function");
+X return NULL;
+X }
+X }
+X
+X co = getfunccode(func);
+X if (co == NULL) {
+X XDECREF(newarg);
+X return NULL;
+X }
+X if (!is_codeobject(co)) {
+X fprintf(stderr, "XXX Bad code\n");
+X abort();
+X }
+X newlocals = newdictobject();
+X if (newlocals == NULL) {
+X XDECREF(newarg);
+X return NULL;
+X }
+X
+X newglobals = getfuncglobals(func);
+X INCREF(newglobals);
+X
+X v = eval_code((codeobject *)co, newglobals, newlocals, arg);
+X
+X DECREF(newlocals);
+X DECREF(newglobals);
+X
+X XDECREF(newarg);
+X
+X return v;
+X}
+X
+Xstatic object *
+Xapply_subscript(v, w)
+X object *v, *w;
+X{
+X typeobject *tp = v->ob_type;
+X if (tp->tp_as_sequence == NULL && tp->tp_as_mapping == NULL) {
+X err_setstr(TypeError, "unsubscriptable object");
+X return NULL;
+X }
+X if (tp->tp_as_sequence != NULL) {
+X int i;
+X if (!is_intobject(w)) {
+X err_setstr(TypeError, "sequence subscript not int");
+X return NULL;
+X }
+X i = getintvalue(w);
+X return (*tp->tp_as_sequence->sq_item)(v, i);
+X }
+X return (*tp->tp_as_mapping->mp_subscript)(v, w);
+X}
+X
+Xstatic object *
+Xloop_subscript(v, w)
+X object *v, *w;
+X{
+X sequence_methods *sq = v->ob_type->tp_as_sequence;
+X int i, n;
+X if (sq == NULL) {
+X err_setstr(TypeError, "loop over non-sequence");
+X return NULL;
+X }
+X i = getintvalue(w);
+X n = (*sq->sq_length)(v);
+X if (i >= n)
+X return NULL; /* End of loop */
+X return (*sq->sq_item)(v, i);
+X}
+X
+Xstatic int
+Xslice_index(v, isize, pi)
+X object *v;
+X int isize;
+X int *pi;
+X{
+X if (v != NULL) {
+X if (!is_intobject(v)) {
+X err_setstr(TypeError, "slice index must be int");
+X return -1;
+X }
+X *pi = getintvalue(v);
+X if (*pi < 0)
+X *pi += isize;
+X }
+X return 0;
+X}
+X
+Xstatic object *
+Xapply_slice(u, v, w) /* return u[v:w] */
+X object *u, *v, *w;
+X{
+X typeobject *tp = u->ob_type;
+X int ilow, ihigh, isize;
+X if (tp->tp_as_sequence == NULL) {
+X err_setstr(TypeError, "only sequences can be sliced");
+X return NULL;
+X }
+X ilow = 0;
+X isize = ihigh = (*tp->tp_as_sequence->sq_length)(u);
+X if (slice_index(v, isize, &ilow) != 0)
+X return NULL;
+X if (slice_index(w, isize, &ihigh) != 0)
+X return NULL;
+X return (*tp->tp_as_sequence->sq_slice)(u, ilow, ihigh);
+X}
+X
+Xstatic int
+Xassign_subscript(w, key, v) /* w[key] = v */
+X object *w;
+X object *key;
+X object *v;
+X{
+X typeobject *tp = w->ob_type;
+X sequence_methods *sq;
+X mapping_methods *mp;
+X int (*func)();
+X if ((sq = tp->tp_as_sequence) != NULL &&
+X (func = sq->sq_ass_item) != NULL) {
+X if (!is_intobject(key)) {
+X err_setstr(TypeError,
+X "sequence subscript must be integer");
+X return -1;
+X }
+X else
+X return (*func)(w, (int)getintvalue(key), v);
+X }
+X else if ((mp = tp->tp_as_mapping) != NULL &&
+X (func = mp->mp_ass_subscript) != NULL) {
+X return (*func)(w, key, v);
+X }
+X else {
+X err_setstr(TypeError,
+X "can't assign to this subscripted object");
+X return -1;
+X }
+X}
+X
+Xstatic int
+Xassign_slice(u, v, w, x) /* u[v:w] = x */
+X object *u, *v, *w, *x;
+X{
+X sequence_methods *sq = u->ob_type->tp_as_sequence;
+X int ilow, ihigh, isize;
+X if (sq == NULL) {
+X err_setstr(TypeError, "assign to slice of non-sequence");
+X return -1;
+X }
+X if (sq == NULL || sq->sq_ass_slice == NULL) {
+X err_setstr(TypeError, "unassignable slice");
+X return -1;
+X }
+X ilow = 0;
+X isize = ihigh = (*sq->sq_length)(u);
+X if (slice_index(v, isize, &ilow) != 0)
+X return -1;
+X if (slice_index(w, isize, &ihigh) != 0)
+X return -1;
+X return (*sq->sq_ass_slice)(u, ilow, ihigh, x);
+X}
+X
+Xstatic int
+Xcmp_exception(err, v)
+X object *err, *v;
+X{
+X if (is_tupleobject(v)) {
+X int i, n;
+X n = gettuplesize(v);
+X for (i = 0; i < n; i++) {
+X if (err == gettupleitem(v, i))
+X return 1;
+X }
+X return 0;
+X }
+X return err == v;
+X}
+X
+Xstatic int
+Xcmp_member(v, w)
+X object *v, *w;
+X{
+X int i, n, cmp;
+X object *x;
+X sequence_methods *sq;
+X /* Special case for char in string */
+X if (is_stringobject(w)) {
+X register char *s, *end;
+X register char c;
+X if (!is_stringobject(v) || getstringsize(v) != 1) {
+X err_setstr(TypeError,
+X "string member test needs char left operand");
+X return -1;
+X }
+X c = getstringvalue(v)[0];
+X s = getstringvalue(w);
+X end = s + getstringsize(w);
+X while (s < end) {
+X if (c == *s++)
+X return 1;
+X }
+X return 0;
+X }
+X sq = w->ob_type->tp_as_sequence;
+X if (sq == NULL) {
+X err_setstr(TypeError,
+X "'in' or 'not in' needs sequence right argument");
+X return -1;
+X }
+X n = (*sq->sq_length)(w);
+X for (i = 0; i < n; i++) {
+X x = (*sq->sq_item)(w, i);
+X cmp = cmpobject(v, x);
+X XDECREF(x);
+X if (cmp == 0)
+X return 1;
+X }
+X return 0;
+X}
+X
+Xstatic object *
+Xcmp_outcome(op, v, w)
+X enum cmp_op op;
+X register object *v;
+X register object *w;
+X{
+X register int cmp;
+X register int res = 0;
+X switch (op) {
+X case IS:
+X case IS_NOT:
+X res = (v == w);
+X if (op == IS_NOT)
+X res = !res;
+X break;
+X case IN:
+X case NOT_IN:
+X res = cmp_member(v, w);
+X if (res < 0)
+X return NULL;
+X if (op == NOT_IN)
+X res = !res;
+X break;
+X case EXC_MATCH:
+X res = cmp_exception(v, w);
+X break;
+X default:
+X cmp = cmpobject(v, w);
+X switch (op) {
+X case LT: res = cmp < 0; break;
+X case LE: res = cmp <= 0; break;
+X case EQ: res = cmp == 0; break;
+X case NE: res = cmp != 0; break;
+X case GT: res = cmp > 0; break;
+X case GE: res = cmp >= 0; break;
+X /* XXX no default? (res is initialized to 0 though) */
+X }
+X }
+X v = res ? True : False;
+X INCREF(v);
+X return v;
+X}
+X
+Xstatic int
+Ximport_from(locals, v, name)
+X object *locals;
+X object *v;
+X char *name;
+X{
+X object *w, *x;
+X w = getmoduledict(v);
+X if (name[0] == '*') {
+X int i;
+X int n = getdictsize(w);
+X for (i = 0; i < n; i++) {
+X name = getdictkey(w, i);
+X if (name == NULL || name[0] == '_')
+X continue;
+X x = dictlookup(w, name);
+X if (x == NULL) {
+X /* XXX can't happen? */
+X err_setstr(NameError, name);
+X return -1;
+X }
+X if (dictinsert(locals, name, x) != 0)
+X return -1;
+X }
+X return 0;
+X }
+X else {
+X x = dictlookup(w, name);
+X if (x == NULL) {
+X err_setstr(NameError, name);
+X return -1;
+X }
+X else
+X return dictinsert(locals, name, x);
+X }
+X}
+X
+Xstatic object *
+Xbuild_class(v, w)
+X object *v; /* None or tuple containing base classes */
+X object *w; /* dictionary */
+X{
+X if (is_tupleobject(v)) {
+X int i;
+X for (i = gettuplesize(v); --i >= 0; ) {
+X object *x = gettupleitem(v, i);
+X if (!is_classobject(x)) {
+X err_setstr(TypeError,
+X "base is not a class object");
+X return NULL;
+X }
+X }
+X }
+X else {
+X v = NULL;
+X }
+X if (!is_dictobject(w)) {
+X err_setstr(SystemError, "build_class with non-dictionary");
+X return NULL;
+X }
+X return newclassobject(v, w);
+X}
+X
+X
+X/* Status code for main loop (reason for stack unwind) */
+X
+Xenum why_code {
+X WHY_NOT, /* No error */
+X WHY_EXCEPTION, /* Exception occurred */
+X WHY_RERAISE, /* Exception re-raised by 'finally' */
+X WHY_RETURN, /* 'return' statement */
+X WHY_BREAK /* 'break' statement */
+X};
+X
+X/* Interpreter main loop */
+X
+Xobject *
+Xeval_code(co, globals, locals, arg)
+X codeobject *co;
+X object *globals;
+X object *locals;
+X object *arg;
+X{
+X register unsigned char *next_instr;
+X register int opcode; /* Current opcode */
+X register int oparg; /* Current opcode argument, if any */
+X register object **stack_pointer;
+X register enum why_code why; /* Reason for block stack unwind */
+X register int err; /* Error status -- nonzero if error */
+X register object *x; /* Result object -- NULL if error */
+X register object *v; /* Temporary objects popped off stack */
+X register object *w;
+X register object *u;
+X register object *t;
+X register frameobject *f; /* Current frame */
+X int lineno; /* Current line number */
+X object *retval; /* Return value iff why == WHY_RETURN */
+X char *name; /* Name used by some instructions */
+X FILE *fp; /* Used by print operations */
+X#ifdef TRACE
+X int trace = dictlookup(globals, "__trace__") != NULL;
+X#endif
+X
+X/* Code access macros */
+X
+X#define GETCONST(i) Getconst(f, i)
+X#define GETNAME(i) Getname(f, i)
+X#define FIRST_INSTR() (GETUSTRINGVALUE(f->f_code->co_code))
+X#define INSTR_OFFSET() (next_instr - FIRST_INSTR())
+X#define NEXTOP() (*next_instr++)
+X#define NEXTARG() (next_instr += 2, (next_instr[-1]<<8) + next_instr[-2])
+X#define JUMPTO(x) (next_instr = FIRST_INSTR() + (x))
+X#define JUMPBY(x) (next_instr += (x))
+X
+X/* Stack manipulation macros */
+X
+X#define STACK_LEVEL() (stack_pointer - f->f_valuestack)
+X#define EMPTY() (STACK_LEVEL() == 0)
+X#define TOP() (stack_pointer[-1])
+X#define BASIC_PUSH(v) (*stack_pointer++ = (v))
+X#define BASIC_POP() (*--stack_pointer)
+X
+X#ifdef TRACE
+X#define PUSH(v) (BASIC_PUSH(v), trace && prtrace(TOP(), "push"))
+X#define POP() (trace && prtrace(TOP(), "pop"), BASIC_POP())
+X#else
+X#define PUSH(v) BASIC_PUSH(v)
+X#define POP() BASIC_POP()
+X#endif
+X
+X f = newframeobject(
+X current_frame, /*back*/
+X co, /*code*/
+X globals, /*globals*/
+X locals, /*locals*/
+X 50, /*nvalues*/
+X 20); /*nblocks*/
+X if (f == NULL)
+X return NULL;
+X
+X current_frame = f;
+X
+X next_instr = GETUSTRINGVALUE(f->f_code->co_code);
+X
+X stack_pointer = f->f_valuestack;
+X
+X if (arg != NULL) {
+X INCREF(arg);
+X PUSH(arg);
+X }
+X
+X why = WHY_NOT;
+X err = 0;
+X x = None; /* Not a reference, just anything non-NULL */
+X lineno = -1;
+X
+X for (;;) {
+X static ticker;
+X
+X /* Do periodic things */
+X
+X if (--ticker < 0) {
+X ticker = 100;
+X if (intrcheck()) {
+X err_set(KeyboardInterrupt);
+X why = WHY_EXCEPTION;
+X tb_here(f, INSTR_OFFSET(), lineno);
+X break;
+X }
+X }
+X
+X /* Extract opcode and argument */
+X
+X opcode = NEXTOP();
+X if (HAS_ARG(opcode))
+X oparg = NEXTARG();
+X
+X#ifdef TRACE
+X /* Instruction tracing */
+X
+X if (trace) {
+X if (HAS_ARG(opcode)) {
+X printf("%d: %d, %d\n",
+X (int) (INSTR_OFFSET() - 3),
+X opcode, oparg);
+X }
+X else {
+X printf("%d: %d\n",
+X (int) (INSTR_OFFSET() - 1), opcode);
+X }
+X }
+X#endif
+X
+X /* Main switch on opcode */
+X
+X switch (opcode) {
+X
+X /* BEWARE!
+X It is essential that any operation that fails sets either
+X x to NULL, err to nonzero, or why to anything but WHY_NOT,
+X and that no operation that succeeds does this! */
+X
+X /* case STOP_CODE: this is an error! */
+X
+X case POP_TOP:
+X v = POP();
+X DECREF(v);
+X break;
+X
+X case ROT_TWO:
+X v = POP();
+X w = POP();
+X PUSH(v);
+X PUSH(w);
+X break;
+X
+X case ROT_THREE:
+X v = POP();
+X w = POP();
+X x = POP();
+X PUSH(v);
+X PUSH(x);
+X PUSH(w);
+X break;
+X
+X case DUP_TOP:
+X v = TOP();
+X INCREF(v);
+X PUSH(v);
+X break;
+X
+X case UNARY_POSITIVE:
+X v = POP();
+X x = pos(v);
+X DECREF(v);
+X PUSH(x);
+X break;
+X
+X case UNARY_NEGATIVE:
+X v = POP();
+X x = neg(v);
+X DECREF(v);
+X PUSH(x);
+X break;
+X
+X case UNARY_NOT:
+X v = POP();
+X x = not(v);
+X DECREF(v);
+X PUSH(x);
+X break;
+X
+X case UNARY_CONVERT:
+X v = POP();
+X x = reprobject(v);
+X DECREF(v);
+X PUSH(x);
+X break;
+X
+X case UNARY_CALL:
+X v = POP();
+X if (is_classmethodobject(v) || is_funcobject(v))
+X x = call_function(v, (object *)NULL);
+X else
+X x = call_builtin(v, (object *)NULL);
+X DECREF(v);
+X PUSH(x);
+X break;
+X
+X case BINARY_MULTIPLY:
+X w = POP();
+X v = POP();
+X x = mul(v, w);
+X DECREF(v);
+X DECREF(w);
+X PUSH(x);
+X break;
+X
+X case BINARY_DIVIDE:
+X w = POP();
+X v = POP();
+X x = divide(v, w);
+X DECREF(v);
+X DECREF(w);
+X PUSH(x);
+X break;
+X
+X case BINARY_MODULO:
+X w = POP();
+X v = POP();
+X x = rem(v, w);
+X DECREF(v);
+X DECREF(w);
+X PUSH(x);
+X break;
+X
+X case BINARY_ADD:
+X w = POP();
+X v = POP();
+X x = add(v, w);
+X DECREF(v);
+X DECREF(w);
+X PUSH(x);
+X break;
+X
+X case BINARY_SUBTRACT:
+X w = POP();
+X v = POP();
+X x = sub(v, w);
+X DECREF(v);
+X DECREF(w);
+X PUSH(x);
+X break;
+X
+X case BINARY_SUBSCR:
+X w = POP();
+X v = POP();
+X x = apply_subscript(v, w);
+X DECREF(v);
+X DECREF(w);
+X PUSH(x);
+X break;
+X
+X case BINARY_CALL:
+X w = POP();
+X v = POP();
+X if (is_classmethodobject(v) || is_funcobject(v))
+X x = call_function(v, w);
+X else
+X x = call_builtin(v, w);
+X DECREF(v);
+X DECREF(w);
+X PUSH(x);
+X break;
+X
+X case SLICE+0:
+X case SLICE+1:
+X case SLICE+2:
+X case SLICE+3:
+X if ((opcode-SLICE) & 2)
+X w = POP();
+X else
+X w = NULL;
+X if ((opcode-SLICE) & 1)
+X v = POP();
+X else
+X v = NULL;
+X u = POP();
+X x = apply_slice(u, v, w);
+X DECREF(u);
+X XDECREF(v);
+X XDECREF(w);
+X PUSH(x);
+X break;
+X
+X case STORE_SLICE+0:
+X case STORE_SLICE+1:
+X case STORE_SLICE+2:
+X case STORE_SLICE+3:
+X if ((opcode-STORE_SLICE) & 2)
+X w = POP();
+X else
+X w = NULL;
+X if ((opcode-STORE_SLICE) & 1)
+X v = POP();
+X else
+X v = NULL;
+X u = POP();
+X t = POP();
+X err = assign_slice(u, v, w, t); /* u[v:w] = t */
+X DECREF(t);
+X DECREF(u);
+X XDECREF(v);
+X XDECREF(w);
+X break;
+X
+X case DELETE_SLICE+0:
+X case DELETE_SLICE+1:
+X case DELETE_SLICE+2:
+X case DELETE_SLICE+3:
+X if ((opcode-DELETE_SLICE) & 2)
+X w = POP();
+X else
+X w = NULL;
+X if ((opcode-DELETE_SLICE) & 1)
+X v = POP();
+X else
+X v = NULL;
+X u = POP();
+X err = assign_slice(u, v, w, (object *)NULL);
+X /* del u[v:w] */
+X DECREF(u);
+X XDECREF(v);
+X XDECREF(w);
+X break;
+X
+X case STORE_SUBSCR:
+X w = POP();
+X v = POP();
+X u = POP();
+X /* v[w] = u */
+X err = assign_subscript(v, w, u);
+X DECREF(u);
+X DECREF(v);
+X DECREF(w);
+X break;
+X
+X case DELETE_SUBSCR:
+X w = POP();
+X v = POP();
+X /* del v[w] */
+X err = assign_subscript(v, w, (object *)NULL);
+X DECREF(v);
+X DECREF(w);
+X break;
+X
+X case PRINT_EXPR:
+X v = POP();
+X fp = sysgetfile("stdout", stdout);
+X /* Print value except if procedure result */
+X if (v != None) {
+X flushline();
+X printobject(v, fp, 0);
+X fprintf(fp, "\n");
+X }
+X DECREF(v);
+X break;
+X
+X case PRINT_ITEM:
+X v = POP();
+X fp = sysgetfile("stdout", stdout);
+X if (needspace)
+X fprintf(fp, " ");
+X if (is_stringobject(v)) {
+X char *s = getstringvalue(v);
+X int len = getstringsize(v);
+X fwrite(s, 1, len, fp);
+X if (len > 0 && s[len-1] == '\n')
+X needspace = 0;
+X else
+X needspace = 1;
+X }
+X else {
+X printobject(v, fp, 0);
+X needspace = 1;
+X }
+X DECREF(v);
+X break;
+X
+X case PRINT_NEWLINE:
+X fp = sysgetfile("stdout", stdout);
+X fprintf(fp, "\n");
+X needspace = 0;
+X break;
+X
+X case BREAK_LOOP:
+X why = WHY_BREAK;
+X break;
+X
+X case RAISE_EXCEPTION:
+X v = POP();
+X w = POP();
+X if (!is_stringobject(w))
+X err_setstr(TypeError,
+X "exceptions must be strings");
+X else
+X err_setval(w, v);
+X DECREF(v);
+X DECREF(w);
+X why = WHY_EXCEPTION;
+X break;
+X
+X case LOAD_LOCALS:
+X v = f->f_locals;
+X INCREF(v);
+X PUSH(v);
+X break;
+X
+X case RETURN_VALUE:
+X retval = POP();
+X why = WHY_RETURN;
+X break;
+X
+X case REQUIRE_ARGS:
+X if (EMPTY()) {
+X err_setstr(TypeError,
+X "function expects argument(s)");
+X why = WHY_EXCEPTION;
+X }
+X break;
+X
+X case REFUSE_ARGS:
+X if (!EMPTY()) {
+X err_setstr(TypeError,
+X "function expects no argument(s)");
+X why = WHY_EXCEPTION;
+X }
+X break;
+X
+X case BUILD_FUNCTION:
+X v = POP();
+X x = newfuncobject(v, f->f_globals);
+X DECREF(v);
+X PUSH(x);
+X break;
+X
+X case POP_BLOCK:
+X {
+X block *b = pop_block(f);
+X while (STACK_LEVEL() > b->b_level) {
+X v = POP();
+X DECREF(v);
+X }
+X }
+X break;
+X
+X case END_FINALLY:
+X v = POP();
+X if (is_intobject(v)) {
+X why = (enum why_code) getintvalue(v);
+X if (why == WHY_RETURN)
+X retval = POP();
+X }
+X else if (is_stringobject(v)) {
+X w = POP();
+X err_setval(v, w);
+X DECREF(w);
+X w = POP();
+X tb_store(w);
+X DECREF(w);
+X why = WHY_RERAISE;
+X }
+X else if (v != None) {
+X err_setstr(SystemError,
+X "'finally' pops bad exception");
+X why = WHY_EXCEPTION;
+X }
+X DECREF(v);
+X break;
+X
+X case BUILD_CLASS:
+X w = POP();
+X v = POP();
+X x = build_class(v, w);
+X PUSH(x);
+X DECREF(v);
+X DECREF(w);
+X break;
+X
+X case STORE_NAME:
+X name = GETNAME(oparg);
+X v = POP();
+X err = dictinsert(f->f_locals, name, v);
+X DECREF(v);
+X break;
+X
+X case DELETE_NAME:
+X name = GETNAME(oparg);
+X if ((err = dictremove(f->f_locals, name)) != 0)
+X err_setstr(NameError, name);
+X break;
+X
+X case UNPACK_TUPLE:
+X v = POP();
+X if (!is_tupleobject(v)) {
+X err_setstr(TypeError, "unpack non-tuple");
+X why = WHY_EXCEPTION;
+X }
+X else if (gettuplesize(v) != oparg) {
+X err_setstr(RuntimeError,
+X "unpack tuple of wrong size");
+X why = WHY_EXCEPTION;
+X }
+X else {
+X for (; --oparg >= 0; ) {
+X w = gettupleitem(v, oparg);
+X INCREF(w);
+X PUSH(w);
+X }
+X }
+X DECREF(v);
+X break;
+X
+X case UNPACK_LIST:
+X v = POP();
+X if (!is_listobject(v)) {
+X err_setstr(TypeError, "unpack non-list");
+X why = WHY_EXCEPTION;
+X }
+X else if (getlistsize(v) != oparg) {
+X err_setstr(RuntimeError,
+X "unpack list of wrong size");
+X why = WHY_EXCEPTION;
+X }
+X else {
+X for (; --oparg >= 0; ) {
+X w = getlistitem(v, oparg);
+X INCREF(w);
+X PUSH(w);
+X }
+X }
+X DECREF(v);
+X break;
+X
+X case STORE_ATTR:
+X name = GETNAME(oparg);
+X v = POP();
+X u = POP();
+X err = setattr(v, name, u); /* v.name = u */
+X DECREF(v);
+X DECREF(u);
+X break;
+X
+X case DELETE_ATTR:
+X name = GETNAME(oparg);
+X v = POP();
+X err = setattr(v, name, (object *)NULL);
+X /* del v.name */
+X DECREF(v);
+X break;
+X
+X case LOAD_CONST:
+X x = GETCONST(oparg);
+X INCREF(x);
+X PUSH(x);
+X break;
+X
+X case LOAD_NAME:
+X name = GETNAME(oparg);
+X x = dictlookup(f->f_locals, name);
+X if (x == NULL) {
+X x = dictlookup(f->f_globals, name);
+X if (x == NULL)
+X x = getbuiltin(name);
+X }
+X if (x == NULL)
+X err_setstr(NameError, name);
+X else
+X INCREF(x);
+X PUSH(x);
+X break;
+X
+X case BUILD_TUPLE:
+X x = newtupleobject(oparg);
+X if (x != NULL) {
+X for (; --oparg >= 0;) {
+X w = POP();
+X err = settupleitem(x, oparg, w);
+X if (err != 0)
+X break;
+X }
+X PUSH(x);
+X }
+X break;
+X
+X case BUILD_LIST:
+X x = newlistobject(oparg);
+X if (x != NULL) {
+X for (; --oparg >= 0;) {
+X w = POP();
+X err = setlistitem(x, oparg, w);
+X if (err != 0)
+X break;
+X }
+X PUSH(x);
+X }
+X break;
+X
+X case BUILD_MAP:
+X x = newdictobject();
+X PUSH(x);
+X break;
+X
+X case LOAD_ATTR:
+X name = GETNAME(oparg);
+X v = POP();
+X x = getattr(v, name);
+X DECREF(v);
+X PUSH(x);
+X break;
+X
+X case COMPARE_OP:
+X w = POP();
+X v = POP();
+X x = cmp_outcome((enum cmp_op)oparg, v, w);
+X DECREF(v);
+X DECREF(w);
+X PUSH(x);
+X break;
+X
+X case IMPORT_NAME:
+X name = GETNAME(oparg);
+X x = import_module(name);
+X XINCREF(x);
+X PUSH(x);
+X break;
+X
+X case IMPORT_FROM:
+X name = GETNAME(oparg);
+X v = TOP();
+X err = import_from(f->f_locals, v, name);
+X break;
+X
+X case JUMP_FORWARD:
+X JUMPBY(oparg);
+X break;
+X
+X case JUMP_IF_FALSE:
+X if (!testbool(TOP()))
+X JUMPBY(oparg);
+X break;
+X
+X case JUMP_IF_TRUE:
+X if (testbool(TOP()))
+X JUMPBY(oparg);
+X break;
+X
+X case JUMP_ABSOLUTE:
+X JUMPTO(oparg);
+X break;
+X
+X case FOR_LOOP:
+X /* for v in s: ...
+X On entry: stack contains s, i.
+X On exit: stack contains s, i+1, s[i];
+X but if loop exhausted:
+X s, i are popped, and we jump */
+X w = POP(); /* Loop index */
+X v = POP(); /* Sequence object */
+X u = loop_subscript(v, w);
+X if (u != NULL) {
+X PUSH(v);
+X x = newintobject(getintvalue(w)+1);
+X PUSH(x);
+X DECREF(w);
+X PUSH(u);
+X }
+X else {
+X DECREF(v);
+X DECREF(w);
+X /* A NULL can mean "s exhausted"
+X but also an error: */
+X if (err_occurred())
+X why = WHY_EXCEPTION;
+X else
+X JUMPBY(oparg);
+X }
+X break;
+X
+X case SETUP_LOOP:
+X case SETUP_EXCEPT:
+X case SETUP_FINALLY:
+X setup_block(f, opcode, INSTR_OFFSET() + oparg,
+X STACK_LEVEL());
+X break;
+X
+X case SET_LINENO:
+X#ifdef TRACE
+X if (trace)
+X printf("--- Line %d ---\n", oparg);
+X#endif
+X lineno = oparg;
+X break;
+X
+X default:
+X fprintf(stderr,
+X "XXX lineno: %d, opcode: %d\n",
+X lineno, opcode);
+X err_setstr(SystemError, "eval_code: unknown opcode");
+X why = WHY_EXCEPTION;
+X break;
+X
+X } /* switch */
+X
+X
+X /* Quickly continue if no error occurred */
+X
+X if (why == WHY_NOT) {
+X if (err == 0 && x != NULL)
+X continue; /* Normal, fast path */
+X why = WHY_EXCEPTION;
+X x = None;
+X err = 0;
+X }
+X
+X#ifndef NDEBUG
+X /* Double-check exception status */
+X
+X if (why == WHY_EXCEPTION || why == WHY_RERAISE) {
+X if (!err_occurred()) {
+X fprintf(stderr, "XXX ghost error\n");
+X err_setstr(SystemError, "ghost error");
+X why = WHY_EXCEPTION;
+X }
+X }
+X else {
+X if (err_occurred()) {
+X fprintf(stderr, "XXX undetected error\n");
+X why = WHY_EXCEPTION;
+X }
+X }
+X#endif
+X
+X /* Log traceback info if this is a real exception */
+X
+X if (why == WHY_EXCEPTION) {
+X int lasti = INSTR_OFFSET() - 1;
+X if (HAS_ARG(opcode))
+X lasti -= 2;
+X tb_here(f, lasti, lineno);
+X }
+X
+X /* For the rest, treat WHY_RERAISE as WHY_EXCEPTION */
+X
+X if (why == WHY_RERAISE)
+X why = WHY_EXCEPTION;
+X
+X /* Unwind stacks if a (pseudo) exception occurred */
+X
+X while (why != WHY_NOT && f->f_iblock > 0) {
+X block *b = pop_block(f);
+X while (STACK_LEVEL() > b->b_level) {
+X v = POP();
+X XDECREF(v);
+X }
+X if (b->b_type == SETUP_LOOP && why == WHY_BREAK) {
+X why = WHY_NOT;
+X JUMPTO(b->b_handler);
+X break;
+X }
+X if (b->b_type == SETUP_FINALLY ||
+X b->b_type == SETUP_EXCEPT &&
+X why == WHY_EXCEPTION) {
+X if (why == WHY_EXCEPTION) {
+X object *exc, *val;
+X err_get(&exc, &val);
+X if (val == NULL) {
+X val = None;
+X INCREF(val);
+X }
+X v = tb_fetch();
+X /* Make the raw exception data
+X available to the handler,
+X so a program can emulate the
+X Python main loop. Don't do
+X this for 'finally'. */
+X if (b->b_type == SETUP_EXCEPT) {
+X#if 0 /* Oops, this breaks too many things */
+X sysset("exc_traceback", v);
+X#endif
+X sysset("exc_value", val);
+X sysset("exc_type", exc);
+X err_clear();
+X }
+X PUSH(v);
+X PUSH(val);
+X PUSH(exc);
+X }
+X else {
+X if (why == WHY_RETURN)
+X PUSH(retval);
+X v = newintobject((long)why);
+X PUSH(v);
+X }
+X why = WHY_NOT;
+X JUMPTO(b->b_handler);
+X break;
+X }
+X } /* unwind stack */
+X
+X /* End the loop if we still have an error (or return) */
+X
+X if (why != WHY_NOT)
+X break;
+X
+X } /* main loop */
+X
+X /* Pop remaining stack entries */
+X
+X while (!EMPTY()) {
+X v = POP();
+X XDECREF(v);
+X }
+X
+X /* Restore previous frame and release the current one */
+X
+X current_frame = f->f_back;
+X DECREF(f);
+X
+X if (why == WHY_RETURN)
+X return retval;
+X else
+X return NULL;
+X}
+EOF
+fi
+if test -s 'src/object.h'
+then echo '*** I will not over-write existing file src/object.h'
+else
+echo 'x - src/object.h'
+sed 's/^X//' > 'src/object.h' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X#define NDEBUG
+X/* Object and type object interface */
+X
+X/*
+X123456789-123456789-123456789-123456789-123456789-123456789-123456789-12
+X
+XObjects are structures allocated on the heap. Special rules apply to
+Xthe use of objects to ensure they are properly garbage-collected.
+XObjects are never allocated statically or on the stack; they must be
+Xaccessed through special macros and functions only. (Type objects are
+Xexceptions to the first rule; the standard types are represented by
+Xstatically initialized type objects.)
+X
+XAn object has a 'reference count' that is increased or decreased when a
+Xpointer to the object is copied or deleted; when the reference count
+Xreaches zero there are no references to the object left and it can be
+Xremoved from the heap.
+X
+XAn object has a 'type' that determines what it represents and what kind
+Xof data it contains. An object's type is fixed when it is created.
+XTypes themselves are represented as objects; an object contains a
+Xpointer to the corresponding type object. The type itself has a type
+Xpointer pointing to the object representing the type 'type', which
+Xcontains a pointer to itself!).
+X
+XObjects do not float around in memory; once allocated an object keeps
+Xthe same size and address. Objects that must hold variable-size data
+Xcan contain pointers to variable-size parts of the object. Not all
+Xobjects of the same type have the same size; but the size cannot change
+Xafter allocation. (These restrictions are made so a reference to an
+Xobject can be simply a pointer -- moving an object would require
+Xupdating all the pointers, and changing an object's size would require
+Xmoving it if there was another object right next to it.)
+X
+XObjects are always accessed through pointers of the type 'object *'.
+XThe type 'object' is a structure that only contains the reference count
+Xand the type pointer. The actual memory allocated for an object
+Xcontains other data that can only be accessed after casting the pointer
+Xto a pointer to a longer structure type. This longer type must start
+Xwith the reference count and type fields; the macro OB_HEAD should be
+Xused for this (to accomodate for future changes). The implementation
+Xof a particular object type can cast the object pointer to the proper
+Xtype and back.
+X
+XA standard interface exists for objects that contain an array of items
+Xwhose size is determined when the object is allocated.
+X
+X123456789-123456789-123456789-123456789-123456789-123456789-123456789-12
+X*/
+X
+X#ifndef NDEBUG
+X
+X/* Turn on heavy reference debugging */
+X#define TRACE_REFS
+X
+X/* Turn on reference counting */
+X#define REF_DEBUG
+X
+X#endif /* NDEBUG */
+X
+X#ifdef TRACE_REFS
+X#define OB_HEAD \
+X struct _object *_ob_next, *_ob_prev; \
+X int ob_refcnt; \
+X struct _typeobject *ob_type;
+X#define OB_HEAD_INIT(type) 0, 0, 1, type,
+X#else
+X#define OB_HEAD \
+X unsigned int ob_refcnt; \
+X struct _typeobject *ob_type;
+X#define OB_HEAD_INIT(type) 1, type,
+X#endif
+X
+X#define OB_VARHEAD \
+X OB_HEAD \
+X unsigned int ob_size; /* Number of items in variable part */
+X
+Xtypedef struct _object {
+X OB_HEAD
+X} object;
+X
+Xtypedef struct {
+X OB_VARHEAD
+X} varobject;
+X
+X
+X/*
+X123456789-123456789-123456789-123456789-123456789-123456789-123456789-12
+X
+XType objects contain a string containing the type name (to help somewhat
+Xin debugging), the allocation parameters (see newobj() and newvarobj()),
+Xand methods for accessing objects of the type. Methods are optional,a
+Xnil pointer meaning that particular kind of access is not available for
+Xthis type. The DECREF() macro uses the tp_dealloc method without
+Xchecking for a nil pointer; it should always be implemented except if
+Xthe implementation can guarantee that the reference count will never
+Xreach zero (e.g., for type objects).
+X
+XNB: the methods for certain type groups are now contained in separate
+Xmethod blocks.
+X*/
+X
+Xtypedef struct {
+X object *(*nb_add) FPROTO((object *, object *));
+X object *(*nb_subtract) FPROTO((object *, object *));
+X object *(*nb_multiply) FPROTO((object *, object *));
+X object *(*nb_divide) FPROTO((object *, object *));
+X object *(*nb_remainder) FPROTO((object *, object *));
+X object *(*nb_power) FPROTO((object *, object *));
+X object *(*nb_negative) FPROTO((object *));
+X object *(*nb_positive) FPROTO((object *));
+X} number_methods;
+X
+Xtypedef struct {
+X int (*sq_length) FPROTO((object *));
+X object *(*sq_concat) FPROTO((object *, object *));
+X object *(*sq_repeat) FPROTO((object *, int));
+X object *(*sq_item) FPROTO((object *, int));
+X object *(*sq_slice) FPROTO((object *, int, int));
+X int (*sq_ass_item) FPROTO((object *, int, object *));
+X int (*sq_ass_slice) FPROTO((object *, int, int, object *));
+X} sequence_methods;
+X
+Xtypedef struct {
+X int (*mp_length) FPROTO((object *));
+X object *(*mp_subscript) FPROTO((object *, object *));
+X int (*mp_ass_subscript) FPROTO((object *, object *, object *));
+X} mapping_methods;
+X
+Xtypedef struct _typeobject {
+X OB_VARHEAD
+X char *tp_name; /* For printing */
+X unsigned int tp_basicsize, tp_itemsize; /* For allocation */
+X
+X /* Methods to implement standard operations */
+X
+X void (*tp_dealloc) FPROTO((object *));
+X void (*tp_print) FPROTO((object *, FILE *, int));
+X object *(*tp_getattr) FPROTO((object *, char *));
+X int (*tp_setattr) FPROTO((object *, char *, object *));
+X int (*tp_compare) FPROTO((object *, object *));
+X object *(*tp_repr) FPROTO((object *));
+X
+X /* Method suites for standard classes */
+X
+X number_methods *tp_as_number;
+X sequence_methods *tp_as_sequence;
+X mapping_methods *tp_as_mapping;
+X} typeobject;
+X
+Xextern typeobject Typetype; /* The type of type objects */
+X
+X#define is_typeobject(op) ((op)->ob_type == &Typetype)
+X
+X/* Generic operations on objects */
+Xextern void printobject PROTO((object *, FILE *, int));
+Xextern object * reprobject PROTO((object *));
+Xextern int cmpobject PROTO((object *, object *));
+Xextern object *getattr PROTO((object *, char *));
+Xextern int setattr PROTO((object *, char *, object *));
+X
+X/* Flag bits for printing: */
+X#define PRINT_RAW 1 /* No string quotes etc. */
+X
+X/*
+X123456789-123456789-123456789-123456789-123456789-123456789-123456789-12
+X
+XThe macros INCREF(op) and DECREF(op) are used to increment or decrement
+Xreference counts. DECREF calls the object's deallocator function; for
+Xobjects that don't contain references to other objects or heap memory
+Xthis can be the standard function free(). Both macros can be used
+Xwhereever a void expression is allowed. The argument shouldn't be a
+XNIL pointer. The macro NEWREF(op) is used only to initialize reference
+Xcounts to 1; it is defined here for convenience.
+X
+XWe assume that the reference count field can never overflow; this can
+Xbe proven when the size of the field is the same as the pointer size
+Xbut even with a 16-bit reference count field it is pretty unlikely so
+Xwe ignore the possibility. (If you are paranoid, make it a long.)
+X
+XType objects should never be deallocated; the type pointer in an object
+Xis not considered to be a reference to the type object, to save
+Xcomplications in the deallocation function. (This is actually a
+Xdecision that's up to the implementer of each new type so if you want,
+Xyou can count such references to the type object.)
+X
+X*** WARNING*** The DECREF macro must have a side-effect-free argument
+Xsince it may evaluate its argument multiple times. (The alternative
+Xwould be to mace it a proper function or assign it to a global temporary
+Xvariable first, both of which are slower; and in a multi-threaded
+Xenvironment the global variable trick is not safe.)
+X*/
+X
+X#ifdef TRACE_REFS
+X#ifndef REF_DEBUG
+X#define REF_DEBUG
+X#endif
+X#endif
+X
+X#ifndef TRACE_REFS
+X#define DELREF(op) (*(op)->ob_type->tp_dealloc)((object *)(op))
+X#define UNREF(op) /*empty*/
+X#endif
+X
+X#ifdef REF_DEBUG
+Xextern long ref_total;
+X#ifndef TRACE_REFS
+X#define NEWREF(op) (ref_total++, (op)->ob_refcnt = 1)
+X#endif
+X#define INCREF(op) (ref_total++, (op)->ob_refcnt++)
+X#define DECREF(op) \
+X if (--ref_total, --(op)->ob_refcnt > 0) \
+X ; \
+X else \
+X DELREF(op)
+X#else
+X#define NEWREF(op) ((op)->ob_refcnt = 1)
+X#define INCREF(op) ((op)->ob_refcnt++)
+X#define DECREF(op) \
+X if (--(op)->ob_refcnt > 0) \
+X ; \
+X else \
+X DELREF(op)
+X#endif
+X
+X/* Macros to use in case the object pointer may be NULL: */
+X
+X#define XINCREF(op) if ((op) == NULL) ; else INCREF(op)
+X#define XDECREF(op) if ((op) == NULL) ; else DECREF(op)
+X
+X/* Definition of NULL, so you don't have to include <stdio.h> */
+X
+X#ifndef NULL
+X#define NULL 0
+X#endif
+X
+X
+X/*
+XNoObject is an object of undefined type which can be used in contexts
+Xwhere NULL (nil) is not suitable (since NULL often means 'error').
+X
+XDon't forget to apply INCREF() when returning this value!!!
+X*/
+X
+Xextern object NoObject; /* Don't use this directly */
+X
+X#define None (&NoObject)
+X
+X
+X/*
+X123456789-123456789-123456789-123456789-123456789-123456789-123456789-12
+X
+XMore conventions
+X================
+X
+XArgument Checking
+X-----------------
+X
+XFunctions that take objects as arguments normally don't check for nil
+Xarguments, but they do check the type of the argument, and return an
+Xerror if the function doesn't apply to the type.
+X
+XFailure Modes
+X-------------
+X
+XFunctions may fail for a variety of reasons, including running out of
+Xmemory. This is communicated to the caller in two ways: an error string
+Xis set (see errors.h), and the function result differs: functions that
+Xnormally return a pointer return NULL for failure, functions returning
+Xan integer return -1 (which could be a legal return value too!), and
+Xother functions return 0 for success and -1 for failure.
+XCallers should always check for errors before using the result.
+X
+XReference Counts
+X----------------
+X
+XIt takes a while to get used to the proper usage of reference counts.
+X
+XFunctions that create an object set the reference count to 1; such new
+Xobjects must be stored somewhere or destroyed again with DECREF().
+XFunctions that 'store' objects such as settupleitem() and dictinsert()
+Xdon't increment the reference count of the object, since the most
+Xfrequent use is to store a fresh object. Functions that 'retrieve'
+Xobjects such as gettupleitem() and dictlookup() also don't increment
+Xthe reference count, since most frequently the object is only looked at
+Xquickly. Thus, to retrieve an object and store it again, the caller
+Xmust call INCREF() explicitly.
+X
+XNOTE: functions that 'consume' a reference count like dictinsert() even
+Xconsume the reference if the object wasn't stored, to simplify error
+Xhandling.
+X
+XIt seems attractive to make other functions that take an object as
+Xargument consume a reference count; however this may quickly get
+Xconfusing (even the current practice is already confusing). Consider
+Xit carefully, it may safe lots of calls to INCREF() and DECREF() at
+Xtimes.
+X
+X123456789-123456789-123456789-123456789-123456789-123456789-123456789-12
+X*/
+EOF
+fi
+echo 'Part 07 out of 21 of pack.out complete.'
+exit 0
diff --git a/shar/python-0.9.1-08-21.shar b/shar/python-0.9.1-08-21.shar
new file mode 100644
index 0000000..7ac6f14
--- /dev/null
+++ b/shar/python-0.9.1-08-21.shar
@@ -0,0 +1,2349 @@
+: This is a shell archive.
+: Extract with 'sh this_file'.
+:
+: Extract part 01 first since it makes all directories
+echo 'Start of pack.out, part 08 out of 21:'
+if test -s 'doc/mod1.tex'
+then echo '*** I will not over-write existing file doc/mod1.tex'
+else
+echo 'x - doc/mod1.tex'
+sed 's/^X//' > 'doc/mod1.tex' << 'EOF'
+X\section{Introduction}
+X
+XThe {\Python} library consists of three parts, with different levels of
+Xintegration with the interpreter.
+XClosest to the interpreter are built-in types, exceptions and functions.
+XNext are built-in modules, which are written in C and linked statically
+Xwith the interpreter.
+XFinally there are standard modules that are implemented entirely in
+X{\Python}, but are always available.
+XFor efficiency, some standard modules may become built-in modules in
+Xfuture versions of the interpreter.
+X
+X\section{Built-in Types, Exceptions and Functions}
+X
+XNames for built-in exceptions and functions are found in a separate
+Xread-only symbol table which cannot be modified.
+XThis table is searched last, so local and global user-defined names can
+Xoverride built-in names.
+XBuilt-in types have no names but are created by syntactic constructs
+X(such as constants) or built-in functions.
+XThey are described together here for easy reference.%
+X\footnote{
+XThe descriptions sorely lack explanations of the exceptions that
+Xmay be raised---this will be fixed in a future version of this
+Xdocument.
+X}
+X
+X\subsection{Built-in Types}
+X
+XThe following sections describe the standard types that are built into the
+Xinterpreter.
+X\subsubsection{Numeric Types}
+X
+XThere are two numeric types: integers and floating point numbers.
+XIntegers are implemented using {\tt long} in C, so they have at least 32
+Xbits of precision.
+XFloating point numbers are implemented using {\tt double} in C.
+XAll bets on precision are off.
+XNumbers are created by numeric constants or as the result of built-in
+Xfunctions and operators.
+X
+XNumeric types support the following operations:
+X
+X\begin{center}
+X\begin{tabular}{|c|l|c|}
+X\hline
+XOperation & Result & Notes \\
+X\hline
+X{\tt abs}({\em x}) & absolute value of {\em x} & \\
+X{\tt int}({\em x}) & {\em x} converted to integer & (1) \\
+X{\tt float}({\em x}) & {\em x} converted to floating point & \\
+X{\tt -}{\em x} & {\em x} negated & \\
+X{\tt +}{\em x} & {\em x} unchanged & \\
+X{\em x}{\tt +}{\em y} & sum of {\em x} and {\em y} & \\
+X{\em x}{\tt -}{\em y} & difference of {\em x} and {\em y} & \\
+X{\em x}{\tt *}{\em y} & product of {\em x} and {\em y} & \\
+X{\em x}{\tt /}{\em y} & quotient of {\em x} and {\em y} & (2) \\
+X{\em x}{\tt \%}{\em y} & remainder of {\em x}{\tt /}{\em y} & (3) \\
+X\hline
+X\end{tabular}
+X\end{center}
+X
+X\noindent
+XNotes:
+X\begin{description}
+X\item[(1)]
+XThis may round or truncate as in C; see functions {\tt floor} and
+X{\tt ceil} in module {\tt math}.
+X\item[(2)]
+XInteger division is defined as in C: the result is an integer; with
+Xpositive operands, it truncates towards zero; with a negative operand,
+Xthe result is unspecified.
+X\item[(3)]
+XOnly defined for integers.
+X\end{description}
+X
+XMixed arithmetic is not supported; both operands must have the same type.
+XMixed comparisons return the wrong result (floats always compare smaller
+Xthan integers).%
+X\footnote{
+XThese restrictions are bugs in the language definitions and will be
+Xfixed in the future.
+X}
+X\subsubsection{Sequence Types}
+X
+XThere are three sequence types: strings, lists and tuples.
+XStrings constants are written in single quotes: {\tt 'xyzzy'}.
+XLists are constructed with square brackets: {\tt [a,~b,~c]}.
+XTuples are constructed by the comma operator or with an empty set of
+Xparentheses: {\tt a,~b,~c} or {\tt ()}.
+X
+XSequence types support the following operations ({\em s} and {\em t} are
+Xsequences of the same type; {\em n}, {\em i} and {\em j} are integers):
+X
+X\begin{center}
+X\begin{tabular}{|c|l|c|}
+X\hline
+XOperation & Result & Notes \\
+X\hline
+X{\tt len}({\em s}) & length of {\em s} & \\
+X{\tt min}({\em s}) & smallest item of {\em s} & \\
+X{\tt max}({\em s}) & largest item of {\em s} & \\
+X{\em x} {\tt in} {\em s} &
+X true if an item of {\em s} is equal to {\em x} & \\
+X{\em x} {\tt not} {\tt in} {\em s} &
+X false if an item of {\em s} is equal to {\em x} & \\
+X{\em s}{\tt +}{\em t} & the concatenation of {\em s} and {\em t} & \\
+X{\em s}{\tt *}{\em n}, {\em n}*{\em s} &
+X {\em n} copies of {\em s} concatenated & (1) \\
+X{\em s}[{\em i}] & {\em i}'th item of {\em s} & \\
+X{\em s}[{\em i}:{\em j}] &
+X slice of {\em s} from {\em i} to {\em j} & (2) \\
+X\hline
+X\end{tabular}
+X\end{center}
+X
+X\noindent
+XNotes:
+X\begin{description}
+X\item[(1)]
+XSequence repetition is only supported for strings.
+X\item[(2)]
+XThe slice of $s$ from $i$ to $j$ is defined as the sequence
+Xof items with index $k$ such that $i \leq k < j$.
+XSpecial rules apply for negative and omitted indices; see the Tutorial
+Xor the Reference Manual.
+X\end{description}
+X
+X\paragraph{Mutable Sequence Types.}
+X
+XList objects support additional operations that allow in-place
+Xmodification of the object.
+XThese operations would be supported by other mutable sequence types
+X(when added to the language) as well.
+XStrings and tuples are immutable sequence types and such objects cannot
+Xbe modified once created.
+XThe following operations are defined on mutable sequence types (where
+X{\em x} is an arbitrary object):
+X
+X\begin{center}
+X\begin{tabular}{|c|l|}
+X\hline
+XOperation & Result \\
+X\hline
+X{\em s}[{\em i}] = {\em x} &
+X item {\em i} of {\em s} is replaced by {\em x} \\
+X{\em s}[{\em i}:{\em j}] = {\em t} &
+X slice of {\em s} from {\em i} to {\em j} is replaced by {\em t} \\
+X{\tt del} {\em s}[{\em i}:{\em j}] &
+X same as {\em s}[{\em i}:{\em j}] = [] \\
+X{\em s}.{\tt append}({\em x}) &
+X same as {\em s}[{\tt len}({\em x}):{\tt len}({\em x})] = [{\em x}] \\
+X{\em s}.{\tt insert}({\em i}, {\em x}) &
+X same as {\em s}[{\em i}:{\em i}] = [{\em x}] \\
+X{\em s}.{\tt sort}() &
+X the items of {\em s} are permuted to satisfy \\
+X &
+X $s[i] \leq s[j]$ for $i < j$\\
+X\hline
+X\end{tabular}
+X\end{center}
+X
+X\subsubsection{Mapping Types}
+X
+XA
+X{\em mapping}
+Xobject maps values of one type (the key type) to arbitrary objects.
+XMappings are mutable objects.
+XThere is currently only one mapping type, the
+X{\em dictionary}.
+XA dictionary's keys are strings.
+XAn empty dictionary is created by the expression \verb"{}".
+XAn extension of this notation is used to display dictionaries when
+Xwritten (see the example below).
+X
+XThe following operations are defined on mappings (where {\em a} is a
+Xmapping, {\em k} is a key and {\em x} is an arbitrary object):
+X
+X\begin{center}
+X\begin{tabular}{|c|l|c|}
+X\hline
+XOperation & Result & Notes\\
+X\hline
+X{\tt len}({\em a}) & the number of elements in {\em a} & \\
+X{\em a}[{\em k}] & the item of {\em a} with key {\em k} & \\
+X{\em a}[{\em k}] = {\em x} & set {\em a}[{\em k}] to {\em x} & \\
+X{\tt del} {\em a}[{\em k}] & remove {\em a}[{\em k}] from {\em a} & \\
+X{\em a}.{\tt keys}() & a copy of {\em a}'s list of keys & (1) \\
+X{\em a}.{\tt has\_key}({\em k}) & true if {\em a} has a key {\em k} & \\
+X\hline
+X\end{tabular}
+X\end{center}
+X
+X\noindent
+XNotes:
+X\begin{description}
+X\item[(1)]
+XKeys are listed in random order.
+X\end{description}
+X
+XA small example using a dictionary:
+X\bcode\begin{verbatim}
+X>>> tel = {}
+X>>> tel['jack'] = 4098
+X>>> tel['sape'] = 4139
+X>>> tel['guido'] = 4127
+X>>> tel['jack']
+X4098
+X>>> tel
+X{'sape': 4139; 'guido': 4127; 'jack': 4098}
+X>>> del tel['sape']
+X>>> tel['irv'] = 4127
+X>>> tel
+X{'guido': 4127; 'irv': 4127; 'jack': 4098}
+X>>> tel.keys()
+X['guido', 'irv', 'jack']
+X>>> tel.has_key('guido')
+X1
+X>>>
+X\end{verbatim}\ecode
+X\subsubsection{Other Built-in Types}
+X
+XThe interpreter supports several other kinds of objects.
+XMost of these support only one or two operations.
+X
+X\paragraph{Modules.}
+X
+XThe only operation on a module is member acces: {\em m}{\tt .}{\em name},
+Xwhere {\em m} is a module and {\em name} accesses a name defined in
+X{\em m}'s symbol table.
+XModule members can be assigned to.
+X
+X\paragraph{Classes and Class Objects.}
+X
+XXXX Classes will be explained at length in a later version of this
+Xdocument.
+X
+X\paragraph{Functions.}
+X
+XFunction objects are created by function definitions.
+XThe only operation on a function object is to call it:
+X{\em func}({\em optional-arguments}).
+X
+XBuilt-in functions have a different type than user-defined functions,
+Xbut they support the same operation.
+X
+X\paragraph{Methods.}
+X
+XMethods are functions that are called using the member acces notation.
+XThere are two flavors: built-in methods (such as {\tt append()} on
+Xlists) and class member methods.
+XBuilt-in methods are described with the types that support them.
+XXXX Class member methods will be described in a later version of this
+Xdocument.
+X
+X\paragraph{Type Objects.}
+X
+XType objects represent the various object types.
+XAn object's type is accessed by the built-in function
+X{\tt type()}.
+XThere are no operations on type objects.
+X
+X\paragraph{The Null Object.}
+X
+XThis object is returned by functions that don't explicitly return a
+Xvalue.
+XIt supports no operations.
+XThere is exactly one null object, named {\tt None}
+X(a built-in name).
+X
+X\paragraph{File Objects.}
+X
+XFile objects are implemented using C's
+X{\em stdio}
+Xpackage and can be created with the built-in function
+X{\tt open()}.
+XThey have the following methods:
+X\begin{description}
+X\funcitem{close}{}
+XCloses the file.
+XA closed file cannot be read or written anymore.
+X\funcitem{read}{size}
+XReads at most
+X{\tt size}
+Xbytes from the file (less if the read hits EOF).
+XThe bytes are returned as a string object.
+XAn empty string is returned when EOF is hit immediately.
+X(For certain files, like ttys, it makes sense to continue reading after
+Xan EOF is hit.)
+X\funcitem{readline}{size}
+XReads a line of at most
+X{\tt size}
+Xbytes from the file.
+XA trailing newline character, if present, is kept in the string.
+XThe size is optional and defaults to a large number (but not infinity).
+XEOF is reported as by
+X{\tt read().}
+X\funcitem{write}{str}
+XWrites a string to the file.
+XReturns no value.
+X\end{description}
+X
+X\subsection{Built-in Exceptions}
+X
+XThe following exceptions can be generated by the interpreter or
+Xbuilt-in functions.
+XExcept where mentioned, they have a string argument (also known as the
+X`associated value' of an exception) indicating the detailed cause of the
+Xerror.
+XThe strings listed with the exception names are their values when used
+Xin an expression or printed.
+X\begin{description}
+X\excitem{EOFError}{end-of-file read}
+X(No argument.)
+XRaised when a built-in function ({\tt input()} or {\tt raw\_input()})
+Xhits an end-of-file condition (EOF) without reading any data.
+X(N.B.: the {\tt read()} and {\tt readline()} methods of file objects
+Xreturn an empty string when they hit EOF.)
+X\excitem{KeyboardInterrupt}{end-of-file read}
+X(No argument.)
+XRaised when the user hits the interrupt key (normally Control-C or DEL).
+XDuring execution, a check for interrupts is made regularly.
+XInterrupts typed when a built-in function ({\tt input()} or
+X{\tt raw\_input()}) is waiting for input also raise this exception.
+X\excitem{MemoryError}{out of memory}
+X%.br
+XRaised when an operation runs out of memory but the situation
+Xmay still be rescued (by deleting some objects).
+X\excitem{NameError}{undefined name}
+X%.br
+XRaised when a name is not found.
+XThis applies to unqualified names, module names (on {\tt import}),
+Xmodule members and object methods.
+XThe string argument is the name that could not be found.
+X\excitem{RuntimeError}{run-time error}
+X%.br
+XRaised for a variety of reasons, e.g., division by zero or index out of
+Xrange.
+X\excitem{SystemError}{system error}
+X%.br
+XRaised when the interpreter finds an internal error, but the situation
+Xdoes not look so serious to cause it to abandon all hope.
+X\excitem{TypeError}{type error}
+X%.br
+XRaised when an operation or built-in function is applied to an object of
+Xinappropriate type.
+X\end{description}
+X
+X\subsection{Built-in Functions}
+X
+XThe {\Python} interpreter has a small number of functions built into it that
+Xare always available.
+XThey are listed here in alphabetical order.
+X\begin{description}
+X\funcitem{abs}{x}
+XReturns the absolute value of a number.
+XThe argument may be an integer or floating point number.
+X\funcitem{chr}{i}
+XReturns a string of one character
+Xwhose ASCII code is the integer {\tt i},
+Xe.g., {\tt chr(97)} returns the string {\tt 'a'}.
+XThis is the inverse of {\tt ord()}.
+X\funcitem{dir}{}
+XWithout arguments, this function returns the list of names in the
+Xcurrent local symbol table, sorted alphabetically.
+XWith a module object as argument, it returns the sorted list of names in
+Xthat module's global symbol table.
+XFor example:
+X\bcode\begin{verbatim}
+X>>> import sys
+X>>> dir()
+X['sys']
+X>>> dir(sys)
+X['argv', 'exit', 'modules', 'path', 'stderr', 'stdin', 'stdout']
+X>>>
+X\end{verbatim}\ecode
+X\funcitem{divmod}{a, b}
+X%.br
+XTakes two integers as arguments and returns a pair of integers
+Xconsisting of their quotient and remainder.
+XFor
+X\bcode\begin{verbatim}
+Xq, r = divmod(a, b)
+X\end{verbatim}\ecode
+Xthe invariants are:
+X\bcode\begin{verbatim}
+Xa = q*b + r
+Xabs(r) < abs(b)
+Xr has the same sign as b
+X\end{verbatim}\ecode
+XFor example:
+X\bcode\begin{verbatim}
+X>>> divmod(100, 7)
+X(14, 2)
+X>>> divmod(-100, 7)
+X(-15, 5)
+X>>> divmod(100, -7)
+X(-15, -5)
+X>>> divmod(-100, -7)
+X(14, -2)
+X>>>
+X\end{verbatim}\ecode
+X\funcitem{eval}{s}
+XTakes a string as argument and parses and evaluates it as a {\Python}
+Xexpression.
+XThe expression is executed using the current local and global symbol
+Xtables.
+XSyntax errors are reported as exceptions.
+XFor example:
+X\bcode\begin{verbatim}
+X>>> x = 1
+X>>> eval('x+1')
+X2
+X>>>
+X\end{verbatim}\ecode
+X\funcitem{exec}{s}
+XTakes a string as argument and parses and evaluates it as a sequence of
+X{\Python} statements.
+XThe string should end with a newline (\verb"'\n'").
+XThe statement is executed using the current local and global symbol
+Xtables.
+XSyntax errors are reported as exceptions.
+XFor example:
+X\bcode\begin{verbatim}
+X>>> x = 1
+X>>> exec('x = x+1\n')
+X>>> x
+X2
+X>>>
+X\end{verbatim}\ecode
+X\funcitem{float}{x}
+XConverts a number to floating point.
+XThe argument may be an integer or floating point number.
+X\funcitem{input}{s}
+XEquivalent to
+X{\tt eval(raw\_input(s))}.
+XAs for
+X{\tt raw\_input()},
+Xthe argument is optional.
+X\funcitem{int}{x}
+XConverts a number to integer.
+XThe argument may be an integer or floating point number.
+X\funcitem{len}{s}
+XReturns the length (the number of items) of an object.
+XThe argument may be a sequence (string, tuple or list) or a mapping
+X(dictionary).
+X\funcitem{max}{s}
+XReturns the largest item of a non-empty sequence (string, tuple or list).
+X\funcitem{min}{s}
+XReturns the smallest item of a non-empty sequence (string, tuple or list).
+X\funcitem{open}{name, mode}
+X%.br
+XReturns a file object (described earlier under Built-in Types).
+XThe string arguments are the same as for stdio's
+X{\tt fopen()}:
+X{\tt 'r'}
+Xopens the file for reading,
+X{\tt 'w'}
+Xopens it for writing (truncating an existing file),
+X{\tt 'a'}
+Xopens it for appending.%
+X\footnote{
+XThis function should go into a built-in module
+X{\tt io}.
+X}
+X\funcitem{ord}{c}
+XTakes a string of one character and returns its
+XASCII value, e.g., {\tt ord('a')} returns the integer {\tt 97}.
+XThis is the inverse of {\tt chr()}.
+X\funcitem{range}{}
+XThis is a versatile function to create lists containing arithmetic
+Xprogressions of integers.
+XWith two integer arguments, it returns the ascending sequence of
+Xintegers starting at the first and ending one before the second
+Xargument.
+XA single argument is used as the end point of the sequence, with 0 used
+Xas the starting point.
+XA third argument specifies the step size; negative steps are allowed and
+Xwork as expected, but don't specify a zero step.
+XThe resulting list may be empty.
+XFor example:
+X\bcode\begin{verbatim}
+X>>> range(10)
+X[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+X>>> range(1, 1+10)
+X[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
+X>>> range(0, 30, 5)
+X[0, 5, 10, 15, 20, 25]
+X>>> range(0, 10, 3)
+X[0, 3, 6, 9]
+X>>> range(0, -10, -1)
+X[0, -1, -2, -3, -4, -5, -6, -7, -8, -9]
+X>>> range(0)
+X[]
+X>>> range(1, 0)
+X[]
+X>>>
+X\end{verbatim}\ecode
+X\funcitem{raw\_input}{s}
+X%.br
+XThe argument is optional; if present, it is written to standard output
+Xwithout a trailing newline.
+XThe function then reads a line from input, converts it to a string
+X(stripping a trailing newline), and returns that.
+XEOF is reported as an exception.
+XFor example:
+X\bcode\begin{verbatim}
+X>>> raw_input('Type anything: ')
+XType anything: Mutant Teenage Ninja Turtles
+X'Mutant Teenage Ninja Turtles'
+X>>>
+X\end{verbatim}\ecode
+X\funcitem{reload}{module}
+XCauses an already imported module to be re-parsed and re-initialized.
+XThis is useful if you have edited the module source file and want to
+Xtry out the new version without leaving {\Python}.
+X\funcitem{type}{x}
+XReturns the type of an object.
+XTypes are objects themselves:
+Xthe type of a type object is its own type.
+X\end{description}
+EOF
+fi
+if test -s 'src/Makefile'
+then echo '*** I will not over-write existing file src/Makefile'
+else
+echo 'x - src/Makefile'
+sed 's/^X//' > 'src/Makefile' << 'EOF'
+X# /***********************************************************
+X# Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+X# Netherlands.
+X#
+X# All Rights Reserved
+X#
+X# Permission to use, copy, modify, and distribute this software and its
+X# documentation for any purpose and without fee is hereby granted,
+X# provided that the above copyright notice appear in all copies and that
+X# both that copyright notice and this permission notice appear in
+X# supporting documentation, and that the names of Stichting Mathematisch
+X# Centrum or CWI not be used in advertising or publicity pertaining to
+X# distribution of the software without specific, written prior permission.
+X#
+X# STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+X# THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+X# FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+X# FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+X# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+X# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+X# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X#
+X# ******************************************************************/
+X
+X# Makefile for Python
+X# ===================
+X#
+X# If you are in a hurry, you can just edit this Makefile to choose the
+X# correct settings for SYSV and RANLIB below, and type "make" in this
+X# directory. If you are using a recent version of SunOS (or Ultrix?)
+X# you don't even have to edit: the Makefile comes pre-configured for
+X# such systems with all configurable options turned off, building the
+X# minimal portable version of the Python interpreter.
+X#
+X# If have more time, read the section on configurable options below.
+X# It may still be wise to begin building the minimal portable Python,
+X# to see if it works at all, and select options later. You don't have
+X# to rebuild all objects when you turn on options; all dependencies
+X# are concentrated in the file "config.c" which is rebuilt whenever
+X# the Makefile changes. (Except if you turn on the GNU Readline option
+X# you may have to toss out the tokenizer.o object.)
+X
+X
+X# Operating System Defines (ALWAYS READ THIS)
+X# ===========================================
+X
+X# Uncomment the following line if you are using a System V derivative.
+X# This must be used, for instance, on an SGI IRIS. Don't use it for
+X# SunOS. (This is only needed by posixmodule.c...)
+X
+X#SYSVDEF= -DSYSV
+X
+X# Choose one of the following two lines depending on whether your system
+X# requires the use of 'ranlib' after creating a library, or not.
+X
+X#RANLIB = true # For System V
+XRANLIB = ranlib # For BSD
+X
+X# If your system doesn't have symbolic links, uncomment the following
+X# line.
+X
+X#NOSYMLINKDEF= -DNO_LSTAT
+X
+X
+X# Installation Options
+X# ====================
+X
+X# You may want to change PYTHONPATH to reflect where you install the
+X# Python module library.
+X
+XPYTHONPATH= .:/usr/local/lib/python:/ufs/guido/lib/python
+X
+X
+X# For "Pure" BSD Systems
+X# ======================
+X#
+X# "Pure" BSD systems (as opposed to enhanced BSD derivatives like SunOS)
+X# often miss certain standard library functions. Source for
+X# these is provided, you just have to turn it on. This may work for
+X# other systems as well, where these things are needed.
+X
+X# If your system does not have a strerror() function in the library,
+X# uncomment the following two lines to use one I wrote. (Actually, this
+X# is missing in most systems I have encountered, so it is turned on
+X# in the Makefile. Turn it off if your system doesn't have sys_errlist.)
+X
+XSTRERROR_SRC= strerror.c
+XSTRERROR_OBJ= strerror.o
+X
+X# If your BSD system does not have a fmod() function in the library,
+X# uncomment the following two lines to use one I wrote.
+X
+X#FMOD_SRC= fmod.c
+X#FMOD_OBJ= fmod.o
+X
+X# If your BSD system does not have a strtol() function in the library,
+X# uncomment the following two lines to use one I wrote.
+X
+X#STRTOL_SRC= strtol.c
+X#STRTOL_OBJ= strtol.o
+X
+X# If your BSD system does not have a getcwd() function in the library,
+X# but it does have a getwd() function, uncomment the following two lines
+X# to use one I wrote. (If you don't have getwd() either, turn on the
+X# NO_GETWD #define in getcwd.c.)
+X
+X#GETCWD_SRC= getcwd.c
+X#GETCWD_OBJ= getcwd.o
+X
+X# If your signal() function believes signal handlers return int,
+X# uncomment the following line.
+X
+X#SIGTYPEDEF= -DSIGTYPE=int
+X
+X
+X# Further porting hints
+X# =====================
+X#
+X# If you don't have the header file <string.h>, but you do have
+X# <strings.h>, create a file "string.h" in this directory which contains
+X# the single line "#include <strings.h>", and add "-I." to CFLAGS.
+X# If you don't have the functions strchr and strrchr, add definitions
+X# "-Dstrchr=index -Dstrrchr=rindex" to CFLAGS. (NB: CFLAGS is not
+X# defined in this Makefile.)
+X
+X
+X# Configurable Options
+X# ====================
+X#
+X# Python can be configured to interface to various system libraries that
+X# are not available on all systems. It is also possible to configure
+X# the input module to use the GNU Readline library for interactive
+X# input. For each configuration choice you must uncomment the relevant
+X# section of the Makefile below. Note: you may also have to change a
+X# pathname and/or an architecture identifier that is hardcoded in the
+X# Makefile.
+X#
+X# Read the comments to determine if you can use the option. (You can
+X# always leave all options off and build a minimal portable version of
+X# Python.)
+X
+X
+X# BSD Time Option
+X# ===============
+X#
+X# This option does not add a new module but adds two functions to
+X# an existing module.
+X#
+X# It implements time.millisleep() and time.millitimer()
+X# using the BSD system calls select() and gettimeofday().
+X#
+X# Uncomment the following line to select this option.
+X
+X#BSDTIMEDEF= -DBSD_TIME
+X
+X
+X# GNU Readline Option
+X# ===================
+X#
+X# If you have the sources of the GNU Readline library you can have
+X# full interactive command line editing and history in Python.
+X# The GNU Readline library is distributed with the BASH shell
+X# (I only know of version 1.05). You must build the GNU Readline
+X# library and the alloca routine it needs in their own source
+X# directories (which are subdirectories of the basg source directory),
+X# and plant a pointer to the BASH source directory in this Makefile.
+X#
+X# Uncomment and edit the following block to use the GNU Readline option.
+X# - Edit the definition of BASHDIR to point to the bash source tree.
+X# You may have to fix the definition of LIBTERMCAP; leave the LIBALLOCA
+X# definition commented if alloca() is in your C library.
+X
+X#BASHDIR= ../../bash-1.05
+X#LIBREADLINE= $(BASHDIR)/readline/libreadline.a
+X#LIBALLOCA= $(BASHDIR)/alloc-files/alloca.o
+X#LIBTERMCAP= -ltermcap
+X#RL_USE = -DUSE_READLINE
+X#RL_LIBS= $(LIBREADLINE) $(LIBALLOCA) $(LIBTERMCAP)
+X#RL_LIBDEPS= $(LIBREADLINE) $(LIBALLOCA)
+X
+X
+X# STDWIN Option
+X# =============
+X#
+X# If you have the sources of STDWIN (by the same author) you can
+X# configure Python to incorporate the built-in module 'stdwin'.
+X# This requires a fairly recent version of STDWIN (dated late 1990).
+X#
+X# Uncomment and edit the following block to use the STDWIN option.
+X# - Edit the STDWINDIR defition to reflect the top of the STDWIN source
+X# tree.
+X# - Edit the ARCH definition to reflect your system's architecture
+X# (usually the program 'arch' or 'machine' returns this).
+X# You may have to edit the LIBX11 defition to reflect the location of
+X# the X11 runtime library if it is non-standard.
+X
+X#STDWINDIR= ../../stdwin
+X#ARCH= sgi
+X#LIBSTDWIN= $(STDWINDIR)/Build/$(ARCH)/x11/lib/lib.a
+X#LIBX11 = -lX11
+X#STDW_INCL= -I$(STDWINDIR)/H
+X#STDW_USE= -DUSE_STDWIN
+X#STDW_LIBS= $(LIBSTDWIN) $(LIBX11)
+X#STDW_LIBDEPS= $(LIBSTDWIN)
+X#STDW_SRC= stdwinmodule.c
+X#STDW_OBJ= stdwinmodule.o
+X
+X
+X# Amoeba Option
+X# =============
+X#
+X# If you have the Amoeba 4.0 distribution (Beta or otherwise) you can
+X# configure Python to incorporate the built-in module 'amoeba'.
+X# (Python can also be built for native Amoeba, but it requires more
+X# work and thought. Contact the author.)
+X#
+X# Uncomment and edit the following block to use the Amoeba option.
+X# - Edit the AMOEBADIR defition to reflect the top of the Amoeba source
+X# tree.
+X# - Edit the AM_CONF definition to reflect the machine/operating system
+X# configuration needed by Amoeba (this is the name of a subdirectory
+X# of $(AMOEBADIR)/conf/unix, e.g., vax.ultrix).
+X
+X#AMOEBADIR= /usr/amoeba
+X#AM_CONF= mipseb.irix
+X#LIBAMUNIX= $(AMOEBADIR)/conf/unix/$(AM_CONF)/lib/amunix/libamunix.a
+X#AM_INCL= -I$(AMOEBADIR)/src/h
+X#AM_USE = -DUSE_AMOEBA
+X#AM_LIBDEPS= $(LIBAMUNIX)
+X#AM_LIBS= $(LIBAMUNIX)
+X#AM_SRC = amoebamodule.c sc_interpr.c sc_errors.c
+X#AM_OBJ = amoebamodule.o sc_interpr.o sc_errors.o
+X
+X
+X# Silicon Graphics IRIS Options
+X# =============================
+X#
+X# The following three options are only relevant if you are using a
+X# Silicon Graphics IRIS machine. These have been tested with IRIX 3.3.1
+X# on a 4D/25.
+X
+X
+X# GL Option
+X# =========
+X#
+X# This option incorporates the built-in module 'gl', which provides a
+X# complete interface to the Silicon Graphics GL library. It adds
+X# about 70K to the Python text size and about 260K to the unstripped
+X# binary size.
+X#
+X# Note: the file 'glmodule.c' is created by a Python script. If you
+X# lost the file and have no working Python interpreter, turn off the GL
+X# and Panel options, rebuild the Python interpreter, use it to create
+X# glmodule.c, and then turn the options back on.
+X#
+X# Uncomment the following block to use the GL option.
+X
+X#GL_USE = -DUSE_GL
+X#GL_LIBDEPS=
+X#GL_LIBS= -lgl_s
+X#GL_SRC = glmodule.c cgensupport.c
+X#GL_OBJ = glmodule.o cgensupport.o
+X
+X
+X# Panel Option
+X# ============
+X#
+X# If you have source to the NASA Ames Panel Library, you can configure
+X# Python to incorporate the built-in module 'pnl', which is used byu
+X# the standard module 'panel' to provide an interface to most features
+X# of the Panel Library. This option requires that you also turn on the
+X# GL option. It adds about 100K to the Python text size and about 160K
+X# to the unstripped binary size.
+X#
+X# Uncomment and edit the following block to use the Panel option.
+X# - Edit the PANELDIR definition to point to the top-level directory
+X# of the Panel distribution tree.
+X
+X#PANELDIR= /usr/people/guido/src/pl
+X#PANELLIBDIR= $(PANELDIR)/library
+X#LIBPANEL= $(PANELLIBDIR)/lib/libpanel.a
+X#PANEL_USE= -DUSE_PANEL
+X#PANEL_INCL= -I$(PANELLIBDIR)/include
+X#PANEL_LIBDEPS= $(LIBPANEL)
+X#PANEL_LIBS= $(LIBPANEL)
+X#PANEL_SRC= panelmodule.c
+X#PANEL_OBJ= panelmodule.o
+X
+X
+X# Audio Option
+X# ============
+X#
+X# This option lets you play with /dev/audio on the IRIS 4D/25.
+X# It incorporates the built-in module 'audio'.
+X# Warning: using the asynchronous I/O facilities of this module can
+X# create a second 'thread', which looks in the listings of 'ps' like a
+X# forked child. However, it shares its address space with the parent.
+X#
+X# Uncomment the following block to use the Audio option.
+X
+X#AUDIO_USE= -DUSE_AUDIO
+X#AUDIO_SRC= audiomodule.c asa.c
+X#AUDIO_OBJ= audiomodule.o asa.o
+X
+X
+X# Major Definitions
+X# =================
+X
+XSTANDARD_OBJ= acceler.o bltinmodule.o ceval.o classobject.o \
+X compile.o dictobject.o errors.o fgetsintr.o \
+X fileobject.o floatobject.o $(FMOD_OBJ) frameobject.o \
+X funcobject.o $(GETCWD_OBJ) \
+X graminit.o grammar1.o import.o \
+X intobject.o intrcheck.o listnode.o listobject.o \
+X mathmodule.o methodobject.o modsupport.o \
+X moduleobject.o node.o object.o parser.o \
+X parsetok.o posixmodule.o regexp.o regexpmodule.o \
+X strdup.o $(STRERROR_OBJ) \
+X stringobject.o $(STRTOL_OBJ) structmember.o \
+X sysmodule.o timemodule.o tokenizer.o traceback.o \
+X tupleobject.o typeobject.o
+X
+XSTANDARD_SRC= acceler.c bltinmodule.c ceval.c classobject.c \
+X compile.c dictobject.c errors.c fgetsintr.c \
+X fileobject.c floatobject.c $(FMOD_SRC) frameobject.c \
+X funcobject.c $(GETCWD_SRC) \
+X graminit.c grammar1.c import.c \
+X intobject.c intrcheck.c listnode.c listobject.c \
+X mathmodule.c methodobject.c modsupport.c \
+X moduleobject.c node.c object.c parser.c \
+X parsetok.c posixmodule.c regexp.c regexpmodule.c \
+X strdup.c $(STRERROR_SRC) \
+X stringobject.c $(STRTOL_SRC) structmember.c \
+X sysmodule.c timemodule.c tokenizer.c traceback.c \
+X tupleobject.c typeobject.c
+X
+XCONFIGDEFS= $(STDW_USE) $(AM_USE) $(AUDIO_USE) $(GL_USE) $(PANEL_USE) \
+X '-DPYTHONPATH="$(PYTHONPATH)"'
+X
+XCONFIGINCLS= $(STDW_INCL)
+X
+XLIBDEPS= libpython.a $(STDW_LIBDEPS) $(AM_LIBDEPS) \
+X $(GL_LIBDEPS) $(PANEL_LIBSDEP) $(RL_LIBDEPS)
+X
+X# NB: the ordering of items in LIBS is significant!
+XLIBS= libpython.a $(STDW_LIBS) $(AM_LIBS) \
+X $(PANEL_LIBS) $(GL_LIBS) $(RL_LIBS) -lm
+X
+XLIBOBJECTS= $(STANDARD_OBJ) $(STDW_OBJ) $(AM_OBJ) $(AUDIO_OBJ) \
+X $(GL_OBJ) $(PANEL_OBJ)
+X
+XLIBSOURCES= $(STANDARD_SRC) $(STDW_SRC) $(AM_SRC) $(AUDIO_SRC) \
+X $(GL_SRC) $(PANEL_SRC)
+X
+XOBJECTS= pythonmain.o config.o
+X
+XSOURCES= $(LIBSOURCES) pythonmain.c config.c
+X
+XGENOBJECTS= acceler.o fgetsintr.o grammar1.o \
+X intrcheck.o listnode.o node.o parser.o \
+X parsetok.o strdup.o tokenizer.o bitset.o \
+X firstsets.o grammar.o metagrammar.o pgen.o \
+X pgenmain.o printgrammar.o
+X
+XGENSOURCES= acceler.c fgetsintr.c grammar1.c \
+X intrcheck.c listnode.c node.c parser.c \
+X parsetok.c strdup.c tokenizer.c bitset.c \
+X firstsets.c grammar.c metagrammar.c pgen.c \
+X pgenmain.c printgrammar.c
+X
+X
+X# Main Targets
+X# ============
+X
+Xpython: libpython.a $(OBJECTS) $(LIBDEPS) Makefile
+X $(CC) $(CFLAGS) $(OBJECTS) $(LIBS) -o @python
+X mv @python python
+X
+Xlibpython.a: $(LIBOBJECTS)
+X -rm -f @lib
+X ar cr @lib $(LIBOBJECTS)
+X $(RANLIB) @lib
+X mv @lib libpython.a
+X
+Xpython_gen: $(GENOBJECTS) $(RL_LIBDEPS)
+X $(CC) $(CFLAGS) $(GENOBJECTS) $(RL_LIBS) -o python_gen
+X
+X
+X# Utility Targets
+X# ===============
+X
+X# Don't take the output from lint too seriously. I have not attempted
+X# to make Python lint-free. But I use function prototypes.
+X
+XLINTFLAGS= -h
+X
+XLINTCPPFLAGS= $(CONFIGDEFS) $(CONFIGINCLS) $(SYSVDEF) \
+X $(AM_INCL) $(PANEL_INCL)
+X
+XLINT= lint
+X
+Xlint:: $(SOURCES)
+X $(LINT) $(LINTFLAGS) $(LINTCPPFLAGS) $(SOURCES)
+X
+Xlint:: $(GENSOURCES)
+X $(LINT) $(LINTFLAGS) $(GENSOURCES)
+X
+X# Generating dependencies is only necessary if you intend to hack Python.
+X# You may change $(MKDEP) to your favorite dependency generator (it should
+X# edit the Makefile in place).
+X
+XMKDEP= mkdep
+X
+Xdepend::
+X $(MKDEP) $(LINTCPPFLAGS) $(SOURCES) $(GENSOURCES)
+X
+X# You may change $(CTAGS) to suit your taste...
+X
+XCTAGS= ctags -t -w
+X
+XHEADERS= *.h
+X
+Xtags: $(SOURCES) $(GENSOURCES) $(HEADERS)
+X $(CTAGS) $(SOURCES) $(GENSOURCES) $(HEADERS)
+X
+Xclean::
+X -rm -f *.o core [,#@]*
+X
+Xclobber:: clean
+X -rm -f python python_gen libpython.a tags
+X
+X
+X# Build Special Objects
+X# =====================
+X
+X# You may change $(COMPILE) to reflect the default .c.o rule...
+X
+XCOMPILE= $(CC) -c $(CFLAGS)
+X
+Xamoebamodule.o: amoebamodule.c
+X $(COMPILE) $(AM_INCL) $*.c
+X
+Xconfig.o: config.c Makefile
+X $(COMPILE) $(CONFIGDEFS) $(CONFIGINCLS) $*.c
+X
+Xfgetsintr.o: fgetsintr.c
+X $(COMPILE) $(SIGTYPEDEF) $*.c
+X
+Xintrcheck.o: intrcheck.c
+X $(COMPILE) $(SIGTYPEDEF) $*.c
+X
+Xpanelmodule.o: panelmodule.c
+X $(COMPILE) $(PANEL_INCL) $*.c
+X
+Xposixmodule.o: posixmodule.c
+X $(COMPILE) $(SYSVDEF) $(NOSYMLINKDEF) $*.c
+X
+Xsc_interpr.o: sc_interpr.c
+X $(COMPILE) $(AM_INCL) $*.c
+X
+Xsc_error.o: sc_error.c
+X $(COMPILE) $(AM_INCL) $*.c
+X
+Xstdwinmodule.o: stdwinmodule.c
+X $(COMPILE) $(STDW_INCL) $*.c
+X
+Xtimemodule.o: timemodule.c
+X $(COMPILE) $(SIGTYPEDEF) $(BSDTIMEDEF) $*.c
+X
+Xtokenizer.o: tokenizer.c
+X $(COMPILE) $(RL_USE) $*.c
+X
+X.PRECIOUS: python libpython.a glmodule.c graminit.c graminit.h
+X
+X
+X# Generated Sources
+X# =================
+X#
+X# Some source files are (or may be) generated.
+X# The rules for doing so are given here.
+X
+X# Build "glmodule.c", the GL interface.
+X# Ignore the messages emitted by the cgen script.
+X# Also ignore the warnings emitted while compiling glmodule.c; it works.
+X
+Xglmodule.c: cstubs cgen
+X python cgen <cstubs >@glmodule.c
+X mv @glmodule.c glmodule.c
+X
+X# The dependencies for graminit.[ch] are not turned on in the
+X# distributed Makefile because the files themselves are distributed.
+X# Turn them on if you want to hack the grammar.
+X
+X#graminit.c graminit.h: Grammar python_gen
+X# python_gen Grammar
+X
+EOF
+fi
+if test -s 'src/amoebamodule.c'
+then echo '*** I will not over-write existing file src/amoebamodule.c'
+else
+echo 'x - src/amoebamodule.c'
+sed 's/^X//' > 'src/amoebamodule.c' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/* Amoeba module implementation */
+X
+X/* Amoeba includes */
+X#include <amoeba.h>
+X#include <cmdreg.h>
+X#include <stdcom.h>
+X#include <stderr.h>
+X#include <caplist.h>
+X#include <server/bullet/bullet.h>
+X#include <server/tod/tod.h>
+X#include <module/name.h>
+X#include <module/direct.h>
+X#include <module/mutex.h>
+X#include <module/prv.h>
+X#include <module/stdcmd.h>
+X
+X/* C includes */
+X#include <stdlib.h>
+X#include <ctype.h>
+X
+X/* POSIX includes */
+X#include <fcntl.h>
+X#include <sys/types.h>
+X#include <sys/stat.h>
+X
+X/* Python includes */
+X#include "allobjects.h"
+X#include "modsupport.h"
+X#include "sc_global.h"
+X#include "stubcode.h"
+X
+Xextern char *err_why();
+Xextern char *ar_cap();
+X
+X#define STUBCODE "+stubcode"
+X
+Xstatic object *AmoebaError;
+Xobject *StubcodeError;
+X
+Xstatic object *sc_dict;
+X
+X/* Module initialization */
+X
+Xextern struct methodlist amoeba_methods[]; /* Forward */
+Xextern object *convertcapv(); /* Forward */
+X
+Xstatic void
+Xins(d, name, v)
+X object *d;
+X char *name;
+X object *v;
+X{
+X if (v == NULL || dictinsert(d, name, v) != 0)
+X fatal("can't initialize amoeba module");
+X}
+X
+Xvoid
+Xinitamoeba()
+X{
+X object *m, *d, *v;
+X
+X m = initmodule("amoeba", amoeba_methods);
+X d = getmoduledict(m);
+X
+X /* Define capv */
+X v = convertcapv();
+X ins(d, "capv", v);
+X DECREF(v);
+X
+X /* Set timeout */
+X timeout((interval)2000);
+X
+X /* Initialize amoeba.error exception */
+X AmoebaError = newstringobject("amoeba.error");
+X ins(d, "error", AmoebaError);
+X StubcodeError = newstringobject("amoeba.stubcode_error");
+X ins(d, "stubcode_error", StubcodeError);
+X sc_dict = newdictobject();
+X}
+X
+X
+X/* Set an Amoeba-specific error, and return NULL */
+X
+Xobject *
+Xamoeba_error(err)
+X errstat err;
+X{
+X object *v = newtupleobject(2);
+X if (v != NULL) {
+X settupleitem(v, 0, newintobject((long)err));
+X settupleitem(v, 1, newstringobject(err_why(err)));
+X }
+X err_setval(AmoebaError, v);
+X if (v != NULL)
+X DECREF(v);
+X return NULL;
+X}
+X
+X
+X/* Capability object implementation */
+X
+Xextern typeobject Captype; /* Forward */
+X
+X#define is_capobject(v) ((v)->ob_type == &Captype)
+X
+Xtypedef struct {
+X OB_HEAD
+X capability ob_cap;
+X} capobject;
+X
+Xobject *
+Xnewcapobject(cap)
+X capability *cap;
+X{
+X capobject *v = NEWOBJ(capobject, &Captype);
+X if (v == NULL)
+X return NULL;
+X v->ob_cap = *cap;
+X return (object *)v;
+X}
+X
+Xgetcapability(v, cap)
+X object *v;
+X capability *cap;
+X{
+X
+X if (!is_capobject(v))
+X return err_badarg();
+X *cap = ((capobject *)v)->ob_cap;
+X return 0;
+X}
+X
+X/*
+X * is_capobj exports the is_capobject macro to the stubcode modules
+X */
+X
+Xint
+Xis_capobj(v)
+X object *v;
+X{
+X
+X return is_capobject(v);
+X}
+X
+X/* Methods */
+X
+Xstatic void
+Xcapprint(v, fp, flags)
+X capobject *v;
+X FILE *fp;
+X int flags;
+X{
+X /* XXX needs lock when multi-threading */
+X fputs(ar_cap(&v->ob_cap), fp);
+X}
+X
+Xstatic object *
+Xcaprepr(v)
+X capobject *v;
+X{
+X /* XXX needs lock when multi-threading */
+X return newstringobject(ar_cap(&v->ob_cap));
+X}
+X
+Xextern object *sc_interpreter();
+X
+Xextern struct methodlist cap_methods[]; /* Forward */
+X
+Xobject *
+Xsc_makeself(cap, stubcode, name)
+X object *cap, *stubcode;
+X char *name;
+X{
+X object *sc_name, *sc_self;
+X
+X sc_name = newstringobject(name);
+X if (sc_name == NULL)
+X return NULL;
+X sc_self = newtupleobject(3);
+X if (sc_self == NULL) {
+X DECREF(sc_name);
+X return NULL;
+X }
+X if (settupleitem(sc_self, NAME, sc_name) != 0) {
+X DECREF(sc_self);
+X return NULL;
+X }
+X INCREF(cap);
+X if (settupleitem(sc_self, CAP, cap) != 0) {
+X DECREF(sc_self);
+X return NULL;
+X }
+X INCREF(stubcode);
+X if (settupleitem(sc_self, STUBC, stubcode) != 0) {
+X DECREF(sc_self);
+X return NULL;
+X }
+X return sc_self;
+X}
+X
+X
+Xstatic void
+Xswapcode(code, len)
+X char *code;
+X int len;
+X{
+X int i = sizeof(TscOperand);
+X TscOpcode opcode;
+X TscOperand operand;
+X
+X while (i < len) {
+X memcpy(&opcode, &code[i], sizeof(TscOpcode));
+X SwapOpcode(opcode);
+X memcpy(&code[i], &opcode, sizeof(TscOpcode));
+X i += sizeof(TscOpcode);
+X if (opcode & OPERAND) {
+X memcpy(&operand, &code[i], sizeof(TscOperand));
+X SwapOperand(operand);
+X memcpy(&code[i], &operand, sizeof(TscOperand));
+X i += sizeof(TscOperand);
+X }
+X }
+X}
+X
+Xobject *
+Xsc_findstubcode(v, name)
+X object *v;
+X char *name;
+X{
+X int fd, fsize;
+X char *fname, *buffer;
+X struct stat statbuf;
+X object *sc_stubcode, *ret;
+X TscOperand sc_magic;
+X
+X /*
+X * Only look in the current directory for now.
+X */
+X fname = malloc(strlen(name) + 4);
+X if (fname == NULL) {
+X return err_nomem();
+X }
+X sprintf(fname, "%s.sc", name);
+X if ((fd = open(fname, O_RDONLY)) == -1) {
+X extern int errno;
+X
+X if (errno == 2) {
+X /*
+X ** errno == 2 is file not found.
+X */
+X err_setstr(NameError, fname);
+X return NULL;
+X }
+X free(fname);
+X return err_errno(newstringobject(name));
+X }
+X fstat(fd, &statbuf);
+X fsize = (int)statbuf.st_size;
+X buffer = malloc(fsize);
+X if (buffer == NULL) {
+X free(fname);
+X close(fd);
+X return err_nomem();
+X }
+X if (read(fd, buffer, fsize) != fsize) {
+X close(fd);
+X free(fname);
+X return err_errno(newstringobject(name));
+X }
+X close(fd);
+X free(fname);
+X memcpy(&sc_magic, buffer, sizeof(TscOperand));
+X if (sc_magic != SC_MAGIC) {
+X SwapOperand(sc_magic);
+X if (sc_magic != SC_MAGIC) {
+X free(buffer);
+X return NULL;
+X } else {
+X swapcode(buffer, fsize);
+X }
+X }
+X sc_stubcode = newsizedstringobject( &buffer[sizeof(TscOperand)],
+X fsize - sizeof(TscOperand));
+X free(buffer);
+X if (sc_stubcode == NULL) {
+X return NULL;
+X }
+X if (dictinsert(sc_dict, name, sc_stubcode) != 0) {
+X DECREF(sc_stubcode);
+X return NULL;
+X }
+X DECREF(sc_stubcode); /* XXXX */
+X sc_stubcode = sc_makeself(v, sc_stubcode, name);
+X if (sc_stubcode == NULL) {
+X return NULL;
+X }
+X return sc_stubcode;
+X}
+X
+Xobject *
+Xcapgetattr(v, name)
+X capobject *v;
+X char *name;
+X{
+X object *sc_method, *sc_stubcodemethod;
+X
+X if (sc_dict == NULL) {
+X /*
+X ** For some reason the dictionary has not been
+X ** initialized. Try to find one of the built in
+X ** methods.
+X */
+X return findmethod(cap_methods, (object *)v, name);
+X }
+X sc_stubcodemethod = dictlookup(sc_dict, name);
+X if (sc_stubcodemethod != NULL) {
+X /*
+X ** There is a stubcode method in the dictionary.
+X ** Execute the stubcode interpreter with the right
+X ** arguments.
+X */
+X object *self, *ret;
+X
+X self = sc_makeself((object *)v, sc_stubcodemethod, name);
+X if (self == NULL) {
+X return NULL;
+X }
+X ret = findmethod(cap_methods, self, STUBCODE);
+X DECREF(self);
+X return ret;
+X }
+X err_clear();
+X sc_method = findmethod(cap_methods, (object *)v, name);
+X if (sc_method == NULL) {
+X /*
+X ** The method is not built in and not in the
+X ** dictionary. Try to find it as a stubcode file.
+X */
+X object *self, *ret;
+X
+X err_clear();
+X self = sc_findstubcode((object *)v, name);
+X if (self == NULL) {
+X return NULL;
+X }
+X ret = findmethod(cap_methods, self, STUBCODE);
+X DECREF(self);
+X return ret;
+X }
+X return sc_method;
+X}
+X
+Xint
+Xcapcompare(v, w)
+X capobject *v, *w;
+X{
+X int cmp = bcmp((char *)&v->ob_cap.cap_port,
+X (char *)&w->ob_cap, PORTSIZE);
+X if (cmp != 0)
+X return cmp;
+X return prv_number(&v->ob_cap.cap_priv) -
+X prv_number(&w->ob_cap.cap_priv);
+X}
+X
+Xstatic typeobject Captype = {
+X OB_HEAD_INIT(&Typetype)
+X 0,
+X "capability",
+X sizeof(capobject),
+X 0,
+X free, /*tp_dealloc*/
+X capprint, /*tp_print*/
+X capgetattr, /*tp_getattr*/
+X 0, /*tp_setattr*/
+X capcompare, /*tp_comp
+are*/
+X caprepr, /*tp_repr*/
+X 0, /*tp_as_number*/
+X 0, /*tp_as_sequence*/
+X 0, /*tp_as_mapping*/
+X};
+X
+X
+X/* Return a dictionary corresponding to capv */
+X
+Xextern struct caplist *capv;
+X
+Xstatic object *
+Xconvertcapv()
+X{
+X object *d;
+X struct caplist *c;
+X d = newdictobject();
+X if (d == NULL)
+X return NULL;
+X if (capv == NULL)
+X return d;
+X for (c = capv; c->cl_name != NULL; c++) {
+X object *v = newcapobject(c->cl_cap);
+X if (v == NULL || dictinsert(d, c->cl_name, v) != 0) {
+X DECREF(d);
+X return NULL;
+X }
+X DECREF(v);
+X }
+X return d;
+X}
+X
+X
+X/* Strongly Amoeba-specific argument handlers */
+X
+Xstatic int
+Xgetcaparg(v, a)
+X object *v;
+X capability *a;
+X{
+X if (v == NULL || !is_capobject(v))
+X return err_badarg();
+X *a = ((capobject *)v) -> ob_cap;
+X return 1;
+X}
+X
+Xstatic int
+Xgetstrcapargs(v, a, b)
+X object *v;
+X object **a;
+X capability *b;
+X{
+X if (v == NULL || !is_tupleobject(v) || gettuplesize(v) != 2)
+X return err_badarg();
+X return getstrarg(gettupleitem(v, 0), a) &&
+X getcaparg(gettupleitem(v, 1), b);
+X}
+X
+X
+X/* Amoeba methods */
+X
+Xstatic object *
+Xamoeba_name_lookup(self, args)
+X object *self;
+X object *args;
+X{
+X object *name;
+X capability cap;
+X errstat err;
+X if (!getstrarg(args, &name))
+X return NULL;
+X err = name_lookup(getstringvalue(name), &cap);
+X if (err != STD_OK)
+X return amoeba_error(err);
+X return newcapobject(&cap);
+X}
+X
+Xstatic object *
+Xamoeba_name_append(self, args)
+X object *self;
+X object *args;
+X{
+X object *name;
+X capability cap;
+X errstat err;
+X if (!getstrcapargs(args, &name, &cap))
+X return NULL;
+X err = name_append(getstringvalue(name), &cap);
+X if (err != STD_OK)
+X return amoeba_error(err);
+X INCREF(None);
+X return None;
+X}
+X
+Xstatic object *
+Xamoeba_name_replace(self, args)
+X object *self;
+X object *args;
+X{
+X object *name;
+X capability cap;
+X errstat err;
+X if (!getstrcapargs(args, &name, &cap))
+X return NULL;
+X err = name_replace(getstringvalue(name), &cap);
+X if (err != STD_OK)
+X return amoeba_error(err);
+X INCREF(None);
+X return None;
+X}
+X
+Xstatic object *
+Xamoeba_name_delete(self, args)
+X object *self;
+X object *args;
+X{
+X object *name;
+X errstat err;
+X if (!getstrarg(args, &name))
+X return NULL;
+X err = name_delete(getstringvalue(name));
+X if (err != STD_OK)
+X return amoeba_error(err);
+X INCREF(None);
+X return None;
+X}
+X
+Xstatic object *
+Xamoeba_timeout(self, args)
+X object *self;
+X object *args;
+X{
+X int i;
+X object *v;
+X interval tout;
+X if (!getintarg(args, &i))
+X return NULL;
+X tout = timeout((interval)i);
+X v = newintobject((long)tout);
+X if (v == NULL)
+X timeout(tout);
+X return v;
+X}
+X
+Xstatic struct methodlist amoeba_methods[] = {
+X {"name_append", amoeba_name_append},
+X {"name_delete", amoeba_name_delete},
+X {"name_lookup", amoeba_name_lookup},
+X {"name_replace", amoeba_name_replace},
+X {"timeout", amoeba_timeout},
+X {NULL, NULL} /* Sentinel */
+X};
+X
+X/* Capability methods */
+X
+Xstatic object *
+Xcap_b_size(self, args)
+X capobject *self;
+X object *args;
+X{
+X errstat err;
+X b_fsize size;
+X if (!getnoarg(args))
+X return NULL;
+X err = b_size(&self->ob_cap, &size);
+X if (err != STD_OK)
+X return amoeba_error(err);
+X return newintobject((long)size);
+X}
+X
+Xstatic object *
+Xcap_b_read(self, args)
+X capobject *self;
+X object *args;
+X{
+X errstat err;
+X char *buf;
+X object *v;
+X long offset, size;
+X b_fsize nread;
+X if (!getlonglongargs(args, &offset, &size))
+X return NULL;
+X buf = malloc((unsigned int)size);
+X if (buf == NULL) {
+X return err_nomem();
+X }
+X err = b_read(&self->ob_cap, (b_fsize)offset, buf, (b_fsize)size,
+X &nread);
+X if (err != STD_OK) {
+X free(buf);
+X return amoeba_error(err);
+X }
+X v = newsizedstringobject(buf, (int)nread);
+X free(buf);
+X return v;
+X}
+X
+Xstatic object *
+Xcap_dir_lookup(self, args)
+X capobject *self;
+X object *args;
+X{
+X object *name;
+X capability cap;
+X errstat err;
+X if (!getstrarg(args, &name))
+X return NULL;
+X err = dir_lookup(&self->ob_cap, getstringvalue(name), &cap);
+X if (err != STD_OK)
+X return amoeba_error(err);
+X return newcapobject(&cap);
+X}
+X
+Xstatic object *
+Xcap_dir_append(self, args)
+X capobject *self;
+X object *args;
+X{
+X object *name;
+X capability cap;
+X errstat err;
+X if (!getstrcapargs(args, &name, &cap))
+X return NULL;
+X err = dir_append(&self->ob_cap, getstringvalue(name), &cap);
+X if (err != STD_OK)
+X return amoeba_error(err);
+X INCREF(None);
+X return None;
+X}
+X
+Xstatic object *
+Xcap_dir_delete(self, args)
+X capobject *self;
+X object *args;
+X{
+X object *name;
+X errstat err;
+X if (!getstrarg(args, &name))
+X return NULL;
+X err = dir_delete(&self->ob_cap, getstringvalue(name));
+X if (err != STD_OK)
+X return amoeba_error(err);
+X INCREF(None);
+X return None;
+X}
+X
+Xstatic object *
+Xcap_dir_replace(self, args)
+X capobject *self;
+X object *args;
+X{
+X object *name;
+X capability cap;
+X errstat err;
+X if (!getstrcapargs(args, &name, &cap))
+X return NULL;
+X err = dir_replace(&self->ob_cap, getstringvalue(name), &cap);
+X if (err != STD_OK)
+X return amoeba_error(err);
+X INCREF(None);
+X return None;
+X}
+X
+Xstatic object *
+Xcap_dir_list(self, args)
+X capobject *self;
+X object *args;
+X{
+X errstat err;
+X struct dir_open *dd;
+X object *d;
+X char *name;
+X if (!getnoarg(args))
+X return NULL;
+X if ((dd = dir_open(&self->ob_cap)) == NULL)
+X return amoeba_error(STD_COMBAD);
+X if ((d = newlistobject(0)) == NULL) {
+X dir_close(dd);
+X return NULL;
+X }
+X while ((name = dir_next(dd)) != NULL) {
+X object *v;
+X v = newstringobject(name);
+X if (v == NULL) {
+X DECREF(d);
+X d = NULL;
+X break;
+X }
+X if (addlistitem(d, v) != 0) {
+X DECREF(v);
+X DECREF(d);
+X d = NULL;
+X break;
+X }
+X DECREF(v);
+X }
+X dir_close(dd);
+X return d;
+X}
+X
+Xobject *
+Xcap_std_info(self, args)
+X capobject *self;
+X object *args;
+X{
+X char buf[256];
+X errstat err;
+X int n;
+X if (!getnoarg(args))
+X return NULL;
+X err = std_info(&self->ob_cap, buf, sizeof buf, &n);
+X if (err != STD_OK)
+X return amoeba_error(err);
+X return newsizedstringobject(buf, n);
+X}
+X
+Xobject *
+Xcap_tod_gettime(self, args)
+X capobject *self;
+X object *args;
+X{
+X header h;
+X errstat err;
+X bufsize n;
+X long sec;
+X int msec, tz, dst;
+X if (!getnoarg(args))
+X return NULL;
+X h.h_port = self->ob_cap.cap_port;
+X h.h_priv = self->ob_cap.cap_priv;
+X h.h_command = TOD_GETTIME;
+X n = trans(&h, NILBUF, 0, &h, NILBUF, 0);
+X if (ERR_STATUS(n))
+X return amoeba_error(ERR_CONVERT(n));
+X tod_decode(&h, &sec, &msec, &tz, &dst);
+X return newintobject(sec);
+X}
+X
+Xobject *
+Xcap_tod_settime(self, args)
+X capobject *self;
+X object *args;
+X{
+X header h;
+X errstat err;
+X bufsize n;
+X long sec;
+X if (!getlongarg(args, &sec))
+X return NULL;
+X h.h_port = self->ob_cap.cap_port;
+X h.h_priv = self->ob_cap.cap_priv;
+X h.h_command = TOD_SETTIME;
+X tod_encode(&h, sec, 0, 0, 0);
+X n = trans(&h, NILBUF, 0, &h, NILBUF, 0);
+X if (ERR_STATUS(n))
+X return amoeba_error(ERR_CONVERT(n));
+X INCREF(None);
+X return None;
+X}
+X
+Xstatic struct methodlist cap_methods[] = {
+X { STUBCODE, sc_interpreter},
+X {"b_read", cap_b_read},
+X {"b_size", cap_b_size},
+X {"dir_append", cap_dir_append},
+X {"dir_delete", cap_dir_delete},
+X {"dir_list", cap_dir_list},
+X {"dir_lookup", cap_dir_lookup},
+X {"dir_replace", cap_dir_replace},
+X {"std_info", cap_std_info},
+X {"tod_gettime", cap_tod_gettime},
+X {"tod_settime", cap_tod_settime},
+X {NULL, NULL} /* Sentinel */
+X};
+EOF
+fi
+if test -s 'src/tokenizer.c'
+then echo '*** I will not over-write existing file src/tokenizer.c'
+else
+echo 'x - src/tokenizer.c'
+sed 's/^X//' > 'src/tokenizer.c' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/* Tokenizer implementation */
+X
+X/* XXX This is rather old, should be restructured perhaps */
+X/* XXX Need a better interface to report errors than writing to stderr */
+X/* XXX Should use editor resource to fetch true tab size on Macintosh */
+X
+X#include "pgenheaders.h"
+X
+X#include <ctype.h>
+X#include "string.h"
+X
+X#include "fgetsintr.h"
+X#include "tokenizer.h"
+X#include "errcode.h"
+X
+X#ifdef THINK_C
+X#define TABSIZE 4
+X#endif
+X
+X#ifndef TABSIZE
+X#define TABSIZE 8
+X#endif
+X
+X/* Forward */
+Xstatic struct tok_state *tok_new PROTO((void));
+Xstatic int tok_nextc PROTO((struct tok_state *tok));
+Xstatic void tok_backup PROTO((struct tok_state *tok, int c));
+X
+X/* Token names */
+X
+Xchar *tok_name[] = {
+X "ENDMARKER",
+X "NAME",
+X "NUMBER",
+X "STRING",
+X "NEWLINE",
+X "INDENT",
+X "DEDENT",
+X "LPAR",
+X "RPAR",
+X "LSQB",
+X "RSQB",
+X "COLON",
+X "COMMA",
+X "SEMI",
+X "PLUS",
+X "MINUS",
+X "STAR",
+X "SLASH",
+X "VBAR",
+X "AMPER",
+X "LESS",
+X "GREATER",
+X "EQUAL",
+X "DOT",
+X "PERCENT",
+X "BACKQUOTE",
+X "LBRACE",
+X "RBRACE",
+X "OP",
+X "<ERRORTOKEN>",
+X "<N_TOKENS>"
+X};
+X
+X
+X/* Create and initialize a new tok_state structure */
+X
+Xstatic struct tok_state *
+Xtok_new()
+X{
+X struct tok_state *tok = NEW(struct tok_state, 1);
+X if (tok == NULL)
+X return NULL;
+X tok->buf = tok->cur = tok->end = tok->inp = NULL;
+X tok->done = E_OK;
+X tok->fp = NULL;
+X tok->tabsize = TABSIZE;
+X tok->indent = 0;
+X tok->indstack[0] = 0;
+X tok->atbol = 1;
+X tok->pendin = 0;
+X tok->prompt = tok->nextprompt = NULL;
+X tok->lineno = 0;
+X return tok;
+X}
+X
+X
+X/* Set up tokenizer for string */
+X
+Xstruct tok_state *
+Xtok_setups(str)
+X char *str;
+X{
+X struct tok_state *tok = tok_new();
+X if (tok == NULL)
+X return NULL;
+X tok->buf = tok->cur = str;
+X tok->end = tok->inp = strchr(str, '\0');
+X return tok;
+X}
+X
+X
+X/* Set up tokenizer for string */
+X
+Xstruct tok_state *
+Xtok_setupf(fp, ps1, ps2)
+X FILE *fp;
+X char *ps1, *ps2;
+X{
+X struct tok_state *tok = tok_new();
+X if (tok == NULL)
+X return NULL;
+X if ((tok->buf = NEW(char, BUFSIZ)) == NULL) {
+X DEL(tok);
+X return NULL;
+X }
+X tok->cur = tok->inp = tok->buf;
+X tok->end = tok->buf + BUFSIZ;
+X tok->fp = fp;
+X tok->prompt = ps1;
+X tok->nextprompt = ps2;
+X return tok;
+X}
+X
+X
+X/* Free a tok_state structure */
+X
+Xvoid
+Xtok_free(tok)
+X struct tok_state *tok;
+X{
+X /* XXX really need a separate flag to say 'my buffer' */
+X if (tok->fp != NULL && tok->buf != NULL)
+X DEL(tok->buf);
+X DEL(tok);
+X}
+X
+X
+X/* Get next char, updating state; error code goes into tok->done */
+X
+Xstatic int
+Xtok_nextc(tok)
+X register struct tok_state *tok;
+X{
+X if (tok->done != E_OK)
+X return EOF;
+X
+X for (;;) {
+X if (tok->cur < tok->inp)
+X return *tok->cur++;
+X if (tok->fp == NULL) {
+X tok->done = E_EOF;
+X return EOF;
+X }
+X if (tok->inp > tok->buf && tok->inp[-1] == '\n')
+X tok->inp = tok->buf;
+X if (tok->inp == tok->end) {
+X int n = tok->end - tok->buf;
+X char *new = tok->buf;
+X RESIZE(new, char, n+n);
+X if (new == NULL) {
+X fprintf(stderr, "tokenizer out of mem\n");
+X tok->done = E_NOMEM;
+X return EOF;
+X }
+X tok->buf = new;
+X tok->inp = tok->buf + n;
+X tok->end = tok->inp + n;
+X }
+X#ifdef USE_READLINE
+X if (tok->prompt != NULL) {
+X extern char *readline PROTO((char *prompt));
+X static int been_here;
+X if (!been_here) {
+X /* Force rebind of TAB to insert-tab */
+X extern int rl_insert();
+X rl_bind_key('\t', rl_insert);
+X been_here++;
+X }
+X if (tok->buf != NULL)
+X free(tok->buf);
+X tok->buf = readline(tok->prompt);
+X (void) intrcheck(); /* Clear pending interrupt */
+X if (tok->nextprompt != NULL)
+X tok->prompt = tok->nextprompt;
+X /* XXX different semantics w/o readline()! */
+X if (tok->buf == NULL) {
+X tok->done = E_EOF;
+X }
+X else {
+X unsigned int n = strlen(tok->buf);
+X if (n > 0)
+X add_history(tok->buf);
+X /* Append the '\n' that readline()
+X doesn't give us, for the tokenizer... */
+X tok->buf = realloc(tok->buf, n+2);
+X if (tok->buf == NULL)
+X tok->done = E_NOMEM;
+X else {
+X tok->end = tok->buf + n;
+X *tok->end++ = '\n';
+X *tok->end = '\0';
+X tok->inp = tok->end;
+X tok->cur = tok->buf;
+X }
+X }
+X }
+X else
+X#endif
+X {
+X tok->cur = tok->inp;
+X if (tok->prompt != NULL && tok->inp == tok->buf) {
+X fprintf(stderr, "%s", tok->prompt);
+X tok->prompt = tok->nextprompt;
+X }
+X tok->done = fgets_intr(tok->inp,
+X (int)(tok->end - tok->inp), tok->fp);
+X }
+X if (tok->done != E_OK) {
+X if (tok->prompt != NULL)
+X fprintf(stderr, "\n");
+X return EOF;
+X }
+X tok->inp = strchr(tok->inp, '\0');
+X }
+X}
+X
+X
+X/* Back-up one character */
+X
+Xstatic void
+Xtok_backup(tok, c)
+X register struct tok_state *tok;
+X register int c;
+X{
+X if (c != EOF) {
+X if (--tok->cur < tok->buf) {
+X fprintf(stderr, "tok_backup: begin of buffer\n");
+X abort();
+X }
+X if (*tok->cur != c)
+X *tok->cur = c;
+X }
+X}
+X
+X
+X/* Return the token corresponding to a single character */
+X
+Xint
+Xtok_1char(c)
+X int c;
+X{
+X switch (c) {
+X case '(': return LPAR;
+X case ')': return RPAR;
+X case '[': return LSQB;
+X case ']': return RSQB;
+X case ':': return COLON;
+X case ',': return COMMA;
+X case ';': return SEMI;
+X case '+': return PLUS;
+X case '-': return MINUS;
+X case '*': return STAR;
+X case '/': return SLASH;
+X case '|': return VBAR;
+X case '&': return AMPER;
+X case '<': return LESS;
+X case '>': return GREATER;
+X case '=': return EQUAL;
+X case '.': return DOT;
+X case '%': return PERCENT;
+X case '`': return BACKQUOTE;
+X case '{': return LBRACE;
+X case '}': return RBRACE;
+X default: return OP;
+X }
+X}
+X
+X
+X/* Get next token, after space stripping etc. */
+X
+Xint
+Xtok_get(tok, p_start, p_end)
+X register struct tok_state *tok; /* In/out: tokenizer state */
+X char **p_start, **p_end; /* Out: point to start/end of token */
+X{
+X register int c;
+X
+X /* Get indentation level */
+X if (tok->atbol) {
+X register int col = 0;
+X tok->atbol = 0;
+X tok->lineno++;
+X for (;;) {
+X c = tok_nextc(tok);
+X if (c == ' ')
+X col++;
+X else if (c == '\t')
+X col = (col/tok->tabsize + 1) * tok->tabsize;
+X else
+X break;
+X }
+X tok_backup(tok, c);
+X if (col == tok->indstack[tok->indent]) {
+X /* No change */
+X }
+X else if (col > tok->indstack[tok->indent]) {
+X /* Indent -- always one */
+X if (tok->indent+1 >= MAXINDENT) {
+X fprintf(stderr, "excessive indent\n");
+X tok->done = E_TOKEN;
+X return ERRORTOKEN;
+X }
+X tok->pendin++;
+X tok->indstack[++tok->indent] = col;
+X }
+X else /* col < tok->indstack[tok->indent] */ {
+X /* Dedent -- any number, must be consistent */
+X while (tok->indent > 0 &&
+X col < tok->indstack[tok->indent]) {
+X tok->indent--;
+X tok->pendin--;
+X }
+X if (col != tok->indstack[tok->indent]) {
+X fprintf(stderr, "inconsistent dedent\n");
+X tok->done = E_TOKEN;
+X return ERRORTOKEN;
+X }
+X }
+X }
+X
+X *p_start = *p_end = tok->cur;
+X
+X /* Return pending indents/dedents */
+X if (tok->pendin != 0) {
+X if (tok->pendin < 0) {
+X tok->pendin++;
+X return DEDENT;
+X }
+X else {
+X tok->pendin--;
+X return INDENT;
+X }
+X }
+X
+X again:
+X /* Skip spaces */
+X do {
+X c = tok_nextc(tok);
+X } while (c == ' ' || c == '\t');
+X
+X /* Set start of current token */
+X *p_start = tok->cur - 1;
+X
+X /* Skip comment */
+X if (c == '#') {
+X /* Hack to allow overriding the tabsize in the file.
+X This is also recognized by vi, when it occurs near the
+X beginning or end of the file. (Will vi never die...?) */
+X int x;
+X /* XXX The case to (unsigned char *) is needed by THINK C 3.0 */
+X if (sscanf(/*(unsigned char *)*/tok->cur,
+X " vi:set tabsize=%d:", &x) == 1 &&
+X x >= 1 && x <= 40) {
+X fprintf(stderr, "# vi:set tabsize=%d:\n", x);
+X tok->tabsize = x;
+X }
+X do {
+X c = tok_nextc(tok);
+X } while (c != EOF && c != '\n');
+X }
+X
+X /* Check for EOF and errors now */
+X if (c == EOF)
+X return tok->done == E_EOF ? ENDMARKER : ERRORTOKEN;
+X
+X /* Identifier (most frequent token!) */
+X if (isalpha(c) || c == '_') {
+X do {
+X c = tok_nextc(tok);
+X } while (isalnum(c) || c == '_');
+X tok_backup(tok, c);
+X *p_end = tok->cur;
+X return NAME;
+X }
+X
+X /* Newline */
+X if (c == '\n') {
+X tok->atbol = 1;
+X *p_end = tok->cur - 1; /* Leave '\n' out of the string */
+X return NEWLINE;
+X }
+X
+X /* Number */
+X if (isdigit(c)) {
+X if (c == '0') {
+X /* Hex or octal */
+X c = tok_nextc(tok);
+X if (c == '.')
+X goto fraction;
+X if (c == 'x' || c == 'X') {
+X /* Hex */
+X do {
+X c = tok_nextc(tok);
+X } while (isxdigit(c));
+X }
+X else {
+X /* Octal; c is first char of it */
+X /* There's no 'isoctdigit' macro, sigh */
+X while ('0' <= c && c < '8') {
+X c = tok_nextc(tok);
+X }
+X }
+X }
+X else {
+X /* Decimal */
+X do {
+X c = tok_nextc(tok);
+X } while (isdigit(c));
+X /* Accept floating point numbers.
+X XXX This accepts incomplete things like 12e or 1e+;
+X worry about that at run-time.
+X XXX Doesn't accept numbers starting with a dot */
+X if (c == '.') {
+X fraction:
+X /* Fraction */
+X do {
+X c = tok_nextc(tok);
+X } while (isdigit(c));
+X }
+X if (c == 'e' || c == 'E') {
+X /* Exponent part */
+X c = tok_nextc(tok);
+X if (c == '+' || c == '-')
+X c = tok_nextc(tok);
+X while (isdigit(c)) {
+X c = tok_nextc(tok);
+X }
+X }
+X }
+X tok_backup(tok, c);
+X *p_end = tok->cur;
+X return NUMBER;
+X }
+X
+X /* String */
+X if (c == '\'') {
+X for (;;) {
+X c = tok_nextc(tok);
+X if (c == '\n' || c == EOF) {
+X tok->done = E_TOKEN;
+X return ERRORTOKEN;
+X }
+X if (c == '\\') {
+X c = tok_nextc(tok);
+X *p_end = tok->cur;
+X if (c == '\n' || c == EOF) {
+X tok->done = E_TOKEN;
+X return ERRORTOKEN;
+X }
+X continue;
+X }
+X if (c == '\'')
+X break;
+X }
+X *p_end = tok->cur;
+X return STRING;
+X }
+X
+X /* Line continuation */
+X if (c == '\\') {
+X c = tok_nextc(tok);
+X if (c != '\n') {
+X tok->done = E_TOKEN;
+X return ERRORTOKEN;
+X }
+X tok->lineno++;
+X goto again; /* Read next line */
+X }
+X
+X /* Punctuation character */
+X *p_end = tok->cur;
+X return tok_1char(c);
+X}
+X
+X
+X#ifdef DEBUG
+X
+Xvoid
+Xtok_dump(type, start, end)
+X int type;
+X char *start, *end;
+X{
+X printf("%s", tok_name[type]);
+X if (type == NAME || type == NUMBER || type == STRING || type == OP)
+X printf("(%.*s)", (int)(end - start), start);
+X}
+X
+X#endif
+EOF
+fi
+echo 'Part 08 out of 21 of pack.out complete.'
+exit 0
diff --git a/shar/python-0.9.1-09-21.shar b/shar/python-0.9.1-09-21.shar
new file mode 100644
index 0000000..0aee04d
--- /dev/null
+++ b/shar/python-0.9.1-09-21.shar
@@ -0,0 +1,2688 @@
+: This is a shell archive.
+: Extract with 'sh this_file'.
+:
+: Extract part 01 first since it makes all directories
+echo 'Start of pack.out, part 09 out of 21:'
+if test -s 'doc/mod3.tex'
+then echo '*** I will not over-write existing file doc/mod3.tex'
+else
+echo 'x - doc/mod3.tex'
+sed 's/^X//' > 'doc/mod3.tex' << 'EOF'
+X\section{Standard Modules}
+X
+XThe following standard modules are defined.
+XThey are available in one of the directories in the default module
+Xsearch path (try printing
+X{\tt sys.path}
+Xto find out the default search path.)
+X
+X\subsection{Standard Module {\tt string}}
+X
+XThis module defines some constants useful for checking character
+Xclasses, some exceptions, and some useful string functions.
+XThe constants are:
+X\begin{description}
+X\funcitem{digits}
+XThe string
+X{\tt '0123456789'}.
+X\funcitem{hexdigits}
+XThe string
+X{\tt '0123456789abcdefABCDEF'}.
+X\funcitem{letters}
+XThe concatenation of the strings
+X{\tt lowercase}
+Xand
+X{\tt uppercase}
+Xdescribed below.
+X\funcitem{lowercase}
+XThe string
+X{\tt 'abcdefghijklmnopqrstuvwxyz'}.
+X\funcitem{octdigits}
+XThe string
+X{\tt '01234567'}.
+X\funcitem{uppercase}
+XThe string
+X{\tt 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'}.
+X\funcitem{whitespace}
+XA string containing all characters that are considered whitespace,
+Xi.e.,
+Xspace, tab and newline.
+XThis definition is used by
+X{\tt split()}
+Xand
+X{\tt strip()}.
+X\end{description}
+X
+XThe exceptions are:
+X\begin{description}
+X\excitem{atoi\_error}{non-numeric argument to string.atoi}
+X%.br
+XException raised by
+X{\tt atoi}
+Xwhen a non-numeric string argument is detected.
+XThe exception argument is the offending string.
+X\excitem{index\_error}{substring not found in string.index}
+X%.br
+XException raised by
+X{\tt index}
+Xwhen
+X{\tt sub}
+Xis not found.
+XThe argument are the offending arguments to index: {\tt (s, sub)}.
+X\end{description}
+X
+XThe functions are:
+X\begin{description}
+X\funcitem{atoi}{s}
+XConverts a string to a number.
+XThe string must consist of one or more digits, optionally preceded by a
+Xsign ({\tt '+'} or {\tt '-'}).
+X\funcitem{index}{s, sub}
+XReturns the lowest index in
+X{\tt s}
+Xwhere the substring
+X{\tt sub}
+Xis found.
+X\funcitem{lower}{s}
+XConvert letters to lower case.
+X\funcitem{split}{s}
+XReturns a list of the whitespace-delimited words of the string
+X{\tt s}.
+X\funcitem{splitfields}{s, sep}
+X%.br
+XReturns a list containing the fields of the string
+X{\tt s},
+Xusing the string
+X{\tt sep}
+Xas a separator.
+XThe list will have one more items than the number of non-overlapping
+Xoccurrences of the separator in the string.
+XThus,
+X{\tt string.splitfields(s, ' ')}
+Xis not the same as
+X{\tt string.split(s)},
+Xas the latter only returns non-empty words.
+X\funcitem{strip}{s}
+XRemoves leading and trailing whitespace from the string
+X{\tt s}.
+X\funcitem{swapcase}{s}
+XConverts lower case letters to upper case and vice versa.
+X\funcitem{upper}{s}
+XConvert letters to upper case.
+X\funcitem{ljust(s, width), rjust(s, width), center}{s, width}
+X%.br
+XThese functions respectively left-justify, right-justify and center a
+Xstring in a field of given width.
+XThey return a string that is at least
+X{\tt width}
+Xcharacters wide, created by padding the string
+X{\tt s}
+Xwith spaces until the given width on the right, left or both sides.
+XThe string is never truncated.
+X\end{description}
+X
+X\subsection{Standard Module {\tt path}}
+X
+XThis module implements some useful functions on POSIX pathnames.
+X\begin{description}
+X\funcitem{basename}{p}
+XReturns the base name of pathname
+X{\tt p}.
+XThis is the second half of the pair returned by
+X{\tt path.split(p)}.
+X\funcitem{cat}{p, q}
+XPerforms intelligent pathname concatenation on paths
+X{\tt p}
+Xand
+X{\tt q}:
+XIf
+X{\tt q}
+Xis an absolute path, the return value is
+X{\tt q}.
+XOtherwise, the concatenation of
+X{\tt p}
+Xand
+X{\tt q}
+Xis returned, with a slash ({\tt '/'}) inserted unless
+X{\tt p}
+Xis empty or ends in a slash.
+X\funcitem{commonprefix}{list}
+X%.br
+XReturns the longest string that is a prefix of all strings in
+X{\tt list}.
+XIf
+X{\tt list}
+Xis empty, the empty string ({\tt ''}) is returned.
+X\funcitem{exists}{p}
+XReturns true if
+X{\tt p}
+Xrefers to an existing path.
+X\funcitem{isdir}{p}
+XReturns true if
+X{\tt p}
+Xrefers to an existing directory.
+X\funcitem{islink}{p}
+XReturns true if
+X{\tt p}
+Xrefers to a directory entry that is a symbolic link.
+XAlways false if symbolic links are not supported.
+X\funcitem{ismount}{p}
+XReturns true if
+X{\tt p}
+Xis an absolute path that occurs in the mount table as output by the
+X{\tt /etc/mount}
+Xutility.
+XThis output is read once when the function is used for the first
+Xtime.%
+X\footnote{
+XIs there a better way to check for mount points?
+X}
+X\funcitem{split}{p}
+XReturns a pair
+X{\tt (head,~tail)}
+Xsuch that
+X{\tt tail}
+Xcontains no slashes and
+X{\tt path.cat(head, tail)}
+Xis equal to
+X{\tt p}.
+X\funcitem{walk}{p, visit, arg}
+X%.br
+XCalls the function
+X{\tt visit}
+Xwith arguments
+X{\tt (arg, dirname, names)}
+Xfor each directory in the directory tree rooted at
+X{\tt p}
+X(including
+X{\tt p}
+Xitself, if it is a directory).
+XThe argument
+X{\tt dirname}
+Xspecifies the visited directory, the argument
+X{\tt names}
+Xlists the files in the directory (gotten from
+X{\tt posix.listdir(dirname)}).
+XThe
+X{\tt visit}
+Xfunction may modify
+X{\tt names}
+Xto influence the set of directories visited below
+X{\tt dirname},
+Xe.g.,
+Xto avoid visiting certain parts of the tree.
+X(The object referred to by
+X{\tt names}
+Xmust be modified in place, using
+X{\tt del}
+Xor slice assignment.)
+X\end{description}
+X
+X\subsection{Standard Module {\tt getopt}}
+X
+XThis module helps scripts to parse the command line arguments in
+X{\tt sys.argv}.
+XIt uses the same conventions as the {\UNIX}
+X{\tt getopt()}
+Xfunction.
+XIt defines the function
+X{\tt getopt.getopt(args, options)}
+Xand the exception
+X{\tt getopt.error}.
+X
+XThe first argument to
+X{\tt getopt()}
+Xis the argument list passed to the script with its first element
+Xchopped off (i.e.,
+X{\tt sys.argv[1:]}).
+XThe second argument is the string of option letters that the
+Xscript wants to recognize, with options that require an argument
+Xfollowed by a colon (i.e., the same format that {\UNIX}
+X{\tt getopt()}
+Xuses).
+XThe return value consists of two elements: the first is a list of
+Xoption-and-value pairs; the second is the list of program arguments
+Xleft after the option list was stripped (this is a trailing slice of the
+Xfirst argument).
+XEach option-and-value pair returned has the option as its first element,
+Xprefixed with a hyphen (e.g.,
+X{\tt '-x'}),
+Xand the option argument as its second element, or an empty string if the
+Xoption has no argument.
+XThe options occur in the list in the same order in which they were
+Xfound, thus allowing multiple occurrences.
+XExample:
+X\bcode\begin{verbatim}
+X>>> import getopt, string
+X>>> args = string.split('-a -b -cfoo -d bar a1 a2')
+X>>> args
+X['-a', '-b', '-cfoo', '-d', 'bar', 'a1', 'a2']
+X>>> optlist, args = getopt.getopt(args, 'abc:d:')
+X>>> optlist
+X[('-a', ''), ('-b', ''), ('-c', 'foo'), ('-d', 'bar')]
+X>>> args
+X['a1', 'a2']
+X>>>
+X\end{verbatim}\ecode
+XThe exception
+X{\tt getopt.error = 'getopt error'}
+Xis raised when an unrecognized option is found in the argument list or
+Xwhen an option requiring an argument is given none.
+XThe argument to the exception is a string indicating the cause of the
+Xerror.
+X
+X\subsection{Standard Module {\tt rand}}
+X
+XThis module implements a pseudo-random number generator similar to
+X{\tt rand()}
+Xin C.
+XIt defines the following functions:
+X\begin{description}
+X\funcitem{rand}{}
+XReturns an integer random number in the range [0 ... 32768).
+X\funcitem{choice}{s}
+XReturns a random element from the sequence (string, tuple or list)
+X{\tt s.}
+X\funcitem{srand}{seed}
+XInitializes the random number generator with the given integral seed.
+XWhen the module is first imported, the random number is initialized with
+Xthe current time.
+X\end{description}
+X
+X\subsection{Standard Module {\tt whrandom}}
+X
+XThis module implements a Wichmann-Hill pseudo-random number generator.
+XIt defines the following functions:
+X\begin{description}
+X\funcitem{random}{}
+XReturns the next random floating point number in the range [0.0 ... 1.0).
+X\funcitem{seed}{x, y, z}
+XInitializes the random number generator from the integers
+X{\tt x},
+X{\tt y}
+Xand
+X{\tt z}.
+XWhen the module is first imported, the random number is initialized
+Xusing values derived from the current time.
+X\end{description}
+X
+X\subsection{Standard Module {\tt stdwinevents}}
+X
+XThis module defines constants used by STDWIN for event types
+X({\tt WE\_ACTIVATE} etc.), command codes ({\tt WC\_LEFT} etc.)
+Xand selection types ({\tt WS\_PRIMARY} etc.).
+XRead the file for details.
+XSuggested usage is
+X\bcode\begin{verbatim}
+X>>> from stdwinevents import *
+X>>>
+X\end{verbatim}\ecode
+X
+X\subsection{Standard Module {\tt rect}}
+X
+XThis module contains useful operations on rectangles.
+XA rectangle is defined as in module
+X{\tt stdwin}:
+Xa pair of points, where a point is a pair of integers.
+XFor example, the rectangle
+X\bcode\begin{verbatim}
+X(10, 20), (90, 80)
+X\end{verbatim}\ecode
+Xis a rectangle whose left, top, right and bottom edges are 10, 20, 90
+Xand 80, respectively.
+XNote that the positive vertical axis points down (as in
+X{\tt stdwin}).
+X
+XThe module defines the following objects:
+X\begin{description}
+X\excitem{error}{rect.error}
+X%.br
+XThe exception raised by functions in this module when they detect an
+Xerror.
+XThe exception argument is a string describing the problem in more
+Xdetail.
+X\funcitem{empty}
+X%.br
+XThe rectangle returned when some operations return an empty result.
+XThis makes it possible to quickly check whether a result is empty:
+X\bcode\begin{verbatim}
+X>>> import rect
+X>>> r1 = (10, 20), (90, 80)
+X>>> r2 = (0, 0), (10, 20)
+X>>> r3 = rect.intersect(r1, r2)
+X>>> if r3 is rect.empty: print 'Empty intersection'
+XEmpty intersection
+X>>>
+X\end{verbatim}\ecode
+X\funcitem{is\_empty}{r}
+X%.br
+XReturns true if the given rectangle is empty.
+XA rectangle
+X{\em (left,~top), (right,~bottom)}
+Xis empty if
+X{\em left~$\geq$~right}
+Xor
+X{\em top~$\leq$~bottom}.
+X\funcitem{intersect}{list}
+X%.br
+XReturns the intersection of all rectangles in the list argument.
+XIt may also be called with a tuple argument or with two or more
+Xrectangles as arguments.
+XRaises
+X{\tt rect.error}
+Xif the list is empty.
+XReturns
+X{\tt rect.empty}
+Xif the intersection of the rectangles is empty.
+X\funcitem{union}{list}
+X%.br
+XReturns the smallest rectangle that contains all non-empty rectangles in
+Xthe list argument.
+XIt may also be called with a tuple argument or with two or more
+Xrectangles as arguments.
+XReturns
+X{\tt rect.empty}
+Xif the list is empty or all its rectangles are empty.
+X\funcitem{pointinrect}{point, rect}
+X%.br
+XReturns true if the point is inside the rectangle.
+XBy definition, a point
+X{\em (h,~v)}
+Xis inside a rectangle
+X{\em (left,~top),}
+X{\em (right,~bottom)}
+Xif
+X{\em left~$\leq$~h~$<$~right}
+Xand
+X{\em top~$\leq$~v~$<$~bottom}.
+X\funcitem{inset(rect, }{dh, dv)}
+X%.br
+XReturns a rectangle that lies inside the
+X{\tt rect}
+Xargument by
+X{\tt dh}
+Xpixels horizontally
+Xand
+X{\tt dv}
+Xpixels
+Xvertically.
+XIf
+X{\tt dh}
+Xor
+X{\tt dv}
+Xis negative, the result lies outside
+X{\tt rect}.
+X\funcitem{rect2geom}{rect}
+X%.br
+XConverts a rectangle to geometry representation:
+X{\em (left,~top),}
+X{\em (width,~height)}.
+X\funcitem{geom2rect}{geom}
+X%.br
+XConverts a rectangle given in geometry representation back to the
+Xstandard rectangle representation
+X{\em (left,~top),}
+X{\em (right,~bottom)}.
+X\end{description}
+X
+X\subsection{Standard Modules {\tt GL} and {\tt DEVICE}}
+X
+XThese modules define the constants used by the Silicon Graphics
+X{\em Graphics Library}
+Xthat C programmers find in the header files
+X{\tt <gl/gl.h>}
+Xand
+X{\tt <gl/device.h>}.
+XRead the module files for details.
+X
+X\subsection{Standard Module {\tt panel}}
+X
+XThis module should be used instead of the built-in module
+X{\tt pnl}
+Xto interface with the
+X{\em Panel Library}.
+X
+XThe module is too large to document here in its entirety.
+XOne interesting function:
+X\begin{description}
+X\funcitem{defpanellist}{filename}
+X%.br
+XParses a panel description file containing S-expressions written by the
+X{\em Panel Editor}
+Xthat accompanies the Panel Library and creates the described panels.
+XIt returns a list of panel objects.
+X\end{description}
+X
+X{\bf Warning:}
+Xthe {\Python} interpreter will dump core if you don't create a GL window
+Xbefore calling
+X{\tt panel.mkpanel()}
+Xor
+X{\tt panel.defpanellist()}.
+X
+X\subsection{Standard Module {\tt panelparser}}
+X
+XThis module defines a self-contained parser for S-expressions as output
+Xby the Panel Editor (which is written in Scheme so it can't help writing
+XS-expressions).
+XThe relevant function is
+X{\tt panelparser.parse\_file(file)}
+Xwhich has a file object (not a filename!) as argument and returns a list
+Xof parsed S-expressions.
+XEach S-expression is converted into a {\Python} list, with atoms converted
+Xto {\Python} strings and sub-expressions (recursively) to {\Python} lists.
+XFor more details, read the module file.
+X
+X\section{P.M.}
+X
+X\begin{verse}
+X
+Xcommands
+X
+Xcmp?
+X
+X*cache?
+X
+Xlocaltime?
+X
+Xcalendar?
+X
+X\_\_dict?
+X
+Xmac?
+X
+X\end{verse}
+EOF
+fi
+if test -s 'src/audiomodule.c'
+then echo '*** I will not over-write existing file src/audiomodule.c'
+else
+echo 'x - src/audiomodule.c'
+sed 's/^X//' > 'src/audiomodule.c' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/* Silicon Graphics audio module implementation */
+X/* For SGI Personal IRIS 4D/20 under IRIX 3.3; <sys/audio.h> mentions "IP6" */
+X/* Note: The set-in-gain ioctl exists but is non-functional */
+X
+X#include <errno.h>
+X#include <sys/audio.h>
+X#include "asa.h"
+X
+X#include "allobjects.h"
+X#include "modsupport.h"
+X
+Xstatic int audio_fd = -1;
+X
+Xstatic int
+Xinit()
+X{
+X if (audio_fd >= 0)
+X return 1;
+X if ((audio_fd = asa_init()) >= 0)
+X return 1;
+X err_setstr(RuntimeError, "can't initialize async audio");
+X return 0;
+X}
+X
+X
+X/* POSIX methods */
+X
+Xstatic object *
+Xaudio_get_ioctl(self, args, code)
+X object *self;
+X object *args;
+X long code;
+X{
+X long x;
+X if (!getnoarg(args))
+X return NULL;
+X if (!init())
+X return NULL;
+X if ((x = ioctl(audio_fd, code, (char *) NULL)) < 0) {
+X return NULL;
+X }
+X return newintobject(x);
+X}
+X
+Xstatic object *
+Xaudio_set_ioctl(self, args, code)
+X object *self;
+X object *args;
+X long code;
+X{
+X long x;
+X if (!getlongarg(args, &x))
+X return NULL;
+X if (!init())
+X return NULL;
+X if (ioctl(audio_fd, code, (char *) x) != 0)
+X return NULL;
+X INCREF(None);
+X return None;
+X}
+X
+Xstatic object *
+Xaudio_getingain(self, args)
+X object *self;
+X object *args;
+X{
+X return audio_get_ioctl(self, args, AUDIOCGETINGAIN);
+X}
+X
+Xstatic object *
+Xaudio_getoutgain(self, args)
+X object *self;
+X object *args;
+X{
+X return audio_get_ioctl(self, args, AUDIOCGETOUTGAIN);
+X}
+X
+Xstatic object *
+Xaudio_setingain(self, args)
+X object *self;
+X object *args;
+X{
+X return audio_set_ioctl(self, args, AUDIOCSETINGAIN);
+X}
+X
+Xstatic object *
+Xaudio_setoutgain(self, args)
+X object *self;
+X object *args;
+X{
+X return audio_set_ioctl(self, args, AUDIOCSETOUTGAIN);
+X}
+X
+Xstatic object *
+Xaudio_setrate(self, args)
+X object *self;
+X object *args;
+X{
+X return audio_set_ioctl(self, args, AUDIOCSETRATE);
+X}
+X
+Xstatic object *
+Xaudio_setduration(self, args)
+X object *self;
+X object *args;
+X{
+X return audio_set_ioctl(self, args, AUDIOCDURATION);
+X}
+X
+X/* Compute average bias, and remove it */
+X
+Xstatic void
+Xunbias(buf, len)
+X char *buf;
+X int len;
+X{
+X register int i;
+X register int c;
+X register long bias;
+X if (len == 0)
+X return;
+X bias = 0;
+X for (i = 0; i < len; i++) {
+X c = buf[i];
+X if (c > 127)
+X c -= 256;
+X bias += c;
+X }
+X bias = (bias + len/2) / len; /* Rounded average */
+X if (bias != 0) {
+X for (i = 0; i < len; i++) {
+X buf[i] -= bias;
+X }
+X }
+X}
+X
+Xstatic object *
+Xaudio_read(self, args)
+X object *self;
+X object *args;
+X{
+X int c, i, n;
+X object *v;
+X char *s;
+X if (!getintarg(args, &n))
+X return NULL;
+X if (n <= 0) {
+X err_setstr(RuntimeError, "audio.read: arg <= 0");
+X return NULL;
+X }
+X if (!init())
+X return NULL;
+X v = newsizedstringobject((char *)NULL, n);
+X if (v == NULL)
+X return err_nomem();
+X s = getstringvalue(v);
+X n = read(audio_fd, s, n);
+X if (intrcheck()) {
+X DECREF(v);
+X err_set(KeyboardInterrupt);
+X return NULL;
+X }
+X /* Check for errors */
+X if (n < 0) {
+X DECREF(v);
+X return NULL;
+X }
+X /* But EOF is reported as an empty string */
+X
+X unbias(s, n);
+X resizestring(&v, n);
+X return v;
+X}
+X
+Xstatic object *
+Xaudio_write(self, args)
+X object *self;
+X object *args;
+X{
+X int n, n2;
+X object *v;
+X if (!getstrarg(args, &v))
+X return NULL;
+X if (!init())
+X return NULL;
+X errno = 0;
+X n2 = write(audio_fd, getstringvalue(v), n = getstringsize(v));
+X if (intrcheck()) {
+X err_set(KeyboardInterrupt);
+X return NULL;
+X }
+X /* Check for other errors */
+X if (n2 != n) {
+X if (errno == 0)
+X errno = EIO;
+X return NULL;
+X }
+X INCREF(None);
+X return None;
+X}
+X
+X/* audio.amplify(sample, f1, f2).
+X Amplify a sample by a factor changing from f1/256 to (almost) f2/256.
+X Negative factors are allowed. Sound values that are to large
+X to fit in a byte are clipped. */
+X
+Xstatic object *
+Xaudio_amplify(self, args)
+X object *self;
+X object *args;
+X{
+X object *v;
+X char *s, *t;
+X int f1, f2;
+X int i, n;
+X int c;
+X if (!getstrintintarg(args, &v, &f1, &f2))
+X return NULL;
+X n = getstringsize(v);
+X s = getstringvalue(v);
+X v = newsizedstringobject((char *)NULL, n);
+X if (v == NULL)
+X return err_nomem();
+X t = getstringvalue(v);
+X for (i = 0; i < n; i++) {
+X c = s[i];
+X if (c > 127) c -= 256; /* If chars are unsigned */
+X c = c * ( f1*(n-i) + f2*i ) / ( n*256 );
+X if (c > 127) c = 127;
+X else if (c < -128) c = -128;
+X t[i] = c;
+X }
+X return v;
+X}
+X
+X/* audio.reverse(s): return a sample backwards */
+X
+Xstatic object *
+Xaudio_reverse(self, args)
+X object *self;
+X object *args;
+X{
+X object *v;
+X char *s, *t;
+X int i, n;
+X if (!getstrarg(args, &v))
+X return NULL;
+X n = getstringsize(v);
+X s = getstringvalue(v);
+X v = newsizedstringobject((char *)NULL, n);
+X if (v == NULL)
+X return err_nomem();
+X t = getstringvalue(v);
+X for (i = 0; i < n; i++) {
+X t[n-1-i] = s[i];
+X }
+X return v;
+X}
+X
+X/* audio.add(a, b): add two samples.
+X Bytes that exceed the range are clipped.
+X If one is shorter, the rest of the longer sample is returned unchanged. */
+X
+Xstatic object *
+Xaudio_add(self, args)
+X object *self;
+X object *args;
+X{
+X object *a, *b, *v;
+X char *sa, *sb, *t;
+X int i, n, na, nb, c, ca, cb;
+X if (!getstrstrarg(args, &a, &b))
+X return NULL;
+X na = getstringsize(a);
+X sa = getstringvalue(a);
+X nb = getstringsize(b);
+X sb = getstringvalue(b);
+X n = (na > nb) ? na : nb;
+X v = newsizedstringobject((char *)NULL, n);
+X if (v == NULL)
+X return err_nomem();
+X t = getstringvalue(v);
+X for (i = 0; i < n; i++) {
+X c = 0;
+X if (i < na) {
+X ca = sa[i];
+X if (ca > 127) ca = ca - 256;
+X c = c + ca;
+X }
+X if (i < nb) {
+X cb = sb[i];
+X if (cb > 127) cb = cb - 256;
+X c = c + cb;
+X }
+X if (c > 127) c = 127;
+X else if (c < -128) c = -128;
+X t[i] = c;
+X }
+X return v;
+X}
+X
+X/* audio.chr2num(s) returns a list containing the numeric values
+X of the samples. */
+X
+Xstatic object *
+Xaudio_chr2num(self, args)
+X object *self;
+X object *args;
+X{
+X object *v, *w;
+X char *s;
+X int c, i, n;
+X static object *ints[256];
+X
+X /* To avoid filling memory with all those int objects, we create
+X integer objects for all the desired values and reference these. */
+X if (ints[255] == NULL) {
+X for (i = 0; i < 256; i++) {
+X if (ints[i] != NULL)
+X continue;
+X c = i;
+X if (c > 127) c -= 256;
+X ints[i] = newintobject((long)c);
+X if (ints[i] == NULL)
+X return NULL;
+X }
+X }
+X
+X if (!getstrarg(args, &v))
+X return NULL;
+X n = getstringsize(v);
+X s = getstringvalue(v);
+X v = newlistobject(n);
+X if (v == NULL)
+X return err_nomem();
+X for (i = 0; i < n; i++) {
+X c = s[i] & 0xff;
+X w = ints[c];
+X INCREF(w);
+X if (setlistitem(v, i, w) != 0) {
+X DECREF(v);
+X return NULL;
+X }
+X }
+X return v;
+X}
+X
+X/* audio.num2chr is the inverse of audio.chr2num.
+X Excess values are clipped. */
+X
+Xstatic object *
+Xaudio_num2chr(self, args)
+X object *self;
+X object *args;
+X{
+X object *v, *w;
+X char *s;
+X int c, i, n;
+X if (!is_listobject(args)) {
+X err_badarg();
+X return NULL;
+X }
+X n = getlistsize(args);
+X v = newsizedstringobject((char *)NULL, n);
+X if (v == NULL)
+X return NULL;
+X s = getstringvalue(v);
+X for (i = 0; i < n; i++) {
+X w = getlistitem(args, i);
+X if (!is_intobject(w)) {
+X DECREF(v);
+X err_badarg();
+X return NULL;
+X }
+X s[i] = getintvalue(w);
+X }
+X return v;
+X}
+X
+Xstatic object *stdaudio_buffer = NULL;
+X
+Xstatic object *
+Xaudio_start_recording(self, args)
+X object *self;
+X object *args;
+X{
+X int n;
+X object *v;
+X char *s;
+X if (!getintarg(args, &n))
+X return NULL;
+X if (stdaudio_buffer != NULL) {
+X err_setstr(RuntimeError, "audio.start_recording: device busy");
+X return NULL;
+X }
+X if (n <= 0) {
+X err_setstr(TypeError, "audio.start_recording: arg <= 0");
+X return NULL;
+X }
+X if (!init())
+X return NULL;
+X v = newsizedstringobject((char *)NULL, n);
+X if (v == NULL)
+X return err_nomem();
+X s = getstringvalue(v);
+X asa_start_read(s, n);
+X stdaudio_buffer = v;
+X INCREF(None);
+X return None;
+X}
+X
+Xstatic object *
+Xaudio_poll(self, args)
+X object *self;
+X object *args;
+X{
+X int n;
+X if (!getnoarg(args))
+X return NULL;
+X if (stdaudio_buffer == NULL) {
+X err_setstr(RuntimeError, "audio.poll: not busy");
+X return NULL;
+X }
+X if (!init())
+X return NULL;
+X if ((n = asa_poll()) < 0)
+X return NULL;
+X return newintobject(n);
+X}
+X
+Xstatic object *
+Xaudio_wait_recording(self, args)
+X object *self;
+X object *args;
+X{
+X object *v;
+X int n;
+X if (!getnoarg(args))
+X return NULL;
+X if (stdaudio_buffer == NULL) {
+X err_setstr(RuntimeError, "audio.wait_recording: not busy");
+X return NULL;
+X }
+X if (!init())
+X return NULL;
+X if ((n = asa_wait()) < 0)
+X return NULL;
+X v = stdaudio_buffer;
+X stdaudio_buffer = NULL;
+X unbias(getstringvalue(v), n);
+X resizestring(&v, n);
+X return v;
+X}
+X
+Xstatic object *
+Xaudio_stop_recording(self, args)
+X object *self;
+X object *args;
+X{
+X int n;
+X object *v;
+X char *s;
+X if (!getnoarg(args))
+X return NULL;
+X if (stdaudio_buffer == NULL) {
+X err_setstr(RuntimeError, "audio.stop_recording: not busy");
+X return NULL;
+X }
+X if ((n = asa_cancel()) < 0)
+X return NULL;
+X v = stdaudio_buffer;
+X stdaudio_buffer = NULL;
+X s = getstringvalue(v);
+X unbias(s, n);
+X resizestring(&v, n);
+X return v;
+X}
+X
+Xstatic object *
+Xaudio_start_playing(self, args)
+X object *self;
+X object *args;
+X{
+X object *v;
+X if (!getstrarg(args, &v))
+X return NULL;
+X if (stdaudio_buffer != NULL) {
+X err_setstr(RuntimeError, "audio.start_recording: device rbusy");
+X return NULL;
+X }
+X asa_start_write(getstringvalue(v), (int)getstringsize(v));
+X INCREF(v);
+X stdaudio_buffer = v;
+X INCREF(None);
+X return None;
+X}
+X
+Xstatic object *
+Xaudio_wait_playing(self, args)
+X object *self;
+X object *args;
+X{
+X int n;
+X if (!getnoarg(args))
+X return NULL;
+X if (stdaudio_buffer == NULL) {
+X err_setstr(RuntimeError, "audio.wait_playing: not busy");
+X return NULL;
+X }
+X if ((n = asa_wait()) < 0)
+X return NULL;
+X DECREF(stdaudio_buffer);
+X stdaudio_buffer = NULL;
+X /* XXX return newintobject((long)n); ??? */
+X INCREF(None);
+X return None;
+X}
+X
+Xstatic object *
+Xaudio_stop_playing(self, args)
+X object *self;
+X object *args;
+X{
+X int n;
+X if (!getnoarg(args))
+X return NULL;
+X if (stdaudio_buffer == NULL) {
+X err_setstr(RuntimeError, "audio.stop_playing: not busy");
+X return NULL;
+X }
+X if ((n = asa_cancel()) < 0)
+X return NULL;
+X DECREF(stdaudio_buffer);
+X stdaudio_buffer = NULL;
+X return newintobject((long)n);
+X}
+X
+Xstatic object *
+Xaudio_audio_done(self, args)
+X object *self;
+X object *args;
+X{
+X if (!getnoarg(args))
+X return NULL;
+X asa_done();
+X if (stdaudio_buffer != NULL)
+X DECREF(stdaudio_buffer);
+X stdaudio_buffer = NULL;
+X audio_fd = -1;
+X INCREF(None);
+X return None;
+X}
+X
+X
+Xstatic struct methodlist audio_methods[] = {
+X {"getingain", audio_getingain},
+X {"getoutgain", audio_getoutgain},
+X {"setingain", audio_setingain},
+X {"setoutgain", audio_setoutgain},
+X {"setrate", audio_setrate},
+X {"setduration", audio_setduration},
+X {"read", audio_read},
+X {"write", audio_write},
+X {"amplify", audio_amplify},
+X {"reverse", audio_reverse},
+X {"add", audio_add},
+X {"chr2num", audio_chr2num},
+X {"num2chr", audio_num2chr},
+X
+X /* "asa" interface: */
+X
+X {"start_recording", audio_start_recording},
+X {"poll_recording", audio_poll},
+X {"wait_recording", audio_wait_recording},
+X {"stop_recording", audio_stop_recording},
+X
+X {"start_playing", audio_start_playing},
+X {"poll_playing", audio_poll},
+X {"wait_playing", audio_wait_playing},
+X {"stop_playing", audio_stop_playing},
+X
+X {"done", audio_audio_done},
+X
+X {NULL, NULL} /* Sentinel */
+X};
+X
+Xvoid
+Xinitaudio()
+X{
+X initmodule("audio", audio_methods);
+X}
+EOF
+fi
+if test -s 'src/dictobject.c'
+then echo '*** I will not over-write existing file src/dictobject.c'
+else
+echo 'x - src/dictobject.c'
+sed 's/^X//' > 'src/dictobject.c' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/* Dictionary object implementation; using a hash table */
+X
+X/*
+XXXX Note -- although this may look professional, I didn't think very hard
+Xabout the problem and it is possible that obvious improvements exist.
+XA similar module that I saw by Chris Torek:
+X- uses chaining instead of hashed linear probing
+X- remembers the hash value with the entry to speed up table resizing
+X- sets the table size to a power of 2
+X- uses a different hash function:
+X h = 0; p = str; while (*p) h = (h<<5) - h + *p++;
+X*/
+X
+X#include "allobjects.h"
+X
+X
+X/*
+XTable of primes suitable as keys, in ascending order.
+XThe first line are the largest primes less than some powers of two,
+Xthe second line is the largest prime less than 6000,
+Xand the third line is a selection from Knuth, Vol. 3, Sec. 6.1, Table 1.
+XThe final value is a sentinel and should cause the memory allocation
+Xof that many entries to fail (if none of the earlier values cause such
+Xfailure already).
+X*/
+Xstatic unsigned int primes[] = {
+X 3, 7, 13, 31, 61, 127, 251, 509, 1021, 2017, 4093,
+X 5987,
+X 9551, 15683, 19609, 31397,
+X 0xffffffff /* All bits set -- truncation OK */
+X};
+X
+X/* String used as dummy key to fill deleted entries */
+Xstatic stringobject *dummy; /* Initialized by first call to newdictobject() */
+X
+X/*
+XInvariant for entries: when in use, de_value is not NULL and de_key is
+Xnot NULL and not dummy; when not in use, de_value is NULL and de_key
+Xis either NULL or dummy. A dummy key value cannot be replaced by NULL,
+Xsince otherwise other keys may be lost.
+X*/
+Xtypedef struct {
+X stringobject *de_key;
+X object *de_value;
+X} dictentry;
+X
+X/*
+XTo ensure the lookup algorithm terminates, the table size must be a
+Xprime number and there must be at least one NULL key in the table.
+XThe value di_fill is the number of non-NULL keys; di_used is the number
+Xof non-NULL, non-dummy keys.
+XTo avoid slowing down lookups on a near-full table, we resize the table
+Xwhen it is more than half filled.
+X*/
+Xtypedef struct {
+X OB_HEAD
+X int di_fill;
+X int di_used;
+X int di_size;
+X dictentry *di_table;
+X} dictobject;
+X
+Xobject *
+Xnewdictobject()
+X{
+X register dictobject *dp;
+X if (dummy == NULL) { /* Auto-initialize dummy */
+X dummy = (stringobject *) newstringobject("");
+X if (dummy == NULL)
+X return NULL;
+X }
+X dp = NEWOBJ(dictobject, &Dicttype);
+X if (dp == NULL)
+X return NULL;
+X dp->di_size = primes[0];
+X dp->di_table = (dictentry *) calloc(sizeof(dictentry), dp->di_size);
+X if (dp->di_table == NULL) {
+X DEL(dp);
+X return err_nomem();
+X }
+X dp->di_fill = 0;
+X dp->di_used = 0;
+X return (object *)dp;
+X}
+X
+X/*
+XThe basic lookup function used by all operations.
+XThis is essentially Algorithm D from Knuth Vol. 3, Sec. 6.4.
+XOpen addressing is preferred over chaining since the link overhead for
+Xchaining would be substantial (100% with typical malloc overhead).
+X
+XFirst a 32-bit hash value, 'sum', is computed from the key string.
+XThe first character is added an extra time shifted by 8 to avoid hashing
+Xsingle-character keys (often heavily used variables) too close together.
+XAll arithmetic on sum should ignore overflow.
+X
+XThe initial probe index is then computed as sum mod the table size.
+XSubsequent probe indices are incr apart (mod table size), where incr
+Xis also derived from sum, with the additional requirement that it is
+Xrelative prime to the table size (i.e., 1 <= incr < size, since the size
+Xis a prime number). My choice for incr is somewhat arbitrary.
+X*/
+Xstatic dictentry *lookdict PROTO((dictobject *, char *));
+Xstatic dictentry *
+Xlookdict(dp, key)
+X register dictobject *dp;
+X char *key;
+X{
+X register int i, incr;
+X register dictentry *freeslot = NULL;
+X register unsigned char *p = (unsigned char *) key;
+X register unsigned long sum = *p << 7;
+X while (*p != '\0')
+X sum = sum + sum + *p++;
+X i = sum % dp->di_size;
+X do {
+X sum = sum + sum + 1;
+X incr = sum % dp->di_size;
+X } while (incr == 0);
+X for (;;) {
+X register dictentry *ep = &dp->di_table[i];
+X if (ep->de_key == NULL) {
+X if (freeslot != NULL)
+X return freeslot;
+X else
+X return ep;
+X }
+X if (ep->de_key == dummy) {
+X if (freeslot != NULL)
+X freeslot = ep;
+X }
+X else if (GETSTRINGVALUE(ep->de_key)[0] == key[0]) {
+X if (strcmp(GETSTRINGVALUE(ep->de_key), key) == 0) {
+X return ep;
+X }
+X }
+X i = (i + incr) % dp->di_size;
+X }
+X}
+X
+X/*
+XInternal routine to insert a new item into the table.
+XUsed both by the internal resize routine and by the public insert routine.
+XEats a reference to key and one to value.
+X*/
+Xstatic void insertdict PROTO((dictobject *, stringobject *, object *));
+Xstatic void
+Xinsertdict(dp, key, value)
+X register dictobject *dp;
+X stringobject *key;
+X object *value;
+X{
+X register dictentry *ep;
+X ep = lookdict(dp, GETSTRINGVALUE(key));
+X if (ep->de_value != NULL) {
+X DECREF(ep->de_value);
+X DECREF(key);
+X }
+X else {
+X if (ep->de_key == NULL)
+X dp->di_fill++;
+X else
+X DECREF(ep->de_key);
+X ep->de_key = key;
+X dp->di_used++;
+X }
+X ep->de_value = value;
+X}
+X
+X/*
+XRestructure the table by allocating a new table and reinserting all
+Xitems again. When entries have been deleted, the new table may
+Xactually be smaller than the old one.
+X*/
+Xstatic int dictresize PROTO((dictobject *));
+Xstatic int
+Xdictresize(dp)
+X dictobject *dp;
+X{
+X register int oldsize = dp->di_size;
+X register int newsize;
+X register dictentry *oldtable = dp->di_table;
+X register dictentry *newtable;
+X register dictentry *ep;
+X register int i;
+X newsize = dp->di_size;
+X for (i = 0; ; i++) {
+X if (primes[i] > dp->di_used*2) {
+X newsize = primes[i];
+X break;
+X }
+X }
+X newtable = (dictentry *) calloc(sizeof(dictentry), newsize);
+X if (newtable == NULL) {
+X err_nomem();
+X return -1;
+X }
+X dp->di_size = newsize;
+X dp->di_table = newtable;
+X dp->di_fill = 0;
+X dp->di_used = 0;
+X for (i = 0, ep = oldtable; i < oldsize; i++, ep++) {
+X if (ep->de_value != NULL)
+X insertdict(dp, ep->de_key, ep->de_value);
+X else if (ep->de_key != NULL)
+X DECREF(ep->de_key);
+X }
+X DEL(oldtable);
+X return 0;
+X}
+X
+Xobject *
+Xdictlookup(op, key)
+X object *op;
+X char *key;
+X{
+X if (!is_dictobject(op))
+X fatal("dictlookup on non-dictionary");
+X return lookdict((dictobject *)op, key) -> de_value;
+X}
+X
+X#ifdef NOT_USED
+Xstatic object *
+Xdict2lookup(op, key)
+X register object *op;
+X register object *key;
+X{
+X register object *res;
+X if (!is_dictobject(op)) {
+X err_badcall();
+X return NULL;
+X }
+X if (!is_stringobject(key)) {
+X err_badarg();
+X return NULL;
+X }
+X res = lookdict((dictobject *)op, ((stringobject *)key)->ob_sval)
+X -> de_value;
+X if (res == NULL)
+X err_setstr(KeyError, "key not in dictionary");
+X return res;
+X}
+X#endif
+X
+Xstatic int
+Xdict2insert(op, key, value)
+X register object *op;
+X object *key;
+X object *value;
+X{
+X register dictobject *dp;
+X register stringobject *keyobj;
+X if (!is_dictobject(op)) {
+X err_badcall();
+X return -1;
+X }
+X dp = (dictobject *)op;
+X if (!is_stringobject(key)) {
+X err_badarg();
+X return -1;
+X }
+X keyobj = (stringobject *)key;
+X /* if fill >= 2/3 size, resize */
+X if (dp->di_fill*3 >= dp->di_size*2) {
+X if (dictresize(dp) != 0) {
+X if (dp->di_fill+1 > dp->di_size)
+X return -1;
+X }
+X }
+X INCREF(keyobj);
+X INCREF(value);
+X insertdict(dp, keyobj, value);
+X return 0;
+X}
+X
+Xint
+Xdictinsert(op, key, value)
+X object *op;
+X char *key;
+X object *value;
+X{
+X register object *keyobj;
+X register int err;
+X keyobj = newstringobject(key);
+X if (keyobj == NULL) {
+X err_nomem();
+X return -1;
+X }
+X err = dict2insert(op, keyobj, value);
+X DECREF(keyobj);
+X return err;
+X}
+X
+Xint
+Xdictremove(op, key)
+X object *op;
+X char *key;
+X{
+X register dictobject *dp;
+X register dictentry *ep;
+X if (!is_dictobject(op)) {
+X err_badcall();
+X return -1;
+X }
+X dp = (dictobject *)op;
+X ep = lookdict(dp, key);
+X if (ep->de_value == NULL) {
+X err_setstr(KeyError, "key not in dictionary");
+X return -1;
+X }
+X DECREF(ep->de_key);
+X INCREF(dummy);
+X ep->de_key = dummy;
+X DECREF(ep->de_value);
+X ep->de_value = NULL;
+X dp->di_used--;
+X return 0;
+X}
+X
+Xstatic int
+Xdict2remove(op, key)
+X object *op;
+X register object *key;
+X{
+X if (!is_stringobject(key)) {
+X err_badarg();
+X return -1;
+X }
+X return dictremove(op, GETSTRINGVALUE((stringobject *)key));
+X}
+X
+Xint
+Xgetdictsize(op)
+X register object *op;
+X{
+X if (!is_dictobject(op)) {
+X err_badcall();
+X return -1;
+X }
+X return ((dictobject *)op) -> di_size;
+X}
+X
+Xstatic object *
+Xgetdict2key(op, i)
+X object *op;
+X register int i;
+X{
+X /* XXX This can't return errors since its callers assume
+X that NULL means there was no key at that point */
+X register dictobject *dp;
+X if (!is_dictobject(op)) {
+X /* err_badcall(); */
+X return NULL;
+X }
+X dp = (dictobject *)op;
+X if (i < 0 || i >= dp->di_size) {
+X /* err_badarg(); */
+X return NULL;
+X }
+X if (dp->di_table[i].de_value == NULL) {
+X /* Not an error! */
+X return NULL;
+X }
+X return (object *) dp->di_table[i].de_key;
+X}
+X
+Xchar *
+Xgetdictkey(op, i)
+X object *op;
+X int i;
+X{
+X register object *keyobj = getdict2key(op, i);
+X if (keyobj == NULL)
+X return NULL;
+X return GETSTRINGVALUE((stringobject *)keyobj);
+X}
+X
+X/* Methods */
+X
+Xstatic void
+Xdict_dealloc(dp)
+X register dictobject *dp;
+X{
+X register int i;
+X register dictentry *ep;
+X for (i = 0, ep = dp->di_table; i < dp->di_size; i++, ep++) {
+X if (ep->de_key != NULL)
+X DECREF(ep->de_key);
+X if (ep->de_value != NULL)
+X DECREF(ep->de_value);
+X }
+X if (dp->di_table != NULL)
+X DEL(dp->di_table);
+X DEL(dp);
+X}
+X
+Xstatic void
+Xdict_print(dp, fp, flags)
+X register dictobject *dp;
+X register FILE *fp;
+X register int flags;
+X{
+X register int i;
+X register int any;
+X register dictentry *ep;
+X fprintf(fp, "{");
+X any = 0;
+X for (i = 0, ep = dp->di_table; i < dp->di_size && !StopPrint;
+X i++, ep++) {
+X if (ep->de_value != NULL) {
+X if (any++ > 0)
+X fprintf(fp, "; ");
+X printobject((object *)ep->de_key, fp, flags);
+X fprintf(fp, ": ");
+X printobject(ep->de_value, fp, flags);
+X }
+X }
+X fprintf(fp, "}");
+X}
+X
+Xstatic void
+Xjs(pv, w)
+X object **pv;
+X object *w;
+X{
+X joinstring(pv, w);
+X if (w != NULL)
+X DECREF(w);
+X}
+X
+Xstatic object *
+Xdict_repr(dp)
+X dictobject *dp;
+X{
+X auto object *v;
+X register object *w;
+X object *semi, *colon;
+X register int i;
+X register int any;
+X register dictentry *ep;
+X v = newstringobject("{");
+X semi = newstringobject("; ");
+X colon = newstringobject(": ");
+X any = 0;
+X for (i = 0, ep = dp->di_table; i < dp->di_size && !StopPrint;
+X i++, ep++) {
+X if (ep->de_value != NULL) {
+X if (any++)
+X joinstring(&v, semi);
+X js(&v, w = reprobject((object *)ep->de_key));
+X joinstring(&v, colon);
+X js(&v, w = reprobject(ep->de_value));
+X }
+X }
+X js(&v, w = newstringobject("}"));
+X if (semi != NULL)
+X DECREF(semi);
+X if (colon != NULL)
+X DECREF(colon);
+X return v;
+X}
+X
+Xstatic int
+Xdict_length(dp)
+X dictobject *dp;
+X{
+X return dp->di_used;
+X}
+X
+Xstatic object *
+Xdict_subscript(dp, v)
+X dictobject *dp;
+X register object *v;
+X{
+X if (!is_stringobject(v)) {
+X err_badarg();
+X return NULL;
+X }
+X v = lookdict(dp, GETSTRINGVALUE((stringobject *)v)) -> de_value;
+X if (v == NULL)
+X err_setstr(KeyError, "key not in dictionary");
+X else
+X INCREF(v);
+X return v;
+X}
+X
+Xstatic int
+Xdict_ass_sub(dp, v, w)
+X dictobject *dp;
+X object *v, *w;
+X{
+X if (w == NULL)
+X return dict2remove((object *)dp, v);
+X else
+X return dict2insert((object *)dp, v, w);
+X}
+X
+Xstatic mapping_methods dict_as_mapping = {
+X dict_length, /*mp_length*/
+X dict_subscript, /*mp_subscript*/
+X dict_ass_sub, /*mp_ass_subscript*/
+X};
+X
+Xstatic object *
+Xdict_keys(dp, args)
+X register dictobject *dp;
+X object *args;
+X{
+X register object *v;
+X register int i, j;
+X if (!getnoarg(args))
+X return NULL;
+X v = newlistobject(dp->di_used);
+X if (v == NULL)
+X return NULL;
+X for (i = 0, j = 0; i < dp->di_size; i++) {
+X if (dp->di_table[i].de_value != NULL) {
+X stringobject *key = dp->di_table[i].de_key;
+X INCREF(key);
+X setlistitem(v, j, (object *)key);
+X j++;
+X }
+X }
+X return v;
+X}
+X
+Xobject *
+Xgetdictkeys(dp)
+X object *dp;
+X{
+X if (dp == NULL || !is_dictobject(dp)) {
+X err_badcall();
+X return NULL;
+X }
+X return dict_keys((dictobject *)dp, (object *)NULL);
+X}
+X
+Xstatic object *
+Xdict_has_key(dp, args)
+X register dictobject *dp;
+X object *args;
+X{
+X object *key;
+X register long ok;
+X if (!getstrarg(args, &key))
+X return NULL;
+X ok = lookdict(dp, GETSTRINGVALUE((stringobject *)key))->de_value
+X != NULL;
+X return newintobject(ok);
+X}
+X
+Xstatic struct methodlist dict_methods[] = {
+X {"keys", dict_keys},
+X {"has_key", dict_has_key},
+X {NULL, NULL} /* sentinel */
+X};
+X
+Xstatic object *
+Xdict_getattr(dp, name)
+X dictobject *dp;
+X char *name;
+X{
+X return findmethod(dict_methods, (object *)dp, name);
+X}
+X
+Xtypeobject Dicttype = {
+X OB_HEAD_INIT(&Typetype)
+X 0,
+X "dictionary",
+X sizeof(dictobject),
+X 0,
+X dict_dealloc, /*tp_dealloc*/
+X dict_print, /*tp_print*/
+X dict_getattr, /*tp_getattr*/
+X 0, /*tp_setattr*/
+X 0, /*tp_compare*/
+X dict_repr, /*tp_repr*/
+X 0, /*tp_as_number*/
+X 0, /*tp_as_sequence*/
+X &dict_as_mapping, /*tp_as_mapping*/
+X};
+EOF
+fi
+if test -s 'src/pgen.c'
+then echo '*** I will not over-write existing file src/pgen.c'
+else
+echo 'x - src/pgen.c'
+sed 's/^X//' > 'src/pgen.c' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/* Parser generator */
+X/* XXX This file is not yet fully PROTOized */
+X
+X/* For a description, see the comments at end of this file */
+X
+X#include "pgenheaders.h"
+X#include "assert.h"
+X#include "token.h"
+X#include "node.h"
+X#include "grammar.h"
+X#include "metagrammar.h"
+X#include "pgen.h"
+X
+Xextern int debugging;
+X
+X
+X/* PART ONE -- CONSTRUCT NFA -- Cf. Algorithm 3.2 from [Aho&Ullman 77] */
+X
+Xtypedef struct _nfaarc {
+X int ar_label;
+X int ar_arrow;
+X} nfaarc;
+X
+Xtypedef struct _nfastate {
+X int st_narcs;
+X nfaarc *st_arc;
+X} nfastate;
+X
+Xtypedef struct _nfa {
+X int nf_type;
+X char *nf_name;
+X int nf_nstates;
+X nfastate *nf_state;
+X int nf_start, nf_finish;
+X} nfa;
+X
+Xstatic int
+Xaddnfastate(nf)
+X nfa *nf;
+X{
+X nfastate *st;
+X
+X RESIZE(nf->nf_state, nfastate, nf->nf_nstates + 1);
+X if (nf->nf_state == NULL)
+X fatal("out of mem");
+X st = &nf->nf_state[nf->nf_nstates++];
+X st->st_narcs = 0;
+X st->st_arc = NULL;
+X return st - nf->nf_state;
+X}
+X
+Xstatic void
+Xaddnfaarc(nf, from, to, lbl)
+X nfa *nf;
+X int from, to, lbl;
+X{
+X nfastate *st;
+X nfaarc *ar;
+X
+X st = &nf->nf_state[from];
+X RESIZE(st->st_arc, nfaarc, st->st_narcs + 1);
+X if (st->st_arc == NULL)
+X fatal("out of mem");
+X ar = &st->st_arc[st->st_narcs++];
+X ar->ar_label = lbl;
+X ar->ar_arrow = to;
+X}
+X
+Xstatic nfa *
+Xnewnfa(name)
+X char *name;
+X{
+X nfa *nf;
+X static type = NT_OFFSET; /* All types will be disjunct */
+X
+X nf = NEW(nfa, 1);
+X if (nf == NULL)
+X fatal("no mem for new nfa");
+X nf->nf_type = type++;
+X nf->nf_name = name; /* XXX strdup(name) ??? */
+X nf->nf_nstates = 0;
+X nf->nf_state = NULL;
+X nf->nf_start = nf->nf_finish = -1;
+X return nf;
+X}
+X
+Xtypedef struct _nfagrammar {
+X int gr_nnfas;
+X nfa **gr_nfa;
+X labellist gr_ll;
+X} nfagrammar;
+X
+Xstatic nfagrammar *
+Xnewnfagrammar()
+X{
+X nfagrammar *gr;
+X
+X gr = NEW(nfagrammar, 1);
+X if (gr == NULL)
+X fatal("no mem for new nfa grammar");
+X gr->gr_nnfas = 0;
+X gr->gr_nfa = NULL;
+X gr->gr_ll.ll_nlabels = 0;
+X gr->gr_ll.ll_label = NULL;
+X addlabel(&gr->gr_ll, ENDMARKER, "EMPTY");
+X return gr;
+X}
+X
+Xstatic nfa *
+Xaddnfa(gr, name)
+X nfagrammar *gr;
+X char *name;
+X{
+X nfa *nf;
+X
+X nf = newnfa(name);
+X RESIZE(gr->gr_nfa, nfa *, gr->gr_nnfas + 1);
+X if (gr->gr_nfa == NULL)
+X fatal("out of mem");
+X gr->gr_nfa[gr->gr_nnfas++] = nf;
+X addlabel(&gr->gr_ll, NAME, nf->nf_name);
+X return nf;
+X}
+X
+X#ifdef DEBUG
+X
+Xstatic char REQNFMT[] = "metacompile: less than %d children\n";
+X
+X#define REQN(i, count) \
+X if (i < count) { \
+X fprintf(stderr, REQNFMT, count); \
+X abort(); \
+X } else
+X
+X#else
+X#define REQN(i, count) /* empty */
+X#endif
+X
+Xstatic nfagrammar *
+Xmetacompile(n)
+X node *n;
+X{
+X nfagrammar *gr;
+X int i;
+X
+X printf("Compiling (meta-) parse tree into NFA grammar\n");
+X gr = newnfagrammar();
+X REQ(n, MSTART);
+X i = n->n_nchildren - 1; /* Last child is ENDMARKER */
+X n = n->n_child;
+X for (; --i >= 0; n++) {
+X if (n->n_type != NEWLINE)
+X compile_rule(gr, n);
+X }
+X return gr;
+X}
+X
+Xstatic
+Xcompile_rule(gr, n)
+X nfagrammar *gr;
+X node *n;
+X{
+X nfa *nf;
+X
+X REQ(n, RULE);
+X REQN(n->n_nchildren, 4);
+X n = n->n_child;
+X REQ(n, NAME);
+X nf = addnfa(gr, n->n_str);
+X n++;
+X REQ(n, COLON);
+X n++;
+X REQ(n, RHS);
+X compile_rhs(&gr->gr_ll, nf, n, &nf->nf_start, &nf->nf_finish);
+X n++;
+X REQ(n, NEWLINE);
+X}
+X
+Xstatic
+Xcompile_rhs(ll, nf, n, pa, pb)
+X labellist *ll;
+X nfa *nf;
+X node *n;
+X int *pa, *pb;
+X{
+X int i;
+X int a, b;
+X
+X REQ(n, RHS);
+X i = n->n_nchildren;
+X REQN(i, 1);
+X n = n->n_child;
+X REQ(n, ALT);
+X compile_alt(ll, nf, n, pa, pb);
+X if (--i <= 0)
+X return;
+X n++;
+X a = *pa;
+X b = *pb;
+X *pa = addnfastate(nf);
+X *pb = addnfastate(nf);
+X addnfaarc(nf, *pa, a, EMPTY);
+X addnfaarc(nf, b, *pb, EMPTY);
+X for (; --i >= 0; n++) {
+X REQ(n, VBAR);
+X REQN(i, 1);
+X --i;
+X n++;
+X REQ(n, ALT);
+X compile_alt(ll, nf, n, &a, &b);
+X addnfaarc(nf, *pa, a, EMPTY);
+X addnfaarc(nf, b, *pb, EMPTY);
+X }
+X}
+X
+Xstatic
+Xcompile_alt(ll, nf, n, pa, pb)
+X labellist *ll;
+X nfa *nf;
+X node *n;
+X int *pa, *pb;
+X{
+X int i;
+X int a, b;
+X
+X REQ(n, ALT);
+X i = n->n_nchildren;
+X REQN(i, 1);
+X n = n->n_child;
+X REQ(n, ITEM);
+X compile_item(ll, nf, n, pa, pb);
+X --i;
+X n++;
+X for (; --i >= 0; n++) {
+X if (n->n_type == COMMA) { /* XXX Temporary */
+X REQN(i, 1);
+X --i;
+X n++;
+X }
+X REQ(n, ITEM);
+X compile_item(ll, nf, n, &a, &b);
+X addnfaarc(nf, *pb, a, EMPTY);
+X *pb = b;
+X }
+X}
+X
+Xstatic
+Xcompile_item(ll, nf, n, pa, pb)
+X labellist *ll;
+X nfa *nf;
+X node *n;
+X int *pa, *pb;
+X{
+X int i;
+X int a, b;
+X
+X REQ(n, ITEM);
+X i = n->n_nchildren;
+X REQN(i, 1);
+X n = n->n_child;
+X if (n->n_type == LSQB) {
+X REQN(i, 3);
+X n++;
+X REQ(n, RHS);
+X *pa = addnfastate(nf);
+X *pb = addnfastate(nf);
+X addnfaarc(nf, *pa, *pb, EMPTY);
+X compile_rhs(ll, nf, n, &a, &b);
+X addnfaarc(nf, *pa, a, EMPTY);
+X addnfaarc(nf, b, *pb, EMPTY);
+X REQN(i, 1);
+X n++;
+X REQ(n, RSQB);
+X }
+X else {
+X compile_atom(ll, nf, n, pa, pb);
+X if (--i <= 0)
+X return;
+X n++;
+X addnfaarc(nf, *pb, *pa, EMPTY);
+X if (n->n_type == STAR)
+X *pb = *pa;
+X else
+X REQ(n, PLUS);
+X }
+X}
+X
+Xstatic
+Xcompile_atom(ll, nf, n, pa, pb)
+X labellist *ll;
+X nfa *nf;
+X node *n;
+X int *pa, *pb;
+X{
+X int i;
+X
+X REQ(n, ATOM);
+X i = n->n_nchildren;
+X REQN(i, 1);
+X n = n->n_child;
+X if (n->n_type == LPAR) {
+X REQN(i, 3);
+X n++;
+X REQ(n, RHS);
+X compile_rhs(ll, nf, n, pa, pb);
+X n++;
+X REQ(n, RPAR);
+X }
+X else if (n->n_type == NAME || n->n_type == STRING) {
+X *pa = addnfastate(nf);
+X *pb = addnfastate(nf);
+X addnfaarc(nf, *pa, *pb, addlabel(ll, n->n_type, n->n_str));
+X }
+X else
+X REQ(n, NAME);
+X}
+X
+Xstatic void
+Xdumpstate(ll, nf, istate)
+X labellist *ll;
+X nfa *nf;
+X int istate;
+X{
+X nfastate *st;
+X int i;
+X nfaarc *ar;
+X
+X printf("%c%2d%c",
+X istate == nf->nf_start ? '*' : ' ',
+X istate,
+X istate == nf->nf_finish ? '.' : ' ');
+X st = &nf->nf_state[istate];
+X ar = st->st_arc;
+X for (i = 0; i < st->st_narcs; i++) {
+X if (i > 0)
+X printf("\n ");
+X printf("-> %2d %s", ar->ar_arrow,
+X labelrepr(&ll->ll_label[ar->ar_label]));
+X ar++;
+X }
+X printf("\n");
+X}
+X
+Xstatic void
+Xdumpnfa(ll, nf)
+X labellist *ll;
+X nfa *nf;
+X{
+X int i;
+X
+X printf("NFA '%s' has %d states; start %d, finish %d\n",
+X nf->nf_name, nf->nf_nstates, nf->nf_start, nf->nf_finish);
+X for (i = 0; i < nf->nf_nstates; i++)
+X dumpstate(ll, nf, i);
+X}
+X
+X
+X/* PART TWO -- CONSTRUCT DFA -- Algorithm 3.1 from [Aho&Ullman 77] */
+X
+Xstatic int
+Xaddclosure(ss, nf, istate)
+X bitset ss;
+X nfa *nf;
+X int istate;
+X{
+X if (addbit(ss, istate)) {
+X nfastate *st = &nf->nf_state[istate];
+X nfaarc *ar = st->st_arc;
+X int i;
+X
+X for (i = st->st_narcs; --i >= 0; ) {
+X if (ar->ar_label == EMPTY)
+X addclosure(ss, nf, ar->ar_arrow);
+X ar++;
+X }
+X }
+X}
+X
+Xtypedef struct _ss_arc {
+X bitset sa_bitset;
+X int sa_arrow;
+X int sa_label;
+X} ss_arc;
+X
+Xtypedef struct _ss_state {
+X bitset ss_ss;
+X int ss_narcs;
+X ss_arc *ss_arc;
+X int ss_deleted;
+X int ss_finish;
+X int ss_rename;
+X} ss_state;
+X
+Xtypedef struct _ss_dfa {
+X int sd_nstates;
+X ss_state *sd_state;
+X} ss_dfa;
+X
+Xstatic
+Xmakedfa(gr, nf, d)
+X nfagrammar *gr;
+X nfa *nf;
+X dfa *d;
+X{
+X int nbits = nf->nf_nstates;
+X bitset ss;
+X int xx_nstates;
+X ss_state *xx_state, *yy;
+X ss_arc *zz;
+X int istate, jstate, iarc, jarc, ibit;
+X nfastate *st;
+X nfaarc *ar;
+X
+X ss = newbitset(nbits);
+X addclosure(ss, nf, nf->nf_start);
+X xx_state = NEW(ss_state, 1);
+X if (xx_state == NULL)
+X fatal("no mem for xx_state in makedfa");
+X xx_nstates = 1;
+X yy = &xx_state[0];
+X yy->ss_ss = ss;
+X yy->ss_narcs = 0;
+X yy->ss_arc = NULL;
+X yy->ss_deleted = 0;
+X yy->ss_finish = testbit(ss, nf->nf_finish);
+X if (yy->ss_finish)
+X printf("Error: nonterminal '%s' may produce empty.\n",
+X nf->nf_name);
+X
+X /* This algorithm is from a book written before
+X the invention of structured programming... */
+X
+X /* For each unmarked state... */
+X for (istate = 0; istate < xx_nstates; ++istate) {
+X yy = &xx_state[istate];
+X ss = yy->ss_ss;
+X /* For all its states... */
+X for (ibit = 0; ibit < nf->nf_nstates; ++ibit) {
+X if (!testbit(ss, ibit))
+X continue;
+X st = &nf->nf_state[ibit];
+X /* For all non-empty arcs from this state... */
+X for (iarc = 0; iarc < st->st_narcs; iarc++) {
+X ar = &st->st_arc[iarc];
+X if (ar->ar_label == EMPTY)
+X continue;
+X /* Look up in list of arcs from this state */
+X for (jarc = 0; jarc < yy->ss_narcs; ++jarc) {
+X zz = &yy->ss_arc[jarc];
+X if (ar->ar_label == zz->sa_label)
+X goto found;
+X }
+X /* Add new arc for this state */
+X RESIZE(yy->ss_arc, ss_arc, yy->ss_narcs + 1);
+X if (yy->ss_arc == NULL)
+X fatal("out of mem");
+X zz = &yy->ss_arc[yy->ss_narcs++];
+X zz->sa_label = ar->ar_label;
+X zz->sa_bitset = newbitset(nbits);
+X zz->sa_arrow = -1;
+X found: ;
+X /* Add destination */
+X addclosure(zz->sa_bitset, nf, ar->ar_arrow);
+X }
+X }
+X /* Now look up all the arrow states */
+X for (jarc = 0; jarc < xx_state[istate].ss_narcs; jarc++) {
+X zz = &xx_state[istate].ss_arc[jarc];
+X for (jstate = 0; jstate < xx_nstates; jstate++) {
+X if (samebitset(zz->sa_bitset,
+X xx_state[jstate].ss_ss, nbits)) {
+X zz->sa_arrow = jstate;
+X goto done;
+X }
+X }
+X RESIZE(xx_state, ss_state, xx_nstates + 1);
+X if (xx_state == NULL)
+X fatal("out of mem");
+X zz->sa_arrow = xx_nstates;
+X yy = &xx_state[xx_nstates++];
+X yy->ss_ss = zz->sa_bitset;
+X yy->ss_narcs = 0;
+X yy->ss_arc = NULL;
+X yy->ss_deleted = 0;
+X yy->ss_finish = testbit(yy->ss_ss, nf->nf_finish);
+X done: ;
+X }
+X }
+X
+X if (debugging)
+X printssdfa(xx_nstates, xx_state, nbits, &gr->gr_ll,
+X "before minimizing");
+X
+X simplify(xx_nstates, xx_state);
+X
+X if (debugging)
+X printssdfa(xx_nstates, xx_state, nbits, &gr->gr_ll,
+X "after minimizing");
+X
+X convert(d, xx_nstates, xx_state);
+X
+X /* XXX cleanup */
+X}
+X
+Xstatic
+Xprintssdfa(xx_nstates, xx_state, nbits, ll, msg)
+X int xx_nstates;
+X ss_state *xx_state;
+X int nbits;
+X labellist *ll;
+X char *msg;
+X{
+X int i, ibit, iarc;
+X ss_state *yy;
+X ss_arc *zz;
+X
+X printf("Subset DFA %s\n", msg);
+X for (i = 0; i < xx_nstates; i++) {
+X yy = &xx_state[i];
+X if (yy->ss_deleted)
+X continue;
+X printf(" Subset %d", i);
+X if (yy->ss_finish)
+X printf(" (finish)");
+X printf(" { ");
+X for (ibit = 0; ibit < nbits; ibit++) {
+X if (testbit(yy->ss_ss, ibit))
+X printf("%d ", ibit);
+X }
+X printf("}\n");
+X for (iarc = 0; iarc < yy->ss_narcs; iarc++) {
+X zz = &yy->ss_arc[iarc];
+X printf(" Arc to state %d, label %s\n",
+X zz->sa_arrow,
+X labelrepr(&ll->ll_label[zz->sa_label]));
+X }
+X }
+X}
+X
+X
+X/* PART THREE -- SIMPLIFY DFA */
+X
+X/* Simplify the DFA by repeatedly eliminating states that are
+X equivalent to another oner. This is NOT Algorithm 3.3 from
+X [Aho&Ullman 77]. It does not always finds the minimal DFA,
+X but it does usually make a much smaller one... (For an example
+X of sub-optimal behaviour, try S: x a b+ | y a b+.)
+X*/
+X
+Xstatic int
+Xsamestate(s1, s2)
+X ss_state *s1, *s2;
+X{
+X int i;
+X
+X if (s1->ss_narcs != s2->ss_narcs || s1->ss_finish != s2->ss_finish)
+X return 0;
+X for (i = 0; i < s1->ss_narcs; i++) {
+X if (s1->ss_arc[i].sa_arrow != s2->ss_arc[i].sa_arrow ||
+X s1->ss_arc[i].sa_label != s2->ss_arc[i].sa_label)
+X return 0;
+X }
+X return 1;
+X}
+X
+Xstatic void
+Xrenamestates(xx_nstates, xx_state, from, to)
+X int xx_nstates;
+X ss_state *xx_state;
+X int from, to;
+X{
+X int i, j;
+X
+X if (debugging)
+X printf("Rename state %d to %d.\n", from, to);
+X for (i = 0; i < xx_nstates; i++) {
+X if (xx_state[i].ss_deleted)
+X continue;
+X for (j = 0; j < xx_state[i].ss_narcs; j++) {
+X if (xx_state[i].ss_arc[j].sa_arrow == from)
+X xx_state[i].ss_arc[j].sa_arrow = to;
+X }
+X }
+X}
+X
+Xstatic
+Xsimplify(xx_nstates, xx_state)
+X int xx_nstates;
+X ss_state *xx_state;
+X{
+X int changes;
+X int i, j, k;
+X
+X do {
+X changes = 0;
+X for (i = 1; i < xx_nstates; i++) {
+X if (xx_state[i].ss_deleted)
+X continue;
+X for (j = 0; j < i; j++) {
+X if (xx_state[j].ss_deleted)
+X continue;
+X if (samestate(&xx_state[i], &xx_state[j])) {
+X xx_state[i].ss_deleted++;
+X renamestates(xx_nstates, xx_state, i, j);
+X changes++;
+X break;
+X }
+X }
+X }
+X } while (changes);
+X}
+X
+X
+X/* PART FOUR -- GENERATE PARSING TABLES */
+X
+X/* Convert the DFA into a grammar that can be used by our parser */
+X
+Xstatic
+Xconvert(d, xx_nstates, xx_state)
+X dfa *d;
+X int xx_nstates;
+X ss_state *xx_state;
+X{
+X int i, j;
+X ss_state *yy;
+X ss_arc *zz;
+X
+X for (i = 0; i < xx_nstates; i++) {
+X yy = &xx_state[i];
+X if (yy->ss_deleted)
+X continue;
+X yy->ss_rename = addstate(d);
+X }
+X
+X for (i = 0; i < xx_nstates; i++) {
+X yy = &xx_state[i];
+X if (yy->ss_deleted)
+X continue;
+X for (j = 0; j < yy->ss_narcs; j++) {
+X zz = &yy->ss_arc[j];
+X addarc(d, yy->ss_rename,
+X xx_state[zz->sa_arrow].ss_rename,
+X zz->sa_label);
+X }
+X if (yy->ss_finish)
+X addarc(d, yy->ss_rename, yy->ss_rename, 0);
+X }
+X
+X d->d_initial = 0;
+X}
+X
+X
+X/* PART FIVE -- GLUE IT ALL TOGETHER */
+X
+Xstatic grammar *
+Xmaketables(gr)
+X nfagrammar *gr;
+X{
+X int i;
+X nfa *nf;
+X dfa *d;
+X grammar *g;
+X
+X if (gr->gr_nnfas == 0)
+X return NULL;
+X g = newgrammar(gr->gr_nfa[0]->nf_type);
+X /* XXX first rule must be start rule */
+X g->g_ll = gr->gr_ll;
+X
+X for (i = 0; i < gr->gr_nnfas; i++) {
+X nf = gr->gr_nfa[i];
+X if (debugging) {
+X printf("Dump of NFA for '%s' ...\n", nf->nf_name);
+X dumpnfa(&gr->gr_ll, nf);
+X }
+X printf("Making DFA for '%s' ...\n", nf->nf_name);
+X d = adddfa(g, nf->nf_type, nf->nf_name);
+X makedfa(gr, gr->gr_nfa[i], d);
+X }
+X
+X return g;
+X}
+X
+Xgrammar *
+Xpgen(n)
+X node *n;
+X{
+X nfagrammar *gr;
+X grammar *g;
+X
+X gr = metacompile(n);
+X g = maketables(gr);
+X translatelabels(g);
+X addfirstsets(g);
+X return g;
+X}
+X
+X
+X/*
+X
+XDescription
+X-----------
+X
+XInput is a grammar in extended BNF (using * for repetition, + for
+Xat-least-once repetition, [] for optional parts, | for alternatives and
+X() for grouping). This has already been parsed and turned into a parse
+Xtree.
+X
+XEach rule is considered as a regular expression in its own right.
+XIt is turned into a Non-deterministic Finite Automaton (NFA), which
+Xis then turned into a Deterministic Finite Automaton (DFA), which is then
+Xoptimized to reduce the number of states. See [Aho&Ullman 77] chapter 3,
+Xor similar compiler books (this technique is more often used for lexical
+Xanalyzers).
+X
+XThe DFA's are used by the parser as parsing tables in a special way
+Xthat's probably unique. Before they are usable, the FIRST sets of all
+Xnon-terminals are computed.
+X
+XReference
+X---------
+X
+X[Aho&Ullman 77]
+X Aho&Ullman, Principles of Compiler Design, Addison-Wesley 1977
+X (first edition)
+X
+X*/
+EOF
+fi
+if test -s 'src/regexpmodule.c'
+then echo '*** I will not over-write existing file src/regexpmodule.c'
+else
+echo 'x - src/regexpmodule.c'
+sed 's/^X//' > 'src/regexpmodule.c' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/* Regular expression objects */
+X/* This needs V8 or Henry Spencer's regexp! */
+X
+X#include "allobjects.h"
+X#include "modsupport.h"
+X
+X#include "regexp.h"
+X
+Xstatic object *RegexpError; /* Exception */
+X
+Xtypedef struct {
+X OB_HEAD
+X object *re_string; /* The string (for printing) */
+X regexp *re_prog; /* The compiled regular expression */
+X} regexpobject;
+X
+Xextern typeobject Regexptype; /* Really static, forward */
+X
+Xstatic regexpobject *
+Xnewregexpobject(string, prog)
+X object *string;
+X regexp *prog;
+X{
+X regexpobject *re;
+X re = NEWOBJ(regexpobject, &Regexptype);
+X if (re != NULL) {
+X XINCREF(string);
+X re->re_string = string;
+X re->re_prog = prog;
+X }
+X return re;
+X}
+X
+X/* Regexp methods */
+X
+Xstatic void
+Xregexp_dealloc(re)
+X regexpobject *re;
+X{
+X XDECREF(re->re_string);
+X XDEL(re->re_prog);
+X DEL(re);
+X}
+X
+Xstatic object *
+Xmakeresult(prog, buffer)
+X regexp *prog;
+X char *buffer;
+X{
+X int n;
+X object *v;
+X /* Count substrings found, including \0, the main one */
+X for (n = 0; n < 10 && prog->startp[n] != NULL; n++)
+X ;
+X v = newtupleobject(n);
+X if (v != NULL) {
+X int i;
+X for (i = 0; i < n; i++) {
+X object *w, *u;
+X long start, end;
+X start = prog->startp[i] - buffer;
+X end = prog->endp[i] - buffer;
+X if ( (w = newtupleobject(2)) == NULL ||
+X (u = newintobject(start)) == NULL ||
+X settupleitem(w, 0, u) != 0 ||
+X (u = newintobject(end)) == NULL ||
+X settupleitem(w, 1, u) != 0) {
+X XDECREF(w);
+X DECREF(v);
+X return NULL;
+X }
+X settupleitem(v, i, w);
+X }
+X }
+X return v;
+X}
+X
+Xstatic object *
+Xregexp_exec(re, args)
+X regexpobject *re;
+X object *args;
+X{
+X object *v;
+X char *buffer;
+X int offset;
+X if (args != NULL && is_stringobject(args)) {
+X v = args;
+X offset = 0;
+X }
+X else if (!getstrintarg(args, &v, &offset))
+X return NULL;
+X buffer = getstringvalue(v);
+X#ifndef MULTILINE
+X#define reglexec(prog, str, offset) regexec((prog), (str)+(offset))
+X#endif
+X if (!reglexec(re->re_prog, buffer, offset))
+X return newtupleobject(0);
+X return makeresult(re->re_prog, buffer);
+X}
+X
+Xstatic struct methodlist regexp_methods[] = {
+X "exec", regexp_exec,
+X {NULL, NULL} /* sentinel */
+X};
+X
+Xstatic object *
+Xregexp_getattr(re, name)
+X regexpobject *re;
+X char *name;
+X{
+X return findmethod(regexp_methods, (object *)re, name);
+X}
+X
+Xstatic typeobject Regexptype = {
+X OB_HEAD_INIT(&Typetype)
+X 0, /*ob_size*/
+X "regexp", /*tp_name*/
+X sizeof(regexpobject), /*tp_size*/
+X 0, /*tp_itemsize*/
+X /* methods */
+X regexp_dealloc, /*tp_dealloc*/
+X 0, /*tp_print*/
+X regexp_getattr, /*tp_getattr*/
+X 0, /*tp_setattr*/
+X 0, /*tp_compare*/
+X 0, /*tp_repr*/
+X};
+X
+Xvoid
+Xregerror(str)
+X char *str;
+X{
+X err_setstr(RegexpError, str);
+X}
+X
+Xstatic object *
+Xregexp_compile(self, args)
+X object *self;
+X object *args;
+X{
+X object *string;
+X regexp *prog;
+X if (!getstrarg(args, &string))
+X return NULL;
+X prog = regcomp(getstringvalue(string));
+X if (prog == NULL)
+X return NULL; /* regerror() has called err_seterr() */
+X return (object *)newregexpobject(string, prog);
+X}
+X
+Xstatic struct methodlist regexp_global_methods[] = {
+X {"compile", regexp_compile},
+X {NULL, NULL} /* sentinel */
+X};
+X
+Xinitregexp()
+X{
+X object *m, *d;
+X
+X m = initmodule("regexp", regexp_global_methods);
+X d = getmoduledict(m);
+X
+X /* Initialize regexp.error exception */
+X RegexpError = newstringobject("regexp.error");
+X if (RegexpError == NULL || dictinsert(d, "error", RegexpError) != 0)
+X fatal("can't define regexp.error");
+X}
+EOF
+fi
+echo 'Part 09 out of 21 of pack.out complete.'
+exit 0
diff --git a/shar/python-0.9.1-10-21.shar b/shar/python-0.9.1-10-21.shar
new file mode 100644
index 0000000..962819a
--- /dev/null
+++ b/shar/python-0.9.1-10-21.shar
@@ -0,0 +1,2508 @@
+: This is a shell archive.
+: Extract with 'sh this_file'.
+:
+: Extract part 01 first since it makes all directories
+echo 'Start of pack.out, part 10 out of 21:'
+if test -s 'demo/sgi/gl_panel/flying/light.py'
+then echo '*** I will not over-write existing file demo/sgi/gl_panel/flying/light.py'
+else
+echo 'x - demo/sgi/gl_panel/flying/light.py'
+sed 's/^X//' > 'demo/sgi/gl_panel/flying/light.py' << 'EOF'
+Xfrom GL import *
+Xfrom gl import *
+X
+X# identity matrix
+Xidmat=[1.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,1.0]
+X
+X# the different materials.
+Xm1=[SPECULAR,0.8,0.0,0.0,DIFFUSE,0.4,0.0,0.0,SHININESS,40.0,LMNULL]
+Xm2=[SPECULAR,1.0,0.4,0.0,DIFFUSE,1.0,0.4,0.0,SHININESS,80.0,LMNULL]
+Xm3=[SPECULAR,0.0,0.0,0.6,DIFFUSE,0.0,0.0,0.8,SHININESS,60.0,LMNULL]
+Xm4=[SPECULAR,0.0,1.0,0.0,DIFFUSE,0.0,0.6,0.0,SHININESS,120.0,LMNULL]
+Xm5=[SPECULAR,1.0,1.0,0.0,DIFFUSE,0.6,0.6,0.0,SHININESS,100.0,LMNULL]
+Xm6=[SPECULAR,1.0,0.0,1.0,DIFFUSE,0.6,0.0,0.6,SHININESS,120.0,LMNULL]
+Xm7=[SPECULAR,0.9,0.9,0.9,DIFFUSE,0.6,0.6,0.6,SHININESS,120.0,LMNULL]
+Xm8=[SPECULAR,0.4,0.7,0.4,DIFFUSE,0.5,1.0,0.5,SHININESS,50.0,LMNULL]
+Xm9=[SPECULAR,0.2,0.0,0.1,DIFFUSE,0.8,0.0,0.3,SHININESS,10.0,LMNULL]
+X
+X#the lightsources.
+Xlight1 = [LCOLOR,1.0,1.0,1.0,POSITION,10.0,10.0,5.0,0.0,LMNULL]
+Xlight2 = [LCOLOR,1.0,1.0,1.0,POSITION,-10.0,10.0,5.0,0.0,LMNULL]
+X
+X# the lightmodel.
+Xmodel = [AMBIENT,0.4,0.4,0.4,LMNULL]
+X
+Xdef bindlight (bool) :
+X # Initializes all settings for a window.
+X if bool <> 0 :
+X mmode(MVIEWING)
+X perspective (900, 1.0, 1.0, 35.0)
+X loadmatrix(idmat)
+X # define materials and lights
+X lmdef(DEFMATERIAL, 1, m1)
+X lmdef(DEFMATERIAL, 2, m2)
+X lmdef(DEFMATERIAL, 3, m3)
+X lmdef(DEFMATERIAL, 4, m4)
+X lmdef(DEFMATERIAL, 5, m5)
+X lmdef(DEFMATERIAL, 6, m6)
+X lmdef(DEFMATERIAL, 7, m7)
+X lmdef(DEFMATERIAL, 8, m8)
+X lmdef(DEFMATERIAL, 9, m9)
+X lmdef(DEFLIGHT, 1, light1)
+X lmdef(DEFLIGHT, 2, light2)
+X lmdef(DEFLMODEL, 1, model)
+X lmbind(LIGHT0,1)
+X lmbind(LIGHT1,2)
+X lmbind(LMODEL,1)
+EOF
+fi
+if test -s 'demo/stdwin/wdiff.py'
+then echo '*** I will not over-write existing file demo/stdwin/wdiff.py'
+else
+echo 'x - demo/stdwin/wdiff.py'
+sed 's/^X//' > 'demo/stdwin/wdiff.py' << 'EOF'
+X#! /ufs/guido/bin/sgi/python
+X
+X# A window-oriented recursive diff utility.
+X# NB: This uses undocumented window classing modules.
+X
+X# TO DO:
+X# - faster update after moving/copying one file
+X# - diff flags (-b, etc.) should be global or maintained per window
+X# - use a few fixed windows instead of creating new ones all the time
+X# - ways to specify patterns to skip
+X# (best by pointing at a file and clicking a special menu entry!)
+X# - add rcsdiff menu commands
+X# - add a way to view status of selected files without opening them
+X# - add a way to diff two files with different names
+X# - add a way to rename files
+X# - keep backups of overwritten/deleted files
+X# - a way to mark specified files as uninteresting for dircmp
+X
+Ximport sys
+Ximport posix
+Ximport path
+Ximport rand
+Ximport commands
+Ximport dircache
+Ximport statcache
+Ximport cmp
+Ximport cmpcache
+Ximport stdwin
+Ximport gwin
+Ximport textwin
+Ximport filewin
+Ximport tablewin
+Ximport anywin
+X
+Xmkarg = commands.mkarg
+Xmk2arg = commands.mk2arg
+X
+X# List of names to ignore in dircmp()
+X# (Should be done with function, so we can specify patterns as well)
+X#
+Xskiplist = ['RCS', '.Amake', 'tags', '.', '..']
+X
+X
+Xdef anydiff(a, b, flags): # Display differences between any two objects
+X print 'diff', flags, a, b
+X if path.isdir(a) and path.isdir(b):
+X w = dirdiff(a, b, flags)
+X else:
+X w = filediff(a, b, flags)
+X addstatmenu(w, [a, b])
+X w.original_close = w.close
+X w.close = close_dirwin
+X return w
+X
+Xdef close_dirwin(w):
+X close_subwindows(w, (), 0)
+X w.original_close(w)
+X
+Xdef filediff(a, b, flags): # Display differences between two text files
+X diffcmd = 'diff'
+X if flags: diffcmd = diffcmd + mkarg(flags)
+X diffcmd = diffcmd + mkarg(a) + mkarg(b)
+X difftext = commands.getoutput(diffcmd)
+X return textwin.open_readonly(mktitle(a, b), difftext)
+X
+Xdef dirdiff(a, b, flags): # Display differences between two directories
+X data = diffdata(a, b, flags)
+X w = tablewin.open(mktitle(a, b), data)
+X w.flags = flags
+X w.a = a
+X w.b = b
+X addviewmenu(w)
+X addactionmenu(w)
+X return w
+X
+Xdef diffdata(a, b, flags): # Compute directory differences.
+X #
+X a_only = [('A only:', header_action), ('', header_action)]
+X b_only = [('B only:', header_action), ('', header_action)]
+X ab_diff = [('A <> B:', header_action), ('', header_action)]
+X ab_same = [('A == B:', header_action), ('', header_action)]
+X data = [a_only, b_only, ab_diff, ab_same]
+X #
+X a_list = dircache.listdir(a)[:]
+X b_list = dircache.listdir(b)[:]
+X dircache.annotate(a, a_list)
+X dircache.annotate(b, b_list)
+X a_list.sort()
+X b_list.sort()
+X #
+X for x in a_list:
+X if x in ['./', '../']:
+X pass
+X elif x not in b_list:
+X a_only.append(x, a_only_action)
+X else:
+X ax = path.cat(a, x)
+X bx = path.cat(b, x)
+X if path.isdir(ax) and path.isdir(bx):
+X if flags = '-r':
+X same = dircmp(ax, bx)
+X else:
+X same = 0
+X else:
+X try:
+X same = cmp.cmp(ax, bx)
+X except posix.error:
+X same = 0
+X if same:
+X ab_same.append(x, ab_same_action)
+X else:
+X ab_diff.append(x, ab_diff_action)
+X #
+X for x in b_list:
+X if x in ['./', '../']:
+X pass
+X elif x not in a_list:
+X b_only.append(x, b_only_action)
+X #
+X return data
+X
+X# Re-read the directory.
+X# Attempt to find the selected item back.
+X
+Xdef update(w):
+X setbusy(w)
+X icol, irow = w.selection
+X if 0 <= icol < len(w.data) and 2 <= irow < len(w.data[icol]):
+X selname = w.data[icol][irow][0]
+X else:
+X selname = ''
+X statcache.forget_dir(w.a)
+X statcache.forget_dir(w.b)
+X tablewin.select(w, (-1, -1))
+X tablewin.update(w, diffdata(w.a, w.b, w.flags))
+X if selname:
+X for icol in range(len(w.data)):
+X for irow in range(2, len(w.data[icol])):
+X if w.data[icol][irow][0] = selname:
+X tablewin.select(w, (icol, irow))
+X break
+X
+X# Action functions for table items in directory diff windows
+X
+Xdef header_action(w, string, (icol, irow), (pos, clicks, button, mask)):
+X tablewin.select(w, (-1, -1))
+X
+Xdef a_only_action(w, string, (icol, irow), (pos, clicks, button, mask)):
+X tablewin.select(w, (icol, irow))
+X if clicks = 2:
+X w2 = anyopen(path.cat(w.a, string))
+X if w2:
+X w2.parent = w
+X
+Xdef b_only_action(w, string, (icol, irow), (pos, clicks, button, mask)):
+X tablewin.select(w, (icol, irow))
+X if clicks = 2:
+X w2 = anyopen(path.cat(w.b, string))
+X if w2:
+X w2.parent = w
+X
+Xdef ab_diff_action(w, string, (icol, irow), (pos, clicks, button, mask)):
+X tablewin.select(w, (icol, irow))
+X if clicks = 2:
+X w2 = anydiff(path.cat(w.a, string), path.cat(w.b, string), '')
+X w2.parent = w
+X
+Xdef ab_same_action(w, string, sel, detail):
+X ax = path.cat(w.a, string)
+X if path.isdir(ax):
+X ab_diff_action(w, string, sel, detail)
+X else:
+X a_only_action(w, string, sel, detail)
+X
+Xdef anyopen(name): # Open any kind of document, ignore errors
+X try:
+X w = anywin.open(name)
+X except (RuntimeError, posix.error):
+X stdwin.message('Can\'t open ' + name)
+X return 0
+X addstatmenu(w, [name])
+X return w
+X
+Xdef dircmp(a, b): # Compare whether two directories are the same
+X # To make this as fast as possible, it uses the statcache
+X print ' dircmp', a, b
+X a_list = dircache.listdir(a)
+X b_list = dircache.listdir(b)
+X for x in a_list:
+X if x in skiplist:
+X pass
+X elif x not in b_list:
+X return 0
+X else:
+X ax = path.cat(a, x)
+X bx = path.cat(b, x)
+X if statcache.isdir(ax) and statcache.isdir(bx):
+X if not dircmp(ax, bx): return 0
+X else:
+X try:
+X if not cmpcache.cmp(ax, bx): return 0
+X except posix.error:
+X return 0
+X for x in b_list:
+X if x in skiplist:
+X pass
+X elif x not in a_list:
+X return 0
+X return 1
+X
+X
+X# View menu (for dir diff windows only)
+X
+Xdef addviewmenu(w):
+X w.viewmenu = m = w.menucreate('View')
+X m.action = []
+X add(m, 'diff -r A B', diffr_ab)
+X add(m, 'diff A B', diff_ab)
+X add(m, 'diff -b A B', diffb_ab)
+X add(m, 'diff -c A B', diffc_ab)
+X add(m, 'gdiff A B', gdiff_ab)
+X add(m, ('Open A ', 'A'), open_a)
+X add(m, ('Open B ', 'B'), open_b)
+X add(m, 'Rescan', rescan)
+X add(m, 'Rescan -r', rescan_r)
+X
+X# Action menu (for dir diff windows only)
+X
+Xdef addactionmenu(w):
+X w.actionmenu = m = w.menucreate('Action')
+X m.action = []
+X add(m, 'cp A B', cp_ab)
+X add(m, 'rm B', rm_b)
+X add(m, '', nop)
+X add(m, 'cp B A', cp_ba)
+X add(m, 'rm A', rm_a)
+X
+X# Main menu (global):
+X
+Xdef mainmenu():
+X m = stdwin.menucreate('Wdiff')
+X m.action = []
+X add(m, ('Quit wdiff', 'Q'), quit_wdiff)
+X add(m, 'Close subwindows', close_subwindows)
+X return m
+X
+Xdef add(m, text, action):
+X m.additem(text)
+X m.action.append(action)
+X
+Xdef quit_wdiff(w, m, item):
+X if askyesno('Really quit wdiff altogether?', 1):
+X sys.exit(0)
+X
+Xdef close_subwindows(w, m, item):
+X while 1:
+X for w2 in gwin.windows:
+X if w2.parent = w:
+X close_subwindows(w2, m, item)
+X w2.close(w2)
+X break # inner loop, continue outer loop
+X else:
+X break # outer loop
+X
+Xdef diffr_ab(w, m, item):
+X dodiff(w, '-r')
+X
+Xdef diff_ab(w, m, item):
+X dodiff(w, '')
+X
+Xdef diffb_ab(w, m, item):
+X dodiff(w, '-b')
+X
+Xdef diffc_ab(w, m, item):
+X dodiff(w, '-c')
+X
+Xdef gdiff_ab(w, m, item): # Call SGI's gdiff utility
+X x = getselection(w)
+X if x:
+X a, b = path.cat(w.a, x), path.cat(w.b, x)
+X if path.isdir(a) or path.isdir(b):
+X stdwin.fleep() # This is for files only
+X else:
+X diffcmd = 'gdiff'
+X diffcmd = diffcmd + mkarg(a) + mkarg(b) + ' &'
+X print diffcmd
+X sts = posix.system(diffcmd)
+X if sts: print 'Exit status', sts
+X
+Xdef dodiff(w, flags):
+X x = getselection(w)
+X if x:
+X w2 = anydiff(path.cat(w.a, x), path.cat(w.b, x), flags)
+X w2.parent = w
+X
+Xdef open_a(w, m, item):
+X x = getselection(w)
+X if x:
+X w2 = anyopen(path.cat(w.a, x))
+X if w2:
+X w2.parent = w
+X
+Xdef open_b(w, m, item):
+X x = getselection(w)
+X if x:
+X w2 = anyopen(path.cat(w.b, x))
+X if w2:
+X w2.parent = w
+X
+Xdef rescan(w, m, item):
+X w.flags = ''
+X update(w)
+X
+Xdef rescan_r(w, m, item):
+X w.flags = '-r'
+X update(w)
+X
+Xdef rm_a(w, m, item):
+X x = getselection(w)
+X if x:
+X if x[-1:] = '/': x = x[:-1]
+X x = path.cat(w.a, x)
+X if path.isdir(x):
+X if askyesno('Recursively remove A directory ' + x, 1):
+X runcmd('rm -rf' + mkarg(x))
+X else:
+X runcmd('rm -f' + mkarg(x))
+X update(w)
+X
+Xdef rm_b(w, m, item):
+X x = getselection(w)
+X if x:
+X if x[-1:] = '/': x = x[:-1]
+X x = path.cat(w.b, x)
+X if path.isdir(x):
+X if askyesno('Recursively remove B directory ' + x, 1):
+X runcmd('rm -rf' + mkarg(x))
+X else:
+X runcmd('rm -f' + mkarg(x))
+X update(w)
+X
+Xdef cp_ab(w, m, item):
+X x = getselection(w)
+X if x:
+X if x[-1:] = '/': x = x[:-1]
+X ax = path.cat(w.a, x)
+X bx = path.cat(w.b, x)
+X if path.isdir(ax):
+X if path.exists(bx):
+X m = 'Can\'t copy directory to existing target'
+X stdwin.message(m)
+X return
+X runcmd('cp -r' + mkarg(ax) + mkarg(w.b))
+X else:
+X runcmd('cp' + mkarg(ax) + mk2arg(w.b, x))
+X update(w)
+X
+Xdef cp_ba(w, m, item):
+X x = getselection(w)
+X if x:
+X if x[-1:] = '/': x = x[:-1]
+X ax = path.cat(w.a, x)
+X bx = path.cat(w.b, x)
+X if path.isdir(bx):
+X if path.exists(ax):
+X m = 'Can\'t copy directory to existing target'
+X stdwin.message(m)
+X return
+X runcmd('cp -r' + mkarg(bx) + mkarg(w.a))
+X else:
+X runcmd('cp' + mk2arg(w.b, x) + mkarg(ax))
+X update(w)
+X
+Xdef nop(args):
+X pass
+X
+Xdef getselection(w):
+X icol, irow = w.selection
+X if 0 <= icol < len(w.data):
+X if 0 <= irow < len(w.data[icol]):
+X return w.data[icol][irow][0]
+X stdwin.message('no selection')
+X return ''
+X
+Xdef runcmd(cmd):
+X print cmd
+X sts, output = commands.getstatusoutput(cmd)
+X if sts or output:
+X if not output:
+X output = 'Exit status ' + `sts`
+X stdwin.message(output)
+X
+X
+X# Status menu (for all kinds of windows)
+X
+Xdef addstatmenu(w, files):
+X w.statmenu = m = w.menucreate('Stat')
+X m.files = files
+X m.action = []
+X for file in files:
+X m.additem(commands.getstatus(file))
+X m.action.append(stataction)
+X
+Xdef stataction(w, m, item): # Menu item action for stat menu
+X file = m.files[item]
+X try:
+X m.setitem(item, commands.getstatus(file))
+X except posix.error:
+X stdwin.message('Can\'t get status for ' + file)
+X
+X
+X# Compute a suitable window title from two paths
+X
+Xdef mktitle(a, b):
+X if a = b: return a
+X i = 1
+X while a[-i:] = b[-i:]: i = i+1
+X i = i-1
+X if not i:
+X return a + ' ' + b
+X else:
+X return '{' + a[:-i] + ',' + b[:-i] + '}' + a[-i:]
+X
+X
+X# Ask a confirmation question
+X
+Xdef askyesno(prompt, default):
+X try:
+X return stdwin.askync(prompt, default)
+X except KeyboardInterrupt:
+X return 0
+X
+X
+X# Display a message "busy" in a window, and mark it for updating
+X
+Xdef setbusy(w):
+X left, top = w.getorigin()
+X width, height = w.getwinsize()
+X right, bottom = left + width, top + height
+X d = w.begindrawing()
+X d.erase((0, 0), (10000, 10000))
+X text = 'Busy...'
+X textwidth = d.textwidth(text)
+X textheight = d.lineheight()
+X h, v = left + (width-textwidth)/2, top + (height-textheight)/2
+X d.text((h, v), text)
+X del d
+X w.change((0, 0), (10000, 10000))
+X
+X
+X# Main function
+X
+Xdef main():
+X print 'wdiff: warning: this version does NOT yet make backups'
+X argv = sys.argv
+X flags = ''
+X if len(argv) >= 2 and argv[1][:1] = '-':
+X flags = argv[1]
+X del argv[1]
+X m = mainmenu() # Create menu earlier than windows
+X if len(argv) = 2: # 1 argument
+X w = anyopen(argv[1])
+X if not w: return
+X elif len(argv) = 3: # 2 arguments
+X w = anydiff(argv[1], argv[2], flags)
+X w.parent = ()
+X else:
+X sys.stdout = sys.stderr
+X print 'usage:', argv[0], '[diff-flags] dir-1 [dir-2]'
+X sys.exit(2)
+X del w # It's preserved in gwin.windows
+X while 1:
+X try:
+X gwin.mainloop()
+X break
+X except KeyboardInterrupt:
+X pass # Just continue...
+X
+X# Start the main function (this is a script)
+Xmain()
+EOF
+chmod +x 'demo/stdwin/wdiff.py'
+fi
+if test -s 'lib/Tcl.py'
+then echo '*** I will not over-write existing file lib/Tcl.py'
+else
+echo 'x - lib/Tcl.py'
+sed 's/^X//' > 'lib/Tcl.py' << 'EOF'
+X# An emulator for John Ousterhout's 'Tcl' language in Python (wow!).
+X# Currently only the most basic commands are implemented.
+X#
+X# Design choices:
+X#
+X# - Names used for functions are not exactly those used by C Tcl.
+X# In Python, names without 'Tcl_' prefix are acceptable because
+X# names are less global than in C (and often they are prefixed
+X# with a module name anyway). Parameter conventions also differ.
+X#
+X# - The Tcl Interpreter type is implemented using a Python class.
+X# Almost all functions with an Interpreter as first parameter are
+X# methods of this class.
+X# Applications can create derived classes to add additional commands
+X# or to override specific internal functions.
+X#
+X# - Tcl errors are mapped to Python exceptions.
+X# (I bet Ousterhout would have done the same in a language with
+X# a proper exception mechanism).
+X#
+X# - Tcl expressions are evaluated by Python's built-in function eval().
+X# This makes Python Tcl scripts incompatible with C Tcl scripts,
+X# but is the only sensible solution for a quick-and-dirty version.
+X# It also makes an escape to Python possible.
+X#
+X# - The Backslash function interprets \<newline>, since it
+X# can return a string instead of a character.
+X
+X
+Xfrom TclUtil import *
+X
+X
+X# Exceptions used to signify 'break' and 'continue'
+X
+XTclBreak = 'TclBreak'
+XTclContinue = 'TclContinue'
+XTclReturn = 'TclReturn'
+X
+X
+Xclass CmdBuf():
+X #
+X def Create(buffer):
+X buffer.string = ''
+X return buffer
+X #
+X def Assemble(buffer, str):
+X buffer.string = buffer.string + str
+X if buffer.string[-1:] = '\n':
+X i, end = 0, len(buffer.string)
+X try:
+X while i < end:
+X list, i = FindNextCommand( \
+X buffer.string, i, end, 0)
+X except TclMatchingError:
+X return ''
+X except TclSyntaxError:
+X pass # Let Eval() return the error
+X ret = buffer.string
+X buffer.string = ''
+X return ret
+X else:
+X return ''
+X
+X
+Xclass _Frame():
+X def Create(frame):
+X frame.locals = {}
+X return frame
+X
+Xclass _Proc():
+X #
+X def Create(proc, (interp, args, body)):
+X proc.interp = interp
+X proc.args = SplitList(args) # Do this once here
+X proc.body = body
+X return proc
+X #
+X def Call(proc, argv):
+X if len(argv) <> len(proc.args)+1:
+X raise TclRuntimeError, \
+X 'wrong # args to proc "' + \
+X argv[0] + '"'
+X # XXX No defaults or variable length 'args' yet
+X frame = _Frame().Create()
+X for i in range(len(proc.args)):
+X frame.locals[proc.args[i]] = argv[i+1]
+X proc.interp.stack.append(frame)
+X try:
+X value = proc.interp.Eval(proc.body)
+X except TclReturn, value:
+X pass
+X del proc.interp.stack[-1:]
+X return value
+X
+X
+Ximport regexp
+X_expand_prog = regexp.compile('([^[$\\]+|\n)*')
+Xdel regexp
+X
+Xclass Interpreter():
+X #
+X def Create(interp):
+X interp.globals = {}
+X interp.commands = {}
+X interp.stack = []
+X interp.commands['break'] = interp.BreakCmd
+X interp.commands['concat'] = interp.ConcatCmd
+X interp.commands['continue'] = interp.ContinueCmd
+X interp.commands['echo'] = interp.EchoCmd
+X interp.commands['eval'] = interp.EvalCmd
+X interp.commands['expr'] = interp.ExprCmd
+X interp.commands['for'] = interp.ForCmd
+X interp.commands['glob'] = interp.GlobCmd
+X interp.commands['global'] = interp.GlobalCmd
+X interp.commands['if'] = interp.IfCmd
+X interp.commands['index'] = interp.IndexCmd
+X interp.commands['list'] = interp.ListCmd
+X interp.commands['proc'] = interp.ProcCmd
+X interp.commands['rename'] = interp.RenameCmd
+X interp.commands['return'] = interp.ReturnCmd
+X interp.commands['set'] = interp.SetCmd
+X return interp
+X #
+X def Delete(interp):
+X #
+X # Only break circular references here;
+X # most things will be garbage-collected.
+X #
+X for name in interp.commands.keys():
+X del interp.commands[name]
+X #
+X def CreateCommand(interp, (name, proc)):
+X interp.commands[name] = proc
+X #
+X def DeleteCommand(interp, (name)):
+X del interp.commands[name]
+X #
+X # Local variables are maintained on the stack.
+X # A local variable with value "None" is a dummy
+X # meaning that the corresponding global variable
+X # should be used.
+X #
+X def GetVar(interp, varName):
+X dict = interp.globals
+X if interp.stack:
+X d = interp.stack[-1:][0].locals
+X if d.has_key(varName) and d[varName] = None:
+X pass
+X else:
+X dict = d
+X if not dict.has_key(varName):
+X raise TclRuntimeError, \
+X 'Variable "' + varName + '" not found'
+X return dict[varName]
+X #
+X def SetVar(interp, (varName, newValue)):
+X dict = interp.globals
+X if interp.stack:
+X d = interp.stack[-1:][0].locals
+X if d.has_key(varName) and d[varName] = None:
+X pass
+X else:
+X dict = d
+X dict[varName] = newValue
+X #
+X def Expand(interp, (str, i, end)):
+X if end <= i: return ''
+X if str[i] = '{' and str[end-1] = '}':
+X return str[i+1:end-1]
+X if str[i] = '"' and str[end-1] = '"':
+X i, end = i+1, end-1
+X result = ''
+X while i < end:
+X c = str[i]
+X if c = '\\':
+X x, i = Backslash(str, i, end)
+X result = result + x
+X elif c = '[':
+X j = BalanceBrackets(str, i, end)
+X x = interp.EvalBasic(str, i+1, j-1, 1)
+X result = result + x
+X i = j
+X elif c = '$':
+X i = i+1
+X j = FindVarName(str, i, end)
+X name = str[i:j]
+X i = j
+X if not name:
+X result = result + '$'
+X else:
+X if name[:1] = '{' and name[-1:] = '}':
+X name = name[1:-1]
+X result = result + interp.GetVar(name)
+X else:
+X j = _expand_prog.exec(str, i)
+X j = min(j, end)
+X result = result + str[i:j]
+X i = j
+X return result
+X #
+X def EvalBasic(interp, (str, i, end, bracketed)):
+X result = ''
+X while i < end:
+X indexargv, i = FindNextCommand( \
+X str, i, end, bracketed)
+X if indexargv:
+X argv = []
+X for x, y in indexargv:
+X arg = interp.Expand(str, x, y)
+X argv.append(arg)
+X name = argv[0]
+X if not interp.commands.has_key(name):
+X raise TclRuntimeError, \
+X 'Command "' + name + \
+X '" not found'
+X result = interp.commands[name](argv)
+X return result
+X #
+X def Eval(interp, str):
+X return interp.EvalBasic(str, 0, len(str), 0)
+X #
+X def ExprBasic(interp, (str, begin, end)):
+X expr = interp.Expand(str, begin, end)
+X i = SkipSpaces(expr, 0, len(expr))
+X expr = expr[i:]
+X try:
+X return eval(expr, {})
+X except (NameError, TypeError, RuntimeError, EOFError), msg:
+X import sys
+X raise TclRuntimeError, sys.exc_type + ': ' + msg
+X #
+X def Expr(interp, str):
+X return interp.ExprBasic(str, 0, len(str))
+X #
+X # The rest are command implementations
+X #
+X def BreakCmd(interp, argv):
+X if len(argv) <> 1:
+X raise TclRuntimeError, 'usage: break'
+X raise TclBreak
+X #
+X def ConcatCmd(interp, argv):
+X if len(argv) < 2:
+X raise TclRuntimeError, 'usage: concat arg ...'
+X return Concat(argv[1:])
+X #
+X def ContinueCmd(interp, argv):
+X if len(argv) <> 1:
+X raise TclRuntimeError, 'usage: continue'
+X raise TclContinue
+X #
+X def EchoCmd(interp, argv):
+X for arg in argv[1:]: print arg,
+X print
+X return ''
+X #
+X def EvalCmd(interp, argv):
+X if len(argv) < 2:
+X raise TclRuntimeError, 'usage: eval arg [arg ...]'
+X str = Concat(argv[1:])
+X return interp.Eval(str)
+X #
+X def ExprCmd(interp, argv):
+X if len(argv) <> 2:
+X raise TclRuntimeError, 'usage: expr expression'
+X expr = argv[1]
+X result = interp.Expr(expr)
+X if type(result) <> type(''): result = `result`
+X return result
+X #
+X def ForCmd(interp, argv):
+X if len(argv) <> 5:
+X raise TclRuntimeError, \
+X 'usage: for start test next body'
+X x = interp.Eval(argv[1])
+X while interp.Expr(argv[2]):
+X try:
+X x = interp.Eval(argv[4])
+X except TclBreak:
+X break
+X except TclContinue:
+X pass
+X x = interp.Eval(argv[3])
+X return ''
+X #
+X def GlobCmd(interp, argv):
+X import macglob
+X if len(argv) < 2:
+X raise TclRuntimeError, 'usage: glob pattern ...'
+X list = []
+X for pat in argv[1:]:
+X list = list + macglob.glob(pat)
+X if not list:
+X raise TclRuntimeError, 'no match for glob pattern(s)'
+X return BuildList(list)
+X #
+X def GlobalCmd(interp, argv):
+X if len(argv) < 2:
+X raise TclRuntimeError, 'usage: global varname ...'
+X if not interp.stack:
+X raise TclRuntimeError, 'global used outside proc'
+X dict = interp.stack[-1:][0].locals
+X for name in argv[1:]:
+X dict[name] = None
+X return ''
+X #
+X def IfCmd(interp, argv):
+X argv = argv[:]
+X if len(argv) > 2 and argv[2] = 'then': del argv[2]
+X if len(argv) > 3 and argv[3] = 'else': del argv[3]
+X if not 3 <= len(argv) <= 4:
+X raise TclRuntimeError, \
+X 'usage: if test [then] trueBody [else] falseBody'
+X if interp.Expr(argv[1]):
+X return interp.Eval(argv[2])
+X if len(argv) > 3:
+X return interp.Eval(argv[3])
+X return ''
+X #
+X def IndexCmd(interp, argv):
+X if len(argv) <> 3:
+X raise TclRuntimeError, 'usage: index value index'
+X import string
+X try:
+X index = string.atoi(argv[2])
+X if index < 0: raise string.atoi_error
+X except string.atoi_error:
+X raise TclRuntimeError, 'bad index: ' + argv[2]
+X list = SplitList(argv[1])
+X if index >= len(list): return ''
+X return list[index]
+X #
+X def ListCmd(interp, argv):
+X if len(argv) < 2:
+X raise TclRuntimeError, 'usage: list arg ...'
+X return BuildList(argv[1:])
+X #
+X def ProcCmd(interp, argv):
+X if len(argv) <> 4:
+X raise TclRuntimeError, 'usage: proc name args body'
+X x = _Proc().Create(interp, argv[2], argv[3])
+X interp.CreateCommand(argv[1], x.Call)
+X return ''
+X #
+X def RenameCmd(interp, argv):
+X if len(argv) <> 3:
+X raise TclRuntimeError, 'usage: rename oldName newName'
+X oldName, newName = argv[1], argv[2]
+X if not interp.commands.has_key(oldName):
+X raise TclRuntimeError, \
+X 'command "' + oldName + '" not found'
+X if newName: interp.commands[newName] = interp.commands[oldName]
+X del interp.commands[oldName]
+X return ''
+X #
+X def ReturnCmd(interp, argv):
+X if not 1 <= len(argv) <= 2:
+X raise TclRuntimeError, 'usage: return [arg]'
+X if len(argv) = 1: raise TclReturn, ''
+X raise TclReturn, argv[1]
+X #
+X def SetCmd(interp, argv):
+X n = len(argv)
+X if not 2 <= n <= 3:
+X raise TclRuntimeError, 'usage: set varname [newvalue]'
+X if n = 2: return interp.GetVar(argv[1])
+X interp.SetVar(argv[1], argv[2])
+X return ''
+X
+X
+X# The rest are just demos:
+X
+Xdef MainLoop(interp):
+X buffer = CmdBuf().Create()
+X if not interp.globals.has_key('ps1'): interp.globals['ps1'] = '% '
+X if not interp.globals.has_key('ps2'): interp.globals['ps2'] = ''
+X psname = 'ps1'
+X while 1:
+X try:
+X line = raw_input(interp.globals[psname])
+X except (EOFError, KeyboardInterrupt):
+X print
+X break
+X line = buffer.Assemble(line + '\n')
+X if not line:
+X psname = 'ps2'
+X else:
+X psname = 'ps1'
+X try:
+X x = interp.Eval(line)
+X if x <> '': print 'Result:', `x`
+X except (TclRuntimeError, TclSyntaxError, \
+X TclMatchingError), msg:
+X print 'Error:', msg
+X except (TclBreak, TclContinue):
+X print 'Error: break or continue outside loop'
+X except TclReturn, value:
+X # Return outside proc returns to main loop
+X if value: print value
+X
+X
+Xthe_interpreter = Interpreter().Create()
+X
+Xdef main():
+X MainLoop(the_interpreter)
+X
+X
+X# XXX To do:
+X# for proc: "args" and default arguments
+X# More commands:
+X# case
+X# uplevel
+X# info
+X# string
+X# list operations
+X# error, catch
+X# print
+X# scan, format
+X# source
+X# history?
+X# others?
+EOF
+fi
+if test -s 'src/asa.c'
+then echo '*** I will not over-write existing file src/asa.c'
+else
+echo 'x - src/asa.c'
+sed 's/^X//' > 'src/asa.c' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/* Asynchronous audio module for Silicon Graphics 4D/20 under IRIX 3.3
+X Copyright 1990 Stichting Mathematisch Centrum, Amsterdam
+X Author: Guido van Rossum, <[email protected]>
+X Last modified: [email protected], Oct 14, 1990
+X
+X Callers should #include "asa.h".
+X
+X This code is strongly IRIX 3.3 dependent. (Or are sproc() and
+X friends standard SYSV now?)
+X
+X Caution: if you put printf's in the slave for debugging, use "-lmpc"
+X to get the semaphore version of stdio!
+X
+X
+X This file contains two library layers and a test program:
+X
+X
+X The lower layer implements a simple asynchronous execution facility,
+X built directly on the system calls sproc() and [un]blockproc().
+X
+X A slave thread sits in an infinite loop waiting for work assigned to
+X it by the master thread. Work is represented by a function pointer
+X and an argument of type void*. The function returns a void* pointer
+X which is transferred back to the master when it submits the next bit
+X of work. Submitting a NULL function pointer can be used by the
+X master to wait for completion of the previous work. This lower
+X layer could be generally useful, but is currently implemented by
+X static functions, for exclusive by the asynchronous audio layer.
+X
+X
+X The higher layer implements an asynchronous interface to the
+X /dev/audio device on the Silicon Graphics 4D/20. It defines the
+X following functions:
+X
+X int asa_init()
+X Required initialization function. The other functions will call
+X abort() when they are called before asa_init(). It creates the
+X slave process and returns a file descriptor for the audio
+X device which can be used to set the sampling rate and output
+X gain, etc. It prints a message to stderr and returns -1 if the
+X initialization failed. Calling this function more than onece is
+X harmless.
+X
+X void asa_start_read(char *buf, int len)
+X Starts an asynchronous read call on the audio device. This
+X waits for completion of the previous request, if any.
+X
+X void asa_start_write(char *buf, int len)
+X Starts an asynchronous write call on the audio device. This
+X waits for completion of the previous request, if any.
+X
+X int asa_poll()
+X Polls whether the last asynchronous read or write request is
+X finished. Returns -1 if no request was queued, 0 if the request
+X is not yet finished, and 1 if it is finished.
+X
+X int asa_wait()
+X Waits for completion if the last asynchronous read or write
+X request. It returns the result of the read or write request,
+X and sets the error code to the error code set by the request if
+X the result is -1. If no request was queued, this also returns
+X -1 but leaves the error code unchanged. Note: to get the error
+X code, don't inspect the global variable errno but call the
+X function oserror().
+X
+X int asa_cancel()
+X Cancels the last asynchronous read or write request (by sending
+X the slave thread a signal for which it has a handler) then
+X returns its result and error code as asa_wait().
+X
+X void asa_done()
+X Kills the slave process and closes the audio device. After
+X this, if further use of the module is required, asa_init()
+X should be called again. Calling this function when asa_init()
+X has not been called is harmless.
+X
+X
+X Finally, this file contains a simple test program that is compiled if
+X MAIN is defined (e.g., compile with cc -DMAIN). It makes a recording
+X and plays it back. The user must indicate begin and end of recording
+X and play-back by pressing the Return key.
+X*/
+X
+X
+X#include <stdio.h>
+X#include <stdlib.h>
+X#include <signal.h>
+X#include <sys/types.h>
+X#include <sys/prctl.h>
+X
+X#include "asa.h"
+X
+X
+X/* Asynchronous execution facility (lower layer) */
+X
+X
+X/* Signal used to cancel requests in progress */
+X#define MYSIG SIGUSR1
+X
+X/* Respective process IDs */
+Xstatic pid_t master_pid = -1;
+Xstatic pid_t slave_pid = -1;
+X
+X/* Work and result "queue" (1 element) */
+Xstatic void * (*work_func)();
+Xstatic void *work_arg;
+Xstatic void *work_result;
+X
+X/* Signal handler for MYSIG -- interrupts read or write system call */
+X
+X/*ARGSUSED*/
+Xstatic void
+Xhandler(sig)
+X int sig;
+X{
+X /* Reinstate the handler (non-BSD signal semantics) */
+X signal(sig, handler);
+X}
+X
+X/* Subroutine to fiddle signals */
+X
+Xstatic void
+Xdosig(sig)
+X int sig;
+X{
+X if (signal(sig, SIG_IGN) != SIG_IGN)
+X signal(sig, SIG_DFL);
+X}
+X
+X/* Slave control flow */
+X
+X/*ARGSUSED*/
+Xstatic void
+Xslave(arg)
+X void *arg;
+X{
+X void * (*func)();
+X void *arg;
+X void *result;
+X
+X /* Reset signal handlers that interactive programs often catch.
+X The assumption is that if the master has a handler for these
+X signals, it will be a cleanup function. The slave must die
+X from these. */
+X dosig(SIGHUP);
+X dosig(SIGQUIT);
+X dosig(SIGTERM);
+X dosig(SIGPIPE);
+X
+X /* Ignore SIGINT if caught or ignored */
+X if (signal(SIGINT, SIG_IGN) == SIG_DFL)
+X signal(SIGINT, SIG_DFL);
+X
+X /* Let the handler install itself */
+X handler(MYSIG);
+X
+X /* Set slave_pid. This is also done in the master thread, but
+X there is a race condition whereby the slave begins execution
+X before the master has assigned the result of sproc() to
+X slave_pid. So we set it here as well -- since this sets the
+X same value it should be OK. */
+X slave_pid = getpid();
+X
+X /* Set the dummy result returned by the first rendezvous */
+X result = NULL;
+X
+X /* Loop forever, waiting for and executing work */
+X for (;;) {
+X /* First rendezvous: store previous result */
+X if (blockproc(slave_pid) < 0)
+X perror("slave: [result] blockproc(slave_pid)");
+X work_result = result;
+X if (unblockproc(master_pid) < 0)
+X perror("slave: [result] unblockproc(master_pid)");
+X
+X /* Second rendezvous: fetch work */
+X if (blockproc(slave_pid) < 0)
+X perror("slave: [func,arg] blockproc(slave_pid)");
+X func = work_func;
+X arg = work_arg;
+X if (unblockproc(master_pid) < 0)
+X perror("slave: [func,arg] unblockproc(master_pid)");
+X
+X /* Execute work, computing new result */
+X if (func == NULL) {
+X result = arg;
+X }
+X else {
+X result = (*func)(arg);
+X }
+X }
+X}
+X
+Xstatic int
+Xslave_init()
+X{
+X if (slave_pid > 0)
+X return slave_pid;
+X master_pid = getpid();
+X
+X /* Reset the queue, in case this is a re-init after asa_done() */
+X work_result = NULL;
+X work_func = NULL;
+X work_arg = NULL;
+X
+X /* Create the slave process, sharing all segments and properties */
+X slave_pid = sproc(slave, PR_SALL, (char *)NULL);
+X if (slave_pid < 0)
+X perror("slave_init: sproc(slave, PR_SALL, NULL)");
+X
+X /* Set up initial conditions---tricky!
+X Both the master and the slave start with one credit, since
+X both the result slot and the work/func slots are initially
+X free.
+X Note that we use setblockproccnt() for the master so a
+X possible indeterminate semaphore value caused by a previous
+X asa_done() at an unfortunate moment doesn't harm us.
+X */
+X setblockproccnt(master_pid, 1);
+X unblockproc(slave_pid);
+X
+X return slave_pid;
+X}
+X
+Xstatic void
+Xslave_done()
+X{
+X if (slave_pid > 0) {
+X if (kill(slave_pid, SIGKILL) < 0)
+X perror("slave_done: kill(slave_pid, SIGKILL)");
+X }
+X slave_pid = -1;
+X}
+X
+X/* Queue new work and return result of previous work */
+X
+Xstatic void *
+Xrendezvous(func, arg)
+X void * (*func)();
+X void *arg;
+X{
+X void *result;
+X
+X if (slave_pid <= 0)
+X abort(); /* Illegal call: not initialized properly */
+X
+X /* First rendezvous: store new work */
+X if (blockproc(master_pid) < 0)
+X perror("rendezvous: [func,arg] blockproc(master_pid)");
+X work_func = func;
+X work_arg = arg;
+X if (unblockproc(slave_pid) < 0)
+X perror("rendezvous: [func,arg] unblockproc(slave_pid)");
+X
+X /* Second rendezvous: fetch previous result */
+X if (blockproc(master_pid) < 0)
+X perror("rendezvous: [result] blockproc(master_pid)");
+X result = work_result;
+X if (unblockproc(slave_pid) < 0)
+X perror("rendezvous: [result] unblockproc(slave_pid)");
+X
+X return result;
+X}
+X
+X
+X/* Asynchronous audio interface (higher layer) */
+X
+X
+Xint audio_fd = -1; /* File descriptor -- not initialized yet */
+X
+Xstatic struct queue {
+X int func; /* 0 = read, 1 = write */
+X char *buf;
+X int len;
+X int result;
+X int error;
+X} queue[2];
+X
+Xstatic int qindex = 0;
+X
+Xint
+Xasa_init()
+X{
+X int fd;
+X char *p;
+X
+X if (audio_fd >= 0)
+X return audio_fd;
+X fd = open("/dev/audio", 2);
+X if (fd < 0) {
+X perror("asa_init: Can't open /dev/audio");
+X return -1;
+X }
+X if (slave_init() < 0) {
+X perror("asa_init: Can't create slave process");
+X close(fd);
+X return -1;
+X }
+X audio_fd = fd;
+X return fd;
+X}
+X
+Xvoid
+Xasa_done()
+X{
+X slave_done();
+X if (audio_fd >= 0) {
+X if (close(audio_fd) < 0)
+X perror("asa_done: close(audio_fd)");
+X }
+X audio_fd = -1;
+X}
+X
+Xstatic void *
+Xrunjob(arg)
+X void *arg;
+X{
+X extern int errno;
+X struct queue *q = (struct queue *)arg;
+X char *buf = q->buf;
+X int len = q->len;
+X int n = 0;
+X
+X if (q->func == 0)
+X n = read(audio_fd, buf, len);
+X else
+X n = write(audio_fd, buf, len);
+X if (q->func == 0 && n >= 0) {
+X while (--len >= n && buf[len] == '\0')
+X ;
+X n = len+1;
+X }
+X q->result = n;
+X q->error = oserror();
+X return arg;
+X}
+X
+Xstatic void
+Xstartjob(func, buf, len)
+X int func;
+X char *buf;
+X int len;
+X{
+X struct queue *q;
+X
+X q = &queue[qindex];
+X qindex = (qindex+1) & 1;
+X q->func = func;
+X q->buf = buf;
+X q->len = len;
+X (void) rendezvous(runjob, (void *)q);
+X}
+X
+Xvoid
+Xasa_start_read(buf, len)
+X char *buf;
+X int len;
+X{
+X memset(buf, '\0', len);
+X startjob(0, buf, len);
+X}
+X
+Xvoid
+Xasa_start_write(buf, len)
+X char *buf;
+X int len;
+X{
+X startjob(1, buf, len);
+X}
+X
+Xint
+Xasa_wait()
+X{
+X struct queue *q;
+X
+X q = (struct queue *) rendezvous((void*(*)())NULL, (void *)NULL);
+X if (q == NULL) {
+X setoserror(0);
+X return -1; /* No work was queued */
+X }
+X setoserror(q->error);
+X return q->result;
+X}
+X
+Xint
+Xasa_poll()
+X{
+X int err;
+X
+X err = prctl(PR_ISBLOCKED, slave_pid);
+X if (err < 0) {
+X perror("prctl(PR_ISBLOCKED, slave_pid)");
+X return -1;
+X }
+X else if (err == 0)
+X return 0;
+X else if (work_result == NULL) {
+X setoserror(0);
+X return -1;
+X }
+X else
+X return 1;
+X}
+X
+Xint
+Xasa_cancel()
+X{
+X int result;
+X
+X kill(slave_pid, MYSIG);
+X result = asa_wait();
+X return result;
+X}
+X
+X
+X#ifdef MAIN
+X
+X/* Test program */
+X
+X#include <sys/audio.h>
+X
+Xmain()
+X{
+X static char buf[10*16*1024]; /* 10 seconds of sound at 16K/sec */
+X int n;
+X int afd;
+X
+X if ((afd = asa_init()) < 0)
+X exit(1);
+X ioctl(afd, AUDIOCSETRATE, 3);
+X ioctl(afd, AUDIOCSETOUTGAIN, 0);
+X printf("Poll returns %d\n", asa_poll());
+X go("Hit enter to start recording:\n");
+X asa_start_read(buf, sizeof buf);
+X go("Hit enter to stop recording:\n");
+X /*printf("Poll returns %d\n", asa_poll());*/
+X n = asa_cancel();
+X if (n < 0)
+X perror("Read failed");
+X else {
+X printf("Got %d bytes\n", n);
+X printf("Poll returns %d\n", asa_poll());
+X go("Hit enter to start playing:\n");
+X ioctl(afd, AUDIOCSETOUTGAIN, 50);
+X asa_start_write(buf, n);
+X go("Hit enter to stop playing:\n");
+X printf("Poll returns %d\n", asa_poll());
+X n = asa_cancel();
+X if (n < 0)
+X perror("Write failed");
+X else
+X printf("Stopped at %d bytes\n", n);
+X }
+X ioctl(afd, AUDIOCSETOUTGAIN, 0);
+X asa_done();
+X exit(n < 0 ? 1 : 0);
+X}
+X
+Xgo(str)
+X char *str;
+X{
+X char line[100];
+X
+X sleep(1);
+X fputs(str, stdout);
+X fflush(stdout);
+X fgets(line, sizeof line, stdin);
+X}
+X
+X#endif /* MAIN */
+EOF
+fi
+if test -s 'src/bltinmodule.c'
+then echo '*** I will not over-write existing file src/bltinmodule.c'
+else
+echo 'x - src/bltinmodule.c'
+sed 's/^X//' > 'src/bltinmodule.c' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/* Built-in functions */
+X
+X#include "allobjects.h"
+X
+X#include "node.h"
+X#include "graminit.h"
+X#include "errcode.h"
+X#include "sysmodule.h"
+X#include "bltinmodule.h"
+X#include "import.h"
+X#include "pythonrun.h"
+X#include "compile.h" /* For ceval.h */
+X#include "ceval.h"
+X#include "modsupport.h"
+X
+Xstatic object *
+Xbuiltin_abs(self, v)
+X object *self;
+X object *v;
+X{
+X /* XXX This should be a method in the as_number struct in the type */
+X if (v == NULL) {
+X /* */
+X }
+X else if (is_intobject(v)) {
+X long x = getintvalue(v);
+X if (x < 0)
+X x = -x;
+X return newintobject(x);
+X }
+X else if (is_floatobject(v)) {
+X double x = getfloatvalue(v);
+X if (x < 0)
+X x = -x;
+X return newfloatobject(x);
+X }
+X err_setstr(TypeError, "abs() argument must be float or int");
+X return NULL;
+X}
+X
+Xstatic object *
+Xbuiltin_chr(self, v)
+X object *self;
+X object *v;
+X{
+X long x;
+X char s[1];
+X if (v == NULL || !is_intobject(v)) {
+X err_setstr(TypeError, "chr() must have int argument");
+X return NULL;
+X }
+X x = getintvalue(v);
+X if (x < 0 || x >= 256) {
+X err_setstr(RuntimeError, "chr() arg not in range(256)");
+X return NULL;
+X }
+X s[0] = x;
+X return newsizedstringobject(s, 1);
+X}
+X
+Xstatic object *
+Xbuiltin_dir(self, v)
+X object *self;
+X object *v;
+X{
+X object *d;
+X if (v == NULL) {
+X d = getlocals();
+X }
+X else {
+X if (!is_moduleobject(v)) {
+X err_setstr(TypeError,
+X "dir() argument, must be module or absent");
+X return NULL;
+X }
+X d = getmoduledict(v);
+X }
+X v = getdictkeys(d);
+X if (sortlist(v) != 0) {
+X DECREF(v);
+X v = NULL;
+X }
+X return v;
+X}
+X
+Xstatic object *
+Xbuiltin_divmod(self, v)
+X object *self;
+X object *v;
+X{
+X object *x, *y;
+X long xi, yi, xdivy, xmody;
+X if (v == NULL || !is_tupleobject(v) || gettuplesize(v) != 2) {
+X err_setstr(TypeError, "divmod() requires 2 int arguments");
+X return NULL;
+X }
+X x = gettupleitem(v, 0);
+X y = gettupleitem(v, 1);
+X if (!is_intobject(x) || !is_intobject(y)) {
+X err_setstr(TypeError, "divmod() requires 2 int arguments");
+X return NULL;
+X }
+X xi = getintvalue(x);
+X yi = getintvalue(y);
+X if (yi == 0) {
+X err_setstr(TypeError, "divmod() division by zero");
+X return NULL;
+X }
+X if (yi < 0) {
+X xdivy = -xi / -yi;
+X }
+X else {
+X xdivy = xi / yi;
+X }
+X xmody = xi - xdivy*yi;
+X if (xmody < 0 && yi > 0 || xmody > 0 && yi < 0) {
+X xmody += yi;
+X xdivy -= 1;
+X }
+X v = newtupleobject(2);
+X x = newintobject(xdivy);
+X y = newintobject(xmody);
+X if (v == NULL || x == NULL || y == NULL ||
+X settupleitem(v, 0, x) != 0 ||
+X settupleitem(v, 1, y) != 0) {
+X XDECREF(v);
+X XDECREF(x);
+X XDECREF(y);
+X return NULL;
+X }
+X return v;
+X}
+X
+Xstatic object *
+Xexec_eval(v, start)
+X object *v;
+X int start;
+X{
+X object *str = NULL, *globals = NULL, *locals = NULL;
+X int n;
+X if (v != NULL) {
+X if (is_stringobject(v))
+X str = v;
+X else if (is_tupleobject(v) &&
+X ((n = gettuplesize(v)) == 2 || n == 3)) {
+X str = gettupleitem(v, 0);
+X globals = gettupleitem(v, 1);
+X if (n == 3)
+X locals = gettupleitem(v, 2);
+X }
+X }
+X if (str == NULL || !is_stringobject(str) ||
+X globals != NULL && !is_dictobject(globals) ||
+X locals != NULL && !is_dictobject(locals)) {
+X err_setstr(TypeError,
+X "exec/eval arguments must be string[,dict[,dict]]");
+X return NULL;
+X }
+X return run_string(getstringvalue(str), start, globals, locals);
+X}
+X
+Xstatic object *
+Xbuiltin_eval(self, v)
+X object *self;
+X object *v;
+X{
+X return exec_eval(v, eval_input);
+X}
+X
+Xstatic object *
+Xbuiltin_exec(self, v)
+X object *self;
+X object *v;
+X{
+X return exec_eval(v, file_input);
+X}
+X
+Xstatic object *
+Xbuiltin_float(self, v)
+X object *self;
+X object *v;
+X{
+X if (v == NULL) {
+X /* */
+X }
+X else if (is_floatobject(v)) {
+X INCREF(v);
+X return v;
+X }
+X else if (is_intobject(v)) {
+X long x = getintvalue(v);
+X return newfloatobject((double)x);
+X }
+X err_setstr(TypeError, "float() argument must be float or int");
+X return NULL;
+X}
+X
+Xstatic object *
+Xbuiltin_input(self, v)
+X object *self;
+X object *v;
+X{
+X FILE *in = sysgetfile("stdin", stdin);
+X FILE *out = sysgetfile("stdout", stdout);
+X node *n;
+X int err;
+X object *m, *d;
+X flushline();
+X if (v != NULL)
+X printobject(v, out, PRINT_RAW);
+X m = add_module("__main__");
+X d = getmoduledict(m);
+X return run_file(in, "<stdin>", expr_input, d, d);
+X}
+X
+Xstatic object *
+Xbuiltin_int(self, v)
+X object *self;
+X object *v;
+X{
+X if (v == NULL) {
+X /* */
+X }
+X else if (is_intobject(v)) {
+X INCREF(v);
+X return v;
+X }
+X else if (is_floatobject(v)) {
+X double x = getfloatvalue(v);
+X return newintobject((long)x);
+X }
+X err_setstr(TypeError, "int() argument must be float or int");
+X return NULL;
+X}
+X
+Xstatic object *
+Xbuiltin_len(self, v)
+X object *self;
+X object *v;
+X{
+X long len;
+X typeobject *tp;
+X if (v == NULL) {
+X err_setstr(TypeError, "len() without argument");
+X return NULL;
+X }
+X tp = v->ob_type;
+X if (tp->tp_as_sequence != NULL) {
+X len = (*tp->tp_as_sequence->sq_length)(v);
+X }
+X else if (tp->tp_as_mapping != NULL) {
+X len = (*tp->tp_as_mapping->mp_length)(v);
+X }
+X else {
+X err_setstr(TypeError, "len() of unsized object");
+X return NULL;
+X }
+X return newintobject(len);
+X}
+X
+Xstatic object *
+Xmin_max(v, sign)
+X object *v;
+X int sign;
+X{
+X int i, n, cmp;
+X object *w, *x;
+X sequence_methods *sq;
+X if (v == NULL) {
+X err_setstr(TypeError, "min() or max() without argument");
+X return NULL;
+X }
+X sq = v->ob_type->tp_as_sequence;
+X if (sq == NULL) {
+X err_setstr(TypeError, "min() or max() of non-sequence");
+X return NULL;
+X }
+X n = (*sq->sq_length)(v);
+X if (n == 0) {
+X err_setstr(RuntimeError, "min() or max() of empty sequence");
+X return NULL;
+X }
+X w = (*sq->sq_item)(v, 0); /* Implies INCREF */
+X for (i = 1; i < n; i++) {
+X x = (*sq->sq_item)(v, i); /* Implies INCREF */
+X cmp = cmpobject(x, w);
+X if (cmp * sign > 0) {
+X DECREF(w);
+X w = x;
+X }
+X else
+X DECREF(x);
+X }
+X return w;
+X}
+X
+Xstatic object *
+Xbuiltin_min(self, v)
+X object *self;
+X object *v;
+X{
+X return min_max(v, -1);
+X}
+X
+Xstatic object *
+Xbuiltin_max(self, v)
+X object *self;
+X object *v;
+X{
+X return min_max(v, 1);
+X}
+X
+Xstatic object *
+Xbuiltin_open(self, v)
+X object *self;
+X object *v;
+X{
+X object *name, *mode;
+X if (v == NULL || !is_tupleobject(v) || gettuplesize(v) != 2 ||
+X !is_stringobject(name = gettupleitem(v, 0)) ||
+X !is_stringobject(mode = gettupleitem(v, 1))) {
+X err_setstr(TypeError, "open() requires 2 string arguments");
+X return NULL;
+X }
+X v = newfileobject(getstringvalue(name), getstringvalue(mode));
+X return v;
+X}
+X
+Xstatic object *
+Xbuiltin_ord(self, v)
+X object *self;
+X object *v;
+X{
+X if (v == NULL || !is_stringobject(v)) {
+X err_setstr(TypeError, "ord() must have string argument");
+X return NULL;
+X }
+X if (getstringsize(v) != 1) {
+X err_setstr(RuntimeError, "ord() arg must have length 1");
+X return NULL;
+X }
+X return newintobject((long)(getstringvalue(v)[0] & 0xff));
+X}
+X
+Xstatic object *
+Xbuiltin_range(self, v)
+X object *self;
+X object *v;
+X{
+X static char *errmsg = "range() requires 1-3 int arguments";
+X int i, n;
+X long ilow, ihigh, istep;
+X if (v != NULL && is_intobject(v)) {
+X ilow = 0; ihigh = getintvalue(v); istep = 1;
+X }
+X else if (v == NULL || !is_tupleobject(v)) {
+X err_setstr(TypeError, errmsg);
+X return NULL;
+X }
+X else {
+X n = gettuplesize(v);
+X if (n < 1 || n > 3) {
+X err_setstr(TypeError, errmsg);
+X return NULL;
+X }
+X for (i = 0; i < n; i++) {
+X if (!is_intobject(gettupleitem(v, i))) {
+X err_setstr(TypeError, errmsg);
+X return NULL;
+X }
+X }
+X if (n == 3) {
+X istep = getintvalue(gettupleitem(v, 2));
+X --n;
+X }
+X else
+X istep = 1;
+X ihigh = getintvalue(gettupleitem(v, --n));
+X if (n > 0)
+X ilow = getintvalue(gettupleitem(v, 0));
+X else
+X ilow = 0;
+X }
+X if (istep == 0) {
+X err_setstr(RuntimeError, "zero step for range()");
+X return NULL;
+X }
+X /* XXX ought to check overflow of subtraction */
+X if (istep > 0)
+X n = (ihigh - ilow + istep - 1) / istep;
+X else
+X n = (ihigh - ilow + istep + 1) / istep;
+X if (n < 0)
+X n = 0;
+X v = newlistobject(n);
+X if (v == NULL)
+X return NULL;
+X for (i = 0; i < n; i++) {
+X object *w = newintobject(ilow);
+X if (w == NULL) {
+X DECREF(v);
+X return NULL;
+X }
+X setlistitem(v, i, w);
+X ilow += istep;
+X }
+X return v;
+X}
+X
+Xstatic object *
+Xbuiltin_raw_input(self, v)
+X object *self;
+X object *v;
+X{
+X FILE *in = sysgetfile("stdin", stdin);
+X FILE *out = sysgetfile("stdout", stdout);
+X char *p;
+X int err;
+X int n = 1000;
+X flushline();
+X if (v != NULL)
+X printobject(v, out, PRINT_RAW);
+X v = newsizedstringobject((char *)NULL, n);
+X if (v != NULL) {
+X if ((err = fgets_intr(getstringvalue(v), n+1, in)) != E_OK) {
+X err_input(err);
+X DECREF(v);
+X return NULL;
+X }
+X else {
+X n = strlen(getstringvalue(v));
+X if (n > 0 && getstringvalue(v)[n-1] == '\n')
+X n--;
+X resizestring(&v, n);
+X }
+X }
+X return v;
+X}
+X
+Xstatic object *
+Xbuiltin_reload(self, v)
+X object *self;
+X object *v;
+X{
+X return reload_module(v);
+X}
+X
+Xstatic object *
+Xbuiltin_type(self, v)
+X object *self;
+X object *v;
+X{
+X if (v == NULL) {
+X err_setstr(TypeError, "type() requres an argument");
+X return NULL;
+X }
+X v = (object *)v->ob_type;
+X INCREF(v);
+X return v;
+X}
+X
+Xstatic struct methodlist builtin_methods[] = {
+X {"abs", builtin_abs},
+X {"chr", builtin_chr},
+X {"dir", builtin_dir},
+X {"divmod", builtin_divmod},
+X {"eval", builtin_eval},
+X {"exec", builtin_exec},
+X {"float", builtin_float},
+X {"input", builtin_input},
+X {"int", builtin_int},
+X {"len", builtin_len},
+X {"max", builtin_max},
+X {"min", builtin_min},
+X {"open", builtin_open}, /* XXX move to OS module */
+X {"ord", builtin_ord},
+X {"range", builtin_range},
+X {"raw_input", builtin_raw_input},
+X {"reload", builtin_reload},
+X {"type", builtin_type},
+X {NULL, NULL},
+X};
+X
+Xstatic object *builtin_dict;
+X
+Xobject *
+Xgetbuiltin(name)
+X char *name;
+X{
+X return dictlookup(builtin_dict, name);
+X}
+X
+X/* Predefined exceptions */
+X
+Xobject *RuntimeError;
+Xobject *EOFError;
+Xobject *TypeError;
+Xobject *MemoryError;
+Xobject *NameError;
+Xobject *SystemError;
+Xobject *KeyboardInterrupt;
+X
+Xstatic object *
+Xnewstdexception(name, message)
+X char *name, *message;
+X{
+X object *v = newstringobject(message);
+X if (v == NULL || dictinsert(builtin_dict, name, v) != 0)
+X fatal("no mem for new standard exception");
+X return v;
+X}
+X
+Xstatic void
+Xiniterrors()
+X{
+X RuntimeError = newstdexception("RuntimeError", "run-time error");
+X EOFError = newstdexception("EOFError", "end-of-file read");
+X TypeError = newstdexception("TypeError", "type error");
+X MemoryError = newstdexception("MemoryError", "out of memory");
+X NameError = newstdexception("NameError", "undefined name");
+X SystemError = newstdexception("SystemError", "system error");
+X KeyboardInterrupt =
+X newstdexception("KeyboardInterrupt", "keyboard interrupt");
+X}
+X
+Xvoid
+Xinitbuiltin()
+X{
+X object *m;
+X m = initmodule("builtin", builtin_methods);
+X builtin_dict = getmoduledict(m);
+X INCREF(builtin_dict);
+X initerrors();
+X (void) dictinsert(builtin_dict, "None", None);
+X}
+EOF
+fi
+if test -s 'src/cgen'
+then echo '*** I will not over-write existing file src/cgen'
+else
+echo 'x - src/cgen'
+sed 's/^X//' > 'src/cgen' << 'EOF'
+X# Python script to parse cstubs file for gl and generate C stubs.
+X# usage: python cgen <cstubs >glmodule.c
+X#
+X# XXX BUG return arrays generate wrong code
+X# XXX need to change error returns into gotos to free mallocked arrays
+X
+X
+Ximport string
+Ximport sys
+X
+X
+X# Function to print to stderr
+X#
+Xdef err(args):
+X savestdout = sys.stdout
+X try:
+X sys.stdout = sys.stderr
+X for i in args:
+X print i,
+X print
+X finally:
+X sys.stdout = savestdout
+X
+X
+X# The set of digits that form a number
+X#
+Xdigits = '0123456789'
+X
+X
+X# Function to extract a string of digits from the front of the string.
+X# Returns the leading string of digits and the remaining string.
+X# If no number is found, returns '' and the original string.
+X#
+Xdef getnum(s):
+X n = ''
+X while s and s[0] in digits:
+X n = n + s[0]
+X s = s[1:]
+X return n, s
+X
+X
+X# Function to check if a string is a number
+X#
+Xdef isnum(s):
+X if not s: return 0
+X for c in s:
+X if not c in digits: return 0
+X return 1
+X
+X
+X# Allowed function return types
+X#
+Xreturn_types = ['void', 'short', 'long']
+X
+X
+X# Allowed function argument types
+X#
+Xarg_types = ['char', 'string', 'short', 'float', 'long', 'double']
+X
+X
+X# Need to classify arguments as follows
+X# simple input variable
+X# simple output variable
+X# input array
+X# output array
+X# input giving size of some array
+X#
+X# Array dimensions can be specified as follows
+X# constant
+X# argN
+X# constant * argN
+X# retval
+X# constant * retval
+X#
+X# The dimensions given as constants * something are really
+X# arrays of points where points are 2- 3- or 4-tuples
+X#
+X# We have to consider three lists:
+X# python input arguments
+X# C stub arguments (in & out)
+X# python output arguments (really return values)
+X#
+X# There is a mapping from python input arguments to the input arguments
+X# of the C stub, and a further mapping from C stub arguments to the
+X# python return values
+X
+X
+X# Exception raised by checkarg() and generate()
+X#
+Xarg_error = 'bad arg'
+X
+X
+X# Function to check one argument.
+X# Arguments: the type and the arg "name" (really mode plus subscript).
+X# Raises arg_error if something's wrong.
+X# Return type, mode, factor, rest of subscript; factor and rest may be empty.
+X#
+Xdef checkarg(type, arg):
+X #
+X # Turn "char *x" into "string x".
+X #
+X if type = 'char' and arg[0] = '*':
+X type = 'string'
+X arg = arg[1:]
+X #
+X # Check that the type is supported.
+X #
+X if type not in arg_types:
+X raise arg_error, ('bad type', type)
+X #
+X # Split it in the mode (first character) and the rest.
+X #
+X mode, rest = arg[:1], arg[1:]
+X #
+X # The mode must be 's' for send (= input) or 'r' for return argument.
+X #
+X if mode not in ('r', 's'):
+X raise arg_error, ('bad arg mode', mode)
+X #
+X # Is it a simple argument: if so, we are done.
+X #
+X if not rest:
+X return type, mode, '', ''
+X #
+X # Not a simple argument; must be an array.
+X # The 'rest' must be a subscript enclosed in [ and ].
+X # The subscript must be one of the following forms,
+X # otherwise we don't handle it (where N is a number):
+X # N
+X # argN
+X # retval
+X # N*argN
+X # N*retval
+X #
+X if rest[:1] <> '[' or rest[-1:] <> ']':
+X raise arg_error, ('subscript expected', rest)
+X sub = rest[1:-1]
+X #
+X # Is there a leading number?
+X #
+X num, sub = getnum(sub)
+X if num:
+X # There is a leading number
+X if not sub:
+X # The subscript is just a number
+X return type, mode, num, ''
+X if sub[:1] = '*':
+X # There is a factor prefix
+X sub = sub[1:]
+X else:
+X raise arg_error, ('\'*\' expected', sub)
+X if sub = 'retval':
+X # size is retval -- must be a reply argument
+X if mode <> 'r':
+X raise arg_error, ('non-r mode with [retval]', mode)
+X elif sub[:3] <> 'arg' or not isnum(sub[3:]):
+X raise arg_error, ('bad subscript', sub)
+X #
+X return type, mode, num, sub
+X
+X
+X# List of functions for which we have generated stubs
+X#
+Xfunctions = []
+X
+X
+X# Generate the stub for the given function, using the database of argument
+X# information build by successive calls to checkarg()
+X#
+Xdef generate(type, func, database):
+X #
+X # Check that we can handle this case:
+X # no variable size reply arrays yet
+X #
+X n_in_args = 0
+X n_out_args = 0
+X #
+X for a_type, a_mode, a_factor, a_sub in database:
+X if a_mode = 's':
+X n_in_args = n_in_args + 1
+X elif a_mode = 'r':
+X n_out_args = n_out_args + 1
+X else:
+X # Can't happen
+X raise arg_error, ('bad a_mode', a_mode)
+X if (a_mode = 'r' and a_sub) or a_sub = 'retval':
+X e = 'Function', func, 'too complicated:'
+X err(e + (a_type, a_mode, a_factor, a_sub))
+X print '/* XXX Too complicated to generate code for */'
+X return
+X #
+X functions.append(func)
+X #
+X # Stub header
+X #
+X print
+X print 'static object *'
+X print 'gl_' + func + '(self, args)'
+X print '\tobject *self;'
+X print '\tobject *args;'
+X print '{'
+X #
+X # Declare return value if any
+X #
+X if type <> 'void':
+X print '\t' + type, 'retval;'
+X #
+X # Declare arguments
+X #
+X for i in range(len(database)):
+X a_type, a_mode, a_factor, a_sub = database[i]
+X print '\t' + a_type,
+X if a_sub:
+X print '*',
+X print 'arg' + `i+1`,
+X if a_factor and not a_sub:
+X print '[', a_factor, ']',
+X print ';'
+X #
+X # Find input arguments derived from array sizes
+X #
+X for i in range(len(database)):
+X a_type, a_mode, a_factor, a_sub = database[i]
+X if a_mode = 's' and a_sub[:3] = 'arg' and isnum(a_sub[3:]):
+X # Sending a variable-length array
+X n = eval(a_sub[3:])
+X if 1 <= n <= len(database):
+X b_type, b_mode, b_factor, b_sub = database[n-1]
+X if b_mode = 's':
+X database[n-1] = b_type, 'i', a_factor, `i`
+X n_in_args = n_in_args - 1
+X #
+X # Assign argument positions in the Python argument list
+X #
+X in_pos = []
+X i_in = 0
+X for i in range(len(database)):
+X a_type, a_mode, a_factor, a_sub = database[i]
+X if a_mode = 's':
+X in_pos.append(i_in)
+X i_in = i_in + 1
+X else:
+X in_pos.append(-1)
+X #
+X # Get input arguments
+X #
+X for i in range(len(database)):
+X a_type, a_mode, a_factor, a_sub = database[i]
+X if a_mode = 'i':
+X #
+X # Implicit argument;
+X # a_factor is divisor if present,
+X # a_sub indicates which arg (`database index`)
+X #
+X j = eval(a_sub)
+X print '\tif',
+X print '(!geti' + a_type + 'arraysize(args,',
+X print `n_in_args` + ',',
+X print `in_pos[j]` + ',',
+X print '&arg' + `i+1` + '))'
+X print '\t\treturn NULL;'
+X if a_factor:
+X print '\targ' + `i+1`,
+X print '= arg' + `i+1`,
+X print '/', a_factor + ';'
+X elif a_mode = 's':
+X if a_sub: # Allocate memory for varsize array
+X print '\tif ((arg' + `i+1`, '=',
+X print 'NEW(' + a_type + ',',
+X if a_factor: print a_factor, '*',
+X print a_sub, ')) == NULL)'
+X print '\t\treturn err_nomem();'
+X print '\tif',
+X if a_factor or a_sub: # Get a fixed-size array array
+X print '(!geti' + a_type + 'array(args,',
+X print `n_in_args` + ',',
+X print `in_pos[i]` + ',',
+X if a_factor: print a_factor,
+X if a_factor and a_sub: print '*',
+X if a_sub: print a_sub,
+X print ', arg' + `i+1` + '))'
+X else: # Get a simple variable
+X print '(!geti' + a_type + 'arg(args,',
+X print `n_in_args` + ',',
+X print `in_pos[i]` + ',',
+X print '&arg' + `i+1` + '))'
+X print '\t\treturn NULL;'
+X #
+X # Begin of function call
+X #
+X if type <> 'void':
+X print '\tretval =', func + '(',
+X else:
+X print '\t' + func + '(',
+X #
+X # Argument list
+X #
+X for i in range(len(database)):
+X if i > 0: print ',',
+X a_type, a_mode, a_factor, a_sub = database[i]
+X if a_mode = 'r' and not a_factor:
+X print '&',
+X print 'arg' + `i+1`,
+X #
+X # End of function call
+X #
+X print ');'
+X #
+X # Free varsize arrays
+X #
+X for i in range(len(database)):
+X a_type, a_mode, a_factor, a_sub = database[i]
+X if a_mode = 's' and a_sub:
+X print '\tDEL(arg' + `i+1` + ');'
+X #
+X # Return
+X #
+X if n_out_args:
+X #
+X # Multiple return values -- construct a tuple
+X #
+X if type <> 'void':
+X n_out_args = n_out_args + 1
+X if n_out_args = 1:
+X for i in range(len(database)):
+X a_type, a_mode, a_factor, a_sub = database[i]
+X if a_mode = 'r':
+X break
+X else:
+X raise arg_error, 'expected r arg not found'
+X print '\treturn',
+X print mkobject(a_type, 'arg' + `i+1`) + ';'
+X else:
+X print '\t{ object *v = newtupleobject(',
+X print n_out_args, ');'
+X print '\t if (v == NULL) return NULL;'
+X i_out = 0
+X if type <> 'void':
+X print '\t settupleitem(v,',
+X print `i_out` + ',',
+X print mkobject(type, 'retval') + ');'
+X i_out = i_out + 1
+X for i in range(len(database)):
+X a_type, a_mode, a_factor, a_sub = database[i]
+X if a_mode = 'r':
+X print '\t settupleitem(v,',
+X print `i_out` + ',',
+X s = mkobject(a_type, 'arg' + `i+1`)
+X print s + ');'
+X i_out = i_out + 1
+X print '\t return v;'
+X print '\t}'
+X else:
+X #
+X # Simple function return
+X # Return None or return value
+X #
+X if type = 'void':
+X print '\tINCREF(None);'
+X print '\treturn None;'
+X else:
+X print '\treturn', mkobject(type, 'retval') + ';'
+X #
+X # Stub body closing brace
+X #
+X print '}'
+X
+X
+X# Subroutine to return a function call to mknew<type>object(<arg>)
+X#
+Xdef mkobject(type, arg):
+X return 'mknew' + type + 'object(' + arg + ')'
+X
+X
+X# Input line number
+Xlno = 0
+X
+X
+X# Input is divided in two parts, separated by a line containing '%%'.
+X# <part1> -- literally copied to stdout
+X# <part2> -- stub definitions
+X
+X# Variable indicating the current input part.
+X#
+Xpart = 1
+X
+X# Main loop over the input
+X#
+Xwhile 1:
+X try:
+X line = raw_input()
+X except EOFError:
+X break
+X #
+X lno = lno+1
+X words = string.split(line)
+X #
+X if part = 1:
+X #
+X # In part 1, copy everything literally
+X # except look for a line of just '%%'
+X #
+X if words = ['%%']:
+X part = part + 1
+X else:
+X #
+X # Look for names of manually written
+X # stubs: a single percent followed by the name
+X # of the function in Python.
+X # The stub name is derived by prefixing 'gl_'.
+X #
+X if words and words[0][0] = '%':
+X func = words[0][1:]
+X if (not func) and words[1:]:
+X func = words[1]
+X if func:
+X functions.append(func)
+X else:
+X print line
+X elif not words:
+X pass # skip empty line
+X elif words[0] = '#include':
+X print line
+X elif words[0][:1] = '#':
+X pass # ignore comment
+X elif words[0] not in return_types:
+X err('Line', lno, ': bad return type :', words[0])
+X elif len(words) < 2:
+X err('Line', lno, ': no funcname :', line)
+X else:
+X if len(words) % 2 <> 0:
+X err('Line', lno, ': odd argument list :', words[2:])
+X else:
+X database = []
+X try:
+X for i in range(2, len(words), 2):
+X x = checkarg(words[i], words[i+1])
+X database.append(x)
+X print
+X print '/*',
+X for w in words: print w,
+X print '*/'
+X generate(words[0], words[1], database)
+X except arg_error, msg:
+X err('Line', lno, ':', msg)
+X
+X
+Xprint
+Xprint 'static struct methodlist gl_methods[] = {'
+Xfor func in functions:
+X print '\t{"' + func + '", gl_' + func + '},'
+Xprint '\t{NULL, NULL} /* Sentinel */'
+Xprint '};'
+Xprint
+Xprint 'initgl()'
+Xprint '{'
+Xprint '\tinitmodule("gl", gl_methods);'
+Xprint '}'
+EOF
+fi
+echo 'Part 10 out of 21 of pack.out complete.'
+exit 0
diff --git a/shar/python-0.9.1-11-21.shar b/shar/python-0.9.1-11-21.shar
new file mode 100644
index 0000000..59aa0a2
--- /dev/null
+++ b/shar/python-0.9.1-11-21.shar
@@ -0,0 +1,2618 @@
+: This is a shell archive.
+: Extract with 'sh this_file'.
+:
+: Extract part 01 first since it makes all directories
+echo 'Start of pack.out, part 11 out of 21:'
+if test -s 'lib/Buttons.py'
+then echo '*** I will not over-write existing file lib/Buttons.py'
+else
+echo 'x - lib/Buttons.py'
+sed 's/^X//' > 'lib/Buttons.py' << 'EOF'
+X# Module 'Buttons'
+X
+X
+X# Import module 'rect' renamed as '_rect' to avoid exporting it on
+X# 'from Buttons import *'
+X#
+Ximport rect
+X_rect = rect
+Xdel rect
+X
+X
+X# Field indices in mouse event detail
+X#
+X_HV = 0
+X_CLICKS = 1
+X_BUTTON = 2
+X_MASK = 3
+X
+X
+X# LabelAppearance provides defaults for all appearance methods.
+X# selected state not visible
+X# disabled --> crossed out
+X# hilited --> inverted
+X#
+Xclass LabelAppearance():
+X #
+X # Initialization
+X #
+X def init_appearance(self):
+X self.bounds = _rect.empty
+X self.enabled = 1
+X self.hilited = 0
+X self.selected = 0
+X self.text = ''
+X #
+X # Size enquiry
+X #
+X def minsize(self, m):
+X try:
+X self.text = self.text
+X except NameError:
+X self.text = ''
+X return m.textwidth(self.text) + 6, m.lineheight() + 6
+X #
+X def getbounds(self):
+X return self.bounds
+X #
+X # Changing the parameters
+X #
+X def settext(self, text):
+X self.text = text
+X if self.bounds <> _rect.empty:
+X self.recalctextpos()
+X self.redraw()
+X #
+X def setbounds(self, bounds):
+X if self.bounds <> _rect.empty:
+X self.parent.change(self.bounds)
+X self.bounds = bounds
+X if self.bounds <> _rect.empty:
+X self.recalc()
+X self.parent.change(bounds)
+X #
+X # Changing the state bits
+X #
+X def enable(self, flag):
+X if flag <> self.enabled:
+X self.enabled = flag
+X if self.bounds <> _rect.empty:
+X self.flipenable(self.parent.begindrawing())
+X #
+X def hilite(self, flag):
+X if flag <> self.hilited:
+X self.hilited = flag
+X if self.bounds <> _rect.empty:
+X self.fliphilite(self.parent.begindrawing())
+X #
+X def select(self, flag):
+X if flag <> self.selected:
+X self.selected = flag
+X if self.bounds <> _rect.empty:
+X self.redraw()
+X #
+X # Recalculate the box bounds and text position.
+X # This can be overridden by buttons that draw different boxes
+X # or want their text in a different position.
+X #
+X def recalc(self):
+X if self.bounds <> _rect.empty:
+X self.recalcbounds()
+X self.recalctextpos()
+X #
+X def recalcbounds(self):
+X self.hilitebounds = _rect.inset(self.bounds, (3, 3))
+X self.crossbounds = self.bounds
+X #
+X def recalctextpos(self):
+X (left, top), (right, bottom) = self.bounds
+X m = self.parent.beginmeasuring()
+X h = (left + right - m.textwidth(self.text)) / 2
+X v = (top + bottom - m.lineheight()) / 2
+X self.textpos = h, v
+X #
+X # Generic drawing interface.
+X # Do not override redraw() or draw() methods; override drawit() c.s.
+X #
+X def redraw(self):
+X if self.bounds <> _rect.empty:
+X self.draw(self.parent.begindrawing(), self.bounds)
+X #
+X def draw(self, (d, area)):
+X area = _rect.intersect(area, self.bounds)
+X if area = _rect.empty:
+X return
+X d.cliprect(area)
+X d.erase(self.bounds)
+X self.drawit(d)
+X d.noclip()
+X #
+X # The drawit() method is fairly generic but may be overridden.
+X #
+X def drawit(self, d):
+X self.drawpict(d)
+X if self.text:
+X d.text(self.textpos, self.text)
+X if not self.enabled:
+X self.flipenable(d)
+X if self.hilited:
+X self.fliphilite(d)
+X #
+X # Default drawing detail functions.
+X # Overriding these is normally sufficient to get different
+X # appearances.
+X #
+X def drawpict(self, d):
+X pass
+X #
+X def flipenable(self, d):
+X _xorcross(d, self.crossbounds)
+X #
+X def fliphilite(self, d):
+X d.invert(self.hilitebounds)
+X
+X
+X# ButtonAppearance displays a centered string in a box.
+X# selected --> bold border
+X# disabled --> crossed out
+X# hilited --> inverted
+X#
+Xclass ButtonAppearance() = LabelAppearance():
+X #
+X def drawpict(self, d):
+X d.box(_rect.inset(self.bounds, (1, 1)))
+X if self.selected:
+X # Make a thicker box
+X d.box(self.bounds)
+X d.box(_rect.inset(self.bounds, (2, 2)))
+X d.box(_rect.inset(self.bounds, (3, 3)))
+X #
+X
+X
+X# CheckAppearance displays a small square box and a left-justified string.
+X# selected --> a cross appears in the box
+X# disabled --> whole button crossed out
+X# hilited --> box is inverted
+X#
+Xclass CheckAppearance() = LabelAppearance():
+X #
+X def minsize(self, m):
+X width, height = m.textwidth(self.text) + 6, m.lineheight() + 6
+X return width + height + m.textwidth(' '), height
+X #
+X def drawpict(self, d):
+X d.box(self.boxbounds)
+X if self.selected: _xorcross(d, self.boxbounds)
+X #
+X def recalcbounds(self):
+X LabelAppearance.recalcbounds(self)
+X (left, top), (right, bottom) = self.bounds
+X self.size = bottom - top - 4
+X self.boxbounds = (left+2, top+2), (left+2+self.size, bottom-2)
+X self.hilitebounds = self.boxbounds
+X #
+X def recalctextpos(self):
+X m = self.parent.beginmeasuring()
+X (left, top), (right, bottom) = self.boxbounds
+X h = right + m.textwidth(' ')
+X v = top + (self.size - m.lineheight()) / 2
+X self.textpos = h, v
+X #
+X
+X
+X# RadioAppearance displays a round indicator and a left-justified string.
+X# selected --> a dot appears in the indicator
+X# disabled --> whole button crossed out
+X# hilited --> indicator is inverted
+X#
+Xclass RadioAppearance() = CheckAppearance():
+X #
+X def drawpict(self, d):
+X (left, top), (right, bottom) = self.boxbounds
+X radius = self.size / 2
+X h, v = left + radius, top + radius
+X d.circle((h, v), radius)
+X if self.selected:
+X some = radius/3
+X d.paint((h-some, v-some), (h+some, v+some))
+X #
+X
+X
+X# NoReactivity ignores mouse events.
+X#
+Xclass NoReactivity():
+X def init_reactivity(self): pass
+X
+X
+X# BaseReactivity defines hooks and asks for mouse events,
+X# but provides only dummy mouse event handlers.
+X# The trigger methods call the corresponding hooks set by the user.
+X# Hooks (and triggers) mean the following:
+X# down_hook called on some mouse-down events
+X# move_hook called on some mouse-move events
+X# up_hook called on mouse-up events
+X# on_hook called for buttons with on/off state, when it goes on
+X# hook called when a button 'fires' or a radiobutton goes on
+X# There are usually extra conditions, e.g., hooks are only called
+X# when the button is enabled, or active, or selected (on).
+X#
+Xclass BaseReactivity():
+X #
+X def init_reactivity(self):
+X self.down_hook = self.move_hook = self.up_hook = \
+X self.on_hook = self.off_hook = \
+X self.hook = self.active = 0
+X self.parent.need_mouse(self)
+X #
+X def mousetest(self, hv):
+X return _rect.pointinrect(hv, self.bounds)
+X #
+X def mouse_down(self, detail):
+X pass
+X #
+X def mouse_move(self, detail):
+X pass
+X #
+X def mouse_up(self, detail):
+X pass
+X #
+X def down_trigger(self):
+X if self.down_hook: self.down_hook(self)
+X #
+X def move_trigger(self):
+X if self.move_hook: self.move_hook(self)
+X #
+X def up_trigger(self):
+X if self.up_hook: self.up_hook(self)
+X #
+X def on_trigger(self):
+X if self.on_hook: self.on_hook(self)
+X #
+X def off_trigger(self):
+X if self.off_hook: self.off_hook(self)
+X #
+X def trigger(self):
+X if self.hook: self.hook(self)
+X
+X
+X# ToggleReactivity acts like a simple pushbutton.
+X# It toggles its hilite state on mouse down events.
+X#
+Xclass ToggleReactivity() = BaseReactivity():
+X #
+X def mouse_down(self, detail):
+X if self.enabled and self.mousetest(detail[_HV]):
+X self.active = 1
+X self.hilite(not self.hilited)
+X self.down_trigger()
+X #
+X def mouse_move(self, detail):
+X if self.active:
+X self.move_trigger()
+X #
+X def mouse_up(self, detail):
+X if self.active:
+X self.up_trigger()
+X self.active = 0
+X #
+X def down_trigger(self):
+X if self.hilited:
+X self.on_trigger()
+X else:
+X self.off_trigger()
+X self.trigger()
+X #
+X
+X
+X# TriggerReactivity acts like a fancy pushbutton.
+X# It hilites itself while the mouse is down within its bounds.
+X#
+Xclass TriggerReactivity() = BaseReactivity():
+X #
+X def mouse_down(self, detail):
+X if self.enabled and self.mousetest(detail[_HV]):
+X self.active = 1
+X self.hilite(1)
+X self.down_trigger()
+X #
+X def mouse_move(self, detail):
+X if self.active:
+X self.hilite(self.mousetest(detail[_HV]))
+X if self.hilited:
+X self.move_trigger()
+X #
+X def mouse_up(self, detail):
+X if self.active:
+X self.hilite(self.mousetest(detail[_HV]))
+X if self.hilited:
+X self.up_trigger()
+X self.trigger()
+X self.active = 0
+X self.hilite(0)
+X #
+X
+X
+X# CheckReactivity handles mouse events like TriggerReactivity,
+X# It overrides the up_trigger method to flip its selected state.
+X#
+Xclass CheckReactivity() = TriggerReactivity():
+X #
+X def up_trigger(self):
+X self.select(not self.selected)
+X if self.selected:
+X self.on_trigger()
+X else:
+X self.off_trigger()
+X self.trigger()
+X
+X
+X# RadioReactivity turns itself on and the other buttons in its group
+X# off when its up_trigger method is called.
+X#
+Xclass RadioReactivity() = TriggerReactivity():
+X #
+X def init_reactivity(self):
+X TriggerReactivity.init_reactivity(self)
+X self.group = []
+X #
+X def up_trigger(self):
+X for b in self.group:
+X if b <> self:
+X if b.selected:
+X b.select(0)
+X b.off_trigger()
+X self.select(1)
+X self.on_trigger()
+X self.trigger()
+X
+X
+X# Auxiliary class for 'define' method.
+X# Call the initializers in the right order.
+X#
+Xclass Define():
+X #
+X def define(self, parent):
+X self.parent = parent
+X parent.addchild(self)
+X self.init_appearance()
+X self.init_reactivity()
+X return self
+X #
+X def destroy(self):
+X self.parent = 0
+X #
+X def definetext(self, (parent, text)):
+X self = self.define(parent)
+X self.settext(text)
+X return self
+X
+X
+X# Subroutine to cross out a rectangle.
+X#
+Xdef _xorcross(d, bounds):
+X ((left, top), (right, bottom)) = bounds
+X # This is s bit funny to make it look better
+X left = left + 2
+X right = right - 2
+X top = top + 2
+X bottom = bottom - 3
+X d.xorline(((left, top), (right, bottom)))
+X d.xorline((left, bottom), (right, top))
+X
+X
+X# Ready-made button classes.
+X#
+Xclass Label() = NoReactivity(), LabelAppearance(), Define(): pass
+Xclass PushButton() = TriggerReactivity(), ButtonAppearance(), Define(): pass
+Xclass CheckButton() = CheckReactivity(), CheckAppearance(), Define(): pass
+Xclass RadioButton() = RadioReactivity(), RadioAppearance(), Define(): pass
+Xclass ToggleButton() = ToggleReactivity(), ButtonAppearance(), Define(): pass
+EOF
+fi
+if test -s 'lib/TclUtil.py'
+then echo '*** I will not over-write existing file lib/TclUtil.py'
+else
+echo 'x - lib/TclUtil.py'
+sed 's/^X//' > 'lib/TclUtil.py' << 'EOF'
+X# Utilities used by 'Tcl' emulator.
+X
+X
+X# Many functions in this file parse specific constructs from strings.
+X# In order to limit the number of slice operations (the strings can
+X# be very large), they always receive indices into the string that
+X# indicate the slice of the string that should be considered.
+X# The return value is in general another index, pointing to the first
+X# character in the string beyond the recognized construct.
+X# Errors are reported as exceptions (TclSyntaxError, TclMatchingError).
+X# A few functions have multiple return values.
+X
+X
+X# For efficiency, the Tcl "tokenizing" routines used pre-compiled
+X# regular expressions. This is less readable but should be much faster
+X# than scanning the string a character at a time.
+X#
+X# The global variables
+X# containing the compiled regexp's are named _foo_prog where foo is
+X# an indication of the function that uses them.
+X#
+X# The patterns always
+X# have the form <something>* so they always match at the start of the
+X# search buffer---maybe with the empty string. This makes it possible
+X# to use the expression "_foo_prog.exec(str, i)[0][1]" to find the first
+X# character beyond the matched string. Note that this may be beyond the
+X# end variable -- where this matters, "min(i, end)" is used.
+X
+X# Constructs that cannot
+X# be recognized by a finite automaton (like matching braces) are scanned
+X# by a hybrid technique where the regular expression excludes the
+X# braces.
+X#
+X# Many regular expressions contain an expression that matches
+X# a Tcl backslash sequence as a subpart:
+X# \\\\C?M?(.|\n)
+X#
+X# This is a bit hard to
+X# read because the backslash contained in it must be doubled twice:
+X# once to get past Python's backslash mechanism, once to get past that
+X# of regular expressions. It uses (.|\n) to match absolutely
+X# *every character*, becase the MULTILINE regular expression package does
+X# not accept '\n' as a match for '.'.
+X#
+X# There is also a simplification in the pattern for backslashes:
+X# *any* single character following a backslash is escaped,
+X# so hex and octal
+X# excapes are not scanned fully. The forms \Cx, \Mx and \CMx are
+X# scanned correctly, as these may hide a special character.
+X# (This does not invalidate the recognition of strings, although the
+X# match is effectuated in a different way than by the Backslash function.)
+X
+Ximport regexp
+X
+X
+X# Exceptions raised for various error conditions.
+X
+XTclAssertError = 'Tcl assert error'
+XTclSyntaxError = 'Tcl syntax error'
+XTclRuntimeError = 'Tcl runtime error'
+XTclMatchingError = 'Tcl matching error'
+X
+X
+X# Find a variable name.
+X# A variable name is either a (possiblly empty) sequence of letters,
+X# digits and underscores, or anything enclosed in matching braces.
+X# Return the index past the end of the name.
+X
+X_varname_prog = regexp.compile('[a-zA-Z0-9_]*')
+X
+Xdef FindVarName(str, i, end):
+X if i < end and str[i] = '{': return BalanceBraces(str, i, end)
+X i = _varname_prog.exec(str, i)[0][1]
+X return min(i, end)
+X
+X
+X# Split a list into its elements.
+X# Return a list of elements (strings).
+X
+Xdef SplitList(str):
+X i, end = 0, len(str)
+X list = []
+X while 1:
+X i = SkipSpaces(str, i, end)
+X if i >= end: break
+X j = i
+X i = FindNextElement(str, i, end)
+X if str[j] = '{' and str[i-1] = '}':
+X element = str[j+1:i-1]
+X else:
+X element = Collapse(str[j:i])
+X list.append(element)
+X return list
+X
+X
+X# Find the next element from a list.
+X
+X_element_prog = regexp.compile('([^ \t\n\\]+|\\\\C?M?(.|\n))*')
+X
+Xdef FindNextElement(str, i, end):
+X if i < end and str[i] = '{':
+X i = BalanceBraces(str, i, end)
+X if i < end and str[i] not in ' \t\n':
+X raise TclSyntaxError, 'Garbage after } in list'
+X return i
+X i = _element_prog.exec(str, i)[0][1]
+X return min(i, end)
+X
+X
+X# Copy a string, expanding all backslash sequences.
+X
+X_collapse_prog = regexp.compile('(\n|[^\\]+)*')
+X
+Xdef Collapse(str):
+X if '\\' not in str: return str
+X i, end = 0, len(str)
+X result = ''
+X while i < end:
+X j = _collapse_prog.exec(str, i)[0][1]
+X j = min(j, end)
+X result = result + str[i:j]
+X if j >= end: break
+X c = str[j]
+X if c <> '\\': raise TclAssertError, 'collapse error'
+X x, i = Backslash(str, j, end)
+X result = result + x
+X return result
+X
+X
+X# Find the next full command.
+X# Return a list of begin, end indices of words in the string,
+X# and an index pointing just after the terminating newline or
+X# semicolon.
+X# Initial spaces are skipped.
+X# If the command begins with '#', it is considered empty and
+X# characters until '\n' are skipped.
+X
+X_eol_prog = regexp.compile('[^\n]*')
+X
+Xdef FindNextCommand(str, i, end, bracketed):
+X i = SkipSpaces(str, i, end)
+X if i >= end: return [], end
+X if str[i] = '#':
+X i = _eol_prog.exec(str, i)
+X i = min(i, end)
+X if i < end and str[i] = '\n': i = i+1
+X return [], i
+X if bracketed: terminators = [';']
+X else: terminators = [';', '\n']
+X list = []
+X while i < end:
+X j = FindNextWord(str, i, end)
+X word = str[i:j]
+X if word in terminators:
+X i = j
+X break
+X if word <> '\n': list.append(i, j)
+X i = SkipSpaces(str, j, end)
+X return list, i
+X
+X
+X# Find the next word of a command.
+X# Semicolon and newline terminate words but also count as a word
+X# themselves.
+X# The start index must point to the start of the word.
+X
+X_word_prog = regexp.compile('([^ \t\n;[\\]+|\\\\C?M?(.|\n))*')
+X
+Xdef FindNextWord(str, i, end):
+X if i >= end: return end
+X if str[i] in '{"':
+X if str[i] = '{': i = BalanceBraces(str, i, end)
+X else: i = BalanceQuotes(str, i, end)
+X if i >= end or str[i] in ' \t\n;': return min(i, end)
+X raise TclSyntaxError, 'Garbage after } or "'
+X begin = i
+X while i < end:
+X i = _word_prog.exec(str, i)[0][1]
+X if i >= end:
+X i = end
+X break
+X c = str[i]
+X if c in ' \t': break
+X if c in ';\n':
+X if i = begin: i = i+1
+X break
+X if c = '[': i = BalanceBrackets(str, i, end)
+X else: raise TclAssertError, 'word error'
+X return i
+X
+X
+X# Parse balanced brackets from str[i:end].
+X# str[i] must be '['.
+X# Returns end such that str[i:end] ends with ']'
+X# and contains balanced braces and brackets.
+X
+X_brackets_prog = regexp.compile('([^][{\\]+|\n|\\\\C?M?(.|\n))*')
+X
+Xdef BalanceBrackets(str, i, end):
+X if i >= end or str[i] <> '[':
+X raise TclAssertError, 'BalanceBrackets'
+X nesting = 0
+X while i < end:
+X i = _brackets_prog.exec(str, i)[0][1]
+X if i >= end: break
+X c = str[i]
+X if c = '{': i = BalanceBraces(str, i, end)
+X else:
+X i = i+1
+X if c = '[': nesting = nesting + 1
+X elif c = ']':
+X nesting = nesting - 1
+X if nesting = 0: return i
+X else: raise TclAssertError, 'brackets error'
+X raise TclMatchingError, 'Unmatched bracket ([)'
+X
+X
+X# Parse balanced braces from str[i:end].
+X# str[i] must be '{'.
+X# Returns end such that str[i:end] ends with '}'
+X# and contains balanced braces.
+X
+X_braces_prog = regexp.compile('([^{}\\]+|\n|\\\\C?M?(.|\n))*')
+X
+Xdef BalanceBraces(str, i, end):
+X if i >= end or str[i] <> '{':
+X raise TclAssertError, 'BalanceBraces'
+X nesting = 0
+X while i < end:
+X i = _braces_prog.exec(str, i)[0][1]
+X if i >= end: break
+X c = str[i]
+X i = i+1
+X if c = '{': nesting = nesting + 1
+X elif c = '}':
+X nesting = nesting - 1
+X if nesting = 0: return i
+X else: raise TclAssertError, 'braces error'
+X raise TclMatchingError, 'Unmatched brace ({)'
+X
+X
+X# Parse double quotes from str[i:end].
+X# str[i] must be '"'.
+X# Returns end such that str[i:end] ends with an unescaped '"'.
+X
+X_quotes_prog = regexp.compile('([^"\\]+|\n|\\\\C?M?(.|\n))*')
+X
+Xdef BalanceQuotes(str, i, end):
+X if i >= end or str[i] <> '"':
+X raise TclAssertError, 'BalanceQuotes'
+X i = _quotes_prog.exec(str, i+1)[0][1]
+X if i < end and str[i] = '"': return i+1
+X raise TclMatchingError, 'Unmatched quote (")'
+X
+X
+X# Static data used by Backslash()
+X
+X_bstab = {}
+X_bstab['n'] = '\n'
+X_bstab['r'] = '\r'
+X_bstab['t'] = '\t'
+X_bstab['b'] = '\b'
+X_bstab['e'] = '\033'
+X_bstab['\n'] = ''
+Xfor c in ' {}[]$";\\': _bstab[c] = c
+Xdel c
+X
+X# Backslash interpretation.
+X# First character must be a backslash.
+X# Return a pair (<replacement string>, <end of sequence>).
+X# Unrecognized or incomplete backslash sequences are not errors;
+X# this takes only the backslash itself off the string.
+X
+Xdef Backslash(str, i, end):
+X if i >= end or str[i] <> '\\':
+X raise TclAssertError, 'Backslash'
+X i = i+1
+X if i = end: return '\\', i
+X c = str[i]
+X i = i+1
+X if _bstab.has_key(c): return _bstab[c], i
+X if c = 'C':
+X if i = end: return '\\', i-1
+X c = str[i]
+X i = i+1
+X if c = 'M':
+X if i = end: return '\\', i-2
+X c = str[i]
+X i = i+1
+X x = ord(c) % 040 + 0200
+X else:
+X x = ord(c) % 040
+X return chr(x), i
+X elif c = 'M':
+X if i = end: return '\\', i-1
+X c = str[i]
+X i = i+1
+X x = ord(c)
+X if x < 0200: x = x + 0200
+X return chr(x), i
+X elif c and c in '0123456789':
+X x = ord(c) - ord('0')
+X end = min(end, i+2)
+X while i < end:
+X c = str[i]
+X if c not in '0123456789': break
+X i = i+1
+X x = x*8 + ord(c) - ord('0')
+X return ord(x), i
+X else:
+X # Not something that we recognize
+X return '\\', i-1
+X
+X
+X# Skip over spaces and tabs (but not newlines).
+X
+X_spaces_prog = regexp.compile('[ \t]*')
+X
+Xdef SkipSpaces(str, i, end):
+X i = _spaces_prog.exec(str, i)[0][1]
+X return min(i, end)
+X
+X
+X# Concatenate the elements of a list with intervening spaces.
+X
+Xdef Concat(argv):
+X result = ''
+X sep = ''
+X for arg in argv:
+X result = result + (sep + arg)
+X sep = ' '
+X return result
+X
+X
+X# Concatenate list elements, adding braces etc. to make them parseable
+X# again with SplitList.
+X
+Xdef BuildList(argv):
+X result = ''
+X sep = ''
+X for arg in argv:
+X arg = AddBraces(arg)
+X result = result + (sep + arg)
+X sep = ' '
+X return result
+X
+X
+X# Add braces around a string if necessary to make it parseable by SplitList.
+X
+Xdef AddBraces(str):
+X # Special case for empty string
+X if str = '': return '{}'
+X # See if it contains balanced braces
+X res = '{' + str + '}'
+X if TryNextElement(res):
+X # See if it would survive unquoted
+X # XXX should escape [] and $ as well???
+X if TryNextElement(str) and Collapse(str) = str: return str
+X # No -- return with added braces
+X return res
+X # Unbalanced braces. Add backslashes before suspect characters
+X res = ''
+X for c in str:
+X if c in '$\\[]{} ;': c = '\\' + c
+X elif c = '\n': c = '\\n'
+X elif c = '\t': c = '\\t'
+X res = res + c
+X return res
+X
+X
+Xdef TryNextElement(str):
+X end = len(str)
+X try:
+X i = FindNextElement(str, 0, end)
+X return i = end
+X except (TclSyntaxError, TclMatchingError):
+X return 0
+EOF
+fi
+if test -s 'lib/testall.py'
+then echo '*** I will not over-write existing file lib/testall.py'
+else
+echo 'x - lib/testall.py'
+sed 's/^X//' > 'lib/testall.py' << 'EOF'
+X# Module 'testall'
+X#
+X# Python test set, should exercise:
+X# - all lexical and grammatical constructs
+X# - all opcodes from "opcode.h"
+X# - all operations on all object types
+X# - all builtin functions
+X# Ideally also:
+X# - all possible exception situations (Thank God we've got 'try')
+X# - all boundary cases
+X
+X
+XTestFailed = 'testall -- test failed' # Exception
+X
+X
+X#########################################################
+X# Part 1. Test all lexical and grammatical constructs.
+X# This just tests whether the parser accepts them all.
+X#########################################################
+X
+Xprint '1. Parser'
+X
+Xprint '1.1 Tokens'
+X
+Xprint '1.1.1 Backslashes'
+X
+X# Backslash means line continuation:
+Xx = 1 \
+X+ 1
+Xif x <> 2: raise TestFailed, 'backslash for line continuation'
+X
+X# Backslash does not means continuation in comments :\
+Xx = 0
+Xif x <> 0: raise TestFailed, 'backslash ending comment'
+X
+Xprint '1.1.2 Number formats'
+X
+Xif 0xff <> 255: raise TestFailed, 'hex number'
+Xif 0377 <> 255: raise TestFailed, 'octal number'
+Xx = 3.14
+Xx = 0.314
+Xx = 3e14
+Xx = 3E14
+Xx = 3e-14
+X
+Xprint '1.2 Grammar'
+X
+Xprint 'single_input' # NEWLINE | simple_stmt | compound_stmt NEWLINE
+X# XXX can't test in a script -- this rule is only used when interactive
+X
+Xprint 'file_input' # (NEWLINE | stmt)* ENDMARKER
+X# Being tested as this very moment this very module
+X
+Xprint 'expr_input' # testlist NEWLINE
+X# XXX Hard to test -- used only in calls to input()
+X
+Xprint 'eval_input' # testlist ENDMARKER
+Xx = eval('1, 0 or 1')
+X
+Xprint 'funcdef' # 'def' NAME parameters ':' suite
+X### parameters: '(' [fplist] ')'
+X### fplist: fpdef (',' fpdef)*
+X### fpdef: NAME | '(' fplist ')'
+Xdef f1(): pass
+Xdef f2(one_argument): pass
+Xdef f3(two, arguments): pass
+Xdef f4(two, (compound, (arguments))): pass
+X
+X### stmt: simple_stmt | compound_stmt
+X### simple_stmt: expr_stmt | print_stmt | pass_stmt | del_stmt | flow_stmt | import_stmt
+X# Tested below
+X
+Xprint 'expr_stmt' # (exprlist '=')* exprlist NEWLINE
+X1
+X1, 2, 3
+Xx = 1
+Xx = 1, 2, 3
+Xx = y = z = 1, 2, 3
+Xx, y, z = 1, 2, 3
+Xabc = a, b, c = x, y, z = xyz = 1, 2, (3, 4)
+X# NB these variables are deleted below
+X
+Xprint 'print_stmt' # 'print' (test ',')* [test] NEWLINE
+Xprint 1, 2, 3
+Xprint 1, 2, 3,
+Xprint
+Xprint 0 or 1, 0 or 1,
+Xprint 0 or 1
+X
+Xprint 'del_stmt' # 'del' exprlist NEWLINE
+Xdel abc
+Xdel x, y, (z, xyz)
+X
+Xprint 'pass_stmt' # 'pass' NEWLINE
+Xpass
+X
+Xprint 'flow_stmt' # break_stmt | return_stmt | raise_stmt
+X# Tested below
+X
+Xprint 'break_stmt' # 'break' NEWLINE
+Xwhile 1: break
+X
+Xprint 'return_stmt' # 'return' [testlist] NEWLINE
+Xdef g1(): return
+Xdef g2(): return 1
+Xg1()
+Xx = g2()
+X
+Xprint 'raise_stmt' # 'raise' expr [',' expr] NEWLINE
+Xtry: raise RuntimeError, 'just testing'
+Xexcept RuntimeError: pass
+Xtry: raise KeyboardInterrupt
+Xexcept KeyboardInterrupt: pass
+X
+Xprint 'import_stmt' # 'import' NAME (',' NAME)* NEWLINE | 'from' NAME 'import' ('*' | NAME (',' NAME)*) NEWLINE
+X[1]
+Ximport sys
+X[2]
+Ximport time, math
+X[3]
+Xfrom time import sleep
+X[4]
+Xfrom math import *
+X[5]
+Xfrom sys import modules, ps1, ps2
+X[6]
+X
+X### compound_stmt: if_stmt | while_stmt | for_stmt | try_stmt | funcdef | classdef
+X# Tested below
+X
+Xprint 'if_stmt' # 'if' test ':' suite ('elif' test ':' suite)* ['else' ':' suite]
+Xif 1: pass
+Xif 1: pass
+Xelse: pass
+Xif 0: pass
+Xelif 0: pass
+Xif 0: pass
+Xelif 0: pass
+Xelif 0: pass
+Xelif 0: pass
+Xelse: pass
+X
+Xprint 'while_stmt' # 'while' test ':' suite ['else' ':' suite]
+Xwhile 0: pass
+Xwhile 0: pass
+Xelse: pass
+X
+Xprint 'for_stmt' # 'for' exprlist 'in' exprlist ':' suite ['else' ':' suite]
+X[1]
+Xfor i in 1, 2, 3: pass
+X[2]
+Xfor i, j, k in (): pass
+Xelse: pass
+X[3]
+X
+Xprint 'try_stmt' # 'try' ':' suite (except_clause ':' suite)* ['finally' ':' suite]
+X### except_clause: 'except' [expr [',' expr]]
+Xtry: pass
+Xtry: 1/0
+Xexcept RuntimeError: pass
+Xtry: 1/0
+Xexcept EOFError: pass
+Xexcept TypeError, msg: pass
+Xexcept RuntimeError, msg: pass
+Xexcept: pass
+Xtry: pass
+Xfinally: pass
+Xtry: 1/0
+Xexcept: pass
+Xfinally: pass
+X
+Xprint 'suite' # simple_stmt | NEWLINE INDENT NEWLINE* (stmt NEWLINE*)+ DEDENT
+Xif 1: pass
+Xif 1:
+X pass
+Xif 1:
+X #
+X #
+X #
+X pass
+X pass
+X #
+X pass
+X #
+X
+Xprint 'test' # and_test ('or' and_test)*
+X### and_test: not_test ('and' not_test)*
+X### not_test: 'not' not_test | comparison
+X### comparison: expr (comp_op expr)*
+X### comp_op: '<'|'>'|'='|'>' '='|'<' '='|'<' '>'|'in'|'not' 'in'|'is'|'is' 'not'
+Xif 1: pass
+Xif 1 = 1: pass
+Xif 1 < 1 > 1 = 1 >= 1 <= 1 <> 1 in 1 not in 1 is 1 is not 1: pass
+Xif not 1 = 1 = 1: pass
+Xif not 1 = 1 and 1 and 1: pass
+Xif 1 and 1 or 1 and 1 and 1 or not 1 = 1 = 1 and 1: pass
+X
+Xprint 'expr' # term (('+'|'-') term)*
+Xx = 1
+Xx = 1 + 1
+Xx = 1 - 1 - 1
+Xx = 1 - 1 + 1 - 1 + 1
+X
+Xprint 'term' # factor (('*'|'/'|'%') factor)*
+Xx = 1 * 1
+Xx = 1 / 1
+Xx = 1 % 1
+Xx = 1 / 1 * 1 % 1
+X
+Xprint 'factor' # ('+'|'-') factor | atom trailer*
+X### trailer: '(' [testlist] ')' | '[' subscript ']' | '.' NAME
+X### subscript: expr | [expr] ':' [expr]
+Xx = +1
+Xx = -1
+Xx = 1
+Xc = sys.ps1[0]
+Xx = time.time()
+Xx = sys.modules['time'].time()
+Xa = '01234'
+Xc = a[0]
+Xc = a[0:5]
+Xc = a[:5]
+Xc = a[0:]
+Xc = a[:]
+Xc = a[-5:]
+Xc = a[:-1]
+Xc = a[-4:-3]
+X
+Xprint 'atom' # '(' [testlist] ')' | '[' [testlist] ']' | '{' '}' | '`' testlist '`' | NAME | NUMBER | STRING
+Xx = (1)
+Xx = (1 or 2 or 3)
+Xx = (1 or 2 or 3, 2, 3)
+Xx = []
+Xx = [1]
+Xx = [1 or 2 or 3]
+Xx = [1 or 2 or 3, 2, 3]
+Xx = []
+Xx = {}
+Xx = `x`
+Xx = x
+Xx = 'x'
+Xx = 123
+X
+X### exprlist: expr (',' expr)* [',']
+X### testlist: test (',' test)* [',']
+X# These have been exercised enough above
+X
+Xprint 'classdef' # 'class' NAME parameters ['=' baselist] ':' suite
+X### baselist: atom arguments (',' atom arguments)*
+X### arguments: '(' [testlist] ')'
+Xclass B(): pass
+Xclass C1() = B(): pass
+Xclass C2() = B(): pass
+Xclass D() = C1(), C2(), B(): pass
+Xclass C():
+X def meth1(self): pass
+X def meth2(self, arg): pass
+X def meth3(self, (a1, a2)): pass
+X
+X
+X#########################################################
+X# Part 2. Test all opcodes from "opcode.h"
+X#########################################################
+X
+Xprint '2. Opcodes'
+Xprint 'XXX Not yet fully implemented'
+X
+Xprint '2.1 try inside for loop'
+Xn = 0
+Xfor i in range(10):
+X n = n+i
+X try: 1/0
+X except NameError: pass
+X except RuntimeError: pass
+X except TypeError: pass
+X finally: pass
+X try: pass
+X except: pass
+X try: pass
+X finally: pass
+X n = n+i
+Xif n <> 90:
+X raise TestFailed, 'try inside for'
+X
+X
+X#########################################################
+X# Part 3. Test all operations on all object types
+X#########################################################
+X
+Xprint '3. Object types'
+Xprint 'XXX Not yet implemented'
+X
+X
+X#########################################################
+X# Part 4. Test all built-in functions
+X#########################################################
+X
+Xprint '4. Built-in functions'
+X
+Xprint 'abs'
+Xif abs(0) <> 0: raise TestFailed, 'abs(0)'
+Xif abs(1234) <> 1234: raise TestFailed, 'abs(1234)'
+Xif abs(-1234) <> 1234: raise TestFailed, 'abs(-1234)'
+Xif abs(0.0) <> 0.0: raise TestFailed, 'abs(0.0)'
+Xif abs(3.14) <> 3.14: raise TestFailed, 'abs(3.14)'
+Xif abs(-3.14) <> 3.14: raise TestFailed, 'abs(-3.14)'
+X
+Xprint 'dir'
+Xif 'x' not in dir(): raise TestFailed, 'dir()'
+Xif 'modules' not in dir(sys): raise TestFailed, 'dir(sys)'
+X
+Xprint 'divmod'
+Xif divmod(12, 7) <> (1, 5): raise TestFailed, 'divmod(12, 7)'
+Xif divmod(-12, 7) <> (-2, 2): raise TestFailed, 'divmod(-12, 7)'
+Xif divmod(12, -7) <> (-2, -2): raise TestFailed, 'divmod(12, -7)'
+Xif divmod(-12, -7) <> (1, -5): raise TestFailed, 'divmod(-12, -7)'
+X
+Xprint 'eval'
+Xif eval('1+1') <> 2: raise TestFailed, 'eval(\'1+1\')'
+X
+Xprint 'exec'
+Xexec('z=1+1\n')
+Xif z <> 2: raise TestFailed, 'exec(\'z=1+1\'\\n)'
+X
+Xprint 'float'
+Xif float(3.14) <> 3.14: raise TestFailed, 'float(3.14)'
+Xif float(314) <> 314.0: raise TestFailed, 'float(314)'
+X
+Xprint 'input'
+X# Can't test in a script
+X
+Xprint 'int'
+Xif int(100) <> 100: raise TestFailed, 'int(100)'
+Xif int(3.14) <> 3: raise TestFailed, 'int(3.14)'
+X
+Xprint 'len'
+Xif len('123') <> 3: raise TestFailed, 'len(\'123\')'
+Xif len(()) <> 0: raise TestFailed, 'len(())'
+Xif len((1, 2, 3, 4)) <> 4: raise TestFailed, 'len((1, 2, 3, 4))'
+Xif len([1, 2, 3, 4]) <> 4: raise TestFailed, 'len([1, 2, 3, 4])'
+Xif len({}) <> 0: raise TestFailed, 'len({})'
+X
+Xprint 'min'
+Xif min('123123') <> '1': raise TestFailed, 'min(\'123123\')'
+Xif min(1, 2, 3) <> 1: raise TestFailed, 'min(1, 2, 3)'
+Xif min((1, 2, 3, 1, 2, 3)) <> 1: raise TestFailed, 'min((1, 2, 3, 1, 2, 3))'
+Xif min([1, 2, 3, 1, 2, 3]) <> 1: raise TestFailed, 'min([1, 2, 3, 1, 2, 3])'
+X
+Xprint 'max'
+Xif max('123123') <> '3': raise TestFailed, 'max(\'123123\')'
+Xif max(1, 2, 3) <> 3: raise TestFailed, 'max(1, 2, 3)'
+Xif max((1, 2, 3, 1, 2, 3)) <> 3: raise TestFailed, 'max((1, 2, 3, 1, 2, 3))'
+Xif max([1, 2, 3, 1, 2, 3]) <> 3: raise TestFailed, 'max([1, 2, 3, 1, 2, 3])'
+X
+Xprint 'open'
+Xprint 'NB! This test creates a file named "@test" in the current directory.'
+Xfp = open('@test', 'w')
+Xfp.write('The quick brown fox jumps over the lazy dog')
+Xfp.write('.\n')
+Xfp.write('Dear John\n')
+Xfp.write('XXX'*100)
+Xfp.write('YYY'*100)
+Xfp.close()
+Xdel fp
+Xfp = open('@test', 'r')
+Xif fp.readline() <> 'The quick brown fox jumps over the lazy dog.\n':
+X raise TestFailed, 'readline()'
+Xif fp.readline(4) <> 'Dear': raise TestFailed, 'readline(4) # short'
+Xif fp.readline(100) <> ' John\n': raise TestFailed, 'readline(100)'
+Xif fp.read(300) <> 'XXX'*100: raise TestFailed, 'read(300)'
+Xif fp.read(1000) <> 'YYY'*100: raise TestFailed, 'read(1000) # truncate'
+Xfp.close()
+Xdel fp
+X
+Xprint 'range'
+Xif range(3) <> [0, 1, 2]: raise TestFailed, 'range(3)'
+Xif range(1, 5) <> [1, 2, 3, 4]: raise TestFailed, 'range(1, 5)'
+Xif range(0) <> []: raise TestFailed, 'range(0)'
+Xif range(-3) <> []: raise TestFailed, 'range(-3)'
+Xif range(1, 10, 3) <> [1, 4, 7]: raise TestFailed, 'range(1, 10, 3)'
+Xif range(5, -5, -3) <> [5, 2, -1, -4]: raise TestFailed, 'range(5, -5, -3)'
+X
+Xprint 'raw_input'
+Xsavestdin = sys.stdin
+Xtry:
+X sys.stdin = open('@test', 'r')
+X if raw_input() <> 'The quick brown fox jumps over the lazy dog.':
+X raise TestFailed, 'raw_input()'
+X if raw_input('testing\n') <> 'Dear John':
+X raise TestFailed, 'raw_input(\'testing\\n\')'
+Xfinally:
+X sys.stdin = savestdin
+X
+Xprint 'reload'
+Ximport string
+Xreload(string)
+X
+Xprint 'type'
+Xif type('') <> type('123') or type('') = type(()):
+X raise TestFailed, 'type()'
+X
+X
+Xprint 'Passed all tests.'
+X
+Xtry:
+X import mac
+X unlink = mac.unlink
+Xexcept NameError:
+X try:
+X import posix
+X unlink = posix.unlink
+X except NameError:
+X pass
+X
+Xunlink('@test')
+Xprint 'Unlinked @test'
+EOF
+fi
+if test -s 'src/listobject.c'
+then echo '*** I will not over-write existing file src/listobject.c'
+else
+echo 'x - src/listobject.c'
+sed 's/^X//' > 'src/listobject.c' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/* List object implementation */
+X
+X#include "allobjects.h"
+X
+Xobject *
+Xnewlistobject(size)
+X int size;
+X{
+X int i;
+X listobject *op;
+X if (size < 0) {
+X err_badcall();
+X return NULL;
+X }
+X op = (listobject *) malloc(sizeof(listobject));
+X if (op == NULL) {
+X return err_nomem();
+X }
+X if (size <= 0) {
+X op->ob_item = NULL;
+X }
+X else {
+X op->ob_item = (object **) malloc(size * sizeof(object *));
+X if (op->ob_item == NULL) {
+X free((ANY *)op);
+X return err_nomem();
+X }
+X }
+X NEWREF(op);
+X op->ob_type = &Listtype;
+X op->ob_size = size;
+X for (i = 0; i < size; i++)
+X op->ob_item[i] = NULL;
+X return (object *) op;
+X}
+X
+Xint
+Xgetlistsize(op)
+X object *op;
+X{
+X if (!is_listobject(op)) {
+X err_badcall();
+X return -1;
+X }
+X else
+X return ((listobject *)op) -> ob_size;
+X}
+X
+Xobject *
+Xgetlistitem(op, i)
+X object *op;
+X int i;
+X{
+X if (!is_listobject(op)) {
+X err_badcall();
+X return NULL;
+X }
+X if (i < 0 || i >= ((listobject *)op) -> ob_size) {
+X err_setstr(IndexError, "list index out of range");
+X return NULL;
+X }
+X return ((listobject *)op) -> ob_item[i];
+X}
+X
+Xint
+Xsetlistitem(op, i, newitem)
+X register object *op;
+X register int i;
+X register object *newitem;
+X{
+X register object *olditem;
+X if (!is_listobject(op)) {
+X if (newitem != NULL)
+X DECREF(newitem);
+X err_badcall();
+X return -1;
+X }
+X if (i < 0 || i >= ((listobject *)op) -> ob_size) {
+X if (newitem != NULL)
+X DECREF(newitem);
+X err_setstr(IndexError, "list assignment index out of range");
+X return -1;
+X }
+X olditem = ((listobject *)op) -> ob_item[i];
+X ((listobject *)op) -> ob_item[i] = newitem;
+X if (olditem != NULL)
+X DECREF(olditem);
+X return 0;
+X}
+X
+Xstatic int
+Xins1(self, where, v)
+X listobject *self;
+X int where;
+X object *v;
+X{
+X int i;
+X object **items;
+X if (v == NULL) {
+X err_badcall();
+X return -1;
+X }
+X items = self->ob_item;
+X RESIZE(items, object *, self->ob_size+1);
+X if (items == NULL) {
+X err_nomem();
+X return -1;
+X }
+X if (where < 0)
+X where = 0;
+X if (where > self->ob_size)
+X where = self->ob_size;
+X for (i = self->ob_size; --i >= where; )
+X items[i+1] = items[i];
+X INCREF(v);
+X items[where] = v;
+X self->ob_item = items;
+X self->ob_size++;
+X return 0;
+X}
+X
+Xint
+Xinslistitem(op, where, newitem)
+X object *op;
+X int where;
+X object *newitem;
+X{
+X if (!is_listobject(op)) {
+X err_badcall();
+X return -1;
+X }
+X return ins1((listobject *)op, where, newitem);
+X}
+X
+Xint
+Xaddlistitem(op, newitem)
+X object *op;
+X object *newitem;
+X{
+X if (!is_listobject(op)) {
+X err_badcall();
+X return -1;
+X }
+X return ins1((listobject *)op,
+X (int) ((listobject *)op)->ob_size, newitem);
+X}
+X
+X/* Methods */
+X
+Xstatic void
+Xlist_dealloc(op)
+X listobject *op;
+X{
+X int i;
+X for (i = 0; i < op->ob_size; i++) {
+X if (op->ob_item[i] != NULL)
+X DECREF(op->ob_item[i]);
+X }
+X if (op->ob_item != NULL)
+X free((ANY *)op->ob_item);
+X free((ANY *)op);
+X}
+X
+Xstatic void
+Xlist_print(op, fp, flags)
+X listobject *op;
+X FILE *fp;
+X int flags;
+X{
+X int i;
+X fprintf(fp, "[");
+X for (i = 0; i < op->ob_size && !StopPrint; i++) {
+X if (i > 0) {
+X fprintf(fp, ", ");
+X }
+X printobject(op->ob_item[i], fp, flags);
+X }
+X fprintf(fp, "]");
+X}
+X
+Xobject *
+Xlist_repr(v)
+X listobject *v;
+X{
+X object *s, *t, *comma;
+X int i;
+X s = newstringobject("[");
+X comma = newstringobject(", ");
+X for (i = 0; i < v->ob_size && s != NULL; i++) {
+X if (i > 0)
+X joinstring(&s, comma);
+X t = reprobject(v->ob_item[i]);
+X joinstring(&s, t);
+X DECREF(t);
+X }
+X DECREF(comma);
+X t = newstringobject("]");
+X joinstring(&s, t);
+X DECREF(t);
+X return s;
+X}
+X
+Xstatic int
+Xlist_compare(v, w)
+X listobject *v, *w;
+X{
+X int len = (v->ob_size < w->ob_size) ? v->ob_size : w->ob_size;
+X int i;
+X for (i = 0; i < len; i++) {
+X int cmp = cmpobject(v->ob_item[i], w->ob_item[i]);
+X if (cmp != 0)
+X return cmp;
+X }
+X return v->ob_size - w->ob_size;
+X}
+X
+Xstatic int
+Xlist_length(a)
+X listobject *a;
+X{
+X return a->ob_size;
+X}
+X
+Xstatic object *
+Xlist_item(a, i)
+X listobject *a;
+X int i;
+X{
+X if (i < 0 || i >= a->ob_size) {
+X err_setstr(IndexError, "list index out of range");
+X return NULL;
+X }
+X INCREF(a->ob_item[i]);
+X return a->ob_item[i];
+X}
+X
+Xstatic object *
+Xlist_slice(a, ilow, ihigh)
+X listobject *a;
+X int ilow, ihigh;
+X{
+X listobject *np;
+X int i;
+X if (ilow < 0)
+X ilow = 0;
+X else if (ilow > a->ob_size)
+X ilow = a->ob_size;
+X if (ihigh < 0)
+X ihigh = 0;
+X if (ihigh < ilow)
+X ihigh = ilow;
+X else if (ihigh > a->ob_size)
+X ihigh = a->ob_size;
+X np = (listobject *) newlistobject(ihigh - ilow);
+X if (np == NULL)
+X return NULL;
+X for (i = ilow; i < ihigh; i++) {
+X object *v = a->ob_item[i];
+X INCREF(v);
+X np->ob_item[i - ilow] = v;
+X }
+X return (object *)np;
+X}
+X
+Xstatic object *
+Xlist_concat(a, bb)
+X listobject *a;
+X object *bb;
+X{
+X int size;
+X int i;
+X listobject *np;
+X if (!is_listobject(bb)) {
+X err_badarg();
+X return NULL;
+X }
+X#define b ((listobject *)bb)
+X size = a->ob_size + b->ob_size;
+X np = (listobject *) newlistobject(size);
+X if (np == NULL) {
+X return err_nomem();
+X }
+X for (i = 0; i < a->ob_size; i++) {
+X object *v = a->ob_item[i];
+X INCREF(v);
+X np->ob_item[i] = v;
+X }
+X for (i = 0; i < b->ob_size; i++) {
+X object *v = b->ob_item[i];
+X INCREF(v);
+X np->ob_item[i + a->ob_size] = v;
+X }
+X return (object *)np;
+X#undef b
+X}
+X
+Xstatic int
+Xlist_ass_item(a, i, v)
+X listobject *a;
+X int i;
+X object *v;
+X{
+X if (i < 0 || i >= a->ob_size) {
+X err_setstr(IndexError, "list assignment index out of range");
+X return -1;
+X }
+X if (v == NULL)
+X return list_ass_slice(a, i, i+1, v);
+X INCREF(v);
+X DECREF(a->ob_item[i]);
+X a->ob_item[i] = v;
+X return 0;
+X}
+X
+Xstatic int
+Xlist_ass_slice(a, ilow, ihigh, v)
+X listobject *a;
+X int ilow, ihigh;
+X object *v;
+X{
+X object **item;
+X int n; /* Size of replacement list */
+X int d; /* Change in size */
+X int k; /* Loop index */
+X#define b ((listobject *)v)
+X if (v == NULL)
+X n = 0;
+X else if (is_listobject(v))
+X n = b->ob_size;
+X else {
+X err_badarg();
+X return -1;
+X }
+X if (ilow < 0)
+X ilow = 0;
+X else if (ilow > a->ob_size)
+X ilow = a->ob_size;
+X if (ihigh < 0)
+X ihigh = 0;
+X if (ihigh < ilow)
+X ihigh = ilow;
+X else if (ihigh > a->ob_size)
+X ihigh = a->ob_size;
+X item = a->ob_item;
+X d = n - (ihigh-ilow);
+X if (d <= 0) { /* Delete -d items; DECREF ihigh-ilow items */
+X for (k = ilow; k < ihigh; k++)
+X DECREF(item[k]);
+X if (d < 0) {
+X for (/*k = ihigh*/; k < a->ob_size; k++)
+X item[k+d] = item[k];
+X a->ob_size += d;
+X RESIZE(item, object *, a->ob_size); /* Can't fail */
+X a->ob_item = item;
+X }
+X }
+X else { /* Insert d items; DECREF ihigh-ilow items */
+X RESIZE(item, object *, a->ob_size + d);
+X if (item == NULL) {
+X err_nomem();
+X return -1;
+X }
+X for (k = a->ob_size; --k >= ihigh; )
+X item[k+d] = item[k];
+X for (/*k = ihigh-1*/; k >= ilow; --k)
+X DECREF(item[k]);
+X a->ob_item = item;
+X a->ob_size += d;
+X }
+X for (k = 0; k < n; k++, ilow++) {
+X object *w = b->ob_item[k];
+X INCREF(w);
+X item[ilow] = w;
+X }
+X return 0;
+X#undef b
+X}
+X
+Xstatic object *
+Xins(self, where, v)
+X listobject *self;
+X int where;
+X object *v;
+X{
+X if (ins1(self, where, v) != 0)
+X return NULL;
+X INCREF(None);
+X return None;
+X}
+X
+Xstatic object *
+Xlistinsert(self, args)
+X listobject *self;
+X object *args;
+X{
+X int i;
+X if (args == NULL || !is_tupleobject(args) || gettuplesize(args) != 2) {
+X err_badarg();
+X return NULL;
+X }
+X if (!getintarg(gettupleitem(args, 0), &i))
+X return NULL;
+X return ins(self, i, gettupleitem(args, 1));
+X}
+X
+Xstatic object *
+Xlistappend(self, args)
+X listobject *self;
+X object *args;
+X{
+X return ins(self, (int) self->ob_size, args);
+X}
+X
+Xstatic int
+Xcmp(v, w)
+X char *v, *w;
+X{
+X return cmpobject(* (object **) v, * (object **) w);
+X}
+X
+Xstatic object *
+Xlistsort(self, args)
+X listobject *self;
+X object *args;
+X{
+X if (args != NULL) {
+X err_badarg();
+X return NULL;
+X }
+X err_clear();
+X if (self->ob_size > 1)
+X qsort((char *)self->ob_item,
+X (int) self->ob_size, sizeof(object *), cmp);
+X if (err_occurred())
+X return NULL;
+X INCREF(None);
+X return None;
+X}
+X
+Xint
+Xsortlist(v)
+X object *v;
+X{
+X if (v == NULL || !is_listobject(v)) {
+X err_badcall();
+X return -1;
+X }
+X v = listsort((listobject *)v, (object *)NULL);
+X if (v == NULL)
+X return -1;
+X DECREF(v);
+X return 0;
+X}
+X
+Xstatic struct methodlist list_methods[] = {
+X {"append", listappend},
+X {"insert", listinsert},
+X {"sort", listsort},
+X {NULL, NULL} /* sentinel */
+X};
+X
+Xstatic object *
+Xlist_getattr(f, name)
+X listobject *f;
+X char *name;
+X{
+X return findmethod(list_methods, (object *)f, name);
+X}
+X
+Xstatic sequence_methods list_as_sequence = {
+X list_length, /*sq_length*/
+X list_concat, /*sq_concat*/
+X 0, /*sq_repeat*/
+X list_item, /*sq_item*/
+X list_slice, /*sq_slice*/
+X list_ass_item, /*sq_ass_item*/
+X list_ass_slice, /*sq_ass_slice*/
+X};
+X
+Xtypeobject Listtype = {
+X OB_HEAD_INIT(&Typetype)
+X 0,
+X "list",
+X sizeof(listobject),
+X 0,
+X list_dealloc, /*tp_dealloc*/
+X list_print, /*tp_print*/
+X list_getattr, /*tp_getattr*/
+X 0, /*tp_setattr*/
+X list_compare, /*tp_compare*/
+X list_repr, /*tp_repr*/
+X 0, /*tp_as_number*/
+X &list_as_sequence, /*tp_as_sequence*/
+X 0, /*tp_as_mapping*/
+X};
+EOF
+fi
+if test -s 'src/parser.c'
+then echo '*** I will not over-write existing file src/parser.c'
+else
+echo 'x - src/parser.c'
+sed 's/^X//' > 'src/parser.c' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/* Parser implementation */
+X
+X/* For a description, see the comments at end of this file */
+X
+X/* XXX To do: error recovery */
+X
+X#include "pgenheaders.h"
+X#include "assert.h"
+X#include "token.h"
+X#include "grammar.h"
+X#include "node.h"
+X#include "parser.h"
+X#include "errcode.h"
+X
+X
+X#ifdef DEBUG
+Xextern int debugging;
+X#define D(x) if (!debugging); else x
+X#else
+X#define D(x)
+X#endif
+X
+X
+X/* STACK DATA TYPE */
+X
+Xstatic void s_reset PROTO((stack *));
+X
+Xstatic void
+Xs_reset(s)
+X stack *s;
+X{
+X s->s_top = &s->s_base[MAXSTACK];
+X}
+X
+X#define s_empty(s) ((s)->s_top == &(s)->s_base[MAXSTACK])
+X
+Xstatic int s_push PROTO((stack *, dfa *, node *));
+X
+Xstatic int
+Xs_push(s, d, parent)
+X register stack *s;
+X dfa *d;
+X node *parent;
+X{
+X register stackentry *top;
+X if (s->s_top == s->s_base) {
+X fprintf(stderr, "s_push: parser stack overflow\n");
+X return -1;
+X }
+X top = --s->s_top;
+X top->s_dfa = d;
+X top->s_parent = parent;
+X top->s_state = 0;
+X return 0;
+X}
+X
+X#ifdef DEBUG
+X
+Xstatic void s_pop PROTO((stack *));
+X
+Xstatic void
+Xs_pop(s)
+X register stack *s;
+X{
+X if (s_empty(s)) {
+X fprintf(stderr, "s_pop: parser stack underflow -- FATAL\n");
+X abort();
+X }
+X s->s_top++;
+X}
+X
+X#else /* !DEBUG */
+X
+X#define s_pop(s) (s)->s_top++
+X
+X#endif
+X
+X
+X/* PARSER CREATION */
+X
+Xparser_state *
+Xnewparser(g, start)
+X grammar *g;
+X int start;
+X{
+X parser_state *ps;
+X
+X if (!g->g_accel)
+X addaccelerators(g);
+X ps = NEW(parser_state, 1);
+X if (ps == NULL)
+X return NULL;
+X ps->p_grammar = g;
+X ps->p_tree = newtree(start);
+X if (ps->p_tree == NULL) {
+X DEL(ps);
+X return NULL;
+X }
+X s_reset(&ps->p_stack);
+X (void) s_push(&ps->p_stack, finddfa(g, start), ps->p_tree);
+X return ps;
+X}
+X
+Xvoid
+Xdelparser(ps)
+X parser_state *ps;
+X{
+X /* NB If you want to save the parse tree,
+X you must set p_tree to NULL before calling delparser! */
+X freetree(ps->p_tree);
+X DEL(ps);
+X}
+X
+X
+X/* PARSER STACK OPERATIONS */
+X
+Xstatic int shift PROTO((stack *, int, char *, int, int));
+X
+Xstatic int
+Xshift(s, type, str, newstate, lineno)
+X register stack *s;
+X int type;
+X char *str;
+X int newstate;
+X int lineno;
+X{
+X assert(!s_empty(s));
+X if (addchild(s->s_top->s_parent, type, str, lineno) == NULL) {
+X fprintf(stderr, "shift: no mem in addchild\n");
+X return -1;
+X }
+X s->s_top->s_state = newstate;
+X return 0;
+X}
+X
+Xstatic int push PROTO((stack *, int, dfa *, int, int));
+X
+Xstatic int
+Xpush(s, type, d, newstate, lineno)
+X register stack *s;
+X int type;
+X dfa *d;
+X int newstate;
+X int lineno;
+X{
+X register node *n;
+X n = s->s_top->s_parent;
+X assert(!s_empty(s));
+X if (addchild(n, type, (char *)NULL, lineno) == NULL) {
+X fprintf(stderr, "push: no mem in addchild\n");
+X return -1;
+X }
+X s->s_top->s_state = newstate;
+X return s_push(s, d, CHILD(n, NCH(n)-1));
+X}
+X
+X
+X/* PARSER PROPER */
+X
+Xstatic int classify PROTO((grammar *, int, char *));
+X
+Xstatic int
+Xclassify(g, type, str)
+X grammar *g;
+X register int type;
+X char *str;
+X{
+X register int n = g->g_ll.ll_nlabels;
+X
+X if (type == NAME) {
+X register char *s = str;
+X register label *l = g->g_ll.ll_label;
+X register int i;
+X for (i = n; i > 0; i--, l++) {
+X if (l->lb_type == NAME && l->lb_str != NULL &&
+X l->lb_str[0] == s[0] &&
+X strcmp(l->lb_str, s) == 0) {
+X D(printf("It's a keyword\n"));
+X return n - i;
+X }
+X }
+X }
+X
+X {
+X register label *l = g->g_ll.ll_label;
+X register int i;
+X for (i = n; i > 0; i--, l++) {
+X if (l->lb_type == type && l->lb_str == NULL) {
+X D(printf("It's a token we know\n"));
+X return n - i;
+X }
+X }
+X }
+X
+X D(printf("Illegal token\n"));
+X return -1;
+X}
+X
+Xint
+Xaddtoken(ps, type, str, lineno)
+X register parser_state *ps;
+X register int type;
+X char *str;
+X int lineno;
+X{
+X register int ilabel;
+X
+X D(printf("Token %s/'%s' ... ", tok_name[type], str));
+X
+X /* Find out which label this token is */
+X ilabel = classify(ps->p_grammar, type, str);
+X if (ilabel < 0)
+X return E_SYNTAX;
+X
+X /* Loop until the token is shifted or an error occurred */
+X for (;;) {
+X /* Fetch the current dfa and state */
+X register dfa *d = ps->p_stack.s_top->s_dfa;
+X register state *s = &d->d_state[ps->p_stack.s_top->s_state];
+X
+X D(printf(" DFA '%s', state %d:",
+X d->d_name, ps->p_stack.s_top->s_state));
+X
+X /* Check accelerator */
+X if (s->s_lower <= ilabel && ilabel < s->s_upper) {
+X register int x = s->s_accel[ilabel - s->s_lower];
+X if (x != -1) {
+X if (x & (1<<7)) {
+X /* Push non-terminal */
+X int nt = (x >> 8) + NT_OFFSET;
+X int arrow = x & ((1<<7)-1);
+X dfa *d1 = finddfa(ps->p_grammar, nt);
+X if (push(&ps->p_stack, nt, d1,
+X arrow, lineno) < 0) {
+X D(printf(" MemError: push.\n"));
+X return E_NOMEM;
+X }
+X D(printf(" Push ...\n"));
+X continue;
+X }
+X
+X /* Shift the token */
+X if (shift(&ps->p_stack, type, str,
+X x, lineno) < 0) {
+X D(printf(" MemError: shift.\n"));
+X return E_NOMEM;
+X }
+X D(printf(" Shift.\n"));
+X /* Pop while we are in an accept-only state */
+X while (s = &d->d_state
+X [ps->p_stack.s_top->s_state],
+X s->s_accept && s->s_narcs == 1) {
+X D(printf(" Direct pop.\n"));
+X s_pop(&ps->p_stack);
+X if (s_empty(&ps->p_stack)) {
+X D(printf(" ACCEPT.\n"));
+X return E_DONE;
+X }
+X d = ps->p_stack.s_top->s_dfa;
+X }
+X return E_OK;
+X }
+X }
+X
+X if (s->s_accept) {
+X /* Pop this dfa and try again */
+X s_pop(&ps->p_stack);
+X D(printf(" Pop ...\n"));
+X if (s_empty(&ps->p_stack)) {
+X D(printf(" Error: bottom of stack.\n"));
+X return E_SYNTAX;
+X }
+X continue;
+X }
+X
+X /* Stuck, report syntax error */
+X D(printf(" Error.\n"));
+X return E_SYNTAX;
+X }
+X}
+X
+X
+X#ifdef DEBUG
+X
+X/* DEBUG OUTPUT */
+X
+Xvoid
+Xdumptree(g, n)
+X grammar *g;
+X node *n;
+X{
+X int i;
+X
+X if (n == NULL)
+X printf("NIL");
+X else {
+X label l;
+X l.lb_type = TYPE(n);
+X l.lb_str = TYPE(str);
+X printf("%s", labelrepr(&l));
+X if (ISNONTERMINAL(TYPE(n))) {
+X printf("(");
+X for (i = 0; i < NCH(n); i++) {
+X if (i > 0)
+X printf(",");
+X dumptree(g, CHILD(n, i));
+X }
+X printf(")");
+X }
+X }
+X}
+X
+Xvoid
+Xshowtree(g, n)
+X grammar *g;
+X node *n;
+X{
+X int i;
+X
+X if (n == NULL)
+X return;
+X if (ISNONTERMINAL(TYPE(n))) {
+X for (i = 0; i < NCH(n); i++)
+X showtree(g, CHILD(n, i));
+X }
+X else if (ISTERMINAL(TYPE(n))) {
+X printf("%s", tok_name[TYPE(n)]);
+X if (TYPE(n) == NUMBER || TYPE(n) == NAME)
+X printf("(%s)", STR(n));
+X printf(" ");
+X }
+X else
+X printf("? ");
+X}
+X
+Xvoid
+Xprinttree(ps)
+X parser_state *ps;
+X{
+X if (debugging) {
+X printf("Parse tree:\n");
+X dumptree(ps->p_grammar, ps->p_tree);
+X printf("\n");
+X printf("Tokens:\n");
+X showtree(ps->p_grammar, ps->p_tree);
+X printf("\n");
+X }
+X printf("Listing:\n");
+X listtree(ps->p_tree);
+X printf("\n");
+X}
+X
+X#endif /* DEBUG */
+X
+X/*
+X
+XDescription
+X-----------
+X
+XThe parser's interface is different than usual: the function addtoken()
+Xmust be called for each token in the input. This makes it possible to
+Xturn it into an incremental parsing system later. The parsing system
+Xconstructs a parse tree as it goes.
+X
+XA parsing rule is represented as a Deterministic Finite-state Automaton
+X(DFA). A node in a DFA represents a state of the parser; an arc represents
+Xa transition. Transitions are either labeled with terminal symbols or
+Xwith non-terminals. When the parser decides to follow an arc labeled
+Xwith a non-terminal, it is invoked recursively with the DFA representing
+Xthe parsing rule for that as its initial state; when that DFA accepts,
+Xthe parser that invoked it continues. The parse tree constructed by the
+Xrecursively called parser is inserted as a child in the current parse tree.
+X
+XThe DFA's can be constructed automatically from a more conventional
+Xlanguage description. An extended LL(1) grammar (ELL(1)) is suitable.
+XCertain restrictions make the parser's life easier: rules that can produce
+Xthe empty string should be outlawed (there are other ways to put loops
+Xor optional parts in the language). To avoid the need to construct
+XFIRST sets, we can require that all but the last alternative of a rule
+X(really: arc going out of a DFA's state) must begin with a terminal
+Xsymbol.
+X
+XAs an example, consider this grammar:
+X
+Xexpr: term (OP term)*
+Xterm: CONSTANT | '(' expr ')'
+X
+XThe DFA corresponding to the rule for expr is:
+X
+X------->.---term-->.------->
+X ^ |
+X | |
+X \----OP----/
+X
+XThe parse tree generated for the input a+b is:
+X
+X(expr: (term: (NAME: a)), (OP: +), (term: (NAME: b)))
+X
+X*/
+EOF
+fi
+if test -s 'src/patchlevel.h'
+then echo '*** I will not over-write existing file src/patchlevel.h'
+else
+echo 'x - src/patchlevel.h'
+sed 's/^X//' > 'src/patchlevel.h' << 'EOF'
+X1
+EOF
+fi
+if test -s 'src/posixmodule.c'
+then echo '*** I will not over-write existing file src/posixmodule.c'
+else
+echo 'x - src/posixmodule.c'
+sed 's/^X//' > 'src/posixmodule.c' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/* POSIX module implementation */
+X
+X#include <signal.h>
+X#include <string.h>
+X#include <setjmp.h>
+X#include <sys/types.h>
+X#include <sys/stat.h>
+X#include <sys/time.h>
+X#ifdef SYSV
+X#include <dirent.h>
+X#define direct dirent
+X#else
+X#include <sys/dir.h>
+X#endif
+X
+X#include "allobjects.h"
+X#include "modsupport.h"
+X
+Xextern char *strerror PROTO((int));
+X
+X#ifdef AMOEBA
+X#define NO_LSTAT
+X#endif
+X
+X
+X/* Return a dictionary corresponding to the POSIX environment table */
+X
+Xextern char **environ;
+X
+Xstatic object *
+Xconvertenviron()
+X{
+X object *d;
+X char **e;
+X d = newdictobject();
+X if (d == NULL)
+X return NULL;
+X if (environ == NULL)
+X return d;
+X /* XXX This part ignores errors */
+X for (e = environ; *e != NULL; e++) {
+X object *v;
+X char *p = strchr(*e, '=');
+X if (p == NULL)
+X continue;
+X v = newstringobject(p+1);
+X if (v == NULL)
+X continue;
+X *p = '\0';
+X (void) dictinsert(d, *e, v);
+X *p = '=';
+X DECREF(v);
+X }
+X return d;
+X}
+X
+X
+Xstatic object *PosixError; /* Exception posix.error */
+X
+X/* Set a POSIX-specific error from errno, and return NULL */
+X
+Xstatic object *
+Xposix_error()
+X{
+X return err_errno(PosixError);
+X}
+X
+X
+X/* POSIX generic methods */
+X
+Xstatic object *
+Xposix_1str(args, func)
+X object *args;
+X int (*func) FPROTO((const char *));
+X{
+X object *path1;
+X if (!getstrarg(args, &path1))
+X return NULL;
+X if ((*func)(getstringvalue(path1)) < 0)
+X return posix_error();
+X INCREF(None);
+X return None;
+X}
+X
+Xstatic object *
+Xposix_2str(args, func)
+X object *args;
+X int (*func) FPROTO((const char *, const char *));
+X{
+X object *path1, *path2;
+X if (!getstrstrarg(args, &path1, &path2))
+X return NULL;
+X if ((*func)(getstringvalue(path1), getstringvalue(path2)) < 0)
+X return posix_error();
+X INCREF(None);
+X return None;
+X}
+X
+Xstatic object *
+Xposix_strint(args, func)
+X object *args;
+X int (*func) FPROTO((const char *, int));
+X{
+X object *path1;
+X int i;
+X if (!getstrintarg(args, &path1, &i))
+X return NULL;
+X if ((*func)(getstringvalue(path1), i) < 0)
+X return posix_error();
+X INCREF(None);
+X return None;
+X}
+X
+Xstatic object *
+Xposix_do_stat(self, args, statfunc)
+X object *self;
+X object *args;
+X int (*statfunc) FPROTO((const char *, struct stat *));
+X{
+X struct stat st;
+X object *path;
+X object *v;
+X if (!getstrarg(args, &path))
+X return NULL;
+X if ((*statfunc)(getstringvalue(path), &st) != 0)
+X return posix_error();
+X v = newtupleobject(10);
+X if (v == NULL)
+X return NULL;
+X#define SET(i, st_member) settupleitem(v, i, newintobject((long)st.st_member))
+X SET(0, st_mode);
+X SET(1, st_ino);
+X SET(2, st_dev);
+X SET(3, st_nlink);
+X SET(4, st_uid);
+X SET(5, st_gid);
+X SET(6, st_size);
+X SET(7, st_atime);
+X SET(8, st_mtime);
+X SET(9, st_ctime);
+X#undef SET
+X if (err_occurred()) {
+X DECREF(v);
+X return NULL;
+X }
+X return v;
+X}
+X
+X
+X/* POSIX methods */
+X
+Xstatic object *
+Xposix_chdir(self, args)
+X object *self;
+X object *args;
+X{
+X extern int chdir PROTO((const char *));
+X return posix_1str(args, chdir);
+X}
+X
+Xstatic object *
+Xposix_chmod(self, args)
+X object *self;
+X object *args;
+X{
+X extern int chmod PROTO((const char *, mode_t));
+X return posix_strint(args, chmod);
+X}
+X
+Xstatic object *
+Xposix_getcwd(self, args)
+X object *self;
+X object *args;
+X{
+X char buf[1026];
+X extern char *getcwd PROTO((char *, int));
+X if (!getnoarg(args))
+X return NULL;
+X if (getcwd(buf, sizeof buf) == NULL)
+X return posix_error();
+X return newstringobject(buf);
+X}
+X
+Xstatic object *
+Xposix_link(self, args)
+X object *self;
+X object *args;
+X{
+X extern int link PROTO((const char *, const char *));
+X return posix_2str(args, link);
+X}
+X
+Xstatic object *
+Xposix_listdir(self, args)
+X object *self;
+X object *args;
+X{
+X object *name, *d, *v;
+X DIR *dirp;
+X struct direct *ep;
+X if (!getstrarg(args, &name))
+X return NULL;
+X if ((dirp = opendir(getstringvalue(name))) == NULL)
+X return posix_error();
+X if ((d = newlistobject(0)) == NULL) {
+X closedir(dirp);
+X return NULL;
+X }
+X while ((ep = readdir(dirp)) != NULL) {
+X v = newstringobject(ep->d_name);
+X if (v == NULL) {
+X DECREF(d);
+X d = NULL;
+X break;
+X }
+X if (addlistitem(d, v) != 0) {
+X DECREF(v);
+X DECREF(d);
+X d = NULL;
+X break;
+X }
+X DECREF(v);
+X }
+X closedir(dirp);
+X return d;
+X}
+X
+Xstatic object *
+Xposix_mkdir(self, args)
+X object *self;
+X object *args;
+X{
+X extern int mkdir PROTO((const char *, mode_t));
+X return posix_strint(args, mkdir);
+X}
+X
+Xstatic object *
+Xposix_rename(self, args)
+X object *self;
+X object *args;
+X{
+X extern int rename PROTO((const char *, const char *));
+X return posix_2str(args, rename);
+X}
+X
+Xstatic object *
+Xposix_rmdir(self, args)
+X object *self;
+X object *args;
+X{
+X extern int rmdir PROTO((const char *));
+X return posix_1str(args, rmdir);
+X}
+X
+Xstatic object *
+Xposix_stat(self, args)
+X object *self;
+X object *args;
+X{
+X extern int stat PROTO((const char *, struct stat *));
+X return posix_do_stat(self, args, stat);
+X}
+X
+Xstatic object *
+Xposix_system(self, args)
+X object *self;
+X object *args;
+X{
+X object *command;
+X int sts;
+X if (!getstrarg(args, &command))
+X return NULL;
+X sts = system(getstringvalue(command));
+X return newintobject((long)sts);
+X}
+X
+Xstatic object *
+Xposix_umask(self, args)
+X object *self;
+X object *args;
+X{
+X int i;
+X if (!getintarg(args, &i))
+X return NULL;
+X i = umask(i);
+X if (i < 0)
+X return posix_error();
+X return newintobject((long)i);
+X}
+X
+Xstatic object *
+Xposix_unlink(self, args)
+X object *self;
+X object *args;
+X{
+X extern int unlink PROTO((const char *));
+X return posix_1str(args, unlink);
+X}
+X
+Xstatic object *
+Xposix_utimes(self, args)
+X object *self;
+X object *args;
+X{
+X object *path;
+X struct timeval tv[2];
+X if (args == NULL || !is_tupleobject(args) || gettuplesize(args) != 2) {
+X err_badarg();
+X return NULL;
+X }
+X if (!getstrarg(gettupleitem(args, 0), &path) ||
+X !getlonglongargs(gettupleitem(args, 1),
+X &tv[0].tv_sec, &tv[1].tv_sec))
+X return NULL;
+X tv[0].tv_usec = tv[1].tv_usec = 0;
+X if (utimes(getstringvalue(path), tv) < 0)
+X return posix_error();
+X INCREF(None);
+X return None;
+X}
+X
+X
+X#ifndef NO_LSTAT
+X
+Xstatic object *
+Xposix_lstat(self, args)
+X object *self;
+X object *args;
+X{
+X extern int lstat PROTO((const char *, struct stat *));
+X return posix_do_stat(self, args, lstat);
+X}
+X
+Xstatic object *
+Xposix_readlink(self, args)
+X object *self;
+X object *args;
+X{
+X char buf[1024]; /* XXX Should use MAXPATHLEN */
+X object *path;
+X int n;
+X if (!getstrarg(args, &path))
+X return NULL;
+X n = readlink(getstringvalue(path), buf, sizeof buf);
+X if (n < 0)
+X return posix_error();
+X return newsizedstringobject(buf, n);
+X}
+X
+Xstatic object *
+Xposix_symlink(self, args)
+X object *self;
+X object *args;
+X{
+X extern int symlink PROTO((const char *, const char *));
+X return posix_2str(args, symlink);
+X}
+X
+X#endif /* NO_LSTAT */
+X
+X
+Xstatic struct methodlist posix_methods[] = {
+X {"chdir", posix_chdir},
+X {"chmod", posix_chmod},
+X {"getcwd", posix_getcwd},
+X {"link", posix_link},
+X {"listdir", posix_listdir},
+X {"mkdir", posix_mkdir},
+X {"rename", posix_rename},
+X {"rmdir", posix_rmdir},
+X {"stat", posix_stat},
+X {"system", posix_system},
+X {"umask", posix_umask},
+X {"unlink", posix_unlink},
+X {"utimes", posix_utimes},
+X#ifndef NO_LSTAT
+X {"lstat", posix_lstat},
+X {"readlink", posix_readlink},
+X {"symlink", posix_symlink},
+X#endif
+X {NULL, NULL} /* Sentinel */
+X};
+X
+X
+Xvoid
+Xinitposix()
+X{
+X object *m, *d, *v;
+X
+X m = initmodule("posix", posix_methods);
+X d = getmoduledict(m);
+X
+X /* Initialize posix.environ dictionary */
+X v = convertenviron();
+X if (v == NULL || dictinsert(d, "environ", v) != 0)
+X fatal("can't define posix.environ");
+X DECREF(v);
+X
+X /* Initialize posix.error exception */
+X PosixError = newstringobject("posix.error");
+X if (PosixError == NULL || dictinsert(d, "error", PosixError) != 0)
+X fatal("can't define posix.error");
+X}
+EOF
+fi
+echo 'Part 11 out of 21 of pack.out complete.'
+exit 0
diff --git a/shar/python-0.9.1-12-21.shar b/shar/python-0.9.1-12-21.shar
new file mode 100644
index 0000000..adb9780
--- /dev/null
+++ b/shar/python-0.9.1-12-21.shar
@@ -0,0 +1,2833 @@
+: This is a shell archive.
+: Extract with 'sh this_file'.
+:
+: Extract part 01 first since it makes all directories
+echo 'Start of pack.out, part 12 out of 21:'
+if test -s 'demo/sgi/gl_panel/flying/flying.py'
+then echo '*** I will not over-write existing file demo/sgi/gl_panel/flying/flying.py'
+else
+echo 'x - demo/sgi/gl_panel/flying/flying.py'
+sed 's/^X//' > 'demo/sgi/gl_panel/flying/flying.py' << 'EOF'
+X#! /ufs/guido/bin/sgi/python
+X
+Xfrom gl import *
+Xfrom objdict import *
+Xfrom GL import *
+Ximport DEVICE, time
+Ximport objectdef, light, panel, material
+X
+Xdef fixmatact (p) :
+X p.diffR.fixact ()
+X p.diffG.fixact ()
+X p.diffB.fixact ()
+X p.specR.fixact ()
+X p.specG.fixact ()
+X p.specB.fixact ()
+X p.shine.fixact ()
+X
+Xdef fixlichtact (p) :
+X p.R.fixact ()
+X p.G.fixact ()
+X p.B.fixact ()
+X p.X.fixact ()
+X p.Y.fixact ()
+X p.Z.fixact ()
+X p.local.fixact ()
+X
+Xdef cbsetlight (a) :
+X p = a.back
+X setlight (p, a.label)
+X
+Xdef cbsetmaterial (a) :
+X p = a.back
+X setmaterial (p, a.label)
+X
+Xmater = [0]
+Xlicht = [0]
+X
+Xdef setmaterial (p, mname) :
+X #
+X mater [0:1] = [material.materdict [mname]]
+X #
+X p.diffR.val = mater [0][1]
+X p.diffG.val = mater [0][2]
+X p.diffB.val = mater [0][3]
+X #
+X p.specR.val = mater [0][5]
+X p.specG.val = mater [0][6]
+X p.specB.val = mater [0][7]
+X #
+X p.shine.val = mater [0][9] / 128.0
+X fixmatact (p)
+X
+Xdef setlight (p, mname) :
+X #
+X licht [0:1] = [material.lichtdict [mname]]
+X #
+X p.R.val = licht [0][1]
+X p.G.val = licht [0][2]
+X p.B.val = licht [0][3]
+X #
+X p.X.val = (licht [0][5] + 10.0) / 20.0
+X p.Y.val = (licht [0][6] + 10.0) / 20.0
+X p.Z.val = (licht [0][7] + 10.0) / 20.0
+X #
+X p.local.val = licht [0][8]
+X #
+X fixlichtact (p)
+X
+Xdef cbmaterial (a) :
+X #
+X if mater[0] = 0 : return
+X #
+X p = a.back
+X mater [0][5:8] = [p.diffR.val, p.diffG.val, p.diffB.val]
+X mater [0][1:4] = [p.specR.val, p.specG.val, p.specB.val]
+X mater [0][9:10] = [128.0 * p.shine.val]
+X light.bindlight (0)
+X
+Xdef cblight (a) :
+X #
+X if licht[0] = 0 : return
+X #
+X p = a.back
+X licht [0][1:4] = [p.R.val, p.G.val, p.B.val]
+X licht [0][5:8] = [20.0 * p.X.val - 10.0, 20.0 * p.Y.val - 10.0, 20.0 * p.Z.val - 10.0]
+X if p.local.val = 0.0 :
+X licht [0][8:9] = [0.0]
+X else:
+X licht [0][8:9] = [1.0]
+X #
+X light.bindlight (0)
+X
+X#
+X# initgl : initialize window, pipeline, light, viewing
+X#
+Xdef initgl () :
+X #
+X # init window
+X #
+X foreground ()
+X keepaspect (1, 1)
+X prefposition (100, 500, 100, 500)
+X w = winopen ('flying objects')
+X keepaspect (1, 1)
+X winconstraints ()
+X #
+X # configure pipline
+X #
+X doublebuffer ()
+X shademodel (GOURAUD)
+X zbuffer (1)
+X RGBmode ()
+X gconfig ()
+X #
+X # init lighting
+X #
+X light.bindlight (1)
+X #
+X # set viewing
+X #
+X lookat (0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0)
+X #
+X
+X#
+X# drawit : draws the object with the given attributes.
+X#
+X# rfac : the rotation factor.
+X# mat : the material identification
+X# attr : a list of attributes :
+X#
+X# [[rotate vector ], [tranlate vector], [scale vector]]
+X# i.e :
+X# [[rX, rY, rZ], [tX, tY, tZ], [sX, sY, sZ]]
+X#
+Xdef drawit(object, rfac, attr, mat) :
+X pushmatrix()
+X rot (attr[0][0] * float (rfac), 'X')
+X rot (attr[0][1] * float (rfac), 'Y')
+X rot (attr[0][2] * float (rfac), 'Z')
+X translate(attr[1][0], attr[1][1], attr[1][2])
+X scale(attr[2][0], attr[2][1], attr[2][2])
+X lmbind(MATERIAL, mat)
+X objectdef.drawobject(object)
+X popmatrix()
+X
+Xdef callbacksphere (a) :
+X putDict (objects, 'sphere', int (a.val))
+X
+Xdef callbackcylinder (a) :
+X putDict (objects, 'cylinder', int (a.val))
+X
+Xdef callbackcube (a) :
+X putDict (objects, 'cube', int (a.val))
+X
+Xdef callbackicecream (a) :
+X putDict (objects, 'icecream', int (a.val))
+X
+Xdef callbackdisk (a) :
+X putDict (objects, 'disk', int (a.val))
+X
+Xdef callbackdiamond (a) :
+X putDict (objects, 'diamond', int (a.val))
+X
+Xdef callbackglass (a) :
+X putDict (objects, 'glass', int (a.val))
+X
+Xdef callbackpyramid (a) :
+X putDict (objects, 'pyramid', int (a.val))
+X
+Xdef callbacktable (a) :
+X putDict (objects, 'table', int (a.val))
+X
+Xdef callbackflat (a) :
+X shademodel(FLAT)
+X
+Xdef callbackgouraud (a) :
+X shademodel(GOURAUD)
+X
+Xdef callbackwire (a) :
+X objectdef.putFunc ([bgnclosedline, endclosedline])
+X
+Xdef callbackfilled (a) :
+X objectdef.putFunc ([bgnpolygon, endpolygon])
+X
+Xdef callbackquit (a) :
+X import sys
+X sys.exit (-1)
+X
+Xdef allObjects(p, val) :
+X p.sphere.val = val
+X p.sphere.fixact ()
+X p.cube.val = val
+X p.cube.fixact ()
+X p.cylinder.val = val
+X p.cylinder.fixact ()
+X p.pyramid.val = val
+X p.pyramid.fixact ()
+X p.disk.val = val
+X p.disk.fixact ()
+X p.diamond.val = val
+X p.diamond.fixact ()
+X p.icecream.val = val
+X p.icecream.fixact ()
+X p.table.val = val
+X p.table.fixact ()
+X p.fixpanel()
+X
+X
+Xdef callbackshowall (a) :
+X #print objects
+X for key in objects.keys () :
+X #print key
+X putDict (objects, key, 1)
+X allObjects (a.back, 1.0)
+X
+Xdef callbackshownone (a) :
+X for key in objects.keys () :
+X putDict (objects, key, 0)
+X allObjects (a.back, 0.0)
+X
+X#
+X# main : makeobjects, initialze graphics, and loop continuously.
+X#
+Xdef main () :
+X #
+X # iter keeps track of the iterations. It is used as the
+X # (x, y, z) rotation increments to which the objects rotate.
+X iter = 0
+X #
+X # make the objects. the objects are put in the odict dictionary
+X #
+X od = objectdef.makeobjects ()
+X #
+X # initialize gl
+X #
+X initgl ()
+X #
+X # initialize time and iterations per second
+X #
+X time0 = time.time () # epoch-time of previous second
+X fps = 0 # frames per second
+X #
+X # initialize panels
+X #
+X panel.needredraw()
+X panels = panel.defpanellist('flying.s') #XXX
+X p = panels[0]
+X p.sphere.upfunc = callbacksphere
+X p.cylinder.upfunc = callbackcylinder
+X p.cube.upfunc = callbackcube
+X p.icecream.upfunc = callbackicecream
+X p.disk.upfunc = callbackdisk
+X p.diamond.upfunc = callbackdiamond
+X # NOT YET IMPLEMENTED p.glass.upfunc = callbackglass
+X p.pyramid.upfunc = callbackpyramid
+X p.table.upfunc = callbacktable
+X p.wire.upfunc = callbackwire
+X p.filled.upfunc = callbackfilled
+X p.flat.upfunc = callbackflat
+X p.gouraud.upfunc = callbackgouraud
+X p.quit.upfunc = callbackquit
+X p.showall.upfunc = callbackshowall
+X p.shownone.upfunc = callbackshownone
+X p.showall.back = p
+X p.shownone.back = p
+X #
+X qanels = panel.defpanellist('freeze.s') #XXX
+X q = qanels[0]
+X #
+X ranels = panel.defpanellist('materials.s') #XXX
+X r = ranels[0]
+X r.m9.upfunc = cbsetmaterial
+X r.m8.upfunc = cbsetmaterial
+X r.m7.upfunc = cbsetmaterial
+X r.m6.upfunc = cbsetmaterial
+X r.m5.upfunc = cbsetmaterial
+X r.m4.upfunc = cbsetmaterial
+X r.m3.upfunc = cbsetmaterial
+X r.m2.upfunc = cbsetmaterial
+X r.m1.upfunc = cbsetmaterial
+X r.specR.activefunc = cbmaterial
+X r.specG.activefunc = cbmaterial
+X r.specB.activefunc = cbmaterial
+X r.diffR.activefunc = cbmaterial
+X r.diffG.activefunc = cbmaterial
+X r.diffB.activefunc = cbmaterial
+X r.shine.activefunc = cbmaterial
+X r.m9.back = r
+X r.m8.back = r
+X r.m7.back = r
+X r.m6.back = r
+X r.m5.back = r
+X r.m4.back = r
+X r.m3.back = r
+X r.m2.back = r
+X r.m1.back = r
+X r.diffR.back = r
+X r.diffG.back = r
+X r.diffB.back = r
+X r.specR.back = r
+X r.specG.back = r
+X r.specB.back = r
+X r.shine.back = r
+X #
+X sanels = panel.defpanellist('light.s') #XXX
+X s = sanels[0]
+X s.X.back = s
+X s.Y.back = s
+X s.Z.back = s
+X s.R.back = s
+X s.G.back = s
+X s.B.back = s
+X s.light1.back = s
+X s.light2.back = s
+X s.local.back = s
+X s.light1.upfunc = cbsetlight
+X s.light2.upfunc = cbsetlight
+X s.R.activefunc = cblight
+X s.G.activefunc = cblight
+X s.B.activefunc = cblight
+X s.X.activefunc = cblight
+X s.Y.activefunc = cblight
+X s.Z.activefunc = cblight
+X #
+X while 1 :
+X #
+X act = panel.dopanel()
+X #
+X wid = panel.userredraw ()
+X if wid :
+X winset (wid)
+X reshapeviewport()
+X #
+X # increment iter
+X #
+X if int (q.freeze.val) = 0 :
+X iter = iter + 1
+X fps = fps + 1
+X if time.time() - time0 >= 1 :
+X f = float(fps)/float(time.time()-time0)
+X q.mystrip.val = f
+X q.mystrip.fixact ()
+X q.fixpanel()
+X time0 = time.time()
+X fps = 0
+X #
+X # clear the zbuffer and make the background light blue
+X #
+X zclear()
+X c3i (LightBlue)
+X clear()
+X #
+X # for each object in the objects dictionary
+X #
+X for key in objects.keys() :
+X #
+X # if the object should be displayed
+X #
+X if getDict (objects, key, 0) = ONE :
+X loo = getDict (objects, key, 1)
+X for o in loo :
+X #
+X # get attributes and materail
+X #
+X attr = o [1]
+X mat = o [2]
+X #
+X # display the object
+X #
+X drawit(od[o[0]],iter,attr,mat)
+X #
+X swapbuffers()
+X #
+X
+Xmain()
+EOF
+chmod +x 'demo/sgi/gl_panel/flying/flying.py'
+fi
+if test -s 'lib/adv.py'
+then echo '*** I will not over-write existing file lib/adv.py'
+else
+echo 'x - lib/adv.py'
+sed 's/^X//' > 'lib/adv.py' << 'EOF'
+X#! /ufs/guido/bin/sgi/python
+X
+X# Module 'adv' -- text-oriented adventure game.
+X
+X
+X# Name a constant that may once appear in the language...
+X
+Xdef return_nil(): return
+Xnil = return_nil()
+X
+X
+X# Copy of string.split() (to avoid loading all of string.py)
+X
+Xwhitespace = ' \t\n'
+Xdef split(s):
+X res = []
+X i, n = 0, len(s)
+X while i < n:
+X while i < n and s[i] in whitespace: i = i+1
+X if i = n: break
+X j = i
+X while j < n and s[j] not in whitespace: j = j+1
+X res.append(s[i:j])
+X i = j
+X return res
+X
+X
+X# Constants to name directions
+X
+XN = 'north'
+XS = 'south'
+XW = 'west'
+XE = 'east'
+XU = 'up'
+XD = 'down'
+XNW = 'nw'
+XNE = 'ne'
+XSW = 'sw'
+XSE = 'se'
+X
+X
+X# Constants to name other commands
+X
+XINVENT = 'invent'
+XLOOK = 'look'
+XBACK = 'back'
+XHELP = 'help'
+XGET = 'get'
+XPUT = 'put'
+X
+X
+X# Aliases recognized by the parser
+X
+Xalias = {}
+Xalias['n'] = N
+Xalias['s'] = S
+Xalias['e'] = E
+Xalias['w'] = W
+Xalias['u'] = U
+Xalias['d'] = D
+Xalias['i'] = INVENT
+Xalias['l'] = LOOK
+Xalias['b'] = BACK
+Xalias['take'] = GET
+Xalias['drop'] = PUT
+X
+X
+X# Normalize a command, in place: truncate words to 6 chars, and expand aliases.
+X
+Xdef normalize(cmd):
+X for i in range(len(cmd)):
+X word = cmd[i][:6]
+X if alias.has_key(word):
+X word = alias[word]
+X cmd[i] = word
+X
+X
+X# The Object class describes objects that the player can carry around.
+X
+Xclass Object():
+X def init(this, name):
+X this.name = name
+X return this
+X def describe(this):
+X print 'A', this.name + '.'
+X def get(this, (player, room)):
+X del room.objects[this.name]
+X player.objects[this.name] = this
+X def put(this, (player, room)):
+X del player.objects[this.name]
+X room.objects[this.name] = this
+X
+X
+X# The Player class embodies first person control.
+X
+Xclass Player():
+X # Set initial state, except current room.
+X def init(self, initial_room):
+X self.blind = 0
+X self.here = initial_room
+X self.prev = nil
+X self.objects = {}
+X return self
+X # Read and execute commands forever.
+X def play(self):
+X self.here.casualdescribe()
+X while 1:
+X self.move()
+X # Read and execute one command.
+X def move(self):
+X next = self.here.parser()
+X if next and next <> self.here:
+X self.prev = self.here
+X self.here = next
+X if not self.blind:
+X self.here.casualdescribe()
+X # Print inventory.
+X def inventory(self):
+X if not self.objects:
+X print 'You aren\'t carrying anything.'
+X return
+X print 'You are carrying:'
+X for key in self.objects.keys():
+X self.objects[key].describe()
+X # Go back to previous room.
+X def back(self):
+X if self.prev: return self.prev
+X print 'You can\'t go back now.'
+X # Get an object from the room.
+X def get(self, name):
+X if self.here.objects.has_key(name):
+X self.here.objects[name].get(self, self.here)
+X else:
+X print 'I see no', name, 'here.'
+X # Put an object in the room.
+X def put(self, name):
+X if self.objects.has_key(name):
+X self.objects[name].put(self, self.here)
+X else:
+X print 'You have no', name, 'with you.'
+X
+X
+X# The Room class describes a generic room.
+X# Rooms with special properties are defined by derived classes
+X# that override certain operations.
+X
+Xclass Room():
+X # Initialize a featureless room.
+X def init(here, name):
+X here.seen = 0
+X here.name = name
+X here.exits = {}
+X here.objects = {}
+X here.description = []
+X return here
+X # Add an object to the room. Used during initialization.
+X def add(here, obj):
+X here.objects[obj.name] = obj
+X # Print a casual description.
+X def casualdescribe(here):
+X if here.seen:
+X print here.name + '.'
+X here.listobjects()
+X return
+X here.seen = 1
+X here.describe()
+X # Print a full description, including all exits and objects seen.
+X def describe(here):
+X if not here.description:
+X print here.name + '.'
+X here.listexits()
+X else:
+X for line in here.description: print line
+X here.listobjects()
+X # List exits.
+X def listexits(here):
+X there = here.exits.keys()
+X if there:
+X if len(there) = 1:
+X print 'There is an exit leading',
+X else:
+X print 'There are exits leading',
+X for name in there[:-2]:
+X print name + ',',
+X print there[len(there)-2], 'and',
+X print there[len(there)-1] + '.'
+X # List objects
+X def listobjects(here):
+X if here.objects:
+X print 'I see:'
+X for key in here.objects.keys():
+X here.objects[key].describe()
+X # Default parser. Returns next room (possibly the same) or nil.
+X def parser(here):
+X cmd = here.getcmd(here.prompt())
+X return here.decide(cmd)
+X # Return default prompt string.
+X def prompt(here): return '> '
+X # Default input routine. Returns a non-empty list of words.
+X def getcmd(here, prompt):
+X # Loop until non-empty command gotten
+X # EOFError and KeyboardInterrupt may be caught elsewhere
+X while 1:
+X line = raw_input(prompt)
+X cmd = split(line)
+X if cmd:
+X normalize(cmd)
+X return cmd
+X # Default decision routine. Override for room-specific commands.
+X def decide(here, cmd):
+X key, args = cmd[0], cmd[1:]
+X if not args:
+X if key = N: return here.north()
+X if key = S: return here.south()
+X if key = E: return here.east()
+X if key = W: return here.west()
+X if key = U: return here.up()
+X if key = D: return here.down()
+X if key = NW: return here.nw()
+X if key = NE: return here.ne()
+X if key = SW: return here.sw()
+X if key = SE: return here.se()
+X if key = LOOK: return here.look()
+X if key = INVENT: return here.inventory()
+X if key = BACK: return here.back()
+X if here.objects.has_key(key):
+X print 'What do you want to do with the', key+'?'
+X else:
+X print 'Huh?'
+X return
+X if key = GET:
+X for arg in args:
+X player.get(arg)
+X return
+X if key = PUT:
+X for arg in args:
+X player.put(arg)
+X # Standard commands.
+X def look(here):
+X here.describe()
+X def inventory(here):
+X player.inventory()
+X def back(here):
+X return player.back()
+X # Standard exits.
+X def north(here): return here.take_exit(N)
+X def south(here): return here.take_exit(S)
+X def west(here): return here.take_exit(W)
+X def east(here): return here.take_exit(E)
+X def up(here): return here.take_exit(U)
+X def down(here): return here.take_exit(D)
+X def nw(here): return here.take_exit(NW)
+X def ne(here): return here.take_exit(NE)
+X def sw(here): return here.take_exit(SW)
+X def se(here): return here.take_exit(SE)
+X # Subroutine for standard exits.
+X def take_exit(here, key):
+X if here.exits.has_key(key):
+X return here.exits[key]
+X print 'You cannot go in that direction.'
+X return here
+X
+X
+X# Create the objects we know about.
+X# Object names begin with 'o_'.
+X
+Xo_lamp = Object().init('lamp')
+Xo_python = Object().init('python')
+X
+X
+X# Subroutine to connect two rooms.
+X
+Xdef connect(rm1, rm2, dir1, dir2):
+X if dir1:
+X rm1.exits[dir1] = rm2
+X if dir2:
+X rm2.exits[dir2] = rm1
+X
+X
+X# Create the rooms and connect them together.
+X# Room names begin with 'r_'.
+X
+Xr_front = Room().init('Front of building')
+Xr_initial = r_front
+Xr_front.description = [ \
+X 'You are standing in front of a large, desolate building.', \
+X 'Huge neon letters spell "CWI". The "I" is blinking.', \
+X 'There are entrances north and west from where you are standing.', \
+X ]
+X
+Xr_entrance = Room().init('Entrance')
+Xr_entrance.description = [ \
+X 'You are standing in a small entrance room.', \
+X 'On the east side is a window to a reception room.', \
+X 'South is a door leading outside the building.', \
+X 'North is a large hall.' \
+X ]
+X
+Xr_hall_s = Room().init('South of hall')
+Xr_hall_s.description = [ \
+X 'You are standing at the south side of a very large hall.', \
+X 'There are doors leading west, southwest, south and southeast,', \
+X 'and a corridor leads east.', \
+X 'The hall continues to the north.' \
+X ]
+X
+Xr_hall_n = Room().init('North of hall')
+Xr_hall_n.description = [ \
+X 'You are stanting at the north side of a very large hall.', \
+X 'There are corridors leading west, northwest, northeast,', \
+X 'an elevator door north, and a door leading outside east.', \
+X 'There are stairs leading up, and the hall continues to the south.' \
+X ]
+X
+Xr_reception = Room().init('Reception')
+X
+Xr_mail = Room().init('Mail room')
+X
+Xconnect(r_front, r_entrance, N, S)
+Xconnect(r_entrance, r_hall_s, N, SW)
+Xconnect(r_hall_s, r_hall_n, N, S)
+Xconnect(r_hall_s, r_reception, S, N)
+Xconnect(r_hall_s, r_mail, SE, N)
+Xconnect(r_reception, r_mail, E, W)
+X
+Xr_aud_front = Room().init('Front of Auditorium')
+Xr_aud_back = Room().init('Back of Auditorium')
+Xr_aud_tech = Room().init('Technician\'s room in Auditorium')
+Xr_aud_proj = Room().init('Projection room in Auditorium')
+X
+Xconnect(r_aud_front, r_hall_s, E, W)
+Xconnect(r_aud_front, r_aud_back, S, N)
+Xconnect(r_aud_back, r_aud_proj, SE, N)
+Xconnect(r_aud_front, r_aud_tech, W, E)
+X
+Xr_floor1 = Room().init('First floor')
+Xr_floor2 = Room().init('Second floor')
+Xr_floor3 = Room().init('Third floor')
+X
+Xconnect(r_hall_n, r_floor1, U, D)
+Xconnect(r_floor1, r_floor2, U, D)
+Xconnect(r_floor2, r_floor3, U, D)
+X
+X
+X# Drop objects here and there
+X
+Xr_aud_proj.add(o_python)
+Xr_reception.add(o_lamp)
+X
+X# Create an uninitialized player object.
+X# It is initialized by main(), but must be created here (as global)
+X# since some Room methods reference it. (Though maybe they shouldn't?)
+X
+Xplayer = Player()
+X
+X
+X# Play the game from the beginning.
+X
+Xdef main():
+X x = player.init(r_initial)
+X try:
+X player.play()
+X except (EOFError, KeyboardInterrupt):
+X pass
+X
+Xmain()
+EOF
+fi
+if test -s 'lib/cmpcache.py'
+then echo '*** I will not over-write existing file lib/cmpcache.py'
+else
+echo 'x - lib/cmpcache.py'
+sed 's/^X//' > 'lib/cmpcache.py' << 'EOF'
+X# Module 'cmpcache'
+X#
+X# Efficiently compare files, boolean outcome only (equal / not equal).
+X#
+X# Tricks (used in this order):
+X# - Use the statcache module to avoid statting files more than once
+X# - Files with identical type, size & mtime are assumed to be clones
+X# - Files with different type or size cannot be identical
+X# - We keep a cache of outcomes of earlier comparisons
+X# - We don't fork a process to run 'cmp' but read the files ourselves
+X
+Ximport posix
+Xfrom stat import *
+Ximport statcache
+X
+X
+X# The cache.
+X#
+Xcache = {}
+X
+X
+X# Compare two files, use the cache if possible.
+X# May raise posix.error if a stat or open of either fails.
+X#
+Xdef cmp(f1, f2):
+X # Return 1 for identical files, 0 for different.
+X # Raise exceptions if either file could not be statted, read, etc.
+X s1, s2 = sig(statcache.stat(f1)), sig(statcache.stat(f2))
+X if not S_ISREG(s1[0]) or not S_ISREG(s2[0]):
+X # Either is a not a plain file -- always report as different
+X return 0
+X if s1 = s2:
+X # type, size & mtime match -- report same
+X return 1
+X if s1[:2] <> s2[:2]: # Types or sizes differ, don't bother
+X # types or sizes differ -- report different
+X return 0
+X # same type and size -- look in the cache
+X key = f1 + ' ' + f2
+X if cache.has_key(key):
+X cs1, cs2, outcome = cache[key]
+X # cache hit
+X if s1 = cs1 and s2 = cs2:
+X # cached signatures match
+X return outcome
+X # stale cached signature(s)
+X # really compare
+X outcome = do_cmp(f1, f2)
+X cache[key] = s1, s2, outcome
+X return outcome
+X
+X# Return signature (i.e., type, size, mtime) from raw stat data.
+X#
+Xdef sig(st):
+X return S_IFMT(st[ST_MODE]), st[ST_SIZE], st[ST_MTIME]
+X
+X# Compare two files, really.
+X#
+Xdef do_cmp(f1, f2):
+X #print ' cmp', f1, f2 # XXX remove when debugged
+X bufsize = 8096 # Could be tuned
+X fp1 = open(f1, 'r')
+X fp2 = open(f2, 'r')
+X while 1:
+X b1 = fp1.read(bufsize)
+X b2 = fp2.read(bufsize)
+X if b1 <> b2: return 0
+X if not b1: return 1
+EOF
+fi
+if test -s 'lib/macshell.py'
+then echo '*** I will not over-write existing file lib/macshell.py'
+else
+echo 'x - lib/macshell.py'
+sed 's/^X//' > 'lib/macshell.py' << 'EOF'
+X# Macintosh 'shell'
+X# vi:set tabsize=4:
+X
+X# XXX string quoting in arguments
+X# XXX directory stack
+X# XXX $macros?
+X# XXX ^C during any command
+X# XXX 'sh' builtin command?
+X# XXX why does open require absolute path? (need to fix chdir.c)
+X
+X
+Ximport mac
+X
+Ximport macpath
+Ximport string
+Ximport glob
+Xfrom macpath import isfile, isdir, exists
+Ximport TclUtil # For splitting/quoting mechanisms
+X
+Xclass Struct(): pass
+XG = Struct()
+X
+Xdef reset():
+X G.debug = 0
+X G.ps1 = '$ '
+X G.homedir = mac.getcwd()
+X G.commands = mkcmdtab()
+X G.aliases = {}
+X
+Xdef mkcmdtab():
+X tab = {}
+X tab['alias'] = do_alias
+X tab['cd'] = do_cd
+X tab['debug'] = do_debug
+X tab['grep'] = do_grep
+X tab['help'] = do_help
+X tab['ls'] = do_ls
+X tab['mkdir'] = do_mkdir
+X tab['mv'] = do_mv
+X tab['page'] = do_page
+X tab['pwd'] = do_pwd
+X tab['reset'] = do_reset
+X tab['rm'] = do_rm
+X tab['rmdir'] = do_rmdir
+X tab['sync'] = do_sync
+X tab['unalias'] = do_unalias
+X return tab
+X
+Xdef main():
+X while 1:
+X try:
+X line = raw_input(G.ps1)
+X except EOFError:
+X print '[EOF]'
+X break
+X except KeyboardInterrupt:
+X print '[Intr]'
+X line = ''
+X if G.debug:
+X print 'line:', `line`
+X words = TclUtil.SplitList(line)
+X if G.debug:
+X print 'words:', words
+X if words and words[0][0] <> '#':
+X run(words)
+X
+Xdef run(words):
+X expandaliases(words)
+X cmd = words[0]
+X args = words[1:]
+X if G.commands.has_key(cmd):
+X if args:
+X try:
+X args = expandgloblist(args)
+X except glob_error, msg:
+X print cmd, ': glob error :', msg
+X return
+X G.commands[cmd](args)
+X return
+X if hasglobchar(cmd):
+X if args:
+X print cmd, ': cannot glob pattern with arguments'
+X return
+X try:
+X words = expandglobword(cmd)
+X except glob_error, msg:
+X print cmd, ': glob error :', msg
+X return
+X if len(words) > 1:
+X columnize(words)
+X return
+X cmd = words[0]
+X print cmd
+X if isfile(cmd):
+X if args:
+X print cmd, ': file command expects no arguments'
+X return
+X do_page([cmd])
+X elif isdir(cmd):
+X if args:
+X print cmd, ': directory command expects no arguments'
+X return
+X do_cd([cmd])
+X else:
+X print cmd, ': no such command, file or directory'
+X
+Xglob_error = 'glob error'
+X
+Xdef expandgloblist(words):
+X res = []
+X for word in words:
+X if hasglobchar(word):
+X res = res + expandglobword(word)
+X else:
+X res.append(word)
+X return res
+X
+Xdef expandglobword(word):
+X names = glob.globlist(mac.listdir(':'), word)
+X if not names: raise glob_error, 'no match for pattern ' + word
+X return names
+X
+Xdef hasglobchar(word):
+X return '*' in word or '?' in word
+X
+Xdef expandaliases(words):
+X seen = []
+X cmd = words[0]
+X while cmd not in seen and G.aliases.has_key(cmd):
+X seen.append(cmd)
+X words[:1] = G.aliases[cmd]
+X cmd = words[0]
+X
+Xdef do_alias(args):
+X if not args:
+X listaliases()
+X elif len(args) = 1:
+X listalias(args[0])
+X else:
+X defalias(args[0], args[1:])
+X
+Xdef listaliases():
+X names = G.aliases.keys()
+X names.sort()
+X for name in names: listalias(name)
+X
+Xdef listalias(name):
+X if not G.aliases.has_key(name):
+X print name, ': no such alias'
+X return
+X print 'alias', name,
+X printlist(G.aliases[name])
+X print
+X
+Xdef defalias(name, expansion):
+X G.aliases[name] = expansion
+X
+Xdef do_cd(args):
+X if len(args) > 1:
+X print 'usage: cd [dirname]'
+X elif args:
+X chdirto(args[0])
+X else:
+X chdirto(G.homedir)
+X
+Xdef chdirto(dirname):
+X try:
+X mac.chdir(dirname)
+X except mac.error, msg:
+X print dirname, ':', msg
+X return
+X
+Xdef do_debug(args):
+X G.debug = (not G.debug)
+X
+Xdef do_grep(args):
+X if len(args) < 2:
+X print 'usage: grep regexp file ...'
+X return
+X import regexp
+X try:
+X prog = regexp.compile(args[0])
+X except regexp.error, msg:
+X print 'regexp.compile error for', args[0], ':', msg
+X return
+X for file in args[1:]:
+X grepfile(prog, file)
+X
+Xdef grepfile(prog, file):
+X try:
+X fp = open(file, 'r')
+X except RuntimeError, msg:
+X print file, ': cannot open :', msg
+X return
+X lineno = 0
+X while 1:
+X line = fp.readline()
+X if not line: break
+X lineno = lineno+1
+X if prog.exec(line):
+X print file+'('+`lineno`+'):', line,
+X
+Xdef do_help(args):
+X if args:
+X print 'usage: help'
+X return
+X names = G.commands.keys()
+X names.sort()
+X columnize(names)
+X
+Xdef do_ls(args):
+X if not args:
+X lsdir(':')
+X else:
+X for dirname in args:
+X lsdir(dirname)
+X
+Xdef lsdir(dirname):
+X if not isdir(dirname):
+X print dirname, ': no such directory'
+X return
+X names = mac.listdir(dirname)
+X lsfiles(names, dirname)
+X
+Xdef lsfiles(names, dirname):
+X names = names[:] # Make a copy so we can modify it
+X for i in range(len(names)):
+X name = names[i]
+X if G.debug: print i, name
+X if isdir(macpath.cat(dirname, name)):
+X names[i] = ':' + name + ':'
+X columnize(names)
+X
+Xdef columnize(list):
+X COLUMNS = 80-1
+X n = len(list)
+X colwidth = maxwidth(list)
+X ncols = (COLUMNS + 1) / (colwidth + 1)
+X if ncols < 1: ncols = 1
+X nrows = (n + ncols - 1) / ncols
+X for irow in range(nrows):
+X line = ''
+X for icol in range(ncols):
+X i = irow + nrows*icol
+X if 0 <= i < n:
+X word = list[i]
+X if i+nrows < n:
+X word = string.ljust(word, colwidth)
+X if icol > 0:
+X word = ' ' + word
+X line = line + word
+X print line
+X
+Xdef maxwidth(list):
+X width = 0
+X for word in list:
+X if len(word) > width:
+X width = len(word)
+X return width
+X
+Xdef do_mv(args):
+X if len(args) <> 2:
+X print 'usage: mv src dst'
+X return
+X src, dst = args[0], args[1]
+X if not exists(src):
+X print src, ': source does not exist'
+X return
+X if exists(dst):
+X print src, ': destination already exists'
+X return
+X try:
+X mac.rename(src, dst)
+X except mac.error, msg:
+X print src, dst, ': rename failed:', msg
+X
+Xdef do_mkdir(args):
+X if not args:
+X print 'usage: mkdir name ...'
+X return
+X for name in args:
+X makedir(name)
+X
+Xdef makedir(name):
+X if exists(name):
+X print name, ': already exists'
+X return
+X try:
+X mac.mkdir(name, 0777)
+X except mac.error, msg:
+X print name, ': mkdir failed:', msg
+X
+Xdef do_page(args):
+X if not args:
+X print 'usage: page file ...'
+X return
+X for name in args:
+X pagefile(name)
+X
+Xdef pagefile(name):
+X if not isfile(name):
+X print name, ': no such file'
+X return
+X LINES = 24 - 1
+X # For THINK C 3.0, make the path absolute:
+X # if not macpath.isabs(name):
+X # name = macpath.cat(mac.getcwd(), name)
+X try:
+X fp = open(name, 'r')
+X except:
+X print name, ': cannot open'
+X return
+X line = fp.readline()
+X while line:
+X for i in range(LINES):
+X print line,
+X line = fp.readline()
+X if not line: break
+X if line:
+X try:
+X more = raw_input('[more]')
+X except (EOFError, KeyboardInterrupt):
+X print
+X break
+X if string.strip(more)[:1] in ('q', 'Q'):
+X break
+X
+Xdef do_pwd(args):
+X if args:
+X print 'usage: pwd'
+X else:
+X print mac.getcwd()
+X
+Xdef do_reset(args):
+X if args:
+X print 'usage: reset'
+X else:
+X reset()
+X
+Xdef do_rm(args):
+X if not args:
+X print 'usage: rm file ...'
+X return
+X for name in args:
+X remove(name)
+X
+Xdef remove(name):
+X if not isfile(name):
+X print name, ': no such file'
+X return
+X try:
+X mac.unlink(name)
+X except mac.error, msg:
+X print name, ': unlink failed:', msg
+X
+Xdef do_rmdir(args):
+X if not args:
+X print 'usage: rmdir dir ...'
+X return
+X for name in args:
+X rmdir(name)
+X
+Xdef rmdir(name):
+X if not isdir(name):
+X print name, ': no such directory'
+X return
+X try:
+X mac.rmdir(name)
+X except mac.error, msg:
+X print name, ': rmdir failed:', msg
+X
+Xdef do_sync(args):
+X if args:
+X print 'usage: sync'
+X return
+X try:
+X mac.sync()
+X except mac.error, msg:
+X print 'sync failed:', msg
+X
+Xdef do_unalias(args):
+X if not args:
+X print 'usage: unalias name ...'
+X return
+X for name in args:
+X unalias(name)
+X
+Xdef unalias(name):
+X if not G.aliases.has_key(name):
+X print name, ': no such alias'
+X return
+X del G.aliases[name]
+X
+Xdef printlist(list):
+X for word in list:
+X print word,
+X
+Xreset()
+Xmain()
+EOF
+fi
+if test -s 'src/cgensupport.c'
+then echo '*** I will not over-write existing file src/cgensupport.c'
+else
+echo 'x - src/cgensupport.c'
+sed 's/^X//' > 'src/cgensupport.c' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/* Functions used by cgen output */
+X
+X#include <stdio.h>
+X
+X#include "PROTO.h"
+X#include "object.h"
+X#include "intobject.h"
+X#include "floatobject.h"
+X#include "stringobject.h"
+X#include "tupleobject.h"
+X#include "listobject.h"
+X#include "methodobject.h"
+X#include "moduleobject.h"
+X#include "modsupport.h"
+X#include "import.h"
+X#include "cgensupport.h"
+X#include "errors.h"
+X
+X
+X/* Functions to construct return values */
+X
+Xobject *
+Xmknewcharobject(c)
+X int c;
+X{
+X char ch[1];
+X ch[0] = c;
+X return newsizedstringobject(ch, 1);
+X}
+X
+X/* Functions to extract arguments.
+X These needs to know the total number of arguments supplied,
+X since the argument list is a tuple only of there is more than
+X one argument. */
+X
+Xint
+Xgetiobjectarg(args, nargs, i, p_arg)
+X register object *args;
+X int nargs, i;
+X object **p_arg;
+X{
+X if (nargs != 1) {
+X if (args == NULL || !is_tupleobject(args) ||
+X nargs != gettuplesize(args) ||
+X i < 0 || i >= nargs) {
+X return err_badarg();
+X }
+X else {
+X args = gettupleitem(args, i);
+X }
+X }
+X if (args == NULL) {
+X return err_badarg();
+X }
+X *p_arg = args;
+X return 1;
+X}
+X
+Xint
+Xgetilongarg(args, nargs, i, p_arg)
+X register object *args;
+X int nargs, i;
+X long *p_arg;
+X{
+X if (nargs != 1) {
+X if (args == NULL || !is_tupleobject(args) ||
+X nargs != gettuplesize(args) ||
+X i < 0 || i >= nargs) {
+X return err_badarg();
+X }
+X args = gettupleitem(args, i);
+X }
+X if (args == NULL || !is_intobject(args)) {
+X return err_badarg();
+X }
+X *p_arg = getintvalue(args);
+X return 1;
+X}
+X
+Xint
+Xgetishortarg(args, nargs, i, p_arg)
+X register object *args;
+X int nargs, i;
+X short *p_arg;
+X{
+X long x;
+X if (!getilongarg(args, nargs, i, &x))
+X return 0;
+X *p_arg = x;
+X return 1;
+X}
+X
+Xstatic int
+Xextractdouble(v, p_arg)
+X register object *v;
+X double *p_arg;
+X{
+X if (v == NULL) {
+X /* Fall through to error return at end of function */
+X }
+X else if (is_floatobject(v)) {
+X *p_arg = GETFLOATVALUE((floatobject *)v);
+X return 1;
+X }
+X else if (is_intobject(v)) {
+X *p_arg = GETINTVALUE((intobject *)v);
+X return 1;
+X }
+X return err_badarg();
+X}
+X
+Xstatic int
+Xextractfloat(v, p_arg)
+X register object *v;
+X float *p_arg;
+X{
+X if (v == NULL) {
+X /* Fall through to error return at end of function */
+X }
+X else if (is_floatobject(v)) {
+X *p_arg = GETFLOATVALUE((floatobject *)v);
+X return 1;
+X }
+X else if (is_intobject(v)) {
+X *p_arg = GETINTVALUE((intobject *)v);
+X return 1;
+X }
+X return err_badarg();
+X}
+X
+Xint
+Xgetifloatarg(args, nargs, i, p_arg)
+X register object *args;
+X int nargs, i;
+X float *p_arg;
+X{
+X object *v;
+X float x;
+X if (!getiobjectarg(args, nargs, i, &v))
+X return 0;
+X if (!extractfloat(v, &x))
+X return 0;
+X *p_arg = x;
+X return 1;
+X}
+X
+Xint
+Xgetistringarg(args, nargs, i, p_arg)
+X object *args;
+X int nargs, i;
+X string *p_arg;
+X{
+X object *v;
+X if (!getiobjectarg(args, nargs, i, &v))
+X return NULL;
+X if (!is_stringobject(v)) {
+X return err_badarg();
+X }
+X *p_arg = getstringvalue(v);
+X return 1;
+X}
+X
+Xint
+Xgetichararg(args, nargs, i, p_arg)
+X object *args;
+X int nargs, i;
+X char *p_arg;
+X{
+X string x;
+X if (!getistringarg(args, nargs, i, &x))
+X return 0;
+X if (x[0] == '\0' || x[1] != '\0') {
+X /* Not exactly one char */
+X return err_badarg();
+X }
+X *p_arg = x[0];
+X return 1;
+X}
+X
+Xint
+Xgetilongarraysize(args, nargs, i, p_arg)
+X object *args;
+X int nargs, i;
+X long *p_arg;
+X{
+X object *v;
+X if (!getiobjectarg(args, nargs, i, &v))
+X return 0;
+X if (is_tupleobject(v)) {
+X *p_arg = gettuplesize(v);
+X return 1;
+X }
+X if (is_listobject(v)) {
+X *p_arg = getlistsize(v);
+X return 1;
+X }
+X return err_badarg();
+X}
+X
+Xint
+Xgetishortarraysize(args, nargs, i, p_arg)
+X object *args;
+X int nargs, i;
+X short *p_arg;
+X{
+X long x;
+X if (!getilongarraysize(args, nargs, i, &x))
+X return 0;
+X *p_arg = x;
+X return 1;
+X}
+X
+X/* XXX The following four are too similar. Should share more code. */
+X
+Xint
+Xgetilongarray(args, nargs, i, n, p_arg)
+X object *args;
+X int nargs, i;
+X int n;
+X long *p_arg; /* [n] */
+X{
+X object *v, *w;
+X if (!getiobjectarg(args, nargs, i, &v))
+X return 0;
+X if (is_tupleobject(v)) {
+X if (gettuplesize(v) != n) {
+X return err_badarg();
+X }
+X for (i = 0; i < n; i++) {
+X w = gettupleitem(v, i);
+X if (!is_intobject(w)) {
+X return err_badarg();
+X }
+X p_arg[i] = getintvalue(w);
+X }
+X return 1;
+X }
+X else if (is_listobject(v)) {
+X if (getlistsize(v) != n) {
+X return err_badarg();
+X }
+X for (i = 0; i < n; i++) {
+X w = getlistitem(v, i);
+X if (!is_intobject(w)) {
+X return err_badarg();
+X }
+X p_arg[i] = getintvalue(w);
+X }
+X return 1;
+X }
+X else {
+X return err_badarg();
+X }
+X}
+X
+Xint
+Xgetishortarray(args, nargs, i, n, p_arg)
+X object *args;
+X int nargs, i;
+X int n;
+X short *p_arg; /* [n] */
+X{
+X object *v, *w;
+X if (!getiobjectarg(args, nargs, i, &v))
+X return 0;
+X if (is_tupleobject(v)) {
+X if (gettuplesize(v) != n) {
+X return err_badarg();
+X }
+X for (i = 0; i < n; i++) {
+X w = gettupleitem(v, i);
+X if (!is_intobject(w)) {
+X return err_badarg();
+X }
+X p_arg[i] = getintvalue(w);
+X }
+X return 1;
+X }
+X else if (is_listobject(v)) {
+X if (getlistsize(v) != n) {
+X return err_badarg();
+X }
+X for (i = 0; i < n; i++) {
+X w = getlistitem(v, i);
+X if (!is_intobject(w)) {
+X return err_badarg();
+X }
+X p_arg[i] = getintvalue(w);
+X }
+X return 1;
+X }
+X else {
+X return err_badarg();
+X }
+X}
+X
+Xint
+Xgetidoublearray(args, nargs, i, n, p_arg)
+X object *args;
+X int nargs, i;
+X int n;
+X double *p_arg; /* [n] */
+X{
+X object *v, *w;
+X if (!getiobjectarg(args, nargs, i, &v))
+X return 0;
+X if (is_tupleobject(v)) {
+X if (gettuplesize(v) != n) {
+X return err_badarg();
+X }
+X for (i = 0; i < n; i++) {
+X w = gettupleitem(v, i);
+X if (!extractdouble(w, &p_arg[i]))
+X return 0;
+X }
+X return 1;
+X }
+X else if (is_listobject(v)) {
+X if (getlistsize(v) != n) {
+X return err_badarg();
+X }
+X for (i = 0; i < n; i++) {
+X w = getlistitem(v, i);
+X if (!extractdouble(w, &p_arg[i]))
+X return 0;
+X }
+X return 1;
+X }
+X else {
+X return err_badarg();
+X }
+X}
+X
+Xint
+Xgetifloatarray(args, nargs, i, n, p_arg)
+X object *args;
+X int nargs, i;
+X int n;
+X float *p_arg; /* [n] */
+X{
+X object *v, *w;
+X if (!getiobjectarg(args, nargs, i, &v))
+X return 0;
+X if (is_tupleobject(v)) {
+X if (gettuplesize(v) != n) {
+X return err_badarg();
+X }
+X for (i = 0; i < n; i++) {
+X w = gettupleitem(v, i);
+X if (!extractfloat(w, &p_arg[i]))
+X return 0;
+X }
+X return 1;
+X }
+X else if (is_listobject(v)) {
+X if (getlistsize(v) != n) {
+X return err_badarg();
+X }
+X for (i = 0; i < n; i++) {
+X w = getlistitem(v, i);
+X if (!extractfloat(w, &p_arg[i]))
+X return 0;
+X }
+X return 1;
+X }
+X else {
+X return err_badarg();
+X }
+X}
+EOF
+fi
+if test -s 'src/modsupport.c'
+then echo '*** I will not over-write existing file src/modsupport.c'
+else
+echo 'x - src/modsupport.c'
+sed 's/^X//' > 'src/modsupport.c' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/* Module support implementation */
+X
+X#include "allobjects.h"
+X#include "modsupport.h"
+X#include "import.h"
+X
+X
+Xobject *
+Xinitmodule(name, methods)
+X char *name;
+X struct methodlist *methods;
+X{
+X object *m, *d, *v;
+X struct methodlist *ml;
+X char namebuf[256];
+X if ((m = add_module(name)) == NULL) {
+X fprintf(stderr, "initializing module: %s\n", name);
+X fatal("can't create a module");
+X }
+X d = getmoduledict(m);
+X for (ml = methods; ml->ml_name != NULL; ml++) {
+X sprintf(namebuf, "%s.%s", name, ml->ml_name);
+X v = newmethodobject(strdup(namebuf), ml->ml_meth,
+X (object *)NULL);
+X /* XXX The strdup'ed memory is never freed */
+X if (v == NULL || dictinsert(d, ml->ml_name, v) != 0) {
+X fprintf(stderr, "initializing module: %s\n", name);
+X fatal("can't initialize module");
+X }
+X DECREF(v);
+X }
+X return m;
+X}
+X
+X
+X/* Argument list handling tools.
+X All return 1 for success, or call err_set*() and return 0 for failure */
+X
+Xint
+Xgetnoarg(v)
+X object *v;
+X{
+X if (v != NULL) {
+X return err_badarg();
+X }
+X return 1;
+X}
+X
+Xint
+Xgetintarg(v, a)
+X object *v;
+X int *a;
+X{
+X if (v == NULL || !is_intobject(v)) {
+X return err_badarg();
+X }
+X *a = getintvalue(v);
+X return 1;
+X}
+X
+Xint
+Xgetintintarg(v, a, b)
+X object *v;
+X int *a;
+X int *b;
+X{
+X if (v == NULL || !is_tupleobject(v) || gettuplesize(v) != 2) {
+X return err_badarg();
+X }
+X return getintarg(gettupleitem(v, 0), a) &&
+X getintarg(gettupleitem(v, 1), b);
+X}
+X
+Xint
+Xgetlongarg(v, a)
+X object *v;
+X long *a;
+X{
+X if (v == NULL || !is_intobject(v)) {
+X return err_badarg();
+X }
+X *a = getintvalue(v);
+X return 1;
+X}
+X
+Xint
+Xgetlonglongargs(v, a, b)
+X object *v;
+X long *a, *b;
+X{
+X if (v == NULL || !is_tupleobject(v) || gettuplesize(v) != 2) {
+X return err_badarg();
+X }
+X return getlongarg(gettupleitem(v, 0), a) &&
+X getlongarg(gettupleitem(v, 1), b);
+X}
+X
+Xint
+Xgetlonglongobjectargs(v, a, b, c)
+X object *v;
+X long *a, *b;
+X object **c;
+X{
+X if (v == NULL || !is_tupleobject(v) || gettuplesize(v) != 3) {
+X return err_badarg();
+X }
+X if (getlongarg(gettupleitem(v, 0), a) &&
+X getlongarg(gettupleitem(v, 1), b)) {
+X *c = gettupleitem(v, 2);
+X return 1;
+X }
+X else {
+X return err_badarg();
+X }
+X}
+X
+Xint
+Xgetstrarg(v, a)
+X object *v;
+X object **a;
+X{
+X if (v == NULL || !is_stringobject(v)) {
+X return err_badarg();
+X }
+X *a = v;
+X return 1;
+X}
+X
+Xint
+Xgetstrstrarg(v, a, b)
+X object *v;
+X object **a;
+X object **b;
+X{
+X if (v == NULL || !is_tupleobject(v) || gettuplesize(v) != 2) {
+X return err_badarg();
+X }
+X return getstrarg(gettupleitem(v, 0), a) &&
+X getstrarg(gettupleitem(v, 1), b);
+X}
+X
+Xint
+Xgetstrstrintarg(v, a, b, c)
+X object *v;
+X object **a;
+X object **b;
+X int *c;
+X{
+X if (v == NULL || !is_tupleobject(v) || gettuplesize(v) != 3) {
+X return err_badarg();
+X }
+X return getstrarg(gettupleitem(v, 0), a) &&
+X getstrarg(gettupleitem(v, 1), b) &&
+X getintarg(gettupleitem(v, 2), c);
+X}
+X
+Xint
+Xgetstrintarg(v, a, b)
+X object *v;
+X object **a;
+X int *b;
+X{
+X if (v == NULL || !is_tupleobject(v) || gettuplesize(v) != 2) {
+X return err_badarg();
+X }
+X return getstrarg(gettupleitem(v, 0), a) &&
+X getintarg(gettupleitem(v, 1), b);
+X}
+X
+Xint
+Xgetintstrarg(v, a, b)
+X object *v;
+X int *a;
+X object **b;
+X{
+X if (v == NULL || !is_tupleobject(v) || gettuplesize(v) != 2) {
+X return err_badarg();
+X }
+X return getintarg(gettupleitem(v, 0), a) &&
+X getstrarg(gettupleitem(v, 1), b);
+X}
+X
+Xint
+Xgetpointarg(v, a)
+X object *v;
+X int *a; /* [2] */
+X{
+X return getintintarg(v, a, a+1);
+X}
+X
+Xint
+Xget3pointarg(v, a)
+X object *v;
+X int *a; /* [6] */
+X{
+X if (v == NULL || !is_tupleobject(v) || gettuplesize(v) != 3) {
+X return err_badarg();
+X }
+X return getpointarg(gettupleitem(v, 0), a) &&
+X getpointarg(gettupleitem(v, 1), a+2) &&
+X getpointarg(gettupleitem(v, 2), a+4);
+X}
+X
+Xint
+Xgetrectarg(v, a)
+X object *v;
+X int *a; /* [2+2] */
+X{
+X if (v == NULL || !is_tupleobject(v) || gettuplesize(v) != 2) {
+X return err_badarg();
+X }
+X return getpointarg(gettupleitem(v, 0), a) &&
+X getpointarg(gettupleitem(v, 1), a+2);
+X}
+X
+Xint
+Xgetrectintarg(v, a)
+X object *v;
+X int *a; /* [4+1] */
+X{
+X if (v == NULL || !is_tupleobject(v) || gettuplesize(v) != 2) {
+X return err_badarg();
+X }
+X return getrectarg(gettupleitem(v, 0), a) &&
+X getintarg(gettupleitem(v, 1), a+4);
+X}
+X
+Xint
+Xgetpointintarg(v, a)
+X object *v;
+X int *a; /* [2+1] */
+X{
+X if (v == NULL || !is_tupleobject(v) || gettuplesize(v) != 2) {
+X return err_badarg();
+X }
+X return getpointarg(gettupleitem(v, 0), a) &&
+X getintarg(gettupleitem(v, 1), a+2);
+X}
+X
+Xint
+Xgetpointstrarg(v, a, b)
+X object *v;
+X int *a; /* [2] */
+X object **b;
+X{
+X if (v == NULL || !is_tupleobject(v) || gettuplesize(v) != 2) {
+X return err_badarg();
+X }
+X return getpointarg(gettupleitem(v, 0), a) &&
+X getstrarg(gettupleitem(v, 1), b);
+X}
+X
+Xint
+Xgetstrintintarg(v, a, b, c)
+X object *v;
+X object *a;
+X int *b, *c;
+X{
+X if (v == NULL || !is_tupleobject(v) || gettuplesize(v) != 3) {
+X return err_badarg();
+X }
+X return getstrarg(gettupleitem(v, 0), a) &&
+X getintarg(gettupleitem(v, 1), b) &&
+X getintarg(gettupleitem(v, 2), c);
+X}
+X
+Xint
+Xgetrectpointarg(v, a)
+X object *v;
+X int *a; /* [4+2] */
+X{
+X if (v == NULL || !is_tupleobject(v) || gettuplesize(v) != 2) {
+X return err_badarg();
+X }
+X return getrectarg(gettupleitem(v, 0), a) &&
+X getpointarg(gettupleitem(v, 1), a+4);
+X}
+X
+Xint
+Xgetlongtuplearg(args, a, n)
+X object *args;
+X long *a; /* [n] */
+X int n;
+X{
+X int i;
+X if (!is_tupleobject(args) || gettuplesize(args) != n) {
+X return err_badarg();
+X }
+X for (i = 0; i < n; i++) {
+X object *v = gettupleitem(args, i);
+X if (!is_intobject(v)) {
+X return err_badarg();
+X }
+X a[i] = getintvalue(v);
+X }
+X return 1;
+X}
+X
+Xint
+Xgetshorttuplearg(args, a, n)
+X object *args;
+X short *a; /* [n] */
+X int n;
+X{
+X int i;
+X if (!is_tupleobject(args) || gettuplesize(args) != n) {
+X return err_badarg();
+X }
+X for (i = 0; i < n; i++) {
+X object *v = gettupleitem(args, i);
+X if (!is_intobject(v)) {
+X return err_badarg();
+X }
+X a[i] = getintvalue(v);
+X }
+X return 1;
+X}
+X
+Xint
+Xgetlonglistarg(args, a, n)
+X object *args;
+X long *a; /* [n] */
+X int n;
+X{
+X int i;
+X if (!is_listobject(args) || getlistsize(args) != n) {
+X return err_badarg();
+X }
+X for (i = 0; i < n; i++) {
+X object *v = getlistitem(args, i);
+X if (!is_intobject(v)) {
+X return err_badarg();
+X }
+X a[i] = getintvalue(v);
+X }
+X return 1;
+X}
+X
+Xint
+Xgetshortlistarg(args, a, n)
+X object *args;
+X short *a; /* [n] */
+X int n;
+X{
+X int i;
+X if (!is_listobject(args) || getlistsize(args) != n) {
+X return err_badarg();
+X }
+X for (i = 0; i < n; i++) {
+X object *v = getlistitem(args, i);
+X if (!is_intobject(v)) {
+X return err_badarg();
+X }
+X a[i] = getintvalue(v);
+X }
+X return 1;
+X}
+EOF
+fi
+if test -s 'src/pythonmain.c'
+then echo '*** I will not over-write existing file src/pythonmain.c'
+else
+echo 'x - src/pythonmain.c'
+sed 's/^X//' > 'src/pythonmain.c' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/* Python interpreter main program */
+X
+X#include "patchlevel.h"
+X
+X#include "allobjects.h"
+X
+X#include "grammar.h"
+X#include "node.h"
+X#include "parsetok.h"
+X#include "graminit.h"
+X#include "errcode.h"
+X#include "sysmodule.h"
+X#include "compile.h"
+X#include "ceval.h"
+X#include "pythonrun.h"
+X#include "import.h"
+X
+Xextern char *getpythonpath();
+X
+Xextern grammar gram; /* From graminit.c */
+X
+X#ifdef DEBUG
+Xint debugging; /* Needed by parser.c */
+X#endif
+X
+Xmain(argc, argv)
+X int argc;
+X char **argv;
+X{
+X char *filename = NULL;
+X FILE *fp = stdin;
+X
+X initargs(&argc, &argv);
+X
+X if (argc > 1 && strcmp(argv[1], "-") != 0)
+X filename = argv[1];
+X
+X if (filename != NULL) {
+X if ((fp = fopen(filename, "r")) == NULL) {
+X fprintf(stderr, "python: can't open file '%s'\n",
+X filename);
+X exit(2);
+X }
+X }
+X
+X initall();
+X
+X setpythonpath(getpythonpath());
+X setpythonargv(argc-1, argv+1);
+X
+X goaway(run(fp, filename == NULL ? "<stdin>" : filename));
+X /*NOTREACHED*/
+X}
+X
+X/* Initialize all */
+X
+Xvoid
+Xinitall()
+X{
+X static int inited;
+X
+X if (inited)
+X return;
+X inited = 1;
+X
+X initimport();
+X
+X /* Modules 'builtin' and 'sys' are initialized here,
+X they are needed by random bits of the interpreter.
+X All other modules are optional and should be initialized
+X by the initcalls() of a specific configuration. */
+X
+X initbuiltin(); /* Also initializes builtin exceptions */
+X initsys();
+X
+X initcalls(); /* Configuration-dependent initializations */
+X
+X initintr(); /* For intrcheck() */
+X}
+X
+X/* Parse input from a file and execute it */
+X
+Xint
+Xrun(fp, filename)
+X FILE *fp;
+X char *filename;
+X{
+X if (filename == NULL)
+X filename = "???";
+X if (isatty(fileno(fp)))
+X return run_tty_loop(fp, filename);
+X else
+X return run_script(fp, filename);
+X}
+X
+Xint
+Xrun_tty_loop(fp, filename)
+X FILE *fp;
+X char *filename;
+X{
+X object *v;
+X int ret;
+X v = sysget("ps1");
+X if (v == NULL) {
+X sysset("ps1", v = newstringobject(">>> "));
+X XDECREF(v);
+X }
+X v = sysget("ps2");
+X if (v == NULL) {
+X sysset("ps2", v = newstringobject("... "));
+X XDECREF(v);
+X }
+X for (;;) {
+X ret = run_tty_1(fp, filename);
+X#ifdef REF_DEBUG
+X fprintf(stderr, "[%ld refs]\n", ref_total);
+X#endif
+X if (ret == E_EOF)
+X return 0;
+X /*
+X if (ret == E_NOMEM)
+X return -1;
+X */
+X }
+X}
+X
+Xint
+Xrun_tty_1(fp, filename)
+X FILE *fp;
+X char *filename;
+X{
+X object *m, *d, *v, *w;
+X node *n;
+X char *ps1, *ps2;
+X int err;
+X v = sysget("ps1");
+X w = sysget("ps2");
+X if (v != NULL && is_stringobject(v)) {
+X INCREF(v);
+X ps1 = getstringvalue(v);
+X }
+X else {
+X v = NULL;
+X ps1 = "";
+X }
+X if (w != NULL && is_stringobject(w)) {
+X INCREF(w);
+X ps2 = getstringvalue(w);
+X }
+X else {
+X w = NULL;
+X ps2 = "";
+X }
+X err = parsefile(fp, filename, &gram, single_input, ps1, ps2, &n);
+X XDECREF(v);
+X XDECREF(w);
+X if (err == E_EOF)
+X return E_EOF;
+X if (err != E_DONE) {
+X err_input(err);
+X print_error();
+X return err;
+X }
+X m = add_module("__main__");
+X if (m == NULL)
+X return -1;
+X d = getmoduledict(m);
+X v = run_node(n, filename, d, d);
+X flushline();
+X if (v == NULL) {
+X print_error();
+X return -1;
+X }
+X DECREF(v);
+X return 0;
+X}
+X
+Xint
+Xrun_script(fp, filename)
+X FILE *fp;
+X char *filename;
+X{
+X object *m, *d, *v;
+X m = add_module("__main__");
+X if (m == NULL)
+X return -1;
+X d = getmoduledict(m);
+X v = run_file(fp, filename, file_input, d, d);
+X flushline();
+X if (v == NULL) {
+X print_error();
+X return -1;
+X }
+X DECREF(v);
+X return 0;
+X}
+X
+Xvoid
+Xprint_error()
+X{
+X object *exception, *v;
+X err_get(&exception, &v);
+X fprintf(stderr, "Unhandled exception: ");
+X printobject(exception, stderr, PRINT_RAW);
+X if (v != NULL && v != None) {
+X fprintf(stderr, ": ");
+X printobject(v, stderr, PRINT_RAW);
+X }
+X fprintf(stderr, "\n");
+X XDECREF(exception);
+X XDECREF(v);
+X printtraceback(stderr);
+X}
+X
+Xobject *
+Xrun_string(str, start, globals, locals)
+X char *str;
+X int start;
+X /*dict*/object *globals, *locals;
+X{
+X node *n;
+X int err;
+X err = parse_string(str, start, &n);
+X return run_err_node(err, n, "<string>", globals, locals);
+X}
+X
+Xobject *
+Xrun_file(fp, filename, start, globals, locals)
+X FILE *fp;
+X char *filename;
+X int start;
+X /*dict*/object *globals, *locals;
+X{
+X node *n;
+X int err;
+X err = parse_file(fp, filename, start, &n);
+X return run_err_node(err, n, filename, globals, locals);
+X}
+X
+Xobject *
+Xrun_err_node(err, n, filename, globals, locals)
+X int err;
+X node *n;
+X char *filename;
+X /*dict*/object *globals, *locals;
+X{
+X if (err != E_DONE) {
+X err_input(err);
+X return NULL;
+X }
+X return run_node(n, filename, globals, locals);
+X}
+X
+Xobject *
+Xrun_node(n, filename, globals, locals)
+X node *n;
+X char *filename;
+X /*dict*/object *globals, *locals;
+X{
+X if (globals == NULL) {
+X globals = getglobals();
+X if (locals == NULL)
+X locals = getlocals();
+X }
+X else {
+X if (locals == NULL)
+X locals = globals;
+X }
+X return eval_node(n, filename, globals, locals);
+X}
+X
+Xobject *
+Xeval_node(n, filename, globals, locals)
+X node *n;
+X char *filename;
+X object *globals;
+X object *locals;
+X{
+X codeobject *co;
+X object *v;
+X co = compile(n, filename);
+X freetree(n);
+X if (co == NULL)
+X return NULL;
+X v = eval_code(co, globals, locals, (object *)NULL);
+X DECREF(co);
+X return v;
+X}
+X
+X/* Simplified interface to parsefile */
+X
+Xint
+Xparse_file(fp, filename, start, n_ret)
+X FILE *fp;
+X char *filename;
+X int start;
+X node **n_ret;
+X{
+X return parsefile(fp, filename, &gram, start,
+X (char *)0, (char *)0, n_ret);
+X}
+X
+X/* Simplified interface to parsestring */
+X
+Xint
+Xparse_string(str, start, n_ret)
+X char *str;
+X int start;
+X node **n_ret;
+X{
+X int err = parsestring(str, &gram, start, n_ret);
+X /* Don't confuse early end of string with early end of input */
+X if (err == E_EOF)
+X err = E_SYNTAX;
+X return err;
+X}
+X
+X/* Print fatal error message and abort */
+X
+Xvoid
+Xfatal(msg)
+X char *msg;
+X{
+X fprintf(stderr, "Fatal error: %s\n", msg);
+X abort();
+X}
+X
+X/* Clean up and exit */
+X
+Xvoid
+Xgoaway(sts)
+X int sts;
+X{
+X flushline();
+X
+X /* XXX Call doneimport() before donecalls(), since donecalls()
+X calls wdone(), and doneimport() may close windows */
+X doneimport();
+X donecalls();
+X
+X err_clear();
+X
+X#ifdef REF_DEBUG
+X fprintf(stderr, "[%ld refs]\n", ref_total);
+X#endif
+X
+X#ifdef THINK_C_3_0
+X if (sts == 0)
+X Click_On(0);
+X#endif
+X
+X#ifdef TRACE_REFS
+X if (askyesno("Print left references?")) {
+X#ifdef THINK_C_3_0
+X Click_On(1);
+X#endif
+X printrefs(stderr);
+X }
+X#endif /* TRACE_REFS */
+X
+X exit(sts);
+X /*NOTREACHED*/
+X}
+X
+Xstatic
+Xfinaloutput()
+X{
+X#ifdef TRACE_REFS
+X if (!askyesno("Print left references?"))
+X return;
+X#ifdef THINK_C_3_0
+X Click_On(1);
+X#endif
+X printrefs(stderr);
+X#endif /* TRACE_REFS */
+X}
+X
+X/* Ask a yes/no question */
+X
+Xstatic int
+Xaskyesno(prompt)
+X char *prompt;
+X{
+X char buf[256];
+X
+X printf("%s [ny] ", prompt);
+X if (fgets(buf, sizeof buf, stdin) == NULL)
+X return 0;
+X return buf[0] == 'y' || buf[0] == 'Y';
+X}
+X
+X#ifdef THINK_C_3_0
+X
+X/* Check for file descriptor connected to interactive device.
+X Pretend that stdin is always interactive, other files never. */
+X
+Xint
+Xisatty(fd)
+X int fd;
+X{
+X return fd == fileno(stdin);
+X}
+X
+X#endif
+X
+X/* XXX WISH LIST
+X
+X - possible new types:
+X - iterator (for range, keys, ...)
+X - improve interpreter error handling, e.g., true tracebacks
+X - save precompiled modules on file?
+X - fork threads, locking
+X - allow syntax extensions
+X*/
+X
+X/* "Floccinaucinihilipilification" */
+EOF
+fi
+if test -s 'src/stringobject.c'
+then echo '*** I will not over-write existing file src/stringobject.c'
+else
+echo 'x - src/stringobject.c'
+sed 's/^X//' > 'src/stringobject.c' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/* String object implementation */
+X
+X#include "allobjects.h"
+X
+Xobject *
+Xnewsizedstringobject(str, size)
+X char *str;
+X int size;
+X{
+X register stringobject *op = (stringobject *)
+X malloc(sizeof(stringobject) + size * sizeof(char));
+X if (op == NULL)
+X return err_nomem();
+X NEWREF(op);
+X op->ob_type = &Stringtype;
+X op->ob_size = size;
+X if (str != NULL)
+X memcpy(op->ob_sval, str, size);
+X op->ob_sval[size] = '\0';
+X return (object *) op;
+X}
+X
+Xobject *
+Xnewstringobject(str)
+X char *str;
+X{
+X register unsigned int size = strlen(str);
+X register stringobject *op = (stringobject *)
+X malloc(sizeof(stringobject) + size * sizeof(char));
+X if (op == NULL)
+X return err_nomem();
+X NEWREF(op);
+X op->ob_type = &Stringtype;
+X op->ob_size = size;
+X strcpy(op->ob_sval, str);
+X return (object *) op;
+X}
+X
+Xunsigned int
+Xgetstringsize(op)
+X register object *op;
+X{
+X if (!is_stringobject(op)) {
+X err_badcall();
+X return -1;
+X }
+X return ((stringobject *)op) -> ob_size;
+X}
+X
+X/*const*/ char *
+Xgetstringvalue(op)
+X register object *op;
+X{
+X if (!is_stringobject(op)) {
+X err_badcall();
+X return NULL;
+X }
+X return ((stringobject *)op) -> ob_sval;
+X}
+X
+X/* Methods */
+X
+Xstatic void
+Xstringprint(op, fp, flags)
+X stringobject *op;
+X FILE *fp;
+X int flags;
+X{
+X int i;
+X char c;
+X if (flags & PRINT_RAW) {
+X fwrite(op->ob_sval, 1, (int) op->ob_size, fp);
+X return;
+X }
+X fprintf(fp, "'");
+X for (i = 0; i < op->ob_size; i++) {
+X c = op->ob_sval[i];
+X if (c == '\'' || c == '\\')
+X fprintf(fp, "\\%c", c);
+X else if (c < ' ' || c >= 0177)
+X fprintf(fp, "\\%03o", c&0377);
+X else
+X putc(c, fp);
+X }
+X fprintf(fp, "'");
+X}
+X
+Xstatic object *
+Xstringrepr(op)
+X register stringobject *op;
+X{
+X /* XXX overflow? */
+X int newsize = 2 + 4 * op->ob_size * sizeof(char);
+X object *v = newsizedstringobject((char *)NULL, newsize);
+X if (v == NULL) {
+X return err_nomem();
+X }
+X else {
+X register int i;
+X register char c;
+X register char *p;
+X NEWREF(v);
+X v->ob_type = &Stringtype;
+X ((stringobject *)v)->ob_size = newsize;
+X p = ((stringobject *)v)->ob_sval;
+X *p++ = '\'';
+X for (i = 0; i < op->ob_size; i++) {
+X c = op->ob_sval[i];
+X if (c == '\'' || c == '\\')
+X *p++ = '\\', *p++ = c;
+X else if (c < ' ' || c >= 0177) {
+X sprintf(p, "\\%03o", c&0377);
+X while (*p != '\0')
+X p++;
+X
+X }
+X else
+X *p++ = c;
+X }
+X *p++ = '\'';
+X *p = '\0';
+X resizestring(&v, (int) (p - ((stringobject *)v)->ob_sval));
+X return v;
+X }
+X}
+X
+Xstatic int
+Xstringlength(a)
+X stringobject *a;
+X{
+X return a->ob_size;
+X}
+X
+Xstatic object *
+Xstringconcat(a, bb)
+X register stringobject *a;
+X register object *bb;
+X{
+X register unsigned int size;
+X register stringobject *op;
+X if (!is_stringobject(bb)) {
+X err_badarg();
+X return NULL;
+X }
+X#define b ((stringobject *)bb)
+X /* Optimize cases with empty left or right operand */
+X if (a->ob_size == 0) {
+X INCREF(bb);
+X return bb;
+X }
+X if (b->ob_size == 0) {
+X INCREF(a);
+X return (object *)a;
+X }
+X size = a->ob_size + b->ob_size;
+X op = (stringobject *)
+X malloc(sizeof(stringobject) + size * sizeof(char));
+X if (op == NULL)
+X return err_nomem();
+X NEWREF(op);
+X op->ob_type = &Stringtype;
+X op->ob_size = size;
+X memcpy(op->ob_sval, a->ob_sval, (int) a->ob_size);
+X memcpy(op->ob_sval + a->ob_size, b->ob_sval, (int) b->ob_size);
+X op->ob_sval[size] = '\0';
+X return (object *) op;
+X#undef b
+X}
+X
+Xstatic object *
+Xstringrepeat(a, n)
+X register stringobject *a;
+X register int n;
+X{
+X register int i;
+X register unsigned int size;
+X register stringobject *op;
+X if (n < 0)
+X n = 0;
+X size = a->ob_size * n;
+X if (size == a->ob_size) {
+X INCREF(a);
+X return (object *)a;
+X }
+X op = (stringobject *)
+X malloc(sizeof(stringobject) + size * sizeof(char));
+X if (op == NULL)
+X return err_nomem();
+X NEWREF(op);
+X op->ob_type = &Stringtype;
+X op->ob_size = size;
+X for (i = 0; i < size; i += a->ob_size)
+X memcpy(op->ob_sval+i, a->ob_sval, (int) a->ob_size);
+X op->ob_sval[size] = '\0';
+X return (object *) op;
+X}
+X
+X/* String slice a[i:j] consists of characters a[i] ... a[j-1] */
+X
+Xstatic object *
+Xstringslice(a, i, j)
+X register stringobject *a;
+X register int i, j; /* May be negative! */
+X{
+X if (i < 0)
+X i = 0;
+X if (j < 0)
+X j = 0; /* Avoid signed/unsigned bug in next line */
+X if (j > a->ob_size)
+X j = a->ob_size;
+X if (i == 0 && j == a->ob_size) { /* It's the same as a */
+X INCREF(a);
+X return (object *)a;
+X }
+X if (j < i)
+X j = i;
+X return newsizedstringobject(a->ob_sval + i, (int) (j-i));
+X}
+X
+Xstatic object *
+Xstringitem(a, i)
+X stringobject *a;
+X register int i;
+X{
+X if (i < 0 || i >= a->ob_size) {
+X err_setstr(IndexError, "string index out of range");
+X return NULL;
+X }
+X return stringslice(a, i, i+1);
+X}
+X
+Xstatic int
+Xstringcompare(a, b)
+X stringobject *a, *b;
+X{
+X int len_a = a->ob_size, len_b = b->ob_size;
+X int min_len = (len_a < len_b) ? len_a : len_b;
+X int cmp = memcmp(a->ob_sval, b->ob_sval, min_len);
+X if (cmp != 0)
+X return cmp;
+X return (len_a < len_b) ? -1 : (len_a > len_b) ? 1 : 0;
+X}
+X
+Xstatic sequence_methods string_as_sequence = {
+X stringlength, /*tp_length*/
+X stringconcat, /*tp_concat*/
+X stringrepeat, /*tp_repeat*/
+X stringitem, /*tp_item*/
+X stringslice, /*tp_slice*/
+X 0, /*tp_ass_item*/
+X 0, /*tp_ass_slice*/
+X};
+X
+Xtypeobject Stringtype = {
+X OB_HEAD_INIT(&Typetype)
+X 0,
+X "string",
+X sizeof(stringobject),
+X sizeof(char),
+X free, /*tp_dealloc*/
+X stringprint, /*tp_print*/
+X 0, /*tp_getattr*/
+X 0, /*tp_setattr*/
+X stringcompare, /*tp_compare*/
+X stringrepr, /*tp_repr*/
+X 0, /*tp_as_number*/
+X &string_as_sequence, /*tp_as_sequence*/
+X 0, /*tp_as_mapping*/
+X};
+X
+Xvoid
+Xjoinstring(pv, w)
+X register object **pv;
+X register object *w;
+X{
+X register object *v;
+X if (*pv == NULL || w == NULL || !is_stringobject(*pv))
+X return;
+X v = stringconcat((stringobject *) *pv, w);
+X DECREF(*pv);
+X *pv = v;
+X}
+X
+X/* The following function breaks the notion that strings are immutable:
+X it changes the size of a string. We get away with this only if there
+X is only one module referencing the object. You can also think of it
+X as creating a new string object and destroying the old one, only
+X more efficiently. In any case, don't use this if the string may
+X already be known to some other part of the code... */
+X
+Xint
+Xresizestring(pv, newsize)
+X object **pv;
+X int newsize;
+X{
+X register object *v;
+X register stringobject *sv;
+X v = *pv;
+X if (!is_stringobject(v) || v->ob_refcnt != 1) {
+X *pv = 0;
+X DECREF(v);
+X err_badcall();
+X return -1;
+X }
+X /* XXX UNREF/NEWREF interface should be more symmetrical */
+X#ifdef REF_DEBUG
+X --ref_total;
+X#endif
+X UNREF(v);
+X *pv = (object *)
+X realloc((char *)v,
+X sizeof(stringobject) + newsize * sizeof(char));
+X if (*pv == NULL) {
+X DEL(v);
+X err_nomem();
+X return -1;
+X }
+X NEWREF(*pv);
+X sv = (stringobject *) *pv;
+X sv->ob_size = newsize;
+X sv->ob_sval[newsize] = '\0';
+X return 0;
+X}
+EOF
+fi
+echo 'Part 12 out of 21 of pack.out complete.'
+exit 0
diff --git a/shar/python-0.9.1-13-21.shar b/shar/python-0.9.1-13-21.shar
new file mode 100644
index 0000000..1d0e2ec
--- /dev/null
+++ b/shar/python-0.9.1-13-21.shar
@@ -0,0 +1,2811 @@
+: This is a shell archive.
+: Extract with 'sh this_file'.
+:
+: Extract part 01 first since it makes all directories
+echo 'Start of pack.out, part 13 out of 21:'
+if test -s 'demo/sgi/audio_stdwin/jukebox.py'
+then echo '*** I will not over-write existing file demo/sgi/audio_stdwin/jukebox.py'
+else
+echo 'x - demo/sgi/audio_stdwin/jukebox.py'
+sed 's/^X//' > 'demo/sgi/audio_stdwin/jukebox.py' << 'EOF'
+X#! /ufs/guido/bin/sgi/python
+X
+X# JUKEBOX: browse directories full of sampled sound files.
+X#
+X# One or more "list windows" display the files and subdirectories of
+X# the arguments. Double-clicking on a subdirectory opens a new window
+X# displaying its contents (and so on recursively). Double clicking
+X# on a file plays it as a sound file (assuming it is one).
+X#
+X# Playing is asynchronous: the application keeps listening to events
+X# while the sample is playing, so you can change the volume (gain)
+X# during playing, cancel playing or start a new sample right away.
+X#
+X# The control window displays the current output gain and a primitive
+X# "stop button" to cancel the current play request.
+X#
+X# Sound files must currently be in Dik Winter's compressed Mac format.
+X# Since decompression is costly, decompressed samples are saved in
+X# /usr/tmp/@j* until the application is left. The files are read
+X# afresh each time, though.
+X
+Ximport audio
+Ximport sunaudio
+Ximport commands
+Ximport getopt
+Ximport path
+Ximport posix
+Ximport rand
+Ximport stdwin
+Xfrom stdwinevents import *
+Ximport string
+Ximport sys
+X
+Xfrom WindowParent import WindowParent
+Xfrom HVSplit import VSplit
+Xfrom Buttons import PushButton
+Xfrom Sliders import ComplexSlider
+X
+X# Pathnames
+X
+XHOME_BIN_SGI = '/ufs/guido/bin/sgi/' # Directory where macsound2sgi lives
+XDEF_DB = '/ufs/dik/sounds/Mac/HCOM' # Default directory of sounds
+X
+X
+X# Global variables
+X
+Xclass struct(): pass # Class to define featureless structures
+X
+XG = struct() # Holds writable global variables
+X
+X
+X# Main program
+X
+Xdef main():
+X G.synchronous = 0 # If set, use synchronous audio.write()
+X G.debug = 0 # If set, print debug messages
+X G.gain = 75 # Output gain
+X G.rate = 3 # Sampling rate
+X G.busy = 0 # Set while asynchronous playing is active
+X G.windows = [] # List of open windows (except control)
+X G.mode = 'mac' # Macintosh mode
+X G.tempprefix = '/usr/tmp/@j' + `rand.rand()` + '-'
+X #
+X optlist, args = getopt.getopt(sys.argv[1:], 'dg:r:sSa')
+X for optname, optarg in optlist:
+X if optname = '-d':
+X G.debug = 1
+X elif optname = '-g':
+X G.gain = string.atoi(optarg)
+X if not (0 < G.gain < 256):
+X raise optarg.error, '-g gain out of range'
+X elif optname = '-r':
+X G.rate = string.atoi(optarg)
+X if not (1 <= G.rate <= 3):
+X raise optarg.error, '-r rate out of range'
+X elif optname = '-s':
+X G.synchronous = 1
+X elif optname = '-S':
+X G.mode = 'sgi'
+X elif optname = '-a':
+X G.mode = 'sun'
+X #
+X if not args:
+X args = [DEF_DB]
+X #
+X G.cw = opencontrolwindow()
+X for dirname in args:
+X G.windows.append(openlistwindow(dirname))
+X #
+X #
+X savegain = audio.getoutgain()
+X try:
+X # Initialize stdaudio
+X audio.setoutgain(0)
+X audio.start_playing('')
+X dummy = audio.wait_playing()
+X audio.setoutgain(0)
+X maineventloop()
+X finally:
+X audio.setoutgain(savegain)
+X audio.done()
+X clearcache()
+X
+Xdef maineventloop():
+X mouse_events = WE_MOUSE_DOWN, WE_MOUSE_MOVE, WE_MOUSE_UP
+X while G.windows:
+X type, w, detail = event = stdwin.getevent()
+X if w = G.cw.win:
+X if type = WE_CLOSE:
+X return
+X G.cw.dispatch(event)
+X else:
+X if type = WE_DRAW:
+X w.drawproc(w, detail)
+X elif type in mouse_events:
+X w.mouse(w, type, detail)
+X elif type = WE_CLOSE:
+X w.close(w)
+X del w, event
+X else:
+X if G.debug: print type, w, detail
+X
+X# Control window -- to set gain and cancel play operations in progress
+X
+Xdef opencontrolwindow():
+X cw = WindowParent().create('Jukebox', (0, 0))
+X v = VSplit().create(cw)
+X #
+X gain = ComplexSlider().define(v)
+X gain.setminvalmax(0, G.gain, 255)
+X gain.settexts(' ', ' ')
+X gain.sethook(gain_setval_hook)
+X #
+X stop = PushButton().definetext(v, 'Stop')
+X stop.hook = stop_hook
+X #
+X cw.realize()
+X return cw
+X
+Xdef gain_setval_hook(self):
+X G.gain = self.val
+X if G.busy: audio.setoutgain(G.gain)
+X
+Xdef stop_hook(self):
+X if G.busy:
+X audio.setoutgain(0)
+X dummy = audio.stop_playing()
+X G.busy = 0
+X
+X
+X# List windows -- to display list of files and subdirectories
+X
+Xdef openlistwindow(dirname):
+X list = posix.listdir(dirname)
+X list.sort()
+X i = 0
+X while i < len(list):
+X if list[i] = '.' or list[i] = '..':
+X del list[i]
+X else:
+X i = i+1
+X for i in range(len(list)):
+X name = list[i]
+X if path.isdir(path.cat(dirname, name)):
+X list[i] = list[i] + '/'
+X width = maxwidth(list)
+X width = width + stdwin.textwidth(' ') # XXX X11 stdwin bug workaround
+X height = len(list) * stdwin.lineheight()
+X stdwin.setdefwinsize(width, min(height, 500))
+X w = stdwin.open(dirname)
+X stdwin.setdefwinsize(0, 0)
+X w.setdocsize(width, height)
+X w.drawproc = drawlistwindow
+X w.mouse = mouselistwindow
+X w.close = closelistwindow
+X w.dirname = dirname
+X w.list = list
+X w.selected = -1
+X return w
+X
+Xdef maxwidth(list):
+X width = 1
+X for name in list:
+X w = stdwin.textwidth(name)
+X if w > width: width = w
+X return width
+X
+Xdef drawlistwindow(w, area):
+X d = w.begindrawing()
+X d.erase((0, 0), (1000, 10000))
+X lh = d.lineheight()
+X h, v = 0, 0
+X for name in w.list:
+X d.text((h, v), name)
+X v = v + lh
+X showselection(w, d)
+X
+Xdef hideselection(w, d):
+X if w.selected >= 0:
+X invertselection(w, d)
+X
+Xdef showselection(w, d):
+X if w.selected >= 0:
+X invertselection(w, d)
+X
+Xdef invertselection(w, d):
+X lh = d.lineheight()
+X h1, v1 = p1 = 0, w.selected*lh
+X h2, v2 = p2 = 1000, v1 + lh
+X d.invert(p1, p2)
+X
+Xdef mouselistwindow(w, type, detail):
+X (h, v), clicks, button = detail[:3]
+X d = w.begindrawing()
+X lh = d.lineheight()
+X if 0 <= v < lh*len(w.list):
+X i = v / lh
+X else:
+X i = -1
+X if w.selected <> i:
+X hideselection(w, d)
+X w.selected = i
+X showselection(w, d)
+X if type = WE_MOUSE_DOWN and clicks >= 2 and i >= 0:
+X name = path.cat(w.dirname, w.list[i])
+X if name[-1:] = '/':
+X if clicks = 2:
+X G.windows.append(openlistwindow(name[:-1]))
+X else:
+X playfile(name)
+X
+Xdef closelistwindow(w):
+X remove(G.windows, w)
+X
+Xdef remove(list, item):
+X for i in range(len(list)):
+X if list[i] = item:
+X del list[i]
+X break
+X
+X
+X# Playing tools
+X
+Xcache = {}
+X
+Xdef clearcache():
+X for x in cache.keys():
+X try:
+X sts = posix.system('rm -f ' + cache[x])
+X if sts:
+X print cmd
+X print 'Exit status', sts
+X except:
+X print cmd
+X print 'Exception?!'
+X del cache[x]
+X
+Xdef playfile(name):
+X if G.mode <> 'mac':
+X tempname = name
+X elif cache.has_key(name):
+X tempname = cache[name]
+X else:
+X tempname = G.tempprefix + `rand.rand()`
+X cmd = HOME_BIN_SGI + 'macsound2sgi'
+X cmd = cmd + ' ' + commands.mkarg(name)
+X cmd = cmd + ' >' + tempname
+X if G.debug: print cmd
+X sts = posix.system(cmd)
+X if sts:
+X print cmd
+X print 'Exit status', sts
+X stdwin.fleep()
+X return
+X cache[name] = tempname
+X fp = open(tempname, 'r')
+X try:
+X hdr = sunaudio.gethdr(fp)
+X except sunaudio.error, msg:
+X hdr = ()
+X if hdr:
+X data_size = hdr[0]
+X data = fp.read(data_size)
+X # XXX this doesn't work yet, need to convert from uLAW!!!
+X del fp
+X else:
+X del fp
+X data = readfile(tempname)
+X if G.debug: print len(data), 'bytes read from', tempname
+X if G.busy:
+X G.busy = 0
+X dummy = audio.stop_playing()
+X #
+X # Completely reset the audio device
+X audio.setrate(G.rate)
+X audio.setduration(0)
+X audio.setoutgain(G.gain)
+X #
+X if G.synchronous:
+X audio.write(data)
+X audio.setoutgain(0)
+X else:
+X try:
+X audio.start_playing(data)
+X G.busy = 1
+X except:
+X stdwin.fleep()
+X del data
+X
+Xdef readfile(filename):
+X return readfp(open(filename, 'r'))
+X
+Xdef readfp(fp):
+X data = ''
+X while 1:
+X buf = fp.read(102400) # Reads most samples in one fell swoop
+X if not buf:
+X return data
+X data = data + buf
+X
+Xmain()
+EOF
+chmod +x 'demo/sgi/audio_stdwin/jukebox.py'
+fi
+if test -s 'demo/sgi/gl_panel/twoview/twoview.py'
+then echo '*** I will not over-write existing file demo/sgi/gl_panel/twoview/twoview.py'
+else
+echo 'x - demo/sgi/gl_panel/twoview/twoview.py'
+sed 's/^X//' > 'demo/sgi/gl_panel/twoview/twoview.py' << 'EOF'
+X#! /ufs/guido/bin/sgi/python
+X
+X# A demo of GL's viewing transformations, showing two views on one scene.
+X# Requires the NASA AMES Panel Library. Requires Z buffer.
+X
+Xfrom gl import *
+Xfrom GL import *
+Ximport panel
+Xfrom math import sin, cos, pi
+X
+Xinf = 1000000.0
+Xfar = 1000.0
+Xnear = 100.0
+X
+Xdef main():
+X foreground()
+X #
+X keepaspect(1, 1)
+X prefposition(10, 610, 10, 610)
+X obswid = winopen('Observer View')
+X doublebuffer()
+X RGBmode()
+X gconfig()
+X #
+X keepaspect(1, 1)
+X prefposition(10, 310, 650, 950)
+X topwid = winopen('Top View')
+X doublebuffer()
+X RGBmode()
+X gconfig()
+X #
+X panels = panel.defpanellist('observer.s')
+X panels = panels + panel.defpanellist('camera.s')
+X panels = panels + panel.defpanellist('topview.s')
+X #
+X p = panels[0]
+X q = panels[1]
+X r = panels[2]
+X #
+X p.farclip = q.farclip
+X p.nearclip = q.nearclip
+X p.zoom = q.zoom
+X p.quitbutton = q.quitbutton
+X #
+X p.xpos = r.xpos
+X p.zpos = r.zpos
+X p.direction = r.direction
+X #
+X p.direction.winds = 1.0 # allow full rotation
+X #
+X def quit(act):
+X import sys
+X sys.exit(0)
+X p.quitbutton.downfunc = quit
+X #
+X p.left.back = p
+X p.fast_left.back = p
+X p.right.back = p
+X p.fast_right.back = p
+X p.forward.back = p
+X p.fast_forward.back = p
+X p.reverse.back = p
+X p.fast_reverse.back = p
+X p.up.back = p
+X p.down.back = p
+X #
+X p.left.activefunc = left
+X p.fast_left.activefunc = fast_left
+X p.right.activefunc = right
+X p.fast_right.activefunc = fast_right
+X p.forward.activefunc = forward
+X p.fast_forward.activefunc = fast_forward
+X p.reverse.activefunc = reverse
+X p.fast_reverse.activefunc = fast_reverse
+X p.up.activefunc = up
+X p.down.activefunc = down
+X #
+X makeobjects()
+X #
+X drawall(p, obswid, topwid)
+X panel.needredraw()
+X while 1:
+X act = panel.dopanel()
+X if panel.userredraw() or act:
+X drawall(p, obswid, topwid)
+X
+Xdef left(a):
+X doturn(a.back, 0.01)
+X
+Xdef fast_left(a):
+X doturn(a.back, 0.1)
+X
+Xdef right(a):
+X doturn(a.back, -0.01)
+X
+Xdef fast_right(a):
+X doturn(a.back, -0.1)
+X
+Xdef doturn(p, angle):
+X alpha = lookangle(p) + angle
+X # Reverse the following assignment:
+X # alpha = pi*1.5 - p.direction.val*2.0*pi
+X val = (pi*1.5 - alpha) / 2.0 / pi
+X while val < 0.0: val = val + 1.0
+X while val > 1.0: val = val - 1.0
+X p.direction.val = val
+X p.direction.fixact()
+X
+Xdef forward(a):
+X dostep(a.back, 1.0)
+X
+Xdef fast_forward(a):
+X dostep(a.back, 10.0)
+X
+Xdef reverse(a):
+X dostep(a.back, -1.0)
+X
+Xdef fast_reverse(a):
+X dostep(a.back, -10.0)
+X
+Xdef dostep(p, step):
+X x, y, z = observerpos(p)
+X alpha = lookangle(p)
+X x = x + step*cos(alpha)
+X z = z - step*sin(alpha)
+X # Reverse the following assignments:
+X # x = 2.0 * p.xpos.val * near - near
+X # z = near - 2.0 * p.zpos.val * near
+X p.xpos.val = (x + near) / 2.0 / near
+X p.zpos.val = - (z - near) / 2.0 / near
+X p.xpos.fixact()
+X p.zpos.fixact()
+X
+Xdef up(a):
+X doup(a.back, 0.2)
+X
+Xdef down(a):
+X doup(a.back, -0.2)
+X
+Xdef doup(p, step):
+X x, y, z = observerpos(p)
+X y = y + step
+X # Reverse:
+X # y = p.ypos.val * near
+X p.ypos.val = y/near
+X p.ypos.fixact()
+X
+Xdef drawall(p, obswid, topwid):
+X #
+X winset(obswid)
+X obsview(p)
+X drawscene()
+X swapbuffers()
+X #
+X winset(topwid)
+X topview(p)
+X drawscene()
+X drawobserver(p)
+X swapbuffers()
+X
+Xdef drawobserver(p):
+X x, y, z = observerpos(p)
+X alpha = lookangle(p)
+X fov = 2.0 + 1798.0 * p.zoom.val
+X beta = fov*pi/3600.0 # Half fov, expressed in radians
+X #
+X c3i(0, 255, 0)
+X #
+X move(x, y, z)
+X x1 = x + inf*cos(alpha+beta)
+X y1 = y
+X z1 = z - inf*sin(alpha+beta)
+X draw(x1, y1, z1)
+X #
+X move(x, y, z)
+X x1 = x + inf*cos(alpha-beta)
+X y1 = y
+X z1 = z - inf*sin(alpha-beta)
+X draw(x1, y1, z1)
+X
+Xdef observerlookat(p):
+X x, y, z = observerpos(p)
+X alpha = lookangle(p)
+X return x, y, z, x+near*cos(alpha), y, z-near*sin(alpha), 0
+X
+Xdef observerpos(p):
+X x = 2.0 * p.xpos.val * near - near
+X y = p.ypos.val * near
+X z = near - 2.0 * p.zpos.val * near
+X return x, y, z
+X
+Xdef lookangle(p):
+X return pi*1.5 - p.direction.val*2.0*pi
+X
+Xidmat = 1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1
+X
+Xdef topview(p):
+X mmode(MVIEWING)
+X ortho(-far, far, -far, far, far, -far)
+X loadmatrix(idmat)
+X rotate(900, 'x')
+X
+Xdef obsview(p):
+X fov = 2.0 + 1798.0 * p.zoom.val
+X nearclip = p.nearclip.val * 10.0
+X farclip = p.farclip.val * 10.0*far
+X aspectratio = 1.0
+X mmode(MVIEWING)
+X perspective(int(fov), aspectratio, nearclip, farclip)
+X loadmatrix(idmat)
+X lookat(observerlookat(p))
+X
+Xdef drawscene():
+X #
+X # clear window
+X #
+X c3i(0, 0, 0)
+X clear()
+X #
+X # turn on z buffering and clear it
+X #
+X zbuffer(TRUE)
+X zclear()
+X #
+X # dark blue sky (depending on your gamma value!)
+X #
+X c3i(0, 0, 150)
+X callobj(41)
+X #
+X # bright red near and far units circle
+X # (use rotate since circ() always draws in x-y plane)
+X #
+X c3i(255, 0, 0)
+X pushmatrix()
+X rotate(900, 'x')
+X circ(0.0, 0.0, near)
+X circ(0.0, 0.0, far)
+X popmatrix()
+X #
+X # bright white striping
+X #
+X c3i(255, 255, 200)
+X callobj(42)
+X #
+X # building (does its own colors)
+X #
+X building()
+X #
+X # some other objects
+X #
+X dice()
+X
+Xdef makeobjects():
+X #
+X # sky object
+X #
+X makeobj(41)
+X pmv(-inf, 0.0, -far)
+X pdr(inf, 0.0, -far)
+X pdr(inf, inf, -far)
+X pdr(-inf, inf, -far)
+X pclos()
+X closeobj()
+X #
+X # road stripes object
+X #
+X makeobj(42)
+X stripes()
+X closeobj()
+X #
+X # lighting model definitions
+X #
+X deflight()
+X
+Xdef stripes():
+X #
+X # left line
+X #
+X botrect(-11, -10, far, -far)
+X #
+X # right line
+X #
+X botrect(10, 11, far, -far)
+X #
+X # center lines
+X #
+X z = far
+X while z > -far:
+X botrect(-0.5, 0.5, z, z - 4.0)
+X z = z - 10.0
+X
+Xdef dice():
+X from block import block
+X uselight()
+X pushmatrix()
+X translate(0.0, 1.0, -20.0)
+X rotate(200, 'y')
+X block(1, 0, 0, 0, 0, 0)
+X translate(1.0, 0.0, 3.0)
+X rotate(500, 'y')
+X block(2, 0, 0, 0, 0, 0)
+X popmatrix()
+X
+Xdef deflight():
+X # Material for first die (red)
+X lmdef(DEFMATERIAL, 1, (DIFFUSE, 1.0, 0.0, 0.0))
+X # Material for second die (green)
+X lmdef(DEFMATERIAL, 2, (DIFFUSE, 0.0, 1.0, 0.0))
+X # First light source (default: white, from front)
+X lmdef(DEFLIGHT, 1, ())
+X # Second light source (red, from back)
+X lmdef(DEFLIGHT, 2, (POSITION, 0.0, 1.0, -1.0, 0.0))
+X lmdef(DEFLIGHT, 2, (LCOLOR, 1.0, 0.0, 0.0))
+X # Lighting model
+X lmdef(DEFLMODEL, 1, (AMBIENT, 0.0, 0.0, 1.0))
+X
+Xdef uselight():
+X lmbind(LIGHT0, 1)
+X lmbind(LIGHT1, 2)
+X lmbind(LMODEL, 1)
+X # (materials are bound later)
+X
+Xdef building():
+X #
+X c3i(0, 255, 255)
+X #
+X # house bounding coordinates
+X #
+X x1 = 20.0
+X x1a = 25.0
+X x2 = 30.0
+X y1 = 0.0
+X y2 = 15.0
+X y2a = 20.0
+X z1 = -40.0
+X z2 = -55.0
+X #
+X # door y and z coordinates
+X #
+X dy1 = 0.0
+X dy2 = 4.0
+X dz1 = -45.0
+X dz2 = -47.0
+X #
+X # front side (seen from origin)
+X #
+X A1 = (x1, y1, z1)
+X B1 = (x2, y1, z1)
+X C1 = (x2, y2, z1)
+X D1 = (x1a, y2a, z1)
+X E1 = (x1, y2, z1)
+X #
+X # back size
+X #
+X A2 = (x1, y1, z2)
+X B2 = (x2, y1, z2)
+X C2 = (x2, y2, z2)
+X D2 = (x1a, y2a, z2)
+X E2 = (x1, y2, z2)
+X #
+X # door in the left side
+X #
+X P = x1, dy1, dz2
+X Q = x1, dy2, dz2
+X R = x1, dy2, dz1
+X S = x1, dy1, dz1
+X #
+X # draw it
+X #
+X concave(TRUE)
+X c3i(255, 0, 0)
+X face(A1, B1, C1, D1, E1)
+X c3i(127, 127, 0)
+X face(A1, E1, E2, A2, P, Q, R, S)
+X c3i(0, 255, 0)
+X face(E1, D1, D2, E2)
+X c3i(0, 127, 127)
+X face(D1, C1, C2, D2)
+X c3i(0, 0, 255)
+X face(C1, B1, B2, C2)
+X c3i(127, 0, 127)
+X face(E2, D2, C2, B2, A2)
+X concave(FALSE)
+X
+Xdef face(points):
+X bgnpolygon()
+X varray(points)
+X endpolygon()
+X
+X# draw a rectangle at y=0.0
+X#
+Xdef botrect(x1, x2, z1, z2):
+X polf(x1, 0.0, z1, x2, 0.0, z1, x2, 0.0, z2, x1, 0.0, z2)
+X
+Xmain()
+EOF
+chmod +x 'demo/sgi/gl_panel/twoview/twoview.py'
+fi
+if test -s 'lib/DEVICE.py'
+then echo '*** I will not over-write existing file lib/DEVICE.py'
+else
+echo 'x - lib/DEVICE.py'
+sed 's/^X//' > 'lib/DEVICE.py' << 'EOF'
+X#/**************************************************************************
+X# * *
+X# * Copyright (C) 1984, Silicon Graphics, Inc. *
+X# * *
+X# * These coded instructions, statements, and computer programs contain *
+X# * unpublished proprietary information of Silicon Graphics, Inc., and *
+X# * are protected by Federal copyright law. They may not be disclosed *
+X# * to third parties or copied or duplicated in any form, in whole or *
+X# * in part, without the prior written consent of Silicon Graphics, Inc. *
+X# * *
+X# **************************************************************************/
+X#/* file with device definitions (see /usr/include/device.h) */
+X
+XNULLDEV = 0
+XBUTOFFSET = 1
+XVALOFFSET = 256
+XTIMOFFSET = 515
+XXKBDOFFSET = 143
+XINOFFSET = 1024
+XOUTOFFSET = 1033
+XBUTCOUNT = 190
+XVALCOUNT = 27
+XTIMCOUNT = 4
+XXKBDCOUNT = 28
+XINCOUNT = 8
+XOUTCOUNT = 8
+X#
+X#
+X#
+X#
+XBUT0 = 1
+XBUT1 = 2
+XBUT2 = 3
+XBUT3 = 4
+XBUT4 = 5
+XBUT5 = 6
+XBUT6 = 7
+XBUT7 = 8
+XBUT8 = 9
+XBUT9 = 10
+XBUT10 = 11
+XBUT11 = 12
+XBUT12 = 13
+XBUT13 = 14
+XBUT14 = 15
+XBUT15 = 16
+XBUT16 = 17
+XBUT17 = 18
+XBUT18 = 19
+XBUT19 = 20
+XBUT20 = 21
+XBUT21 = 22
+XBUT22 = 23
+XBUT23 = 24
+XBUT24 = 25
+XBUT25 = 26
+XBUT26 = 27
+XBUT27 = 28
+XBUT28 = 29
+XBUT29 = 30
+XBUT30 = 31
+XBUT31 = 32
+XBUT32 = 33
+XBUT33 = 34
+XBUT34 = 35
+XBUT35 = 36
+XBUT36 = 37
+XBUT37 = 38
+XBUT38 = 39
+XBUT39 = 40
+XBUT40 = 41
+XBUT41 = 42
+XBUT42 = 43
+XBUT43 = 44
+XBUT44 = 45
+XBUT45 = 46
+XBUT46 = 47
+XBUT47 = 48
+XBUT48 = 49
+XBUT49 = 50
+XBUT50 = 51
+XBUT51 = 52
+XBUT52 = 53
+XBUT53 = 54
+XBUT54 = 55
+XBUT55 = 56
+XBUT56 = 57
+XBUT57 = 58
+XBUT58 = 59
+XBUT59 = 60
+XBUT60 = 61
+XBUT61 = 62
+XBUT62 = 63
+XBUT63 = 64
+XBUT64 = 65
+XBUT65 = 66
+XBUT66 = 67
+XBUT67 = 68
+XBUT68 = 69
+XBUT69 = 70
+XBUT70 = 71
+XBUT71 = 72
+XBUT72 = 73
+XBUT73 = 74
+XBUT74 = 75
+XBUT75 = 76
+XBUT76 = 77
+XBUT77 = 78
+XBUT78 = 79
+XBUT79 = 80
+XBUT80 = 81
+XBUT81 = 82
+XBUT82 = 83
+XMAXKBDBUT = 83
+XBUT100 = 101
+XBUT101 = 102
+XBUT102 = 103
+XBUT110 = 111
+XBUT111 = 112
+XBUT112 = 113
+XBUT113 = 114
+XBUT114 = 115
+XBUT115 = 116
+XBUT116 = 117
+XBUT117 = 118
+XBUT118 = 119
+XBUT119 = 120
+XBUT120 = 121
+XBUT121 = 122
+XBUT122 = 123
+XBUT123 = 124
+XBUT124 = 125
+XBUT125 = 126
+XBUT126 = 127
+XBUT127 = 128
+XBUT128 = 129
+XBUT129 = 130
+XBUT130 = 131
+XBUT131 = 132
+XBUT132 = 133
+XBUT133 = 134
+XBUT134 = 135
+XBUT135 = 136
+XBUT136 = 137
+XBUT137 = 138
+XBUT138 = 139
+XBUT139 = 140
+XBUT140 = 141
+XBUT141 = 142
+XBUT142 = 143
+XBUT143 = 144
+XBUT144 = 145
+XBUT145 = 146
+XBUT146 = 147
+XBUT147 = 148
+XBUT148 = 149
+XBUT149 = 150
+XBUT150 = 151
+XBUT151 = 152
+XBUT152 = 153
+XBUT153 = 154
+XBUT154 = 155
+XBUT155 = 156
+XBUT156 = 157
+XBUT157 = 158
+XBUT158 = 159
+XBUT159 = 160
+XBUT160 = 161
+XBUT161 = 162
+XBUT162 = 163
+XBUT163 = 164
+XBUT164 = 165
+XBUT165 = 166
+XBUT166 = 167
+XBUT167 = 168
+XBUT168 = 169
+XBUT181 = 182
+XBUT182 = 183
+XBUT183 = 184
+XBUT184 = 185
+XBUT185 = 186
+XBUT186 = 187
+XBUT187 = 188
+XBUT188 = 189
+XBUT189 = 190
+XMOUSE1 = 101
+XMOUSE2 = 102
+XMOUSE3 = 103
+XLEFTMOUSE = 103
+XMIDDLEMOUSE = 102
+XRIGHTMOUSE = 101
+XLPENBUT = 104
+XBPAD0 = 105
+XBPAD1 = 106
+XBPAD2 = 107
+XBPAD3 = 108
+XLPENVALID = 109
+XSWBASE = 111
+XSW0 = 111
+XSW1 = 112
+XSW2 = 113
+XSW3 = 114
+XSW4 = 115
+XSW5 = 116
+XSW6 = 117
+XSW7 = 118
+XSW8 = 119
+XSW9 = 120
+XSW10 = 121
+XSW11 = 122
+XSW12 = 123
+XSW13 = 124
+XSW14 = 125
+XSW15 = 126
+XSW16 = 127
+XSW17 = 128
+XSW18 = 129
+XSW19 = 130
+XSW20 = 131
+XSW21 = 132
+XSW22 = 133
+XSW23 = 134
+XSW24 = 135
+XSW25 = 136
+XSW26 = 137
+XSW27 = 138
+XSW28 = 139
+XSW29 = 140
+XSW30 = 141
+XSW31 = 142
+XSBBASE = 182
+XSBPICK = 182
+XSBBUT1 = 183
+XSBBUT2 = 184
+XSBBUT3 = 185
+XSBBUT4 = 186
+XSBBUT5 = 187
+XSBBUT6 = 188
+XSBBUT7 = 189
+XSBBUT8 = 190
+XAKEY = 11
+XBKEY = 36
+XCKEY = 28
+XDKEY = 18
+XEKEY = 17
+XFKEY = 19
+XGKEY = 26
+XHKEY = 27
+XIKEY = 40
+XJKEY = 34
+XKKEY = 35
+XLKEY = 42
+XMKEY = 44
+XNKEY = 37
+XOKEY = 41
+XPKEY = 48
+XQKEY = 10
+XRKEY = 24
+XSKEY = 12
+XTKEY = 25
+XUKEY = 33
+XVKEY = 29
+XWKEY = 16
+XXKEY = 21
+XYKEY = 32
+XZKEY = 20
+XZEROKEY = 46
+XONEKEY = 8
+XTWOKEY = 14
+XTHREEKEY = 15
+XFOURKEY = 22
+XFIVEKEY = 23
+XSIXKEY = 30
+XSEVENKEY = 31
+XEIGHTKEY = 38
+XNINEKEY = 39
+XBREAKKEY = 1
+XSETUPKEY = 2
+XCTRLKEY = 3
+XLEFTCTRLKEY = CTRLKEY
+XCAPSLOCKKEY = 4
+XRIGHTSHIFTKEY = 5
+XLEFTSHIFTKEY = 6
+XNOSCRLKEY = 13
+XESCKEY = 7
+XTABKEY = 9
+XRETKEY = 51
+XSPACEKEY = 83
+XLINEFEEDKEY = 60
+XBACKSPACEKEY = 61
+XDELKEY = 62
+XSEMICOLONKEY = 43
+XPERIODKEY = 52
+XCOMMAKEY = 45
+XQUOTEKEY = 50
+XACCENTGRAVEKEY = 55
+XMINUSKEY = 47
+XVIRGULEKEY = 53
+XBACKSLASHKEY = 57
+XEQUALKEY = 54
+XLEFTBRACKETKEY = 49
+XRIGHTBRACKETKEY = 56
+XLEFTARROWKEY = 73
+XDOWNARROWKEY = 74
+XRIGHTARROWKEY = 80
+XUPARROWKEY = 81
+XPAD0 = 59
+XPAD1 = 58
+XPAD2 = 64
+XPAD3 = 65
+XPAD4 = 63
+XPAD5 = 69
+XPAD6 = 70
+XPAD7 = 67
+XPAD8 = 68
+XPAD9 = 75
+XPADPF1 = 72
+XPADPF2 = 71
+XPADPF3 = 79
+XPADPF4 = 78
+XPADPERIOD = 66
+XPADMINUS = 76
+XPADCOMMA = 77
+XPADENTER = 82
+XLEFTALTKEY = 143
+XRIGHTALTKEY = 144
+XRIGHTCTRLKEY = 145
+XF1KEY = 146
+XF2KEY = 147
+XF3KEY = 148
+XF4KEY = 149
+XF5KEY = 150
+XF6KEY = 151
+XF7KEY = 152
+XF8KEY = 153
+XF9KEY = 154
+XF10KEY = 155
+XF11KEY = 156
+XF12KEY = 157
+XPRINTSCREENKEY = 158
+XSCROLLLOCKKEY = 159
+XPAUSEKEY = 160
+XINSERTKEY = 161
+XHOMEKEY = 162
+XPAGEUPKEY = 163
+XENDKEY = 164
+XPAGEDOWNKEY = 165
+XNUMLOCKKEY = 166
+XPADVIRGULEKEY = 167
+XPADASTERKEY = 168
+XPADPLUSKEY = 169
+XSGIRESERVED = 256
+XDIAL0 = 257
+XDIAL1 = 258
+XDIAL2 = 259
+XDIAL3 = 260
+XDIAL4 = 261
+XDIAL5 = 262
+XDIAL6 = 263
+XDIAL7 = 264
+XDIAL8 = 265
+XMOUSEX = 266
+XMOUSEY = 267
+XLPENX = 268
+XLPENY = 269
+XBPADX = 270
+XBPADY = 271
+XCURSORX = 272
+XCURSORY = 273
+XGHOSTX = 274
+XGHOSTY = 275
+XSBTX = 276
+XSBTY = 277
+XSBTZ = 278
+XSBRX = 279
+XSBRY = 280
+XSBRZ = 281
+XSBPERIOD = 282
+XTIMER0 = 515
+XTIMER1 = 516
+XTIMER2 = 517
+XTIMER3 = 518
+XKEYBD = 513
+XRAWKEYBD = 514
+XVALMARK = 523
+XGERROR = 524
+XREDRAW = 528
+XWMSEND = 529
+XWMREPLY = 530
+XWMGFCLOSE = 531
+XWMTXCLOSE = 532
+XMODECHANGE = 533
+XINPUTCHANGE = 534
+XQFULL = 535
+XPIECECHANGE = 536
+XWINCLOSE = 537
+XQREADERROR = 538
+XWINFREEZE = 539
+XWINTHAW = 540
+XREDRAWICONIC = 541
+XWINQUIT = 542
+XDEPTHCHANGE = 543
+XKEYBDFNAMES = 544
+XKEYBDFSTRINGS = 545
+XWINSHUT = 546
+XINPUT0 = 1024
+XINPUT1 = 1025
+XINPUT2 = 1026
+XINPUT3 = 1027
+XINPUT4 = 1028
+XINPUT5 = 1029
+XINPUT6 = 1030
+XINPUT7 = 1032
+XOUTPUT0 = 1033
+XOUTPUT1 = 1034
+XOUTPUT2 = 1035
+XOUTPUT3 = 1036
+XOUTPUT4 = 1037
+XOUTPUT5 = 1038
+XOUTPUT6 = 1039
+XOUTPUT7 = 1040
+XMAXSGIDEVICE = 20000
+XMENUBUTTON = RIGHTMOUSE
+EOF
+fi
+if test -s 'lib/GL.py'
+then echo '*** I will not over-write existing file lib/GL.py'
+else
+echo 'x - lib/GL.py'
+sed 's/^X//' > 'lib/GL.py' << 'EOF'
+X# Constants defined in <gl.h>
+X
+X#**************************************************************************
+X#* *
+X#* Copyright (C) 1984, Silicon Graphics, Inc. *
+X#* *
+X#* These coded instructions, statements, and computer programs contain *
+X#* unpublished proprietary information of Silicon Graphics, Inc., and *
+X#* are protected by Federal copyright law. They may not be disclosed *
+X#* to third parties or copied or duplicated in any form, in whole or *
+X#* in part, without the prior written consent of Silicon Graphics, Inc. *
+X#* *
+X#**************************************************************************
+X
+X# Graphics Libary constants
+X
+X# Booleans
+XTRUE = 1
+XFALSE = 0
+X
+X# maximum X and Y screen coordinates
+XXMAXSCREEN = 1279
+XYMAXSCREEN = 1023
+XXMAXMEDIUM = 1023 # max for medium res monitor
+XYMAXMEDIUM = 767
+XXMAX170 = 645 # max for RS-170
+XYMAX170 = 484
+XXMAXPAL = 779 # max for PAL
+XYMAXPAL = 574
+X
+X# various hardware/software limits
+XATTRIBSTACKDEPTH = 10
+XVPSTACKDEPTH = 8
+XMATRIXSTACKDEPTH = 32
+XNAMESTACKDEPTH = 1025
+XSTARTTAG = -2
+XENDTAG = -3
+XCPOSX_INVALID = -(2*XMAXSCREEN)
+X
+X# names for colors in color map loaded by greset
+XBLACK = 0
+XRED = 1
+XGREEN = 2
+XYELLOW = 3
+XBLUE = 4
+XMAGENTA = 5
+XCYAN = 6
+XWHITE = 7
+X
+X# popup colors
+XPUP_CLEAR = 0
+XPUP_COLOR = 1
+XPUP_BLACK = 2
+XPUP_WHITE = 3
+X
+X# defines for drawmode
+XNORMALDRAW = 0
+XPUPDRAW = 1
+XOVERDRAW = 2
+XUNDERDRAW = 3
+XCURSORDRAW = 4
+X
+X# defines for defpattern
+XPATTERN_16 = 16
+XPATTERN_32 = 32
+XPATTERN_64 = 64
+X
+XPATTERN_16_SIZE = 16
+XPATTERN_32_SIZE = 64
+XPATTERN_64_SIZE = 256
+X
+X# defines for readsource
+XSRC_AUTO = 0
+XSRC_FRONT = 1
+XSRC_BACK = 2
+XSRC_ZBUFFER = 3
+XSRC_PUP = 4
+XSRC_OVER = 5
+XSRC_UNDER = 6
+XSRC_FRAMEGRABBER = 7
+X
+X# defines for blendfunction
+XBF_ZERO = 0
+XBF_ONE = 1
+XBF_DC = 2
+XBF_SC = 2
+XBF_MDC = 3
+XBF_MSC = 3
+XBF_SA = 4
+XBF_MSA = 5
+XBF_DA = 6
+XBF_MDA = 7
+X
+X# defines for zfunction
+XZF_NEVER = 0
+XZF_LESS = 1
+XZF_EQUAL = 2
+XZF_LEQUAL = 3
+XZF_GREATER = 4
+XZF_NOTEQUAL = 5
+XZF_GEQUAL = 6
+XZF_ALWAYS = 7
+X
+X# defines for zsource
+XZSRC_DEPTH = 0
+XZSRC_COLOR = 1
+X
+X# defines for pntsmooth
+XSMP_OFF = 0
+XSMP_ON = 1
+X
+X# defines for linesmooth
+XSML_OFF = 0
+XSML_ON = 1
+X
+X# defines for setpup
+XPUP_NONE = 0
+XPUP_GREY = 1
+X
+X# defines for glcompat
+XGLC_OLDPOLYGON = 0
+XGLC_ZRANGEMAP = 1
+X
+X# defines for curstype
+XC16X1 = 0
+XC16X2 = 1
+XC32X1 = 2
+XC32X2 = 3
+XCCROSS = 4
+X
+X# defines for shademodel
+XFLAT = 0
+XGOURAUD = 1
+X
+X# defines for logicop
+X### LO_ZERO = 0x0
+X### LO_AND = 0x1
+X### LO_ANDR = 0x2
+X### LO_SRC = 0x3
+X### LO_ANDI = 0x4
+X### LO_DST = 0x5
+X### LO_XOR = 0x6
+X### LO_OR = 0x7
+X### LO_NOR = 0x8
+X### LO_XNOR = 0x9
+X### LO_NDST = 0xa
+X### LO_ORR = 0xb
+X### LO_NSRC = 0xc
+X### LO_ORI = 0xd
+X### LO_NAND = 0xe
+X### LO_ONE = 0xf
+X
+X
+X#
+X# START defines for getgdesc
+X#
+X
+XGD_XPMAX = 0
+XGD_YPMAX = 1
+XGD_XMMAX = 2
+XGD_YMMAX = 3
+XGD_ZMIN = 4
+XGD_ZMAX = 5
+XGD_BITS_NORM_SNG_RED = 6
+XGD_BITS_NORM_SNG_GREEN = 7
+XGD_BITS_NORM_SNG_BLUE = 8
+XGD_BITS_NORM_DBL_RED = 9
+XGD_BITS_NORM_DBL_GREEN = 10
+XGD_BITS_NORM_DBL_BLUE = 11
+XGD_BITS_NORM_SNG_CMODE = 12
+XGD_BITS_NORM_DBL_CMODE = 13
+XGD_BITS_NORM_SNG_MMAP = 14
+XGD_BITS_NORM_DBL_MMAP = 15
+XGD_BITS_NORM_ZBUFFER = 16
+XGD_BITS_OVER_SNG_CMODE = 17
+XGD_BITS_UNDR_SNG_CMODE = 18
+XGD_BITS_PUP_SNG_CMODE = 19
+XGD_BITS_NORM_SNG_ALPHA = 21
+XGD_BITS_NORM_DBL_ALPHA = 22
+XGD_BITS_CURSOR = 23
+XGD_OVERUNDER_SHARED = 24
+XGD_BLEND = 25
+XGD_CIFRACT = 26
+XGD_CROSSHAIR_CINDEX = 27
+XGD_DITHER = 28
+XGD_LINESMOOTH_CMODE = 30
+XGD_LINESMOOTH_RGB = 31
+XGD_LOGICOP = 33
+XGD_NSCRNS = 35
+XGD_NURBS_ORDER = 36
+XGD_NBLINKS = 37
+XGD_NVERTEX_POLY = 39
+XGD_PATSIZE_64 = 40
+XGD_PNTSMOOTH_CMODE = 41
+XGD_PNTSMOOTH_RGB = 42
+XGD_PUP_TO_OVERUNDER = 43
+XGD_READSOURCE = 44
+XGD_READSOURCE_ZBUFFER = 48
+XGD_STEREO = 50
+XGD_SUBPIXEL_LINE = 51
+XGD_SUBPIXEL_PNT = 52
+XGD_SUBPIXEL_POLY = 53
+XGD_TRIMCURVE_ORDER = 54
+XGD_WSYS = 55
+XGD_ZDRAW_GEOM = 57
+XGD_ZDRAW_PIXELS = 58
+XGD_SCRNTYPE = 61
+XGD_TEXTPORT = 62
+XGD_NMMAPS = 63
+XGD_FRAMEGRABBER = 64
+XGD_TIMERHZ = 66
+XGD_DBBOX = 67
+XGD_AFUNCTION = 68
+XGD_ALPHA_OVERUNDER = 69
+XGD_BITS_ACBUF = 70
+XGD_BITS_ACBUF_HW = 71
+XGD_BITS_STENCIL = 72
+XGD_CLIPPLANES = 73
+XGD_FOGVERTEX = 74
+XGD_LIGHTING_TWOSIDE = 76
+XGD_POLYMODE = 77
+XGD_POLYSMOOTH = 78
+XGD_SCRBOX = 79
+XGD_TEXTURE = 80
+X
+X# return value for inquiries when there is no limit
+XGD_NOLIMIT = 2
+X
+X# return values for GD_WSYS
+XGD_WSYS_NONE = 0
+XGD_WSYS_4S = 1
+X
+X# return values for GD_SCRNTYPE
+XGD_SCRNTYPE_WM = 0
+XGD_SCRNTYPE_NOWM = 1
+X
+X#
+X# END defines for getgdesc
+X#
+X
+X
+X#
+X# START NURBS interface definitions
+X#
+X
+X# NURBS Rendering Properties
+XN_PIXEL_TOLERANCE = 1
+XN_CULLING = 2
+XN_DISPLAY = 3
+XN_ERRORCHECKING = 4
+XN_SUBDIVISIONS = 5
+XN_S_STEPS = 6
+XN_T_STEPS = 7
+XN_TILES = 8
+X
+XN_SHADED = 1.0
+X
+X# ---------------------------------------------------------------------------
+X# FLAGS FOR NURBS SURFACES AND CURVES
+X#
+X# Bit: 9876 5432 1 0
+X# |tttt|nnnn|f|r| : r - 1 bit = 1 if rational coordinate exists
+X# : f - 1 bit = 1 if rational coordinate is before rest
+X# : = 0 if rational coordinate is after rest
+X# : nnnn - 4 bits for number of coordinates
+X# : tttt - 4 bits for type of data (color, position, etc.)
+X#
+X# NURBS data type
+X# N_T_ST 0 parametric space data
+X# N_T_XYZ 1 model space data
+X#
+X# rational or non-rational data and position in memory
+X# N_NONRATIONAL 0 non-rational data
+X# N_RATAFTER 1 rational data with rat coord after rest
+X# N_RATBEFORE 3 rational data with rat coord before rest
+X#
+X# N_MKFLAG(a,b,c) ((a<<6) | (b<<2) | c)
+X#
+X# ---------------------------------------------------------------------------
+X#
+XN_ST = 0x8 # N_MKFLAG( N_T_ST, 2, N_NONRATIONAL )
+XN_STW = 0xd # N_MKFLAG( N_T_ST, 3, N_RATAFTER )
+XN_WST = 0xf # N_MKFLAG( N_T_ST, 3, N_RATBEFORE )
+XN_XYZ = 0x4c # N_MKFLAG( N_T_XYZ, 3, N_NONRATIONAL )
+XN_XYZW = 0x51 # N_MKFLAG( N_T_XYZ, 4, N_RATAFTER )
+XN_WXYZ = 0x53 # N_MKFLAG( N_T_XYZ, 4, N_RATBEFORE )
+X
+X#
+X# END NURBS interface definitions
+X#
+X
+X
+X#
+X# START lighting model defines
+X#
+X
+XLMNULL = 0.0
+X
+X# MATRIX modes
+XMSINGLE = 0
+XMPROJECTION = 1
+XMVIEWING = 2
+X
+X# LIGHT constants
+XMAXLIGHTS = 8
+XMAXRESTRICTIONS = 4
+X
+X# MATERIAL properties
+XDEFMATERIAL = 0
+XEMISSION = 1
+XAMBIENT = 2
+XDIFFUSE = 3
+XSPECULAR = 4
+XSHININESS = 5
+XCOLORINDEXES = 6
+XALPHA = 7
+X
+X# LIGHT properties
+XDEFLIGHT = 100
+XLCOLOR = 101
+XPOSITION = 102
+X
+X# LIGHTINGMODEL properties
+XDEFLMODEL = 200
+XLOCALVIEWER = 201
+XATTENUATION = 202
+X
+X# TARGET constants
+XMATERIAL = 1000
+XLIGHT0 = 1100
+XLIGHT1 = 1101
+XLIGHT2 = 1102
+XLIGHT3 = 1103
+XLIGHT4 = 1104
+XLIGHT5 = 1105
+XLIGHT6 = 1106
+XLIGHT7 = 1107
+XLMODEL = 1200
+X
+X# lmcolor modes
+XLMC_COLOR = 0
+XLMC_EMISSION = 1
+XLMC_AMBIENT = 2
+XLMC_DIFFUSE = 3
+XLMC_SPECULAR = 4
+XLMC_AD = 5
+XLMC_NULL = 6
+X
+X#
+X# END lighting model defines
+X#
+X
+X
+X#
+X# START distributed graphics library defines
+X#
+X
+XDGLSINK = 0 # sink connection
+XDGLLOCAL = 1 # local connection
+XDGLTSOCKET = 2 # tcp socket connection
+XDGL4DDN = 3 # 4DDN (DECnet)
+X
+X#
+X# END distributed graphics library defines
+X#
+EOF
+fi
+if test -s 'lib/calendar.py'
+then echo '*** I will not over-write existing file lib/calendar.py'
+else
+echo 'x - lib/calendar.py'
+sed 's/^X//' > 'lib/calendar.py' << 'EOF'
+X# module calendar
+X
+X##############################
+X# Calendar support functions #
+X##############################
+X
+X# This is based on UNIX ctime() et al. (also Standard C and POSIX)
+X# Subtle but crucial differences:
+X# - the order of the elements of a 'struct tm' differs, to ease sorting
+X# - months numbers are 1-12, not 0-11; month arrays have a dummy element 0
+X# - Monday is the first day of the week (numbered 0)
+X
+X# These are really parameters of the 'time' module:
+Xepoch = 1970 # Time began on January 1 of this year (00:00:00 UCT)
+Xday_0 = 3 # The epoch begins on a Thursday (Monday = 0)
+X
+X# Return 1 for leap years, 0 for non-leap years
+Xdef isleap(year):
+X return year % 4 = 0 and (year % 100 <> 0 or year % 400 = 0)
+X
+X# Constants for months referenced later
+XJanuary = 1
+XFebruary = 2
+X
+X# Number of days per month (except for February in leap years)
+Xmdays = (0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)
+X
+X# Exception raised for bad input (with string parameter for details)
+Xerror = 'calendar error'
+X
+X# Turn seconds since epoch into calendar time
+Xdef gmtime(secs):
+X if secs < 0: raise error, 'negative input to gmtime()'
+X mins, secs = divmod(secs, 60)
+X hours, mins = divmod(mins, 60)
+X days, hours = divmod(hours, 24)
+X wday = (days + day_0) % 7
+X year = epoch
+X # XXX Most of the following loop can be replaced by one division
+X while 1:
+X yd = 365 + isleap(year)
+X if days < yd: break
+X days = days - yd
+X year = year + 1
+X yday = days
+X month = January
+X while 1:
+X md = mdays[month] + (month = February and isleap(year))
+X if days < md: break
+X days = days - md
+X month = month + 1
+X return year, month, days + 1, hours, mins, secs, yday, wday
+X # XXX Week number also?
+X
+X# Return number of leap years in range [y1, y2)
+X# Assume y1 <= y2 and no funny (non-leap century) years
+Xdef leapdays(y1, y2):
+X return (y2+3)/4 - (y1+3)/4
+X
+X# Inverse of gmtime():
+X# Turn UCT calendar time (less yday, wday) into seconds since epoch
+Xdef mktime(year, month, day, hours, mins, secs):
+X days = day - 1
+X for m in range(January, month): days = days + mdays[m]
+X if isleap(year) and month > February: days = days+1
+X days = days + (year-epoch)*365 + leapdays(epoch, year)
+X return ((days*24 + hours)*60 + mins)*60 + secs
+X
+X# Full and abbreviated names of weekdays
+Xday_name = ('Monday', 'Tuesday', 'Wednesday', 'Thursday')
+Xday_name = day_name + ('Friday', 'Saturday', 'Sunday')
+Xday_abbr = ('Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun')
+X
+X# Full and abbreviated of months (1-based arrays!!!)
+Xmonth_name = ('', 'January', 'February', 'March', 'April')
+Xmonth_name = month_name + ('May', 'June', 'July', 'August')
+Xmonth_name = month_name + ('September', 'October', 'November', 'December')
+Xmonth_abbr = (' ', 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun')
+Xmonth_abbr = month_abbr + ('Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec')
+X
+X# Zero-fill string to two positions (helper for asctime())
+Xdef dd(s):
+X while len(s) < 2: s = '0' + s
+X return s
+X
+X# Blank-fill string to two positions (helper for asctime())
+Xdef zd(s):
+X while len(s) < 2: s = ' ' + s
+X return s
+X
+X# Turn calendar time as returned by gmtime() into a string
+X# (the yday parameter is for compatibility with gmtime())
+Xdef asctime(year, month, day, hours, mins, secs, yday, wday):
+X s = day_abbr[wday] + ' ' + month_abbr[month] + ' ' + zd(`day`)
+X s = s + ' ' + dd(`hours`) + ':' + dd(`mins`) + ':' + dd(`secs`)
+X return s + ' ' + `year`
+X
+X# Localization: Minutes West from Greenwich
+X# timezone = -2*60 # Middle-European time with DST on
+Xtimezone = 5*60 # EST (sigh -- THINK time() doesn't return UCT)
+X
+X# Local time ignores DST issues for now -- adjust 'timezone' to fake it
+Xdef localtime(secs):
+X return gmtime(secs - timezone*60)
+X
+X# UNIX-style ctime (except it doesn't append '\n'!)
+Xdef ctime(secs):
+X return asctime(localtime(secs))
+X
+X######################
+X# Non-UNIX additions #
+X######################
+X
+X# Calendar printing etc.
+X
+X# Return weekday (0-6 ~ Mon-Sun) for year (1970-...), month (1-12), day (1-31)
+Xdef weekday(year, month, day):
+X secs = mktime(year, month, day, 0, 0, 0)
+X days = secs / (24*60*60)
+X return (days + day_0) % 7
+X
+X# Return weekday (0-6 ~ Mon-Sun) and number of days (28-31) for year, month
+Xdef monthrange(year, month):
+X day1 = weekday(year, month, 1)
+X ndays = mdays[month] + (month = February and isleap(year))
+X return day1, ndays
+X
+X# Return a matrix representing a month's calendar
+X# Each row represents a week; days outside this month are zero
+Xdef _monthcalendar(year, month):
+X day1, ndays = monthrange(year, month)
+X rows = []
+X r7 = range(7)
+X day = 1 - day1
+X while day <= ndays:
+X row = [0, 0, 0, 0, 0, 0, 0]
+X for i in r7:
+X if 1 <= day <= ndays: row[i] = day
+X day = day + 1
+X rows.append(row)
+X return rows
+X
+X# Caching interface to _monthcalendar
+Xmc_cache = {}
+Xdef monthcalendar(year, month):
+X key = `year` + month_abbr[month]
+X try:
+X return mc_cache[key]
+X except RuntimeError:
+X mc_cache[key] = ret = _monthcalendar(year, month)
+X return ret
+X
+X# Center a string in a field
+Xdef center(str, width):
+X n = width - len(str)
+X if n < 0: return str
+X return ' '*(n/2) + str + ' '*(n-n/2)
+X
+X# XXX The following code knows that print separates items with space!
+X
+X# Print a single week (no newline)
+Xdef prweek(week, width):
+X for day in week:
+X if day = 0: print ' '*width,
+X else:
+X if width > 2: print ' '*(width-3),
+X if day < 10: print '',
+X print day,
+X
+X# Return a header for a week
+Xdef weekheader(width):
+X str = ''
+X for i in range(7):
+X if str: str = str + ' '
+X str = str + day_abbr[i%7][:width]
+X return str
+X
+X# Print a month's calendar
+Xdef prmonth(year, month):
+X print weekheader(3)
+X for week in monthcalendar(year, month):
+X prweek(week, 3)
+X print
+X
+X# Spacing between month columns
+Xspacing = ' '
+X
+X# 3-column formatting for year calendars
+Xdef format3c(a, b, c):
+X print center(a, 20), spacing, center(b, 20), spacing, center(c, 20)
+X
+X# Print a year's calendar
+Xdef prcal(year):
+X header = weekheader(2)
+X format3c('', `year`, '')
+X for q in range(January, January+12, 3):
+X print
+X format3c(month_name[q], month_name[q+1], month_name[q+2])
+X format3c(header, header, header)
+X data = []
+X height = 0
+X for month in range(q, q+3):
+X cal = monthcalendar(year, month)
+X if len(cal) > height: height = len(cal)
+X data.append(cal)
+X for i in range(height):
+X for cal in data:
+X if i >= len(cal):
+X print ' '*20,
+X else:
+X prweek(cal[i], 2)
+X print spacing,
+X print
+EOF
+fi
+if test -s 'lib/panel.py'
+then echo '*** I will not over-write existing file lib/panel.py'
+else
+echo 'x - lib/panel.py'
+sed 's/^X//' > 'lib/panel.py' << 'EOF'
+X# Module 'panel'
+X#
+X# Support for the Panel library.
+X# Uses built-in module 'pnl'.
+X# Applciations should use 'panel.function' instead of 'pnl.function';
+X# most 'pnl' functions are transparently exported by 'panel',
+X# but dopanel() is overridden and you have to use this version
+X# if you want to use callbacks.
+X
+X
+Ximport pnl
+X
+X
+Xdebug = 0
+X
+X
+X# Test if an object is a list.
+X#
+Xdef is_list(x):
+X return type(x) = type([])
+X
+X
+X# Reverse a list.
+X#
+Xdef reverse(list):
+X res = []
+X for item in list:
+X res.insert(0, item)
+X return res
+X
+X
+X# Get an attribute of a list, which may itself be another list.
+X# Don't use 'prop' for name.
+X#
+Xdef getattrlist(list, name):
+X for item in list:
+X if item and is_list(item) and item[0] = name:
+X return item[1:]
+X return []
+X
+X
+X# Get a property of a list, which may itself be another list.
+X#
+Xdef getproplist(list, name):
+X for item in list:
+X if item and is_list(item) and item[0] = 'prop':
+X if len(item) > 1 and item[1] = name:
+X return item[2:]
+X return []
+X
+X
+X# Test if an actuator description contains the property 'end-of-group'
+X#
+Xdef is_endgroup(list):
+X x = getproplist(list, 'end-of-group')
+X return (x and x[0] = '#t')
+X
+X
+X# Neatly display an actuator definition given as S-expression
+X# the prefix string is printed before each line.
+X#
+Xdef show_actuator(prefix, a):
+X for item in a:
+X if not is_list(item):
+X print prefix, item
+X elif item and item[0] = 'al':
+X print prefix, 'Subactuator list:'
+X for a in item[1:]:
+X show_actuator(prefix + ' ', a)
+X elif len(item) = 2:
+X print prefix, item[0], '=>', item[1]
+X elif len(item) = 3 and item[0] = 'prop':
+X print prefix, 'Prop', item[1], '=>',
+X print item[2]
+X else:
+X print prefix, '?', item
+X
+X
+X# Neatly display a panel.
+X#
+Xdef show_panel(prefix, p):
+X for item in p:
+X if not is_list(item):
+X print prefix, item
+X elif item and item[0] = 'al':
+X print prefix, 'Actuator list:'
+X for a in item[1:]:
+X show_actuator(prefix + ' ', a)
+X elif len(item) = 2:
+X print prefix, item[0], '=>', item[1]
+X elif len(item) = 3 and item[0] = 'prop':
+X print prefix, 'Prop', item[1], '=>',
+X print item[2]
+X else:
+X print prefix, '?', item
+X
+X
+X# Exception raised by build_actuator or build_panel.
+X#
+Xpanel_error = 'panel error'
+X
+X
+X# Dummy callback used to initialize the callbacks.
+X#
+Xdef dummy_callback(arg):
+X pass
+X
+X
+X# Assign attributes to members of the target.
+X# Attribute names in exclist are ignored.
+X# The member name is the attribute name prefixed with the prefix.
+X#
+Xdef assign_members(target, attrlist, exclist, prefix):
+X for item in attrlist:
+X if is_list(item) and len(item) = 2 and item[0] not in exclist:
+X name, value = item[0], item[1]
+X ok = 1
+X if value[0] in '-0123456789':
+X value = eval(value)
+X elif value[0] = '"':
+X value = value[1:-1]
+X elif value = 'move-then-resize':
+X # Strange default set by Panel Editor...
+X ok = 0
+X else:
+X print 'unknown value', value, 'for', name
+X ok = 0
+X if ok:
+X lhs = 'target.' + prefix + name
+X stmt = lhs + '=' + `value`
+X if debug: print 'exec', stmt
+X try:
+X exec(stmt + '\n')
+X except KeyboardInterrupt: # Don't catch this!
+X raise KeyboardInterrupt
+X except:
+X print 'assign failed:', stmt
+X
+X
+X# Build a real actuator from an actuator descriptior.
+X# Return a pair (actuator, name).
+X#
+Xdef build_actuator(descr):
+X namelist = getattrlist(descr, 'name')
+X if namelist:
+X # Assume it is a string
+X actuatorname = namelist[0][1:-1]
+X else:
+X actuatorname = ''
+X type = descr[0]
+X if type[:4] = 'pnl_': type = type[4:]
+X act = pnl.mkact(type)
+X act.downfunc = act.activefunc = act.upfunc = dummy_callback
+X #
+X assign_members(act, descr[1:], ['al', 'data', 'name'], '')
+X #
+X # Treat actuator-specific data
+X #
+X datalist = getattrlist(descr, 'data')
+X prefix = ''
+X if type[-4:] = 'puck':
+X prefix = 'puck_'
+X elif type = 'mouse':
+X prefix = 'mouse_'
+X assign_members(act, datalist, [], prefix)
+X #
+X return act, actuatorname
+X
+X
+X# Build all sub-actuators and add them to the super-actuator.
+X# The super-actuator must already have been added to the panel.
+X# Sub-actuators with defined names are added as members to the panel
+X# so they can be referenced as p.name.
+X#
+X# Note: I have no idea how panel.endgroup() works when applied
+X# to a sub-actuator.
+X#
+Xdef build_subactuators(panel, super_act, al):
+X #
+X # This is nearly the same loop as below in build_panel(),
+X # except a call is made to addsubact() instead of addact().
+X #
+X for a in al:
+X act, name = build_actuator(a)
+X act.addsubact(super_act)
+X if name:
+X stmt = 'panel.' + name + ' = act'
+X if debug: print 'exec', stmt
+X exec(stmt + '\n')
+X if is_endgroup(a):
+X panel.endgroup()
+X sub_al = getattrlist(a, 'al')
+X if sub_al:
+X build_subactuators(panel, act, sub_al)
+X #
+X # Fix the actuator to which whe just added subactuators.
+X # This can't hurt (I hope) and is needed for the scroll actuator.
+X #
+X super_act.fixact()
+X
+X
+X# Build a real panel from a panel definition.
+X# Return a panel object p, where for each named actuator a, p.name is a
+X# reference to a.
+X#
+Xdef build_panel(descr):
+X #
+X # Sanity check
+X #
+X if (not descr) or descr[0] <> 'panel':
+X raise panel_error, 'panel description must start with "panel"'
+X #
+X if debug: show_panel('', descr)
+X #
+X # Create an empty panel
+X #
+X panel = pnl.mkpanel()
+X #
+X # Assign panel attributes
+X #
+X assign_members(panel, descr[1:], ['al'], '')
+X #
+X # Look for actuator list
+X #
+X al = getattrlist(descr, 'al')
+X #
+X # The order in which actuators are created is important
+X # because of the endgroup() operator.
+X # Unfortunately the Panel Editor outputs the actuator list
+X # in reverse order, so we reverse it here.
+X #
+X al = reverse(al)
+X #
+X for a in al:
+X act, name = build_actuator(a)
+X act.addact(panel)
+X if name:
+X stmt = 'panel.' + name + ' = act'
+X exec(stmt + '\n')
+X if is_endgroup(a):
+X panel.endgroup()
+X sub_al = getattrlist(a, 'al')
+X if sub_al:
+X build_subactuators(panel, act, sub_al)
+X #
+X return panel
+X
+X
+X# Wrapper around pnl.dopanel() which calls call-back functions.
+X#
+Xdef my_dopanel():
+X # Extract only the first 4 elements to allow for future expansion
+X a, down, active, up = pnl.dopanel()[:4]
+X if down:
+X down.downfunc(down)
+X if active:
+X active.activefunc(active)
+X if up:
+X up.upfunc(up)
+X return a
+X
+X
+X# Create one or more panels from a description file (S-expressions)
+X# generated by the Panel Editor.
+X#
+Xdef defpanellist(file):
+X import panelparser
+X descrlist = panelparser.parse_file(open(file, 'r'))
+X panellist = []
+X for descr in descrlist:
+X panellist.append(build_panel(descr))
+X return panellist
+X
+X
+X# Import everything from built-in method pnl, so the user can always
+X# use panel.foo() instead of pnl.foo().
+X# This gives *no* performance penalty once this module is imported.
+X#
+Xfrom pnl import * # for export
+X
+Xdopanel = my_dopanel # override pnl.dopanel
+EOF
+fi
+if test -s 'src/acceler.c'
+then echo '*** I will not over-write existing file src/acceler.c'
+else
+echo 'x - src/acceler.c'
+sed 's/^X//' > 'src/acceler.c' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/* Parser accelerator module */
+X
+X/* The parser as originally conceived had disappointing performance.
+X This module does some precomputation that speeds up the selection
+X of a DFA based upon a token, turning a search through an array
+X into a simple indexing operation. The parser now cannot work
+X without the accelerators installed. Note that the accelerators
+X are installed dynamically when the parser is initialized, they
+X are not part of the static data structure written on graminit.[ch]
+X by the parser generator. */
+X
+X#include "pgenheaders.h"
+X#include "grammar.h"
+X#include "token.h"
+X#include "parser.h"
+X
+X/* Forward references */
+Xstatic void fixdfa PROTO((grammar *, dfa *));
+Xstatic void fixstate PROTO((grammar *, dfa *, state *));
+X
+Xvoid
+Xaddaccelerators(g)
+X grammar *g;
+X{
+X dfa *d;
+X int i;
+X#ifdef DEBUG
+X printf("Adding parser accellerators ...\n");
+X#endif
+X d = g->g_dfa;
+X for (i = g->g_ndfas; --i >= 0; d++)
+X fixdfa(g, d);
+X g->g_accel = 1;
+X#ifdef DEBUG
+X printf("Done.\n");
+X#endif
+X}
+X
+Xstatic void
+Xfixdfa(g, d)
+X grammar *g;
+X dfa *d;
+X{
+X state *s;
+X int j;
+X s = d->d_state;
+X for (j = 0; j < d->d_nstates; j++, s++)
+X fixstate(g, d, s);
+X}
+X
+Xstatic void
+Xfixstate(g, d, s)
+X grammar *g;
+X dfa *d;
+X state *s;
+X{
+X arc *a;
+X int k;
+X int *accel;
+X int nl = g->g_ll.ll_nlabels;
+X s->s_accept = 0;
+X accel = NEW(int, nl);
+X for (k = 0; k < nl; k++)
+X accel[k] = -1;
+X a = s->s_arc;
+X for (k = s->s_narcs; --k >= 0; a++) {
+X int lbl = a->a_lbl;
+X label *l = &g->g_ll.ll_label[lbl];
+X int type = l->lb_type;
+X if (a->a_arrow >= (1 << 7)) {
+X printf("XXX too many states!\n");
+X continue;
+X }
+X if (ISNONTERMINAL(type)) {
+X dfa *d1 = finddfa(g, type);
+X int ibit;
+X if (type - NT_OFFSET >= (1 << 7)) {
+X printf("XXX too high nonterminal number!\n");
+X continue;
+X }
+X for (ibit = 0; ibit < g->g_ll.ll_nlabels; ibit++) {
+X if (testbit(d1->d_first, ibit)) {
+X if (accel[ibit] != -1)
+X printf("XXX ambiguity!\n");
+X accel[ibit] = a->a_arrow | (1 << 7) |
+X ((type - NT_OFFSET) << 8);
+X }
+X }
+X }
+X else if (lbl == EMPTY)
+X s->s_accept = 1;
+X else if (lbl >= 0 && lbl < nl)
+X accel[lbl] = a->a_arrow;
+X }
+X while (nl > 0 && accel[nl-1] == -1)
+X nl--;
+X for (k = 0; k < nl && accel[k] == -1;)
+X k++;
+X if (k < nl) {
+X int i;
+X s->s_accel = NEW(int, nl-k);
+X if (s->s_accel == NULL) {
+X fprintf(stderr, "no mem to add parser accelerators\n");
+X exit(1);
+X }
+X s->s_lower = k;
+X s->s_upper = nl;
+X for (i = 0; k < nl; i++, k++)
+X s->s_accel[i] = accel[k];
+X }
+X DEL(accel);
+X}
+EOF
+fi
+if test -s 'src/classobject.c'
+then echo '*** I will not over-write existing file src/classobject.c'
+else
+echo 'x - src/classobject.c'
+sed 's/^X//' > 'src/classobject.c' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/* Class object implementation */
+X
+X#include "allobjects.h"
+X
+X#include "structmember.h"
+X
+Xtypedef struct {
+X OB_HEAD
+X object *cl_bases; /* A tuple */
+X object *cl_methods; /* A dictionary */
+X} classobject;
+X
+Xobject *
+Xnewclassobject(bases, methods)
+X object *bases; /* NULL or tuple of classobjects! */
+X object *methods;
+X{
+X classobject *op;
+X op = NEWOBJ(classobject, &Classtype);
+X if (op == NULL)
+X return NULL;
+X if (bases != NULL)
+X INCREF(bases);
+X op->cl_bases = bases;
+X INCREF(methods);
+X op->cl_methods = methods;
+X return (object *) op;
+X}
+X
+X/* Class methods */
+X
+Xstatic void
+Xclass_dealloc(op)
+X classobject *op;
+X{
+X int i;
+X if (op->cl_bases != NULL)
+X DECREF(op->cl_bases);
+X DECREF(op->cl_methods);
+X free((ANY *)op);
+X}
+X
+Xstatic object *
+Xclass_getattr(op, name)
+X register classobject *op;
+X register char *name;
+X{
+X register object *v;
+X v = dictlookup(op->cl_methods, name);
+X if (v != NULL) {
+X INCREF(v);
+X return v;
+X }
+X if (op->cl_bases != NULL) {
+X int n = gettuplesize(op->cl_bases);
+X int i;
+X for (i = 0; i < n; i++) {
+X v = class_getattr(gettupleitem(op->cl_bases, i), name);
+X if (v != NULL)
+X return v;
+X err_clear();
+X }
+X }
+X err_setstr(NameError, name);
+X return NULL;
+X}
+X
+Xtypeobject Classtype = {
+X OB_HEAD_INIT(&Typetype)
+X 0,
+X "class",
+X sizeof(classobject),
+X 0,
+X class_dealloc, /*tp_dealloc*/
+X 0, /*tp_print*/
+X class_getattr, /*tp_getattr*/
+X 0, /*tp_setattr*/
+X 0, /*tp_compare*/
+X 0, /*tp_repr*/
+X 0, /*tp_as_number*/
+X 0, /*tp_as_sequence*/
+X 0, /*tp_as_mapping*/
+X};
+X
+X
+X/* We're not done yet: next, we define class member objects... */
+X
+Xtypedef struct {
+X OB_HEAD
+X classobject *cm_class; /* The class object */
+X object *cm_attr; /* A dictionary */
+X} classmemberobject;
+X
+Xobject *
+Xnewclassmemberobject(class)
+X register object *class;
+X{
+X register classmemberobject *cm;
+X if (!is_classobject(class)) {
+X err_badcall();
+X return NULL;
+X }
+X cm = NEWOBJ(classmemberobject, &Classmembertype);
+X if (cm == NULL)
+X return NULL;
+X INCREF(class);
+X cm->cm_class = (classobject *)class;
+X cm->cm_attr = newdictobject();
+X if (cm->cm_attr == NULL) {
+X DECREF(cm);
+X return NULL;
+X }
+X return (object *)cm;
+X}
+X
+X/* Class member methods */
+X
+Xstatic void
+Xclassmember_dealloc(cm)
+X register classmemberobject *cm;
+X{
+X DECREF(cm->cm_class);
+X if (cm->cm_attr != NULL)
+X DECREF(cm->cm_attr);
+X free((ANY *)cm);
+X}
+X
+Xstatic object *
+Xclassmember_getattr(cm, name)
+X register classmemberobject *cm;
+X register char *name;
+X{
+X register object *v = dictlookup(cm->cm_attr, name);
+X if (v != NULL) {
+X INCREF(v);
+X return v;
+X }
+X v = class_getattr(cm->cm_class, name);
+X if (v == NULL)
+X return v; /* class_getattr() has set the error */
+X if (is_funcobject(v)) {
+X object *w = newclassmethodobject(v, (object *)cm);
+X DECREF(v);
+X return w;
+X }
+X DECREF(v);
+X err_setstr(NameError, name);
+X return NULL;
+X}
+X
+Xstatic int
+Xclassmember_setattr(cm, name, v)
+X classmemberobject *cm;
+X char *name;
+X object *v;
+X{
+X if (v == NULL)
+X return dictremove(cm->cm_attr, name);
+X else
+X return dictinsert(cm->cm_attr, name, v);
+X}
+X
+Xtypeobject Classmembertype = {
+X OB_HEAD_INIT(&Typetype)
+X 0,
+X "class member",
+X sizeof(classmemberobject),
+X 0,
+X classmember_dealloc, /*tp_dealloc*/
+X 0, /*tp_print*/
+X classmember_getattr, /*tp_getattr*/
+X classmember_setattr, /*tp_setattr*/
+X 0, /*tp_compare*/
+X 0, /*tp_repr*/
+X 0, /*tp_as_number*/
+X 0, /*tp_as_sequence*/
+X 0, /*tp_as_mapping*/
+X};
+X
+X
+X/* And finally, here are class method objects */
+X/* (Really methods of class members) */
+X
+Xtypedef struct {
+X OB_HEAD
+X object *cm_func; /* The method function */
+X object *cm_self; /* The object to which this applies */
+X} classmethodobject;
+X
+Xobject *
+Xnewclassmethodobject(func, self)
+X object *func;
+X object *self;
+X{
+X register classmethodobject *cm;
+X if (!is_funcobject(func)) {
+X err_badcall();
+X return NULL;
+X }
+X cm = NEWOBJ(classmethodobject, &Classmethodtype);
+X if (cm == NULL)
+X return NULL;
+X INCREF(func);
+X cm->cm_func = func;
+X INCREF(self);
+X cm->cm_self = self;
+X return (object *)cm;
+X}
+X
+Xobject *
+Xclassmethodgetfunc(cm)
+X register object *cm;
+X{
+X if (!is_classmethodobject(cm)) {
+X err_badcall();
+X return NULL;
+X }
+X return ((classmethodobject *)cm)->cm_func;
+X}
+X
+Xobject *
+Xclassmethodgetself(cm)
+X register object *cm;
+X{
+X if (!is_classmethodobject(cm)) {
+X err_badcall();
+X return NULL;
+X }
+X return ((classmethodobject *)cm)->cm_self;
+X}
+X
+X/* Class method methods */
+X
+X#define OFF(x) offsetof(classmethodobject, x)
+X
+Xstatic struct memberlist classmethod_memberlist[] = {
+X {"cm_func", T_OBJECT, OFF(cm_func)},
+X {"cm_self", T_OBJECT, OFF(cm_self)},
+X {NULL} /* Sentinel */
+X};
+X
+Xstatic object *
+Xclassmethod_getattr(cm, name)
+X register classmethodobject *cm;
+X char *name;
+X{
+X return getmember((char *)cm, classmethod_memberlist, name);
+X}
+X
+Xstatic void
+Xclassmethod_dealloc(cm)
+X register classmethodobject *cm;
+X{
+X DECREF(cm->cm_func);
+X DECREF(cm->cm_self);
+X free((ANY *)cm);
+X}
+X
+Xtypeobject Classmethodtype = {
+X OB_HEAD_INIT(&Typetype)
+X 0,
+X "class method",
+X sizeof(classmethodobject),
+X 0,
+X classmethod_dealloc, /*tp_dealloc*/
+X 0, /*tp_print*/
+X classmethod_getattr, /*tp_getattr*/
+X 0, /*tp_setattr*/
+X 0, /*tp_compare*/
+X 0, /*tp_repr*/
+X 0, /*tp_as_number*/
+X 0, /*tp_as_sequence*/
+X 0, /*tp_as_mapping*/
+X};
+EOF
+fi
+if test -s 'src/intobject.c'
+then echo '*** I will not over-write existing file src/intobject.c'
+else
+echo 'x - src/intobject.c'
+sed 's/^X//' > 'src/intobject.c' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/* Integer object implementation */
+X
+X#include "allobjects.h"
+X
+X/* Standard Booleans */
+X
+Xintobject FalseObject = {
+X OB_HEAD_INIT(&Inttype)
+X 0
+X};
+X
+Xintobject TrueObject = {
+X OB_HEAD_INIT(&Inttype)
+X 1
+X};
+X
+Xstatic object *
+Xerr_ovf()
+X{
+X err_setstr(OverflowError, "integer overflow");
+X return NULL;
+X}
+X
+Xstatic object *
+Xerr_zdiv()
+X{
+X err_setstr(ZeroDivisionError, "integer division by zero");
+X return NULL;
+X}
+X
+X/* Integers are quite normal objects, to make object handling uniform.
+X (Using odd pointers to represent integers would save much space
+X but require extra checks for this special case throughout the code.)
+X Since, a typical Python program spends much of its time allocating
+X and deallocating integers, these operations should be very fast.
+X Therefore we use a dedicated allocation scheme with a much lower
+X overhead (in space and time) than straight malloc(): a simple
+X dedicated free list, filled when necessary with memory from malloc().
+X*/
+X
+X#define BLOCK_SIZE 1000 /* 1K less typical malloc overhead */
+X#define N_INTOBJECTS (BLOCK_SIZE / sizeof(intobject))
+X
+Xstatic intobject *
+Xfill_free_list()
+X{
+X intobject *p, *q;
+X p = NEW(intobject, N_INTOBJECTS);
+X if (p == NULL)
+X return (intobject *)err_nomem();
+X q = p + N_INTOBJECTS;
+X while (--q > p)
+X *(intobject **)q = q-1;
+X *(intobject **)q = NULL;
+X return p + N_INTOBJECTS - 1;
+X}
+X
+Xstatic intobject *free_list = NULL;
+X
+Xobject *
+Xnewintobject(ival)
+X long ival;
+X{
+X register intobject *v;
+X if (free_list == NULL) {
+X if ((free_list = fill_free_list()) == NULL)
+X return NULL;
+X }
+X v = free_list;
+X free_list = *(intobject **)free_list;
+X NEWREF(v);
+X v->ob_type = &Inttype;
+X v->ob_ival = ival;
+X return (object *) v;
+X}
+X
+Xstatic void
+Xint_dealloc(v)
+X intobject *v;
+X{
+X *(intobject **)v = free_list;
+X free_list = v;
+X}
+X
+Xlong
+Xgetintvalue(op)
+X register object *op;
+X{
+X if (!is_intobject(op)) {
+X err_badcall();
+X return -1;
+X }
+X else
+X return ((intobject *)op) -> ob_ival;
+X}
+X
+X/* Methods */
+X
+Xstatic void
+Xint_print(v, fp, flags)
+X intobject *v;
+X FILE *fp;
+X int flags;
+X{
+X fprintf(fp, "%ld", v->ob_ival);
+X}
+X
+Xstatic object *
+Xint_repr(v)
+X intobject *v;
+X{
+X char buf[20];
+X sprintf(buf, "%ld", v->ob_ival);
+X return newstringobject(buf);
+X}
+X
+Xstatic int
+Xint_compare(v, w)
+X intobject *v, *w;
+X{
+X register long i = v->ob_ival;
+X register long j = w->ob_ival;
+X return (i < j) ? -1 : (i > j) ? 1 : 0;
+X}
+X
+Xstatic object *
+Xint_add(v, w)
+X intobject *v;
+X register object *w;
+X{
+X register long a, b, x;
+X if (!is_intobject(w)) {
+X err_badarg();
+X return NULL;
+X }
+X a = v->ob_ival;
+X b = ((intobject *)w) -> ob_ival;
+X x = a + b;
+X if ((x^a) < 0 && (x^b) < 0)
+X return err_ovf();
+X return newintobject(x);
+X}
+X
+Xstatic object *
+Xint_sub(v, w)
+X intobject *v;
+X register object *w;
+X{
+X register long a, b, x;
+X if (!is_intobject(w)) {
+X err_badarg();
+X return NULL;
+X }
+X a = v->ob_ival;
+X b = ((intobject *)w) -> ob_ival;
+X x = a - b;
+X if ((x^a) < 0 && (x^~b) < 0)
+X return err_ovf();
+X return newintobject(x);
+X}
+X
+Xstatic object *
+Xint_mul(v, w)
+X intobject *v;
+X register object *w;
+X{
+X register long a, b;
+X double x;
+X if (!is_intobject(w)) {
+X err_badarg();
+X return NULL;
+X }
+X a = v->ob_ival;
+X b = ((intobject *)w) -> ob_ival;
+X x = (double)a * (double)b;
+X if (x > 0x7fffffff || x < (double) (long) 0x80000000)
+X return err_ovf();
+X return newintobject(a * b);
+X}
+X
+Xstatic object *
+Xint_div(v, w)
+X intobject *v;
+X register object *w;
+X{
+X if (!is_intobject(w)) {
+X err_badarg();
+X return NULL;
+X }
+X if (((intobject *)w) -> ob_ival == 0)
+X return err_zdiv();
+X return newintobject(v->ob_ival / ((intobject *)w) -> ob_ival);
+X}
+X
+Xstatic object *
+Xint_rem(v, w)
+X intobject *v;
+X register object *w;
+X{
+X if (!is_intobject(w)) {
+X err_badarg();
+X return NULL;
+X }
+X if (((intobject *)w) -> ob_ival == 0)
+X return err_zdiv();
+X return newintobject(v->ob_ival % ((intobject *)w) -> ob_ival);
+X}
+X
+Xstatic object *
+Xint_pow(v, w)
+X intobject *v;
+X register object *w;
+X{
+X register long iv, iw, ix;
+X register int neg;
+X if (!is_intobject(w)) {
+X err_badarg();
+X return NULL;
+X }
+X iv = v->ob_ival;
+X iw = ((intobject *)w)->ob_ival;
+X neg = 0;
+X if (iw < 0)
+X neg = 1, iw = -iw;
+X ix = 1;
+X for (; iw > 0; iw--)
+X ix = ix * iv;
+X if (neg) {
+X if (ix == 0)
+X return err_zdiv();
+X ix = 1/ix;
+X }
+X /* XXX How to check for overflow? */
+X return newintobject(ix);
+X}
+X
+Xstatic object *
+Xint_neg(v)
+X intobject *v;
+X{
+X register long a, x;
+X a = v->ob_ival;
+X x = -a;
+X if (a < 0 && x < 0)
+X return err_ovf();
+X return newintobject(x);
+X}
+X
+Xstatic object *
+Xint_pos(v)
+X intobject *v;
+X{
+X INCREF(v);
+X return (object *)v;
+X}
+X
+Xstatic number_methods int_as_number = {
+X int_add, /*tp_add*/
+X int_sub, /*tp_subtract*/
+X int_mul, /*tp_multiply*/
+X int_div, /*tp_divide*/
+X int_rem, /*tp_remainder*/
+X int_pow, /*tp_power*/
+X int_neg, /*tp_negate*/
+X int_pos, /*tp_plus*/
+X};
+X
+Xtypeobject Inttype = {
+X OB_HEAD_INIT(&Typetype)
+X 0,
+X "int",
+X sizeof(intobject),
+X 0,
+X int_dealloc, /*tp_dealloc*/
+X int_print, /*tp_print*/
+X 0, /*tp_getattr*/
+X 0, /*tp_setattr*/
+X int_compare, /*tp_compare*/
+X int_repr, /*tp_repr*/
+X &int_as_number, /*tp_as_number*/
+X 0, /*tp_as_sequence*/
+X 0, /*tp_as_mapping*/
+X};
+EOF
+fi
+echo 'Part 13 out of 21 of pack.out complete.'
+exit 0
diff --git a/shar/python-0.9.1-14-21.shar b/shar/python-0.9.1-14-21.shar
new file mode 100644
index 0000000..c819377
--- /dev/null
+++ b/shar/python-0.9.1-14-21.shar
@@ -0,0 +1,2720 @@
+: This is a shell archive.
+: Extract with 'sh this_file'.
+:
+: Extract part 01 first since it makes all directories
+echo 'Start of pack.out, part 14 out of 21:'
+if test -s 'demo/sgi/audio_stdwin/rec.py'
+then echo '*** I will not over-write existing file demo/sgi/audio_stdwin/rec.py'
+else
+echo 'x - demo/sgi/audio_stdwin/rec.py'
+sed 's/^X//' > 'demo/sgi/audio_stdwin/rec.py' << 'EOF'
+X#! /ufs/guido/bin/sgi/python
+X
+Ximport sys
+Ximport audio
+Ximport stdwin
+X
+Ximport string
+Ximport getopt
+X
+Xfrom stdwinevents import *
+Xfrom Buttons import *
+Xfrom Sliders import *
+X#from Soundogram import Soundogram
+Xfrom VUMeter import VUMeter
+Xfrom WindowParent import WindowParent
+Xfrom HVSplit import HSplit, VSplit
+X
+Xclass TimeOutToggleButton() = ToggleButton():
+X def define(self, parent):
+X self = ToggleButton.define(self, parent)
+X self.parent.need_timer(self)
+X self.timer_hook = 0
+X return self
+X def timer(self):
+X if self.timer_hook:
+X self.timer_hook(self)
+X
+XK = 1024
+XBUFSIZE = 30*8*K
+XRates = [0, 32*K, 16*K, 8*K]
+XMagics = ['', '0032', '0016', '0008']
+X
+Xclass Struct(): pass
+XG = Struct()
+X
+Xdef main():
+X #
+X # Set default state
+X #
+X G.gain = 60
+X G.rate = 3
+X G.nomuting = 0
+X G.savefile = '@rec'
+X #
+X # Set default values
+X #
+X G.data = ''
+X G.playing = 0
+X G.recording = 0
+X G.sogram = 0
+X #
+X # Parse options
+X #
+X optlist, args = getopt.getopt(sys.argv[1:], 'mdg:r:')
+X #
+X for optname, optarg in optlist:
+X if 0: # (So all cases start with elif)
+X pass
+X elif optname = '-d':
+X G.debug = 1
+X elif optname = '-g':
+X G.gain = string.atoi(optarg)
+X if not (0 < G.gain < 256):
+X raise optarg.error, '-g gain out of range'
+X elif optname = '-m':
+X G.nomuting = (not G.nomuting)
+X elif optname = '-r':
+X G.rate = string.atoi(optarg)
+X if not (1 <= G.rate <= 3):
+X raise optarg.error, '-r rate out of range'
+X #
+X if args:
+X G.savefile = args[0]
+X #
+X # Initialize the sound package
+X #
+X audio.setoutgain(G.nomuting * G.gain) # Silence the speaker
+X audio.setrate(G.rate)
+X #
+X # Create the WindowParent and VSplit
+X #
+X G.window = WindowParent().create('Recorder', (0, 0))
+X w = G.vsplit = VSplit().create(G.window)
+X #
+X # VU-meter
+X #
+X G.vubtn = VUMeter().define(w)
+X #
+X # Radiobuttons for rates
+X #
+X r1btn = RadioButton().definetext(w, '32 K/sec')
+X r1btn.on_hook = rate_hook
+X r1btn.rate = 1
+X #
+X r2btn = RadioButton().definetext(w, '16 K/sec')
+X r2btn.on_hook = rate_hook
+X r2btn.rate = 2
+X #
+X r3btn = RadioButton().definetext(w, '8 K/sec')
+X r3btn.on_hook = rate_hook
+X r3btn.rate = 3
+X #
+X radios = [r1btn, r2btn, r3btn]
+X r1btn.group = r2btn.group = r3btn.group = radios
+X for r in radios:
+X if r.rate = G.rate: r.select(1)
+X #
+X # Other controls
+X #
+X G.recbtn = TimeOutToggleButton().definetext(w, 'Record')
+X G.recbtn.on_hook = record_on_hook
+X G.recbtn.timer_hook = record_timer_hook
+X G.recbtn.off_hook = record_off_hook
+X #
+X G.mutebtn = CheckButton().definetext(w, 'Mute')
+X G.mutebtn.select(not G.nomuting)
+X G.mutebtn.hook = mute_hook
+X #
+X G.playbtn = TimeOutToggleButton().definetext(w, 'Playback')
+X G.playbtn.on_hook = play_on_hook
+X G.playbtn.timer_hook = play_timer_hook
+X G.playbtn.off_hook = play_off_hook
+X #
+X G.gainbtn = ComplexSlider().define(w)
+X G.gainbtn.settexts(' Volume: ', ' ')
+X G.gainbtn.setminvalmax(0, G.gain, 255)
+X G.gainbtn.sethook(gain_hook)
+X #
+X G.sizebtn = Label().definetext(w, `len(G.data)` + ' bytes')
+X #
+X #G.showbtn = PushButton().definetext(w, 'Sound-o-gram...')
+X #G.showbtn.hook = show_hook
+X #
+X G.savebtn = PushButton().definetext(w, 'Save...')
+X G.savebtn.hook = save_hook
+X #
+X G.quitbtn = PushButton().definetext(w, 'Quit')
+X G.quitbtn.hook = quit_hook
+X G.playbtn.enable(0)
+X G.savebtn.enable(0)
+X #G.showbtn.enable(0)
+X start_vu()
+X G.window.realize()
+X #
+X # Event loop
+X #
+X while 1:
+X e = stdwin.getevent()
+X G.window.dispatch(e)
+X
+X# XXX Disabled...
+Xdef show_hook(self):
+X savetext = self.text
+X self.settext('Be patient...')
+X close_sogram()
+X stdwin.setdefwinsize(400, 300)
+X win = stdwin.open('Sound-o-gram')
+X G.sogram = Soundogram().define(win, G.data)
+X win.buttons = [G.sogram]
+X self.settext(savetext)
+X
+Xdef close_sogram():
+X if G.sogram:
+X # Break circular references
+X G.sogram.win.buttons[:] = []
+X del G.sogram.win
+X G.sogram = 0
+X
+Xdef mute_hook(self):
+X G.nomuting = (not self.selected)
+X audio.setoutgain(G.nomuting * G.gain)
+X
+Xdef rate_hook(self):
+X G.rate = self.rate
+X audio.setrate(G.rate)
+X
+Xdef record_on_hook(self):
+X stop_vu()
+X close_sogram()
+X audio.setrate(G.rate)
+X audio.setoutgain(G.nomuting * G.gain)
+X audio.start_recording(BUFSIZE)
+X G.recording = 1
+X G.playbtn.enable(0)
+X G.window.settimer(10 * BUFSIZE / Rates[G.rate])
+X
+Xdef record_timer_hook(self):
+X if G.recording:
+X if audio.poll_recording():
+X self.hilite(0)
+X record_off_hook(self)
+X else:
+X self.parent.settimer(5)
+X
+Xdef record_off_hook(self):
+X if not G.recording:
+X return
+X G.data = audio.stop_recording()
+X G.recording = 0
+X G.sizebtn.settext(`len(G.data)` + ' bytes')
+X audio.setoutgain(G.nomuting * G.gain)
+X G.playbtn.enable((len(G.data) > 0))
+X G.savebtn.enable((len(G.data) > 0))
+X #G.showbtn.enable((len(G.data) > 0))
+X G.window.settimer(0)
+X start_vu()
+X
+Xdef play_on_hook(self):
+X stop_vu()
+X audio.setrate(G.rate)
+X audio.setoutgain(G.gain)
+X audio.start_playing(G.data)
+X G.playing = 1
+X G.recbtn.enable(0)
+X G.window.settimer(max(10 * len(G.data) / Rates[G.rate], 1))
+X
+Xdef play_timer_hook(self):
+X if G.playing:
+X if audio.poll_playing():
+X self.hilite(0)
+X play_off_hook(self)
+X else:
+X self.parent.settimer(5)
+X
+Xdef play_off_hook(self):
+X if not G.playing:
+X return
+X x = audio.stop_playing()
+X G.playing = 0
+X audio.setoutgain(G.nomuting * G.gain)
+X G.recbtn.enable(1)
+X G.window.settimer(0)
+X start_vu()
+X
+Xdef gain_hook(self):
+X G.gain = self.val
+X if G.playing or G.nomuting: audio.setoutgain(G.gain)
+X
+Xdef save_hook(self):
+X if not G.data:
+X stdwin.fleep()
+X else:
+X prompt = 'Store sampled data on file: '
+X try:
+X G.savefile = stdwin.askfile(prompt, G.savefile, 1)
+X except KeyboardInterrupt:
+X return
+X try:
+X fp = open(G.savefile, 'w')
+X fp.write(Magics[G.rate] + G.data)
+X except:
+X stdwin.message('Cannot create ' + file)
+X
+Xdef stop_vu():
+X G.vubtn.stop()
+X
+Xdef start_vu():
+X G.vubtn.start()
+X
+XExit = 'exit' # exception
+X
+Xdef quit_hook(self):
+X raise Exit, 0
+X
+Xtry:
+X try:
+X main()
+X finally:
+X audio.setoutgain(0)
+Xexcept Exit, sts:
+X sys.exit(sts)
+EOF
+chmod +x 'demo/sgi/audio_stdwin/rec.py'
+fi
+if test -s 'lib/TclShell.py'
+then echo '*** I will not over-write existing file lib/TclShell.py'
+else
+echo 'x - lib/TclShell.py'
+sed 's/^X//' > 'lib/TclShell.py' << 'EOF'
+X# Tcl-based shell (for the Macintosh)
+X
+Ximport TclUtil
+Ximport Tcl
+Xfrom Tcl import Interpreter, TclRuntimeError
+Ximport mac
+Ximport macpath
+Xfrom macpath import isfile, isdir, exists
+X
+XUsageError = TclRuntimeError
+X
+Xclass ShellInterpreter() = Interpreter():
+X #
+X def ResetVariables(interp):
+X interp.globals['ps1'] = '$ '
+X interp.globals['ps2'] = '> '
+X interp.globals['home'] = mac.getcwd()
+X #
+X def DefineCommands(interp):
+X interp.commands['cd'] = interp.CdCmd
+X interp.commands['grep'] = interp.GrepCmd
+X interp.commands['ls'] = interp.LsCmd
+X interp.commands['mkdir'] = interp.MkdirCmd
+X interp.commands['mv'] = interp.MvCmd
+X interp.commands['pg'] = interp.PgCmd
+X interp.commands['pwd'] = interp.PwdCmd
+X interp.commands['rm'] = interp.RmCmd
+X interp.commands['rmdir'] = interp.RmdirCmd
+X interp.commands['sync'] = interp.SyncCmd
+X #
+X def Reset(interp):
+X interp.ResetVariables()
+X interp.DefineCommands()
+X #
+X def Create(interp):
+X interp = Interpreter.Create(interp) # initialize base class
+X interp.Reset()
+X return interp
+X #
+X # Command-implementing functions
+X #
+X def CdCmd(interp, argv):
+X if len(argv) > 2:
+X raise UsageError, 'usage: cd [dirname]'
+X if len(argv) = 2:
+X chdirto(argv[1])
+X else:
+X chdirto(interp.globals['home'])
+X return ''
+X #
+X def GrepCmd(interp, argv):
+X if len(argv) < 3:
+X raise UsageError, 'usage: grep regexp file ...'
+X import regexp
+X try:
+X prog = regexp.compile(argv[1])
+X except regexp.error, msg:
+X raise TclRuntimeError, \
+X ('grep', argv[1], ': bad regexp :', msg)
+X for file in argv[2:]:
+X grepfile(prog, file)
+X return ''
+X #
+X def LsCmd(interp, argv):
+X if len(argv) < 2:
+X lsdir(':')
+X else:
+X for dirname in argv[1:]:
+X lsdir(dirname)
+X return ''
+X #
+X def MkdirCmd(interp, argv):
+X if len(argv) < 2:
+X raise UsageError, 'usage: mkdir name ...'
+X for name in argv[1:]:
+X makedir(name)
+X return ''
+X #
+X def MvCmd(interp, argv):
+X if len(argv) <> 3:
+X raise UsageError, 'usage: mv src dst'
+X src, dst = argv[1], argv[2]
+X if not exists(src):
+X raise TclRuntimeError, \
+X ('mv', src, dst, ': source does not exist')
+X if exists(dst):
+X raise TclRuntimeError, \
+X ('mv', src, dst, ': destination already exists')
+X try:
+X mac.rename(src, dst)
+X except mac.error, msg:
+X raise TclRuntimeError, \
+X (src, dst, ': rename failed :', msg)
+X return ''
+X #
+X def PgCmd(interp, argv):
+X if len(argv) < 2:
+X raise UsageError, 'usage: page file ...'
+X for name in argv[1:]:
+X pagefile(name)
+X return ''
+X #
+X def PwdCmd(interp, argv):
+X if len(argv) > 1:
+X raise UsageError, 'usage: pwd'
+X else:
+X return mac.getcwd()
+X #
+X def RmCmd(interp, argv):
+X if len(argv) < 2:
+X raise UsageError, 'usage: rm file ...'
+X for name in argv[1:]:
+X remove(name)
+X return ''
+X #
+X def RmdirCmd(interp, argv):
+X if len(argv) < 2:
+X raise UsageError, 'usage: rmdir dir ...'
+X for name in argv[1:]:
+X rmdir(name)
+X return ''
+X #
+X def SyncCmd(interp, argv):
+X if len(argv) > 1:
+X raise UsageError, 'usage: sync'
+X try:
+X mac.sync()
+X except mac.error, msg:
+X raise TclRuntimeError, ('sync failed :', msg)
+X #
+X
+Xdef chdirto(dirname):
+X try:
+X mac.chdir(dirname)
+X except mac.error, msg:
+X raise TclRuntimeError, (dirname, ': chdir failed :', msg)
+X
+Xdef grepfile(prog, file):
+X try:
+X fp = open(file, 'r')
+X except RuntimeError, msg:
+X raise TclRuntimeError, (file, ': open failed :', msg)
+X lineno = 0
+X while 1:
+X line = fp.readline()
+X if not line: break
+X lineno = lineno+1
+X if prog.exec(line):
+X print file+'('+`lineno`+'):', line,
+X
+Xdef lsdir(dirname):
+X if not isdir(dirname):
+X print dirname, ': no such directory'
+X return
+X names = mac.listdir(dirname)
+X lsfiles(names, dirname)
+X
+Xdef lsfiles(names, dirname):
+X names = names[:] # Make a copy so we can modify it
+X for i in range(len(names)):
+X name = names[i]
+X if isdir(macpath.cat(dirname, name)):
+X names[i] = ':' + name + ':'
+X columnize(names)
+X
+Xdef makedir(name):
+X if exists(name):
+X print name, ': already exists'
+X return
+X try:
+X mac.mkdir(name, 0777)
+X except mac.error, msg:
+X raise TclRuntimeError, (name, ': mkdir failed :', msg)
+X
+Xdef pagefile(name):
+X import string
+X if not isfile(name):
+X print name, ': no such file'
+X return
+X LINES = 24 - 1
+X # For THINK C 3.0, make the path absolute:
+X # if not macpath.isabs(name):
+X # name = macpath.cat(mac.getcwd(), name)
+X try:
+X fp = open(name, 'r')
+X except RuntimeError, msg:
+X raise TclRuntimeError, (name, ': open failed :', msg)
+X line = fp.readline()
+X while line:
+X for i in range(LINES):
+X print line,
+X line = fp.readline()
+X if not line: break
+X if line:
+X try:
+X more = raw_input('[more]')
+X except (EOFError, KeyboardInterrupt):
+X print
+X break
+X if string.strip(more)[:1] in ('q', 'Q'):
+X break
+X
+Xdef remove(name):
+X if not isfile(name):
+X print name, ': no such file'
+X return
+X try:
+X mac.unlink(name)
+X except mac.error, msg:
+X raise TclRuntimeError, (name, ': unlink failed :', msg)
+X
+Xdef rmdir(name):
+X if not isdir(name):
+X raise TclRuntimeError, (name, ': no such directory')
+X try:
+X mac.rmdir(name)
+X except mac.error, msg:
+X raise TclRuntimeError, (name, ': rmdir failed :', msg)
+X
+Xdef printlist(list):
+X for word in list:
+X print word,
+X
+Xdef columnize(list):
+X import string
+X COLUMNS = 80-1
+X n = len(list)
+X colwidth = maxwidth(list)
+X ncols = (COLUMNS + 1) / (colwidth + 1)
+X if ncols < 1: ncols = 1
+X nrows = (n + ncols - 1) / ncols
+X for irow in range(nrows):
+X line = ''
+X for icol in range(ncols):
+X i = irow + nrows*icol
+X if 0 <= i < n:
+X word = list[i]
+X if i+nrows < n:
+X word = string.ljust(word, colwidth)
+X if icol > 0:
+X word = ' ' + word
+X line = line + word
+X print line
+X
+Xdef maxwidth(list):
+X width = 0
+X for word in list:
+X if len(word) > width:
+X width = len(word)
+X return width
+X
+Xthe_interpreter = ShellInterpreter().Create()
+X
+Xdef main():
+X Tcl.MainLoop(the_interpreter)
+EOF
+fi
+if test -s 'lib/tablewin.py'
+then echo '*** I will not over-write existing file lib/tablewin.py'
+else
+echo 'x - lib/tablewin.py'
+sed 's/^X//' > 'lib/tablewin.py' << 'EOF'
+X# Module 'tablewin'
+X
+X# Display a table, with per-item actions:
+X
+X# A1 | A2 | A3 | .... | AN
+X# B1 | B2 | B3 | .... | BN
+X# C1 | C2 | C3 | .... | CN
+X# .. | .. | .. | .... | ..
+X# Z1 | Z2 | Z3 | .... | ZN
+X
+X# Not all columns need to have the same length.
+X# The data structure is a list of columns;
+X# each column is a list of items.
+X# Each item is a pair of a string and an action procedure.
+X# The first item may be a column title.
+X
+Ximport stdwin
+Ximport gwin
+X
+Xdef open(title, data): # Public function to open a table window
+X #
+X # Set geometry parameters (one day, these may be changeable)
+X #
+X margin = stdwin.textwidth(' ')
+X lineheight = stdwin.lineheight()
+X #
+X # Geometry calculations
+X #
+X colstarts = [0]
+X totwidth = 0
+X maxrows = 0
+X for coldata in data:
+X # Height calculations
+X rows = len(coldata)
+X if rows > maxrows: maxrows = rows
+X # Width calculations
+X width = colwidth(coldata) + margin
+X totwidth = totwidth + width
+X colstarts.append(totwidth)
+X #
+X # Calculate document and window height
+X #
+X docwidth, docheight = totwidth, maxrows*lineheight
+X winwidth, winheight = docwidth, docheight
+X if winwidth > stdwin.textwidth('n')*100: winwidth = 0
+X if winheight > stdwin.lineheight()*30: winheight = 0
+X #
+X # Create the window
+X #
+X stdwin.setdefwinsize(winwidth, winheight)
+X w = gwin.open(title)
+X #
+X # Set properties and override methods
+X #
+X w.data = data
+X w.margin = margin
+X w.lineheight = lineheight
+X w.colstarts = colstarts
+X w.totwidth = totwidth
+X w.maxrows = maxrows
+X w.selection = (-1, -1)
+X w.lastselection = (-1, -1)
+X w.selshown = 0
+X w.setdocsize(docwidth, docheight)
+X w.draw = draw
+X w.mup = mup
+X w.arrow = arrow
+X #
+X # Return
+X #
+X return w
+X
+Xdef update(w, data): # Change the data
+X #
+X # Hide selection
+X #
+X hidesel(w, w.begindrawing())
+X #
+X # Get old geometry parameters
+X #
+X margin = w.margin
+X lineheight = w.lineheight
+X #
+X # Geometry calculations
+X #
+X colstarts = [0]
+X totwidth = 0
+X maxrows = 0
+X for coldata in data:
+X # Height calculations
+X rows = len(coldata)
+X if rows > maxrows: maxrows = rows
+X # Width calculations
+X width = colwidth(coldata) + margin
+X totwidth = totwidth + width
+X colstarts.append(totwidth)
+X #
+X # Calculate document and window height
+X #
+X docwidth, docheight = totwidth, maxrows*lineheight
+X #
+X # Set changed properties and change window size
+X #
+X w.data = data
+X w.colstarts = colstarts
+X w.totwidth = totwidth
+X w.maxrows = maxrows
+X w.change((0, 0), (10000, 10000))
+X w.setdocsize(docwidth, docheight)
+X w.change((0, 0), (docwidth, docheight))
+X #
+X # Show selection, or forget it if out of range
+X #
+X showsel(w, w.begindrawing())
+X if not w.selshown: w.selection = (-1, -1)
+X
+Xdef colwidth(coldata): # Subroutine to calculate column width
+X maxwidth = 0
+X for string, action in coldata:
+X width = stdwin.textwidth(string)
+X if width > maxwidth: maxwidth = width
+X return maxwidth
+X
+Xdef draw(w, ((left, top), (right, bottom))): # Draw method
+X ileft = whichcol(w, left)
+X iright = whichcol(w, right-1) + 1
+X if iright > len(w.data): iright = len(w.data)
+X itop = divmod(top, w.lineheight)[0]
+X if itop < 0: itop = 0
+X ibottom, remainder = divmod(bottom, w.lineheight)
+X if remainder: ibottom = ibottom + 1
+X d = w.begindrawing()
+X if ileft <= w.selection[0] < iright:
+X if itop <= w.selection[1] < ibottom:
+X hidesel(w, d)
+X d.erase((left, top), (right, bottom))
+X for i in range(ileft, iright):
+X col = w.data[i]
+X jbottom = len(col)
+X if ibottom < jbottom: jbottom = ibottom
+X h = w.colstarts[i]
+X v = itop * w.lineheight
+X for j in range(itop, jbottom):
+X string, action = col[j]
+X d.text((h, v), string)
+X v = v + w.lineheight
+X showsel(w, d)
+X
+Xdef mup(w, detail): # Mouse up method
+X (h, v), nclicks, button, mask = detail
+X icol = whichcol(w, h)
+X if 0 <= icol < len(w.data):
+X irow = divmod(v, w.lineheight)[0]
+X col = w.data[icol]
+X if 0 <= irow < len(col):
+X string, action = col[irow]
+X action(w, string, (icol, irow), detail)
+X
+Xdef whichcol(w, h): # Return column number (may be >= len(w.data))
+X for icol in range(0, len(w.data)):
+X if h < w.colstarts[icol+1]:
+X return icol
+X return len(w.data)
+X
+Xdef arrow(w, type):
+X import stdwinsupport
+X S = stdwinsupport
+X if type = S.wc_left:
+X incr = -1, 0
+X elif type = S.wc_up:
+X incr = 0, -1
+X elif type = S.wc_right:
+X incr = 1, 0
+X elif type = S.wc_down:
+X incr = 0, 1
+X else:
+X return
+X icol, irow = w.lastselection
+X icol = icol + incr[0]
+X if icol < 0: icol = len(w.data)-1
+X if icol >= len(w.data): icol = 0
+X if 0 <= icol < len(w.data):
+X irow = irow + incr[1]
+X if irow < 0: irow = len(w.data[icol]) - 1
+X if irow >= len(w.data[icol]): irow = 0
+X else:
+X irow = 0
+X if 0 <= icol < len(w.data) and 0 <= irow < len(w.data[icol]):
+X w.lastselection = icol, irow
+X string, action = w.data[icol][irow]
+X detail = (0, 0), 1, 1, 1
+X action(w, string, (icol, irow), detail)
+X
+X
+X# Selection management
+X# TO DO: allow multiple selected entries
+X
+Xdef select(w, selection): # Public function to set the item selection
+X d = w.begindrawing()
+X hidesel(w, d)
+X w.selection = selection
+X showsel(w, d)
+X if w.selshown: lastselection = selection
+X
+Xdef hidesel(w, d): # Hide the selection, if shown
+X if w.selshown: invertsel(w, d)
+X
+Xdef showsel(w, d): # Show the selection, if hidden
+X if not w.selshown: invertsel(w, d)
+X
+Xdef invertsel(w, d): # Invert the selection, if valid
+X icol, irow = w.selection
+X if 0 <= icol < len(w.data) and 0 <= irow < len(w.data[icol]):
+X left = w.colstarts[icol]
+X right = w.colstarts[icol+1]
+X top = irow * w.lineheight
+X bottom = (irow+1) * w.lineheight
+X d.invert((left, top), (right, bottom))
+X w.selshown = (not w.selshown)
+X
+X
+X# Demonstration
+X
+Xdef demo_action(w, string, (icol, irow), detail): # Action function for demo
+X select(w, (irow, icol))
+X
+Xdef demo(): # Demonstration
+X da = demo_action # shorthand
+X col0 = [('a1', da), ('bbb1', da), ('c1', da)]
+X col1 = [('a2', da), ('bbb2', da)]
+X col2 = [('a3', da), ('b3', da), ('c3', da), ('d4', da), ('d5', da)]
+X col3 = []
+X for i in range(1, 31): col3.append('xxx' + `i`, da)
+X data = [col0, col1, col2, col3]
+X w = open('tablewin.demo', data)
+X gwin.mainloop()
+X return w
+EOF
+fi
+if test -s 'src/fileobject.c'
+then echo '*** I will not over-write existing file src/fileobject.c'
+else
+echo 'x - src/fileobject.c'
+sed 's/^X//' > 'src/fileobject.c' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/* File object implementation */
+X
+X/* XXX This should become a built-in module 'io'. It should support more
+X functionality, better exception handling for invalid calls, etc.
+X (Especially reading on a write-only file or vice versa!)
+X It should also cooperate with posix to support popen(), which should
+X share most code but have a special close function. */
+X
+X#include "allobjects.h"
+X
+X#include "errno.h"
+X#ifndef errno
+Xextern int errno;
+X#endif
+X
+Xtypedef struct {
+X OB_HEAD
+X FILE *f_fp;
+X object *f_name;
+X object *f_mode;
+X /* XXX Should move the 'need space' on printing flag here */
+X} fileobject;
+X
+XFILE *
+Xgetfilefile(f)
+X object *f;
+X{
+X if (!is_fileobject(f)) {
+X err_badcall();
+X return NULL;
+X }
+X return ((fileobject *)f)->f_fp;
+X}
+X
+Xobject *
+Xnewopenfileobject(fp, name, mode)
+X FILE *fp;
+X char *name;
+X char *mode;
+X{
+X fileobject *f = NEWOBJ(fileobject, &Filetype);
+X if (f == NULL)
+X return NULL;
+X f->f_fp = NULL;
+X f->f_name = newstringobject(name);
+X f->f_mode = newstringobject(mode);
+X if (f->f_name == NULL || f->f_mode == NULL) {
+X DECREF(f);
+X return NULL;
+X }
+X f->f_fp = fp;
+X return (object *) f;
+X}
+X
+Xobject *
+Xnewfileobject(name, mode)
+X char *name, *mode;
+X{
+X fileobject *f;
+X FILE *fp;
+X f = (fileobject *) newopenfileobject((FILE *)NULL, name, mode);
+X if (f == NULL)
+X return NULL;
+X#ifdef THINK_C
+X if (*mode == '*') {
+X FILE *fopenRF();
+X f->f_fp = fopenRF(name, mode+1);
+X }
+X else
+X#endif
+X f->f_fp = fopen(name, mode);
+X if (f->f_fp == NULL) {
+X err_errno(RuntimeError);
+X DECREF(f);
+X return NULL;
+X }
+X return (object *)f;
+X}
+X
+X/* Methods */
+X
+Xstatic void
+Xfile_dealloc(f)
+X fileobject *f;
+X{
+X if (f->f_fp != NULL)
+X fclose(f->f_fp);
+X if (f->f_name != NULL)
+X DECREF(f->f_name);
+X if (f->f_mode != NULL)
+X DECREF(f->f_mode);
+X free((char *)f);
+X}
+X
+Xstatic void
+Xfile_print(f, fp, flags)
+X fileobject *f;
+X FILE *fp;
+X int flags;
+X{
+X fprintf(fp, "<%s file ", f->f_fp == NULL ? "closed" : "open");
+X printobject(f->f_name, fp, flags);
+X fprintf(fp, ", mode ");
+X printobject(f->f_mode, fp, flags);
+X fprintf(fp, ">");
+X}
+X
+Xstatic object *
+Xfile_repr(f)
+X fileobject *f;
+X{
+X char buf[300];
+X /* XXX This differs from file_print if the filename contains
+X quotes or other funny characters. */
+X sprintf(buf, "<%s file '%.256s', mode '%.10s'>",
+X f->f_fp == NULL ? "closed" : "open",
+X getstringvalue(f->f_name),
+X getstringvalue(f->f_mode));
+X return newstringobject(buf);
+X}
+X
+Xstatic object *
+Xfile_close(f, args)
+X fileobject *f;
+X object *args;
+X{
+X if (args != NULL) {
+X err_badarg();
+X return NULL;
+X }
+X if (f->f_fp != NULL) {
+X fclose(f->f_fp);
+X f->f_fp = NULL;
+X }
+X INCREF(None);
+X return None;
+X}
+X
+Xstatic object *
+Xfile_read(f, args)
+X fileobject *f;
+X object *args;
+X{
+X int n;
+X object *v;
+X if (f->f_fp == NULL) {
+X err_badarg();
+X return NULL;
+X }
+X if (args == NULL || !is_intobject(args)) {
+X err_badarg();
+X return NULL;
+X }
+X n = getintvalue(args);
+X if (n < 0) {
+X err_badarg();
+X return NULL;
+X }
+X v = newsizedstringobject((char *)NULL, n);
+X if (v == NULL)
+X return NULL;
+X n = fread(getstringvalue(v), 1, n, f->f_fp);
+X /* EOF is reported as an empty string */
+X /* XXX should detect real I/O errors? */
+X resizestring(&v, n);
+X return v;
+X}
+X
+X/* XXX Should this be unified with raw_input()? */
+X
+Xstatic object *
+Xfile_readline(f, args)
+X fileobject *f;
+X object *args;
+X{
+X int n;
+X object *v;
+X if (f->f_fp == NULL) {
+X err_badarg();
+X return NULL;
+X }
+X if (args == NULL) {
+X n = 10000; /* XXX should really be unlimited */
+X }
+X else if (is_intobject(args)) {
+X n = getintvalue(args);
+X if (n < 0) {
+X err_badarg();
+X return NULL;
+X }
+X }
+X else {
+X err_badarg();
+X return NULL;
+X }
+X v = newsizedstringobject((char *)NULL, n);
+X if (v == NULL)
+X return NULL;
+X#ifndef THINK_C_3_0
+X /* XXX Think C 3.0 wrongly reads up to n characters... */
+X n = n+1;
+X#endif
+X if (fgets(getstringvalue(v), n, f->f_fp) == NULL) {
+X /* EOF is reported as an empty string */
+X /* XXX should detect real I/O errors? */
+X n = 0;
+X }
+X else {
+X n = strlen(getstringvalue(v));
+X }
+X resizestring(&v, n);
+X return v;
+X}
+X
+Xstatic object *
+Xfile_write(f, args)
+X fileobject *f;
+X object *args;
+X{
+X int n, n2;
+X if (f->f_fp == NULL) {
+X err_badarg();
+X return NULL;
+X }
+X if (args == NULL || !is_stringobject(args)) {
+X err_badarg();
+X return NULL;
+X }
+X errno = 0;
+X n2 = fwrite(getstringvalue(args), 1, n = getstringsize(args), f->f_fp);
+X if (n2 != n) {
+X if (errno == 0)
+X errno = EIO;
+X err_errno(RuntimeError);
+X return NULL;
+X }
+X INCREF(None);
+X return None;
+X}
+X
+Xstatic struct methodlist file_methods[] = {
+X {"write", file_write},
+X {"read", file_read},
+X {"readline", file_readline},
+X {"close", file_close},
+X {NULL, NULL} /* sentinel */
+X};
+X
+Xstatic object *
+Xfile_getattr(f, name)
+X fileobject *f;
+X char *name;
+X{
+X return findmethod(file_methods, (object *)f, name);
+X}
+X
+Xtypeobject Filetype = {
+X OB_HEAD_INIT(&Typetype)
+X 0,
+X "file",
+X sizeof(fileobject),
+X 0,
+X file_dealloc, /*tp_dealloc*/
+X file_print, /*tp_print*/
+X file_getattr, /*tp_getattr*/
+X 0, /*tp_setattr*/
+X 0, /*tp_compare*/
+X file_repr, /*tp_repr*/
+X};
+EOF
+fi
+if test -s 'src/floatobject.c'
+then echo '*** I will not over-write existing file src/floatobject.c'
+else
+echo 'x - src/floatobject.c'
+sed 's/^X//' > 'src/floatobject.c' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/* Float object implementation */
+X
+X/* XXX There should be overflow checks here, but it's hard to check
+X for any kind of float exception without losing portability. */
+X
+X#include "allobjects.h"
+X
+X#include <errno.h>
+X#ifndef errno
+Xextern int errno;
+X#endif
+X
+X#include <ctype.h>
+X#include <math.h>
+X
+X#ifndef THINK_C
+Xextern double fmod PROTO((double, double));
+Xextern double pow PROTO((double, double));
+X#endif
+X
+Xobject *
+Xnewfloatobject(fval)
+X double fval;
+X{
+X /* For efficiency, this code is copied from newobject() */
+X register floatobject *op = (floatobject *) malloc(sizeof(floatobject));
+X if (op == NULL)
+X return err_nomem();
+X NEWREF(op);
+X op->ob_type = &Floattype;
+X op->ob_fval = fval;
+X return (object *) op;
+X}
+X
+Xdouble
+Xgetfloatvalue(op)
+X object *op;
+X{
+X if (!is_floatobject(op)) {
+X err_badarg();
+X return -1;
+X }
+X else
+X return ((floatobject *)op) -> ob_fval;
+X}
+X
+X/* Methods */
+X
+Xstatic void
+Xfloat_buf_repr(buf, v)
+X char *buf;
+X floatobject *v;
+X{
+X register char *cp;
+X /* Subroutine for float_repr and float_print.
+X We want float numbers to be recognizable as such,
+X i.e., they should contain a decimal point or an exponent.
+X However, %g may print the number as an integer;
+X in such cases, we append ".0" to the string. */
+X sprintf(buf, "%.12g", v->ob_fval);
+X cp = buf;
+X if (*cp == '-')
+X cp++;
+X for (; *cp != '\0'; cp++) {
+X /* Any non-digit means it's not an integer;
+X this takes care of NAN and INF as well. */
+X if (!isdigit(*cp))
+X break;
+X }
+X if (*cp == '\0') {
+X *cp++ = '.';
+X *cp++ = '0';
+X *cp++ = '\0';
+X }
+X}
+X
+Xstatic void
+Xfloat_print(v, fp, flags)
+X floatobject *v;
+X FILE *fp;
+X int flags;
+X{
+X char buf[100];
+X float_buf_repr(buf, v);
+X fputs(buf, fp);
+X}
+X
+Xstatic object *
+Xfloat_repr(v)
+X floatobject *v;
+X{
+X char buf[100];
+X float_buf_repr(buf, v);
+X return newstringobject(buf);
+X}
+X
+Xstatic int
+Xfloat_compare(v, w)
+X floatobject *v, *w;
+X{
+X double i = v->ob_fval;
+X double j = w->ob_fval;
+X return (i < j) ? -1 : (i > j) ? 1 : 0;
+X}
+X
+Xstatic object *
+Xfloat_add(v, w)
+X floatobject *v;
+X object *w;
+X{
+X if (!is_floatobject(w)) {
+X err_badarg();
+X return NULL;
+X }
+X return newfloatobject(v->ob_fval + ((floatobject *)w) -> ob_fval);
+X}
+X
+Xstatic object *
+Xfloat_sub(v, w)
+X floatobject *v;
+X object *w;
+X{
+X if (!is_floatobject(w)) {
+X err_badarg();
+X return NULL;
+X }
+X return newfloatobject(v->ob_fval - ((floatobject *)w) -> ob_fval);
+X}
+X
+Xstatic object *
+Xfloat_mul(v, w)
+X floatobject *v;
+X object *w;
+X{
+X if (!is_floatobject(w)) {
+X err_badarg();
+X return NULL;
+X }
+X return newfloatobject(v->ob_fval * ((floatobject *)w) -> ob_fval);
+X}
+X
+Xstatic object *
+Xfloat_div(v, w)
+X floatobject *v;
+X object *w;
+X{
+X if (!is_floatobject(w)) {
+X err_badarg();
+X return NULL;
+X }
+X if (((floatobject *)w) -> ob_fval == 0) {
+X err_setstr(ZeroDivisionError, "float division by zero");
+X return NULL;
+X }
+X return newfloatobject(v->ob_fval / ((floatobject *)w) -> ob_fval);
+X}
+X
+Xstatic object *
+Xfloat_rem(v, w)
+X floatobject *v;
+X object *w;
+X{
+X double wx;
+X if (!is_floatobject(w)) {
+X err_badarg();
+X return NULL;
+X }
+X wx = ((floatobject *)w) -> ob_fval;
+X if (wx == 0.0) {
+X err_setstr(ZeroDivisionError, "float division by zero");
+X return NULL;
+X }
+X return newfloatobject(fmod(v->ob_fval, wx));
+X}
+X
+Xstatic object *
+Xfloat_pow(v, w)
+X floatobject *v;
+X object *w;
+X{
+X double iv, iw, ix;
+X if (!is_floatobject(w)) {
+X err_badarg();
+X return NULL;
+X }
+X iv = v->ob_fval;
+X iw = ((floatobject *)w)->ob_fval;
+X if (iw == 0.0)
+X return newfloatobject(1.0); /* x**0 is always 1, even 0**0 */
+X errno = 0;
+X ix = pow(iv, iw);
+X if (errno != 0) {
+X /* XXX could it be another type of error? */
+X err_errno(OverflowError);
+X return NULL;
+X }
+X return newfloatobject(ix);
+X}
+X
+Xstatic object *
+Xfloat_neg(v)
+X floatobject *v;
+X{
+X return newfloatobject(-v->ob_fval);
+X}
+X
+Xstatic object *
+Xfloat_pos(v)
+X floatobject *v;
+X{
+X return newfloatobject(v->ob_fval);
+X}
+X
+Xstatic number_methods float_as_number = {
+X float_add, /*tp_add*/
+X float_sub, /*tp_subtract*/
+X float_mul, /*tp_multiply*/
+X float_div, /*tp_divide*/
+X float_rem, /*tp_remainder*/
+X float_pow, /*tp_power*/
+X float_neg, /*tp_negate*/
+X float_pos, /*tp_plus*/
+X};
+X
+Xtypeobject Floattype = {
+X OB_HEAD_INIT(&Typetype)
+X 0,
+X "float",
+X sizeof(floatobject),
+X 0,
+X free, /*tp_dealloc*/
+X float_print, /*tp_print*/
+X 0, /*tp_getattr*/
+X 0, /*tp_setattr*/
+X float_compare, /*tp_compare*/
+X float_repr, /*tp_repr*/
+X &float_as_number, /*tp_as_number*/
+X 0, /*tp_as_sequence*/
+X 0, /*tp_as_mapping*/
+X};
+X
+X/*
+XXXX This is not enough. Need:
+X- automatic casts for mixed arithmetic (3.1 * 4)
+X- mixed comparisons (!)
+X- look at other uses of ints that could be extended to floats
+X*/
+EOF
+fi
+if test -s 'src/grammar.c'
+then echo '*** I will not over-write existing file src/grammar.c'
+else
+echo 'x - src/grammar.c'
+sed 's/^X//' > 'src/grammar.c' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/* Grammar implementation */
+X
+X#include "pgenheaders.h"
+X
+X#include <ctype.h>
+X
+X#include "assert.h"
+X#include "token.h"
+X#include "grammar.h"
+X
+Xextern int debugging;
+X
+Xgrammar *
+Xnewgrammar(start)
+X int start;
+X{
+X grammar *g;
+X
+X g = NEW(grammar, 1);
+X if (g == NULL)
+X fatal("no mem for new grammar");
+X g->g_ndfas = 0;
+X g->g_dfa = NULL;
+X g->g_start = start;
+X g->g_ll.ll_nlabels = 0;
+X g->g_ll.ll_label = NULL;
+X return g;
+X}
+X
+Xdfa *
+Xadddfa(g, type, name)
+X grammar *g;
+X int type;
+X char *name;
+X{
+X dfa *d;
+X
+X RESIZE(g->g_dfa, dfa, g->g_ndfas + 1);
+X if (g->g_dfa == NULL)
+X fatal("no mem to resize dfa in adddfa");
+X d = &g->g_dfa[g->g_ndfas++];
+X d->d_type = type;
+X d->d_name = name;
+X d->d_nstates = 0;
+X d->d_state = NULL;
+X d->d_initial = -1;
+X d->d_first = NULL;
+X return d; /* Only use while fresh! */
+X}
+X
+Xint
+Xaddstate(d)
+X dfa *d;
+X{
+X state *s;
+X
+X RESIZE(d->d_state, state, d->d_nstates + 1);
+X if (d->d_state == NULL)
+X fatal("no mem to resize state in addstate");
+X s = &d->d_state[d->d_nstates++];
+X s->s_narcs = 0;
+X s->s_arc = NULL;
+X return s - d->d_state;
+X}
+X
+Xvoid
+Xaddarc(d, from, to, lbl)
+X dfa *d;
+X int lbl;
+X{
+X state *s;
+X arc *a;
+X
+X assert(0 <= from && from < d->d_nstates);
+X assert(0 <= to && to < d->d_nstates);
+X
+X s = &d->d_state[from];
+X RESIZE(s->s_arc, arc, s->s_narcs + 1);
+X if (s->s_arc == NULL)
+X fatal("no mem to resize arc list in addarc");
+X a = &s->s_arc[s->s_narcs++];
+X a->a_lbl = lbl;
+X a->a_arrow = to;
+X}
+X
+Xint
+Xaddlabel(ll, type, str)
+X labellist *ll;
+X int type;
+X char *str;
+X{
+X int i;
+X label *lb;
+X
+X for (i = 0; i < ll->ll_nlabels; i++) {
+X if (ll->ll_label[i].lb_type == type &&
+X strcmp(ll->ll_label[i].lb_str, str) == 0)
+X return i;
+X }
+X RESIZE(ll->ll_label, label, ll->ll_nlabels + 1);
+X if (ll->ll_label == NULL)
+X fatal("no mem to resize labellist in addlabel");
+X lb = &ll->ll_label[ll->ll_nlabels++];
+X lb->lb_type = type;
+X lb->lb_str = str; /* XXX strdup(str) ??? */
+X return lb - ll->ll_label;
+X}
+X
+X/* Same, but rather dies than adds */
+X
+Xint
+Xfindlabel(ll, type, str)
+X labellist *ll;
+X int type;
+X char *str;
+X{
+X int i;
+X label *lb;
+X
+X for (i = 0; i < ll->ll_nlabels; i++) {
+X if (ll->ll_label[i].lb_type == type /*&&
+X strcmp(ll->ll_label[i].lb_str, str) == 0*/)
+X return i;
+X }
+X fprintf(stderr, "Label %d/'%s' not found\n", type, str);
+X abort();
+X}
+X
+X/* Forward */
+Xstatic void translabel PROTO((grammar *, label *));
+X
+Xvoid
+Xtranslatelabels(g)
+X grammar *g;
+X{
+X int i;
+X
+X printf("Translating labels ...\n");
+X /* Don't translate EMPTY */
+X for (i = EMPTY+1; i < g->g_ll.ll_nlabels; i++)
+X translabel(g, &g->g_ll.ll_label[i]);
+X}
+X
+Xstatic void
+Xtranslabel(g, lb)
+X grammar *g;
+X label *lb;
+X{
+X int i;
+X
+X if (debugging)
+X printf("Translating label %s ...\n", labelrepr(lb));
+X
+X if (lb->lb_type == NAME) {
+X for (i = 0; i < g->g_ndfas; i++) {
+X if (strcmp(lb->lb_str, g->g_dfa[i].d_name) == 0) {
+X if (debugging)
+X printf("Label %s is non-terminal %d.\n",
+X lb->lb_str,
+X g->g_dfa[i].d_type);
+X lb->lb_type = g->g_dfa[i].d_type;
+X lb->lb_str = NULL;
+X return;
+X }
+X }
+X for (i = 0; i < (int)N_TOKENS; i++) {
+X if (strcmp(lb->lb_str, tok_name[i]) == 0) {
+X if (debugging)
+X printf("Label %s is terminal %d.\n",
+X lb->lb_str, i);
+X lb->lb_type = i;
+X lb->lb_str = NULL;
+X return;
+X }
+X }
+X printf("Can't translate NAME label '%s'\n", lb->lb_str);
+X return;
+X }
+X
+X if (lb->lb_type == STRING) {
+X if (isalpha(lb->lb_str[1])) {
+X char *p, *strchr();
+X if (debugging)
+X printf("Label %s is a keyword\n", lb->lb_str);
+X lb->lb_type = NAME;
+X lb->lb_str++;
+X p = strchr(lb->lb_str, '\'');
+X if (p)
+X *p = '\0';
+X }
+X else {
+X if (lb->lb_str[2] == lb->lb_str[0]) {
+X int type = (int) tok_1char(lb->lb_str[1]);
+X if (type != OP) {
+X lb->lb_type = type;
+X lb->lb_str = NULL;
+X }
+X else
+X printf("Unknown OP label %s\n",
+X lb->lb_str);
+X }
+X else
+X printf("Can't translate STRING label %s\n",
+X lb->lb_str);
+X }
+X }
+X else
+X printf("Can't translate label '%s'\n", labelrepr(lb));
+X}
+EOF
+fi
+if test -s 'src/import.c'
+then echo '*** I will not over-write existing file src/import.c'
+else
+echo 'x - src/import.c'
+sed 's/^X//' > 'src/import.c' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/* Module definition and import implementation */
+X
+X#include "allobjects.h"
+X
+X#include "node.h"
+X#include "token.h"
+X#include "graminit.h"
+X#include "import.h"
+X#include "errcode.h"
+X#include "sysmodule.h"
+X#include "pythonrun.h"
+X
+X/* Define pathname separator used in file names */
+X
+X#ifdef THINK_C
+X#define SEP ':'
+X#endif
+X
+X#ifndef SEP
+X#define SEP '/'
+X#endif
+X
+Xstatic object *modules;
+X
+X/* Initialization */
+X
+Xvoid
+Xinitimport()
+X{
+X if ((modules = newdictobject()) == NULL)
+X fatal("no mem for dictionary of modules");
+X}
+X
+Xobject *
+Xget_modules()
+X{
+X return modules;
+X}
+X
+Xobject *
+Xadd_module(name)
+X char *name;
+X{
+X object *m;
+X if ((m = dictlookup(modules, name)) != NULL && is_moduleobject(m))
+X return m;
+X m = newmoduleobject(name);
+X if (m == NULL)
+X return NULL;
+X if (dictinsert(modules, name, m) != 0) {
+X DECREF(m);
+X return NULL;
+X }
+X DECREF(m); /* Yes, it still exists, in modules! */
+X return m;
+X}
+X
+Xstatic FILE *
+Xopen_module(name, suffix, namebuf)
+X char *name;
+X char *suffix;
+X char *namebuf; /* XXX No buffer overflow checks! */
+X{
+X object *path;
+X FILE *fp;
+X
+X path = sysget("path");
+X if (path == NULL || !is_listobject(path)) {
+X strcpy(namebuf, name);
+X strcat(namebuf, suffix);
+X fp = fopen(namebuf, "r");
+X }
+X else {
+X int npath = getlistsize(path);
+X int i;
+X fp = NULL;
+X for (i = 0; i < npath; i++) {
+X object *v = getlistitem(path, i);
+X int len;
+X if (!is_stringobject(v))
+X continue;
+X strcpy(namebuf, getstringvalue(v));
+X len = getstringsize(v);
+X if (len > 0 && namebuf[len-1] != SEP)
+X namebuf[len++] = SEP;
+X strcpy(namebuf+len, name);
+X strcat(namebuf, suffix);
+X fp = fopen(namebuf, "r");
+X if (fp != NULL)
+X break;
+X }
+X }
+X return fp;
+X}
+X
+Xstatic object *
+Xget_module(m, name, m_ret)
+X /*module*/object *m;
+X char *name;
+X object **m_ret;
+X{
+X object *d;
+X FILE *fp;
+X node *n;
+X int err;
+X char namebuf[256];
+X
+X fp = open_module(name, ".py", namebuf);
+X if (fp == NULL) {
+X if (m == NULL)
+X err_setstr(NameError, name);
+X else
+X err_setstr(RuntimeError, "no module source file");
+X return NULL;
+X }
+X err = parse_file(fp, namebuf, file_input, &n);
+X fclose(fp);
+X if (err != E_DONE) {
+X err_input(err);
+X return NULL;
+X }
+X if (m == NULL) {
+X m = add_module(name);
+X if (m == NULL) {
+X freetree(n);
+X return NULL;
+X }
+X *m_ret = m;
+X }
+X d = getmoduledict(m);
+X return run_node(n, namebuf, d, d);
+X}
+X
+Xstatic object *
+Xload_module(name)
+X char *name;
+X{
+X object *m, *v;
+X v = get_module((object *)NULL, name, &m);
+X if (v == NULL)
+X return NULL;
+X DECREF(v);
+X return m;
+X}
+X
+Xobject *
+Ximport_module(name)
+X char *name;
+X{
+X object *m;
+X if ((m = dictlookup(modules, name)) == NULL) {
+X if (init_builtin(name)) {
+X if ((m = dictlookup(modules, name)) == NULL)
+X err_setstr(SystemError, "builtin module missing");
+X }
+X else {
+X m = load_module(name);
+X }
+X }
+X return m;
+X}
+X
+Xobject *
+Xreload_module(m)
+X object *m;
+X{
+X if (m == NULL || !is_moduleobject(m)) {
+X err_setstr(TypeError, "reload() argument must be module");
+X return NULL;
+X }
+X /* XXX Ought to check for builtin modules -- can't reload these... */
+X return get_module(m, getmodulename(m), (object **)NULL);
+X}
+X
+Xstatic void
+Xcleardict(d)
+X object *d;
+X{
+X int i;
+X for (i = getdictsize(d); --i >= 0; ) {
+X char *k;
+X k = getdictkey(d, i);
+X if (k != NULL)
+X (void) dictremove(d, k);
+X }
+X}
+X
+Xvoid
+Xdoneimport()
+X{
+X if (modules != NULL) {
+X int i;
+X /* Explicitly erase all modules; this is the safest way
+X to get rid of at least *some* circular dependencies */
+X for (i = getdictsize(modules); --i >= 0; ) {
+X char *k;
+X k = getdictkey(modules, i);
+X if (k != NULL) {
+X object *m;
+X m = dictlookup(modules, k);
+X if (m != NULL && is_moduleobject(m)) {
+X object *d;
+X d = getmoduledict(m);
+X if (d != NULL && is_dictobject(d)) {
+X cleardict(d);
+X }
+X }
+X }
+X }
+X cleardict(modules);
+X }
+X DECREF(modules);
+X}
+X
+X
+X/* Initialize built-in modules when first imported */
+X
+Xextern struct {
+X char *name;
+X void (*initfunc)();
+X} inittab[];
+X
+Xstatic int
+Xinit_builtin(name)
+X char *name;
+X{
+X int i;
+X for (i = 0; inittab[i].name != NULL; i++) {
+X if (strcmp(name, inittab[i].name) == 0) {
+X (*inittab[i].initfunc)();
+X return 1;
+X }
+X }
+X return 0;
+X}
+EOF
+fi
+if test -s 'src/macmodule.c'
+then echo '*** I will not over-write existing file src/macmodule.c'
+else
+echo 'x - src/macmodule.c'
+sed 's/^X//' > 'src/macmodule.c' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/* Macintosh OS module implementation */
+X
+X#include "allobjects.h"
+X
+X#include "import.h"
+X#include "modsupport.h"
+X
+X#include "sigtype.h"
+X
+X#include "::unixemu:dir.h"
+X#include "::unixemu:stat.h"
+X
+Xstatic object *MacError; /* Exception */
+X
+X
+Xstatic object *
+Xmac_chdir(self, args)
+X object *self;
+X object *args;
+X{
+X object *path;
+X if (!getstrarg(args, &path))
+X return NULL;
+X if (chdir(getstringvalue(path)) != 0)
+X return err_errno(MacError);
+X INCREF(None);
+X return None;
+X}
+X
+X
+Xstatic object *
+Xmac_getcwd(self, args)
+X object *self;
+X object *args;
+X{
+X extern char *getwd();
+X char buf[1025];
+X if (!getnoarg(args))
+X return NULL;
+X strcpy(buf, "mac.getcwd() failed"); /* In case getwd() doesn't set a msg */
+X if (getwd(buf) == NULL) {
+X err_setstr(MacError, buf);
+X return NULL;
+X }
+X return newstringobject(buf);
+X}
+X
+X
+Xstatic object *
+Xmac_listdir(self, args)
+X object *self;
+X object *args;
+X{
+X object *name, *d, *v;
+X DIR *dirp;
+X struct direct *ep;
+X if (!getstrarg(args, &name))
+X return NULL;
+X if ((dirp = opendir(getstringvalue(name))) == NULL)
+X return err_errno(MacError);
+X if ((d = newlistobject(0)) == NULL) {
+X closedir(dirp);
+X return NULL;
+X }
+X while ((ep = readdir(dirp)) != NULL) {
+X v = newstringobject(ep->d_name);
+X if (v == NULL) {
+X DECREF(d);
+X d = NULL;
+X break;
+X }
+X if (addlistitem(d, v) != 0) {
+X DECREF(v);
+X DECREF(d);
+X d = NULL;
+X break;
+X }
+X DECREF(v);
+X }
+X closedir(dirp);
+X return d;
+X}
+X
+X
+Xstatic object *
+Xmac_mkdir(self, args)
+X object *self;
+X object *args;
+X{
+X object *path;
+X int mode;
+X if (!getstrintarg(args, &path, &mode))
+X return NULL;
+X if (mkdir(getstringvalue(path), mode) != 0)
+X return err_errno(MacError);
+X INCREF(None);
+X return None;
+X}
+X
+X
+Xstatic object *
+Xmac_rename(self, args)
+X object *self;
+X object *args;
+X{
+X object *src, *dst;
+X if (!getstrstrarg(args, &src, &dst))
+X return NULL;
+X if (rename(getstringvalue(src), getstringvalue(dst)) != 0)
+X return err_errno(MacError);
+X INCREF(None);
+X return None;
+X}
+X
+X
+Xstatic object *
+Xmac_rmdir(self, args)
+X object *self;
+X object *args;
+X{
+X object *path;
+X if (!getstrarg(args, &path))
+X return NULL;
+X if (rmdir(getstringvalue(path)) != 0)
+X return err_errno(MacError);
+X INCREF(None);
+X return None;
+X}
+X
+X
+Xstatic object *
+Xmac_stat(self, args)
+X object *self;
+X object *args;
+X{
+X struct stat st;
+X object *path;
+X object *v;
+X if (!getstrarg(args, &path))
+X return NULL;
+X if (stat(getstringvalue(path), &st) != 0)
+X return err_errno(MacError);
+X v = newtupleobject(11);
+X if (v == NULL)
+X return NULL;
+X#define SET(i, val) settupleitem(v, i, newintobject((long)(val)))
+X#define XXX(i, val) SET(i, 0) /* For values my Mac stat doesn't support */
+X SET(0, st.st_mode);
+X XXX(1, st.st_ino);
+X XXX(2, st.st_dev);
+X XXX(3, st.st_nlink);
+X XXX(4, st.st_uid);
+X XXX(5, st.st_gid);
+X SET(6, st.st_size);
+X XXX(7, st.st_atime);
+X SET(8, st.st_mtime);
+X XXX(9, st.st_ctime);
+X SET(10, st.st_rsize); /* Mac-specific: resource size */
+X#undef SET
+X if (err_occurred()) {
+X DECREF(v);
+X return NULL;
+X }
+X return v;
+X}
+X
+X
+Xstatic object *
+Xmac_sync(self, args)
+X object *self;
+X object *args;
+X{
+X if (!getnoarg(args))
+X return NULL;
+X sync();
+X INCREF(None);
+X return None;
+X}
+X
+X
+Xstatic object *
+Xmac_unlink(self, args)
+X object *self;
+X object *args;
+X{
+X object *path;
+X if (!getstrarg(args, &path))
+X return NULL;
+X if (unlink(getstringvalue(path)) != 0)
+X return err_errno(MacError);
+X INCREF(None);
+X return None;
+X}
+X
+X
+Xstatic struct methodlist mac_methods[] = {
+X {"chdir", mac_chdir},
+X {"getcwd", mac_getcwd},
+X {"listdir", mac_listdir},
+X {"mkdir", mac_mkdir},
+X {"rename", mac_rename},
+X {"rmdir", mac_rmdir},
+X {"stat", mac_stat},
+X {"sync", mac_sync},
+X {"unlink", mac_unlink},
+X {NULL, NULL} /* Sentinel */
+X};
+X
+X
+Xvoid
+Xinitmac()
+X{
+X object *m, *d;
+X
+X m = initmodule("mac", mac_methods);
+X d = getmoduledict(m);
+X
+X /* Initialize mac.error exception */
+X MacError = newstringobject("mac.error");
+X if (MacError == NULL || dictinsert(d, "error", MacError) != 0)
+X fatal("can't define mac.error");
+X}
+EOF
+fi
+if test -s 'src/object.c'
+then echo '*** I will not over-write existing file src/object.c'
+else
+echo 'x - src/object.c'
+sed 's/^X//' > 'src/object.c' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/* Generic object operations; and implementation of None (NoObject) */
+X
+X#include "allobjects.h"
+X
+X#ifdef REF_DEBUG
+Xlong ref_total;
+X#endif
+X
+X/* Object allocation routines used by NEWOBJ and NEWVAROBJ macros.
+X These are used by the individual routines for object creation.
+X Do not call them otherwise, they do not initialize the object! */
+X
+Xobject *
+Xnewobject(tp)
+X typeobject *tp;
+X{
+X object *op = (object *) malloc(tp->tp_basicsize);
+X if (op == NULL)
+X return err_nomem();
+X NEWREF(op);
+X op->ob_type = tp;
+X return op;
+X}
+X
+X#if 0 /* unused */
+X
+Xvarobject *
+Xnewvarobject(tp, size)
+X typeobject *tp;
+X unsigned int size;
+X{
+X varobject *op = (varobject *)
+X malloc(tp->tp_basicsize + size * tp->tp_itemsize);
+X if (op == NULL)
+X return err_nomem();
+X NEWREF(op);
+X op->ob_type = tp;
+X op->ob_size = size;
+X return op;
+X}
+X
+X#endif
+X
+Xint StopPrint; /* Flag to indicate printing must be stopped */
+X
+Xstatic int prlevel;
+X
+Xvoid
+Xprintobject(op, fp, flags)
+X object *op;
+X FILE *fp;
+X int flags;
+X{
+X /* Hacks to make printing a long or recursive object interruptible */
+X /* XXX Interrupts should leave a more permanent error */
+X prlevel++;
+X if (!StopPrint && intrcheck()) {
+X fprintf(fp, "\n[print interrupted]\n");
+X StopPrint = 1;
+X }
+X if (!StopPrint) {
+X if (op == NULL) {
+X fprintf(fp, "<nil>");
+X }
+X else {
+X if (op->ob_refcnt <= 0)
+X fprintf(fp, "(refcnt %d):", op->ob_refcnt);
+X if (op->ob_type->tp_print == NULL) {
+X fprintf(fp, "<%s object at %lx>",
+X op->ob_type->tp_name, (long)op);
+X }
+X else {
+X (*op->ob_type->tp_print)(op, fp, flags);
+X }
+X }
+X }
+X prlevel--;
+X if (prlevel == 0)
+X StopPrint = 0;
+X}
+X
+Xobject *
+Xreprobject(v)
+X object *v;
+X{
+X object *w = NULL;
+X /* Hacks to make converting a long or recursive object interruptible */
+X prlevel++;
+X if (!StopPrint && intrcheck()) {
+X StopPrint = 1;
+X err_set(KeyboardInterrupt);
+X }
+X if (!StopPrint) {
+X if (v == NULL) {
+X w = newstringobject("<NULL>");
+X }
+X else if (v->ob_type->tp_repr == NULL) {
+X char buf[100];
+X sprintf(buf, "<%.80s object at %lx>",
+X v->ob_type->tp_name, (long)v);
+X w = newstringobject(buf);
+X }
+X else {
+X w = (*v->ob_type->tp_repr)(v);
+X }
+X if (StopPrint) {
+X XDECREF(w);
+X w = NULL;
+X }
+X }
+X prlevel--;
+X if (prlevel == 0)
+X StopPrint = 0;
+X return w;
+X}
+X
+Xint
+Xcmpobject(v, w)
+X object *v, *w;
+X{
+X typeobject *tp;
+X if (v == w)
+X return 0;
+X if (v == NULL)
+X return -1;
+X if (w == NULL)
+X return 1;
+X if ((tp = v->ob_type) != w->ob_type)
+X return strcmp(tp->tp_name, w->ob_type->tp_name);
+X if (tp->tp_compare == NULL)
+X return (v < w) ? -1 : 1;
+X return ((*tp->tp_compare)(v, w));
+X}
+X
+Xobject *
+Xgetattr(v, name)
+X object *v;
+X char *name;
+X{
+X if (v->ob_type->tp_getattr == NULL) {
+X err_setstr(TypeError, "attribute-less object");
+X return NULL;
+X }
+X else {
+X return (*v->ob_type->tp_getattr)(v, name);
+X }
+X}
+X
+Xint
+Xsetattr(v, name, w)
+X object *v;
+X char *name;
+X object *w;
+X{
+X if (v->ob_type->tp_setattr == NULL) {
+X if (v->ob_type->tp_getattr == NULL)
+X err_setstr(TypeError, "attribute-less object");
+X else
+X err_setstr(TypeError, "object has read-only attributes");
+X return -1;
+X }
+X else {
+X return (*v->ob_type->tp_setattr)(v, name, w);
+X }
+X}
+X
+X
+X/*
+XNoObject is usable as a non-NULL undefined value, used by the macro None.
+XThere is (and should be!) no way to create other objects of this type,
+Xso there is exactly one (which is indestructible, by the way).
+X*/
+X
+Xstatic void
+Xnone_print(op, fp, flags)
+X object *op;
+X FILE *fp;
+X int flags;
+X{
+X fprintf(fp, "None");
+X}
+X
+Xstatic object *
+Xnone_repr(op)
+X object *op;
+X{
+X return newstringobject("None");
+X}
+X
+Xstatic typeobject Notype = {
+X OB_HEAD_INIT(&Typetype)
+X 0,
+X "None",
+X 0,
+X 0,
+X 0, /*tp_dealloc*/ /*never called*/
+X none_print, /*tp_print*/
+X 0, /*tp_getattr*/
+X 0, /*tp_setattr*/
+X 0, /*tp_compare*/
+X none_repr, /*tp_repr*/
+X 0, /*tp_as_number*/
+X 0, /*tp_as_sequence*/
+X 0, /*tp_as_mapping*/
+X};
+X
+Xobject NoObject = {
+X OB_HEAD_INIT(&Notype)
+X};
+X
+X
+X#ifdef TRACE_REFS
+X
+Xstatic object refchain = {&refchain, &refchain};
+X
+XNEWREF(op)
+X object *op;
+X{
+X ref_total++;
+X op->ob_refcnt = 1;
+X op->_ob_next = refchain._ob_next;
+X op->_ob_prev = &refchain;
+X refchain._ob_next->_ob_prev = op;
+X refchain._ob_next = op;
+X}
+X
+XUNREF(op)
+X register object *op;
+X{
+X register object *p;
+X if (op->ob_refcnt < 0) {
+X fprintf(stderr, "UNREF negative refcnt\n");
+X abort();
+X }
+X for (p = refchain._ob_next; p != &refchain; p = p->_ob_next) {
+X if (p == op)
+X break;
+X }
+X if (p == &refchain) { /* Not found */
+X fprintf(stderr, "UNREF unknown object\n");
+X abort();
+X }
+X op->_ob_next->_ob_prev = op->_ob_prev;
+X op->_ob_prev->_ob_next = op->_ob_next;
+X}
+X
+XDELREF(op)
+X object *op;
+X{
+X UNREF(op);
+X (*(op)->ob_type->tp_dealloc)(op);
+X}
+X
+Xprintrefs(fp)
+X FILE *fp;
+X{
+X object *op;
+X fprintf(fp, "Remaining objects:\n");
+X for (op = refchain._ob_next; op != &refchain; op = op->_ob_next) {
+X fprintf(fp, "[%d] ", op->ob_refcnt);
+X printobject(op, fp, 0);
+X putc('\n', fp);
+X }
+X}
+X
+X#endif
+EOF
+fi
+if test -s 'src/tupleobject.c'
+then echo '*** I will not over-write existing file src/tupleobject.c'
+else
+echo 'x - src/tupleobject.c'
+sed 's/^X//' > 'src/tupleobject.c' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/* Tuple object implementation */
+X
+X#include "allobjects.h"
+X
+Xobject *
+Xnewtupleobject(size)
+X register int size;
+X{
+X register int i;
+X register tupleobject *op;
+X if (size < 0) {
+X err_badcall();
+X return NULL;
+X }
+X op = (tupleobject *)
+X malloc(sizeof(tupleobject) + size * sizeof(object *));
+X if (op == NULL)
+X return err_nomem();
+X NEWREF(op);
+X op->ob_type = &Tupletype;
+X op->ob_size = size;
+X for (i = 0; i < size; i++)
+X op->ob_item[i] = NULL;
+X return (object *) op;
+X}
+X
+Xint
+Xgettuplesize(op)
+X register object *op;
+X{
+X if (!is_tupleobject(op)) {
+X err_badcall();
+X return -1;
+X }
+X else
+X return ((tupleobject *)op)->ob_size;
+X}
+X
+Xobject *
+Xgettupleitem(op, i)
+X register object *op;
+X register int i;
+X{
+X if (!is_tupleobject(op)) {
+X err_badcall();
+X return NULL;
+X }
+X if (i < 0 || i >= ((tupleobject *)op) -> ob_size) {
+X err_setstr(IndexError, "tuple index out of range");
+X return NULL;
+X }
+X return ((tupleobject *)op) -> ob_item[i];
+X}
+X
+Xint
+Xsettupleitem(op, i, newitem)
+X register object *op;
+X register int i;
+X register object *newitem;
+X{
+X register object *olditem;
+X if (!is_tupleobject(op)) {
+X if (newitem != NULL)
+X DECREF(newitem);
+X err_badcall();
+X return -1;
+X }
+X if (i < 0 || i >= ((tupleobject *)op) -> ob_size) {
+X if (newitem != NULL)
+X DECREF(newitem);
+X err_setstr(IndexError, "tuple assignment index out of range");
+X return -1;
+X }
+X olditem = ((tupleobject *)op) -> ob_item[i];
+X ((tupleobject *)op) -> ob_item[i] = newitem;
+X if (olditem != NULL)
+X DECREF(olditem);
+X return 0;
+X}
+X
+X/* Methods */
+X
+Xstatic void
+Xtupledealloc(op)
+X register tupleobject *op;
+X{
+X register int i;
+X for (i = 0; i < op->ob_size; i++) {
+X if (op->ob_item[i] != NULL)
+X DECREF(op->ob_item[i]);
+X }
+X free((ANY *)op);
+X}
+X
+Xstatic void
+Xtupleprint(op, fp, flags)
+X tupleobject *op;
+X FILE *fp;
+X int flags;
+X{
+X int i;
+X fprintf(fp, "(");
+X for (i = 0; i < op->ob_size && !StopPrint; i++) {
+X if (i > 0) {
+X fprintf(fp, ", ");
+X }
+X printobject(op->ob_item[i], fp, flags);
+X }
+X if (op->ob_size == 1)
+X fprintf(fp, ",");
+X fprintf(fp, ")");
+X}
+X
+Xobject *
+Xtuplerepr(v)
+X tupleobject *v;
+X{
+X object *s, *t, *comma;
+X int i;
+X s = newstringobject("(");
+X comma = newstringobject(", ");
+X for (i = 0; i < v->ob_size && s != NULL; i++) {
+X if (i > 0)
+X joinstring(&s, comma);
+X t = reprobject(v->ob_item[i]);
+X joinstring(&s, t);
+X if (t != NULL)
+X DECREF(t);
+X }
+X DECREF(comma);
+X if (v->ob_size == 1) {
+X t = newstringobject(",");
+X joinstring(&s, t);
+X DECREF(t);
+X }
+X t = newstringobject(")");
+X joinstring(&s, t);
+X DECREF(t);
+X return s;
+X}
+X
+Xstatic int
+Xtuplecompare(v, w)
+X register tupleobject *v, *w;
+X{
+X register int len =
+X (v->ob_size < w->ob_size) ? v->ob_size : w->ob_size;
+X register int i;
+X for (i = 0; i < len; i++) {
+X int cmp = cmpobject(v->ob_item[i], w->ob_item[i]);
+X if (cmp != 0)
+X return cmp;
+X }
+X return v->ob_size - w->ob_size;
+X}
+X
+Xstatic int
+Xtuplelength(a)
+X tupleobject *a;
+X{
+X return a->ob_size;
+X}
+X
+Xstatic object *
+Xtupleitem(a, i)
+X register tupleobject *a;
+X register int i;
+X{
+X if (i < 0 || i >= a->ob_size) {
+X err_setstr(IndexError, "tuple index out of range");
+X return NULL;
+X }
+X INCREF(a->ob_item[i]);
+X return a->ob_item[i];
+X}
+X
+Xstatic object *
+Xtupleslice(a, ilow, ihigh)
+X register tupleobject *a;
+X register int ilow, ihigh;
+X{
+X register tupleobject *np;
+X register int i;
+X if (ilow < 0)
+X ilow = 0;
+X if (ihigh > a->ob_size)
+X ihigh = a->ob_size;
+X if (ihigh < ilow)
+X ihigh = ilow;
+X if (ilow == 0 && ihigh == a->ob_size) {
+X /* XXX can only do this if tuples are immutable! */
+X INCREF(a);
+X return (object *)a;
+X }
+X np = (tupleobject *)newtupleobject(ihigh - ilow);
+X if (np == NULL)
+X return NULL;
+X for (i = ilow; i < ihigh; i++) {
+X object *v = a->ob_item[i];
+X INCREF(v);
+X np->ob_item[i - ilow] = v;
+X }
+X return (object *)np;
+X}
+X
+Xstatic object *
+Xtupleconcat(a, bb)
+X register tupleobject *a;
+X register object *bb;
+X{
+X register int size;
+X register int i;
+X tupleobject *np;
+X if (!is_tupleobject(bb)) {
+X err_badarg();
+X return NULL;
+X }
+X#define b ((tupleobject *)bb)
+X size = a->ob_size + b->ob_size;
+X np = (tupleobject *) newtupleobject(size);
+X if (np == NULL) {
+X return err_nomem();
+X }
+X for (i = 0; i < a->ob_size; i++) {
+X object *v = a->ob_item[i];
+X INCREF(v);
+X np->ob_item[i] = v;
+X }
+X for (i = 0; i < b->ob_size; i++) {
+X object *v = b->ob_item[i];
+X INCREF(v);
+X np->ob_item[i + a->ob_size] = v;
+X }
+X return (object *)np;
+X#undef b
+X}
+X
+Xstatic sequence_methods tuple_as_sequence = {
+X tuplelength, /*sq_length*/
+X tupleconcat, /*sq_concat*/
+X 0, /*sq_repeat*/
+X tupleitem, /*sq_item*/
+X tupleslice, /*sq_slice*/
+X 0, /*sq_ass_item*/
+X 0, /*sq_ass_slice*/
+X};
+X
+Xtypeobject Tupletype = {
+X OB_HEAD_INIT(&Typetype)
+X 0,
+X "tuple",
+X sizeof(tupleobject) - sizeof(object *),
+X sizeof(object *),
+X tupledealloc, /*tp_dealloc*/
+X tupleprint, /*tp_print*/
+X 0, /*tp_getattr*/
+X 0, /*tp_setattr*/
+X tuplecompare, /*tp_compare*/
+X tuplerepr, /*tp_repr*/
+X 0, /*tp_as_number*/
+X &tuple_as_sequence, /*tp_as_sequence*/
+X 0, /*tp_as_mapping*/
+X};
+EOF
+fi
+echo 'Part 14 out of 21 of pack.out complete.'
+exit 0
diff --git a/shar/python-0.9.1-15-21.shar b/shar/python-0.9.1-15-21.shar
new file mode 100644
index 0000000..3cc3c78
--- /dev/null
+++ b/shar/python-0.9.1-15-21.shar
@@ -0,0 +1,2539 @@
+: This is a shell archive.
+: Extract with 'sh this_file'.
+:
+: Extract part 01 first since it makes all directories
+echo 'Start of pack.out, part 15 out of 21:'
+if test -s 'demo/sgi/gl/kites.py'
+then echo '*** I will not over-write existing file demo/sgi/gl/kites.py'
+else
+echo 'x - demo/sgi/gl/kites.py'
+sed 's/^X//' > 'demo/sgi/gl/kites.py' << 'EOF'
+X#! /ufs/guido/bin/sgi/python
+X
+X# *** This only works correctly on a 24 bit-plane machine. ***
+X#
+X# A simple Python program that tests the some parts of the
+X# GL library. It shows the speed that can be obtained when
+X# doing simple graphics.
+X#
+X# The bottleneck in this program is NOT Python but the graphics
+X# engine; i.e Python can feed the graphics pipeline fast enough
+X# on the 4D/25G.
+X#
+X# This program show 3 kites flying around the screen. It uses
+X#
+X# * bgnpolygon, endpolygon
+X# * v3, n3
+X# * lmdef, lmbind
+X#
+X# Usage :
+X#
+X# ESC -> exit program
+X# MOUSE3 -> freeze toggle
+X# MOUSE2 -> one step (use this in freeze state)
+X
+Xfrom GL import *
+Xfrom gl import *
+Ximport DEVICE
+Xfrom math import *
+X
+X#
+X# viewobj : sets the rotation, translation and scaling
+X# set appropiate material, call drawobject()
+X#
+Xdef viewobj (r, s, t, mat) :
+X pushmatrix()
+X rot (r * 10.0, 'X')
+X rot (r * 10.0, 'Y')
+X rot (r * 10.0, 'Z')
+X scale (s[0], s[1], s[2])
+X translate (t[0], t[1], t[2])
+X lmbind(MATERIAL, mat)
+X drawobject()
+X popmatrix()
+X
+X#
+X# makeobj : the contructor of the object
+X#
+Xdef mkobj () :
+X v0 = (-5.0 ,0.0, 0.0)
+X v1 = (0.0 ,5.0, 0.0)
+X v2 = (5.0 ,0.0, 0.0)
+X v3 = (0.0 ,2.0, 0.0)
+X n0 = (sqrt(2.0)/2.0, sqrt(2.0)/2.0, 0.0)
+X vn = ((v0, n0), (v1, n0), (v2, n0), (v3, n0))
+X #
+X return vn
+X
+X#
+X# the object itself as an array of vertices and normals
+X#
+Xkite = mkobj ()
+X
+X#
+X# drawobject : draw a triangle. with bgnpolygon
+X#
+Xdef drawobject () :
+X #
+X bgnpolygon()
+X vnarray (kite)
+X endpolygon()
+X
+X#
+X# identity matrix
+X#
+Xidmat=[1.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,1.0]
+X
+X#
+X# the rgb-value of light-blue
+X#
+XLightBlue = (43,169,255)
+X
+X#
+X# the different materials.
+X#
+Xm1=[SPECULAR,0.0,0.0,0.6,DIFFUSE,0.0,0.0,0.8,SHININESS,20.0,LMNULL]
+Xm2=[SPECULAR,0.8,0.0,0.1,DIFFUSE,0.8,0.0,0.3,SHININESS,120.0,LMNULL]
+Xm3=[SPECULAR,0.0,1.0,0.0,DIFFUSE,0.0,0.6,0.0,SHININESS,120.0,LMNULL]
+X
+X#
+X# lightsources
+X#
+Xlight1 = [LCOLOR,1.0,1.0,1.0,POSITION,15.0,15.0,0.0,1.0,LMNULL]
+Xlight2 = [LCOLOR,1.0,1.0,1.0,POSITION,-15.0,15.0,0.0,1.0,LMNULL]
+X
+X#
+X# the lightmodel
+X#
+Xmodel = [AMBIENT,0.2,0.2,0.2,LMNULL]
+X
+X#
+X# initgl : opens the window, configures the pipeline to 2buf and zbuf,
+X# sets the viewing, defines and binds the materials
+X#
+Xdef initgl () :
+X #
+X # open window
+X #
+X foreground ()
+X keepaspect (1, 1)
+X prefposition (100, 500, 100, 500)
+X w = winopen ('PYTHON lights')
+X keepaspect (1, 1)
+X winconstraints()
+X #
+X # configure pipeline (zbuf, 2buf, GOURAUD and RGBmode)
+X #
+X zbuffer (1)
+X doublebuffer ()
+X shademodel (GOURAUD)
+X RGBmode ()
+X gconfig ()
+X #
+X # define and bind materials (set perspective BEFORE loadmat !)
+X #
+X mmode(MVIEWING)
+X perspective (900, 1.0, 1.0, 20.0)
+X loadmatrix(idmat)
+X lmdef(DEFMATERIAL, 1, m1)
+X lmdef(DEFMATERIAL, 2, m2)
+X lmdef(DEFMATERIAL, 3, m3)
+X lmdef(DEFLIGHT, 1, light1)
+X lmdef(DEFLIGHT, 2, light2)
+X lmdef(DEFLMODEL, 1, model)
+X lmbind(LIGHT0,1)
+X lmbind(LIGHT1,2)
+X lmbind(LMODEL,1)
+X #
+X # set viewing
+X #
+X lookat (0.0, 0.0, 10.0, 0.0, 0.0, 0.0, 0)
+X #
+X # ask for the REDRAW and ESCKEY events
+X #
+X qdevice(DEVICE.MOUSE3)
+X qdevice(DEVICE.MOUSE2)
+X qdevice(DEVICE.REDRAW)
+X qdevice(DEVICE.ESCKEY)
+X
+X#
+X# GoForIT : use 2buf to redraw the object 2n times. index i is used as
+X# the (smoothly changing) rotation angle
+X#
+Xdef GoForIt(i) :
+X freeze = 1
+X while 1 :
+X if freeze <> 0 :
+X i = i + 1
+X #
+X # clear z-buffer and clear background to light-blue
+X #
+X zclear()
+X c3i (LightBlue)
+X clear()
+X #
+X # draw the 3 traiangles scaled above each other.
+X #
+X viewobj(float(i),[1.0,1.0,1.0],[1.0,1.0,1.0],1)
+X viewobj(float(i),[0.75,0.75,0.75],[0.0,2.0,2.0],2)
+X viewobj(float(i),[0.5,0.5,0.5],[0.0,4.0,4.0],3)
+X #
+X swapbuffers()
+X #
+X if qtest() <> 0 :
+X dev, val = qread()
+X if dev = DEVICE.ESCKEY :
+X break
+X elif dev = DEVICE.REDRAW :
+X reshapeviewport ()
+X elif dev = DEVICE.MOUSE3 and val <> 0 :
+X freeze = 1 - freeze
+X elif dev = DEVICE.MOUSE2 and val <> 0 :
+X i = i + 1
+X
+X
+X# the main program
+X#
+Xdef main () :
+X initgl ()
+X GoForIt (0)
+X
+X#
+X# exec main
+X#
+Xmain ()
+EOF
+chmod +x 'demo/sgi/gl/kites.py'
+fi
+if test -s 'demo/sgi/gl_panel/nurbs/nurbs.s'
+then echo '*** I will not over-write existing file demo/sgi/gl_panel/nurbs/nurbs.s'
+else
+echo 'x - demo/sgi/gl_panel/nurbs/nurbs.s'
+sed 's/^X//' > 'demo/sgi/gl_panel/nurbs/nurbs.s' << 'EOF'
+X;;; This file was automatically generated by the panel editor.
+X;;; If you read it into gnu emacs, it will automagically format itself.
+X
+X(panel (prop help creator:user-panel-help)
+X(prop user-panel #t)
+X(label "NURB controls")
+X(x 815)
+X(y 22)
+X(al (pnl_toggle_button (name "trim")
+X(prop help creator:user-act-help)
+X(label "trim on/off")
+X(x 4)
+X(y 4.5)
+X(w 0.45)
+X(h 0.4)
+X(downfunc move-then-resize)
+X)
+X(pnl_toggle_button (name "motion")
+X(prop help creator:user-act-help)
+X(label "motion on/off")
+X(y 1)
+X(downfunc move-then-resize)
+X)
+X(pnl_toggle_button (name "xyzaxis")
+X(prop help creator:user-act-help)
+X(label "xyz-axis")
+X(y 3)
+X(downfunc move-then-resize)
+X)
+X(pnl_toggle_button (name "trimpnts")
+X(prop help creator:user-act-help)
+X(label "trimming pnts")
+X(y 3.5)
+X(downfunc move-then-resize)
+X)
+X(pnl_toggle_button (name "cntlpnts")
+X(prop help creator:user-act-help)
+X(label "control pnts")
+X(y 4)
+X(downfunc move-then-resize)
+X)
+X(pnl_toggle_button (name "nurb")
+X(prop help creator:user-act-help)
+X(label "nurb")
+X(y 4.5)
+X(val 1)
+X(downfunc move-then-resize)
+X)
+X(pnl_button (name "quit")
+X(prop help creator:user-act-help)
+X(label "quit")
+X(x 4)
+X(y 1)
+X(labeltype 1)
+X(downfunc move-then-resize)
+X)
+X(pnl_label (prop help creator:user-act-help)
+X(label "TRIMMING")
+X(x 4)
+X(y 5)
+X(downfunc move-then-resize)
+X)
+X(pnl_label (prop help creator:user-act-help)
+X(label "MOTION")
+X(y 1.5)
+X(downfunc move-then-resize)
+X)
+X(pnl_label (prop help creator:user-act-help)
+X(label "VISIBILITY")
+X(y 5)
+X(downfunc move-then-resize)
+X)
+X)
+X)
+X;;; Local Variables:
+X;;; mode: scheme
+X;;; eval: (save-excursion (goto-char (point-min)) (kill-line 3))
+X;;; eval: (save-excursion (goto-char (point-min)) (replace-regexp "[ \n]*)" ")"))
+X;;; eval: (indent-region (point-min) (point-max) nil)
+X;;; eval: (progn (kill-line -3) (delete-backward-char 1) (save-buffer))
+X;;; End:
+EOF
+fi
+if test -s 'lib/Sliders.py'
+then echo '*** I will not over-write existing file lib/Sliders.py'
+else
+echo 'x - lib/Sliders.py'
+sed 's/^X//' > 'lib/Sliders.py' << 'EOF'
+X# Module 'Sliders'
+X
+X
+Ximport stdwin
+Xfrom stdwinevents import *
+Ximport rect
+Xfrom Buttons import *
+Xfrom HVSplit import HSplit
+X
+X
+X# Field indices in event detail
+X#
+X_HV = 0
+X_CLICKS = 1
+X_BUTTON = 2
+X_MASK = 3
+X
+X
+X# DragSlider is the simplest possible slider.
+X# It looks like a button but dragging the mouse left or right
+X# changes the controlled value.
+X# It does not support any of the triggers or hooks defined by Buttons,
+X# but defines its own setval_trigger and setval_hook.
+X#
+Xclass DragSliderReactivity() = BaseReactivity():
+X #
+X def mouse_down(self, detail):
+X h, v = hv = detail[_HV]
+X if self.enabled and self.mousetest(hv):
+X self.anchor = h
+X self.oldval = self.val
+X self.active = 1
+X #
+X def mouse_move(self, detail):
+X if self.active:
+X h, v = detail[_HV]
+X self.setval(self.oldval + (h - self.anchor))
+X #
+X def mouse_up(self, detail):
+X if self.active:
+X h, v = detail[_HV]
+X self.setval(self.oldval + (h - self.anchor))
+X self.active = 0
+X #
+X
+Xclass DragSliderAppearance() = ButtonAppearance():
+X #
+X # INVARIANTS maintained by the setval method:
+X #
+X # self.min <= self.val <= self.max
+X # self.text = self.pretext + `self.val` + self.postext
+X #
+X # (Notice that unlike Python ranges, the end point belongs
+X # to the range.)
+X #
+X def init_appearance(self):
+X ButtonAppearance.init_appearance(self)
+X self.min = 0
+X self.val = 0
+X self.max = 100
+X self.hook = 0
+X self.pretext = self.postext = ''
+X self.recalctext()
+X #
+X # The 'get*' and 'set*' methods belong to the generic slider interface
+X #
+X def getval(self): return self.val
+X #
+X def sethook(self, hook):
+X self.hook = hook
+X #
+X def setminvalmax(self, (min, val, max)):
+X self.min = min
+X self.max = max
+X self.setval(val)
+X #
+X def settexts(self, (pretext, postext)):
+X self.pretext = pretext
+X self.postext = postext
+X self.recalctext()
+X #
+X def setval(self, val):
+X val = min(self.max, max(self.min, val))
+X if val <> self.val:
+X self.val = val
+X self.recalctext()
+X self.trigger()
+X #
+X def trigger(self):
+X if self.hook:
+X self.hook(self)
+X #
+X def recalctext(self):
+X self.settext(self.pretext + `self.val` + self.postext)
+X #
+X
+Xclass DragSlider() = DragSliderReactivity(), DragSliderAppearance(), Define():
+X def definetext(self, (parent, text)):
+X raise RuntimeError, 'DragSlider.definetext() not supported'
+X
+X
+X# Auxiliary class for PushButton incorporated in ComplexSlider
+X#
+Xclass _StepButton() = PushButton():
+X def define(self, parent):
+X self = PushButton.define(self, parent)
+X self.step = 0
+X return self
+X def setstep(self, step):
+X self.step = step
+X def definetextstep(self, (parent, text, step)):
+X self = self.definetext(parent, text)
+X self.setstep(step)
+X return self
+X def init_reactivity(self):
+X PushButton.init_reactivity(self)
+X self.parent.need_timer(self)
+X def step_trigger(self):
+X self.parent.setval(self.parent.getval() + self.step)
+X def down_trigger(self):
+X self.step_trigger()
+X self.parent.settimer(5)
+X def timer(self):
+X if self.hilited:
+X self.step_trigger()
+X if self.active:
+X self.parent.settimer(1)
+X
+X
+X# A complex slider is an HSplit initialized to three buttons:
+X# one to step down, a dragslider, and one to step up.
+X#
+Xclass ComplexSlider() = HSplit():
+X #
+X # Override Slider define() method
+X #
+X def define(self, parent):
+X self = self.create(parent) # HSplit
+X #
+X self.downbutton = _StepButton().definetextstep(self, '-', -1)
+X self.dragbutton = DragSlider().define(self)
+X self.upbutton = _StepButton().definetextstep(self, '+', 1)
+X #
+X return self
+X #
+X # Override HSplit methods
+X #
+X def minsize(self, m):
+X w1, h1 = self.downbutton.minsize(m)
+X w2, h2 = self.dragbutton.minsize(m)
+X w3, h3 = self.upbutton.minsize(m)
+X height = max(h1, h2, h3)
+X w1 = max(w1, height)
+X w3 = max(w3, height)
+X return w1+w2+w3, height
+X #
+X def setbounds(self, bounds):
+X (left, top), (right, bottom) = self.bounds = bounds
+X size = bottom - top
+X self.downbutton.setbounds((left, top), (left+size, bottom))
+X self.dragbutton.setbounds((left+size, top), \
+X (right-size, bottom))
+X self.upbutton.setbounds((right-size, top), (right, bottom))
+X #
+X # Pass other Slider methods on to dragbutton
+X #
+X def getval(self): return self.dragbutton.getval()
+X def sethook(self, hook): self.dragbutton.sethook(hook)
+X def setminvalmax(self, args): self.dragbutton.setminvalmax(args)
+X def settexts(self, args): self.dragbutton.settexts(args)
+X def setval(self, val): self.dragbutton.setval(val)
+X def enable(self, flag):
+X self.downbutton.enable(flag)
+X self.dragbutton.enable(flag)
+X self.upbutton.enable(flag)
+EOF
+fi
+if test -s 'lib/clock.py'
+then echo '*** I will not over-write existing file lib/clock.py'
+else
+echo 'x - lib/clock.py'
+sed 's/^X//' > 'lib/clock.py' << 'EOF'
+X# 'klok' -- A simple alarm clock
+X
+X# The alarm can be set at 5 minute intervals on a 12 hour basis.
+X# It is controlled with the mouse:
+X# - Click and drag around the circle to set the alarm.
+X# - Click far outside the circle to clear the alarm.
+X# - Click near the center to set the alarm at the last time set.
+X# The alarm time is indicated by a small triangle just outside the circle,
+X# and also by a digital time at the bottom.
+X# The indicators disappear when the alarm is not set.
+X# When the alarm goes off, it beeps every minute for five minutes,
+X# and the clock turns into inverse video.
+X# Click or activate the window to turn the ringing off.
+X
+Ximport stdwin
+Xfrom stdwinevents import WE_MOUSE_DOWN, WE_MOUSE_MOVE, WE_MOUSE_UP, \
+X WE_TIMER, WE_DRAW, WE_SIZE, WE_CLOSE, WE_ACTIVATE
+Ximport time
+Xfrom math import sin, cos, atan2, pi, sqrt
+X
+XDEFWIDTH, DEFHEIGHT = 200, 200
+X
+Xmouse_events = (WE_MOUSE_DOWN, WE_MOUSE_MOVE, WE_MOUSE_UP)
+Xorigin = 0, 0
+Xfaraway = 2000, 2000
+Xeverywhere = origin, faraway
+X
+Xclass struct(): pass # A class to declare featureless objects
+X
+XG = struct() # Global variables (most set in setdimensions())
+XG.tzdiff = 5*3600 # THINK computes UCT from local time assuming EST!
+X
+XA = struct() # Globals used by the alarm
+XA.set = 1 # True when alarm is set
+XA.time = 11*60 + 40 # Time when alarm must go off
+XA.ring = 0 # True when alarm is ringing
+X
+Xdef main():
+X try:
+X realmain()
+X except KeyboardInterrupt:
+X print 'KeyboardInterrupt'
+X finally:
+X G.w = 0
+X
+Xdef realmain():
+X setdimensions(DEFWIDTH, DEFHEIGHT)
+X stdwin.setdefwinsize(G.farcorner)
+X G.w = stdwin.open('klok')
+X settimer()
+X while 1:
+X type, window, detail = stdwin.getevent()
+X if type = WE_DRAW:
+X drawproc(detail)
+X elif type = WE_TIMER:
+X settimer()
+X drawproc(everywhere)
+X elif type in mouse_events:
+X mouseclick(type, detail)
+X elif type = WE_ACTIVATE:
+X if A.ring:
+X # Turn the ringing off
+X A.ring = 0
+X G.w.begindrawing().invert(G.mainarea)
+X elif type = WE_SIZE:
+X G.w.change(everywhere)
+X width, height = G.w.getwinsize()
+X height = height - stdwin.lineheight()
+X setdimensions(width, height)
+X elif type = WE_CLOSE:
+X break
+X
+Xdef setdimensions(width, height):
+X if width < height: size = width
+X else: size = height
+X halfwidth = width/2
+X halfheight = height/2
+X G.center = halfwidth, halfheight
+X G.radius = size*45/100
+X G.width = width
+X G.height = height
+X G.corner = width, height
+X G.mainarea = origin, G.corner
+X G.lineheight = stdwin.lineheight()
+X G.farcorner = width, height + G.lineheight
+X G.statusarea = (0, height), G.farcorner
+X G.fullarea = origin, G.farcorner
+X
+Xdef settimer():
+X now = getlocaltime()
+X G.times = calctime(now)
+X delay = 61 - now % 60
+X G.w.settimer(10 * delay)
+X minutes = (now/60) % 720
+X if A.ring:
+X # Is it time to stop the alarm ringing?
+X since = (minutes - A.time + 720) % 720
+X if since >= 5:
+X # Stop it now
+X A.ring = 0
+X else:
+X # Ring again, once every minute
+X stdwin.fleep()
+X elif A.set and minutes = A.time:
+X # Start the alarm ringing
+X A.ring = 1
+X stdwin.fleep()
+X
+Xdef drawproc(area):
+X hours, minutes, seconds = G.times
+X d = G.w.begindrawing()
+X d.cliprect(area)
+X d.erase(everywhere)
+X d.circle(G.center, G.radius)
+X d.line(G.center, calcpoint(hours*30 + minutes/2, 0.6))
+X d.line(G.center, calcpoint(minutes*6, 1.0))
+X str = dd(hours) + ':' + dd(minutes)
+X p = (G.width - d.textwidth(str))/2, G.height * 3 / 4
+X d.text(p, str)
+X if A.set:
+X drawalarm(d)
+X drawalarmtime(d)
+X if A.ring:
+X d.invert(G.mainarea)
+X
+Xdef mouseclick(type, detail):
+X d = G.w.begindrawing()
+X if A.ring:
+X # First turn the ringing off
+X A.ring = 0
+X d.invert(G.mainarea)
+X h, v = detail[0]
+X ch, cv = G.center
+X x, y = h-ch, cv-v
+X dist = sqrt(x*x + y*y) / float(G.radius)
+X if dist > 1.2:
+X if A.set:
+X drawalarm(d)
+X erasealarmtime(d)
+X A.set = 0
+X elif dist < 0.8:
+X if not A.set:
+X A.set = 1
+X drawalarm(d)
+X drawalarmtime(d)
+X else:
+X # Convert to half-degrees (range 0..720)
+X alpha = atan2(y, x)
+X hdeg = alpha*360.0/pi
+X hdeg = 180.0 - hdeg
+X hdeg = (hdeg + 720.0) % 720.0
+X atime = 5*int(hdeg/5.0 + 0.5)
+X if atime <> A.time or not A.set:
+X if A.set:
+X drawalarm(d)
+X erasealarmtime(d)
+X A.set = 1
+X A.time = atime
+X drawalarm(d)
+X drawalarmtime(d)
+X
+Xdef drawalarm(d):
+X p1 = calcpoint(float(A.time)/2.0, 1.02)
+X p2 = calcpoint(float(A.time)/2.0 - 4.0, 1.1)
+X p3 = calcpoint(float(A.time)/2.0 + 4.0, 1.1)
+X d.xorline(p1, p2)
+X d.xorline(p2, p3)
+X d.xorline(p3, p1)
+X
+Xdef erasealarmtime(d):
+X d.erase(G.statusarea)
+X
+Xdef drawalarmtime(d):
+X # A.time is in the range 0..720 with origin at 12 o'clock
+X # Convert to hours (0..12) and minutes (12*(0..60))
+X hh = A.time/60
+X mm = A.time%60
+X str = 'Alarm@' + dd(hh) + ':' + dd(mm)
+X p1 = (G.width - d.textwidth(str))/2, G.height
+X d.text(p1, str)
+X
+Xdef calctime(now):
+X seconds = now % 60
+X minutes = (now/60) % 60
+X hours = (now/3600) % 12
+X return hours, minutes, seconds
+X
+Xdef calcpoint(degrees, size):
+X alpha = pi/2.0 - float(degrees) * pi/180.0
+X x, y = cos(alpha), sin(alpha)
+X h, v = G.center
+X r = float(G.radius)
+X return h + int(x*size*r), v - int(y*size*r)
+X
+Xdef dd(n):
+X s = `n`
+X return '0'*(2-len(s)) + s
+X
+Xdef getlocaltime():
+X return time.time() - G.tzdiff
+X
+X#main()
+EOF
+fi
+if test -s 'lib/dircmp.py'
+then echo '*** I will not over-write existing file lib/dircmp.py'
+else
+echo 'x - lib/dircmp.py'
+sed 's/^X//' > 'lib/dircmp.py' << 'EOF'
+X# Module 'dirmp'
+X#
+X# Defines a class to build directory diff tools on.
+X
+Ximport posix
+X
+Ximport path
+X
+Ximport dircache
+Ximport cmpcache
+Ximport statcache
+Xfrom stat import *
+X
+X# Directory comparison class.
+X#
+Xclass dircmp():
+X #
+X def new(dd, (a, b)): # Initialize
+X dd.a = a
+X dd.b = b
+X # Properties that caller may change before callingdd. run():
+X dd.hide = ['.', '..'] # Names never to be shown
+X dd.ignore = ['RCS', 'tags'] # Names ignored in comparison
+X #
+X return dd
+X #
+X def run(dd): # Compare everything except common subdirectories
+X dd.a_list = filter(dircache.listdir(dd.a), dd.hide)
+X dd.b_list = filter(dircache.listdir(dd.b), dd.hide)
+X dd.a_list.sort()
+X dd.b_list.sort()
+X dd.phase1()
+X dd.phase2()
+X dd.phase3()
+X #
+X def phase1(dd): # Compute common names
+X dd.a_only = []
+X dd.common = []
+X for x in dd.a_list:
+X if x in dd.b_list:
+X dd.common.append(x)
+X else:
+X dd.a_only.append(x)
+X #
+X dd.b_only = []
+X for x in dd.b_list:
+X if x not in dd.common:
+X dd.b_only.append(x)
+X #
+X def phase2(dd): # Distinguish files, directories, funnies
+X dd.common_dirs = []
+X dd.common_files = []
+X dd.common_funny = []
+X #
+X for x in dd.common:
+X a_path = path.cat(dd.a, x)
+X b_path = path.cat(dd.b, x)
+X #
+X ok = 1
+X try:
+X a_stat = statcache.stat(a_path)
+X except posix.error, why:
+X # print 'Can\'t stat', a_path, ':', why[1]
+X ok = 0
+X try:
+X b_stat = statcache.stat(b_path)
+X except posix.error, why:
+X # print 'Can\'t stat', b_path, ':', why[1]
+X ok = 0
+X #
+X if ok:
+X a_type = S_IFMT(a_stat[ST_MODE])
+X b_type = S_IFMT(b_stat[ST_MODE])
+X if a_type <> b_type:
+X dd.common_funny.append(x)
+X elif S_ISDIR(a_type):
+X dd.common_dirs.append(x)
+X elif S_ISREG(a_type):
+X dd.common_files.append(x)
+X else:
+X dd.common_funny.append(x)
+X else:
+X dd.common_funny.append(x)
+X #
+X def phase3(dd): # Find out differences between common files
+X xx = cmpfiles(dd.a, dd.b, dd.common_files)
+X dd.same_files, dd.diff_files, dd.funny_files = xx
+X #
+X def phase4(dd): # Find out differences between common subdirectories
+X # A new dircmp object is created for each common subdirectory,
+X # these are stored in a dictionary indexed by filename.
+X # The hide and ignore properties are inherited from the parent
+X dd.subdirs = {}
+X for x in dd.common_dirs:
+X a_x = path.cat(dd.a, x)
+X b_x = path.cat(dd.b, x)
+X dd.subdirs[x] = newdd = dircmp().new(a_x, b_x)
+X newdd.hide = dd.hide
+X newdd.ignore = dd.ignore
+X newdd.run()
+X #
+X def phase4_closure(dd): # Recursively call phase4() on subdirectories
+X dd.phase4()
+X for x in dd.subdirs.keys():
+X dd.subdirs[x].phase4_closure()
+X #
+X def report(dd): # Print a report on the differences between a and b
+X # Assume that phases 1 to 3 have been executed
+X # Output format is purposely lousy
+X print 'diff', dd.a, dd.b
+X if dd.a_only:
+X print 'Only in', dd.a, ':', dd.a_only
+X if dd.b_only:
+X print 'Only in', dd.b, ':', dd.b_only
+X if dd.same_files:
+X print 'Identical files :', dd.same_files
+X if dd.diff_files:
+X print 'Differing files :', dd.diff_files
+X if dd.funny_files:
+X print 'Trouble with common files :', dd.funny_files
+X if dd.common_dirs:
+X print 'Common subdirectories :', dd.common_dirs
+X if dd.common_funny:
+X print 'Common funny cases :', dd.common_funny
+X #
+X def report_closure(dd): # Print reports on dd and on subdirs
+X # If phase 4 hasn't been done, no subdir reports are printed
+X dd.report()
+X try:
+X x = dd.subdirs
+X except NameError:
+X return # No subdirectories computed
+X for x in dd.subdirs.keys():
+X print
+X dd.subdirs[x].report_closure()
+X #
+X def report_phase4_closure(dd): # Report and do phase 4 recursively
+X dd.report()
+X dd.phase4()
+X for x in dd.subdirs.keys():
+X print
+X dd.subdirs[x].report_phase4_closure()
+X
+X
+X# Compare common files in two directories.
+X# Return:
+X# - files that compare equal
+X# - files that compare different
+X# - funny cases (can't stat etc.)
+X#
+Xdef cmpfiles(a, b, common):
+X res = ([], [], [])
+X for x in common:
+X res[cmp(path.cat(a, x), path.cat(b, x))].append(x)
+X return res
+X
+X
+X# Compare two files.
+X# Return:
+X# 0 for equal
+X# 1 for different
+X# 2 for funny cases (can't stat, etc.)
+X#
+Xdef cmp(a, b):
+X try:
+X if cmpcache.cmp(a, b): return 0
+X return 1
+X except posix.error:
+X return 2
+X
+X
+X# Remove a list item.
+X# NB: This modifies the list argument.
+X#
+Xdef remove(list, item):
+X for i in range(len(list)):
+X if list[i] = item:
+X del list[i]
+X break
+X
+X
+X# Return a copy with items that occur in skip removed.
+X#
+Xdef filter(list, skip):
+X result = []
+X for item in list:
+X if item not in skip: result.append(item)
+X return result
+X
+X
+X# Demonstration and testing.
+X#
+Xdef demo():
+X import sys
+X import getopt
+X options, args = getopt.getopt(sys.argv[1:], 'r')
+X if len(args) <> 2: raise getopt.error, 'need exactly two args'
+X dd = dircmp().new(args[0], args[1])
+X dd.run()
+X if ('-r', '') in options:
+X dd.report_phase4_closure()
+X else:
+X dd.report()
+X
+X# demo()
+EOF
+fi
+if test -s 'lib/dis.py'
+then echo '*** I will not over-write existing file lib/dis.py'
+else
+echo 'x - lib/dis.py'
+sed 's/^X//' > 'lib/dis.py' << 'EOF'
+X# Disassembler
+X
+Ximport sys
+Ximport string
+X
+Xdef dis():
+X tb = sys.last_traceback
+X while tb.tb_next: tb = tb.tb_next
+X distb(tb)
+X
+Xdef distb(tb):
+X disassemble(tb.tb_frame.f_code, tb.tb_lasti)
+X
+Xdef disco(co):
+X disassemble(co, -1)
+X
+Xdef disassemble(co, lasti):
+X code = co.co_code
+X labels = findlabels(code)
+X n = len(code)
+X i = 0
+X while i < n:
+X c = code[i]
+X op = ord(c)
+X if op = SET_LINENO and i > 0: print # Extra blank line
+X if i = lasti: print '-->',
+X else: print ' ',
+X if i in labels: print '>>',
+X else: print ' ',
+X print string.rjust(`i`, 4),
+X print string.ljust(opname[op], 15),
+X i = i+1
+X if op >= HAVE_ARGUMENT:
+X oparg = ord(code[i]) + ord(code[i+1])*256
+X i = i+2
+X print string.rjust(`oparg`, 5),
+X if op in hasconst:
+X print '(' + `co.co_consts[oparg]` + ')',
+X elif op in hasname:
+X print '(' + co.co_names[oparg] + ')',
+X elif op in hasjrel:
+X print '(to ' + `i + oparg` + ')',
+X print
+X
+Xdef findlabels(code):
+X labels = []
+X n = len(code)
+X i = 0
+X while i < n:
+X c = code[i]
+X op = ord(c)
+X i = i+1
+X if op >= HAVE_ARGUMENT:
+X oparg = ord(code[i]) + ord(code[i+1])*256
+X i = i+2
+X label = -1
+X if op in hasjrel:
+X label = i+oparg
+X elif op in hasjabs:
+X label = oparg
+X if label >= 0:
+X if label not in labels:
+X labels.append(label)
+X return labels
+X
+Xhasconst = []
+Xhasname = []
+Xhasjrel = []
+Xhasjabs = []
+X
+Xopname = range(256)
+Xfor op in opname: opname[op] = '<' + `op` + '>'
+X
+Xdef def_op(name, op):
+X opname[op] = name
+X
+Xdef name_op(name, op):
+X opname[op] = name
+X hasname.append(op)
+X
+Xdef jrel_op(name, op):
+X opname[op] = name
+X hasjrel.append(op)
+X
+Xdef jabs_op(name, op):
+X opname[op] = name
+X hasjabs.append(op)
+X
+X# Instruction opcodes for compiled code
+X
+Xdef_op('STOP_CODE', 0)
+Xdef_op('POP_TOP', 1)
+Xdef_op('ROT_TWO', 2)
+Xdef_op('ROT_THREE', 3)
+Xdef_op('DUP_TOP', 4)
+X
+Xdef_op('UNARY_POSITIVE', 10)
+Xdef_op('UNARY_NEGATIVE', 11)
+Xdef_op('UNARY_NOT', 12)
+Xdef_op('UNARY_CONVERT', 13)
+Xdef_op('UNARY_CALL', 14)
+X
+Xdef_op('BINARY_MULTIPLY', 20)
+Xdef_op('BINARY_DIVIDE', 21)
+Xdef_op('BINARY_MODULO', 22)
+Xdef_op('BINARY_ADD', 23)
+Xdef_op('BINARY_SUBTRACT', 24)
+Xdef_op('BINARY_SUBSCR', 25)
+Xdef_op('BINARY_CALL', 26)
+X
+Xdef_op('SLICE+0', 30)
+Xdef_op('SLICE+1', 31)
+Xdef_op('SLICE+2', 32)
+Xdef_op('SLICE+3', 33)
+X
+Xdef_op('STORE_SLICE+0', 40)
+Xdef_op('STORE_SLICE+1', 41)
+Xdef_op('STORE_SLICE+2', 42)
+Xdef_op('STORE_SLICE+3', 43)
+X
+Xdef_op('DELETE_SLICE+0', 50)
+Xdef_op('DELETE_SLICE+1', 51)
+Xdef_op('DELETE_SLICE+2', 52)
+Xdef_op('DELETE_SLICE+3', 53)
+X
+Xdef_op('STORE_SUBSCR', 60)
+Xdef_op('DELETE_SUBSCR', 61)
+X
+Xdef_op('PRINT_EXPR', 70)
+Xdef_op('PRINT_ITEM', 71)
+Xdef_op('PRINT_NEWLINE', 72)
+X
+Xdef_op('BREAK_LOOP', 80)
+Xdef_op('RAISE_EXCEPTION', 81)
+Xdef_op('LOAD_LOCALS', 82)
+Xdef_op('RETURN_VALUE', 83)
+Xdef_op('REQUIRE_ARGS', 84)
+Xdef_op('REFUSE_ARGS', 85)
+Xdef_op('BUILD_FUNCTION', 86)
+Xdef_op('POP_BLOCK', 87)
+Xdef_op('END_FINALLY', 88)
+Xdef_op('BUILD_CLASS', 89)
+X
+XHAVE_ARGUMENT = 90 # Opcodes from here have an argument:
+X
+Xname_op('STORE_NAME', 90) # Index in name list
+Xname_op('DELETE_NAME', 91) # ""
+Xdef_op('UNPACK_TUPLE', 92) # Number of tuple items
+Xdef_op('UNPACK_LIST', 93) # Number of list items
+X# unused: 94
+Xname_op('STORE_ATTR', 95) # Index in name list
+Xname_op('DELETE_ATTR', 96) # ""
+X
+Xdef_op('LOAD_CONST', 100) # Index in const list
+Xhasconst.append(100)
+Xname_op('LOAD_NAME', 101) # Index in name list
+Xdef_op('BUILD_TUPLE', 102) # Number of tuple items
+Xdef_op('BUILD_LIST', 103) # Number of list items
+Xdef_op('BUILD_MAP', 104) # Always zero for now
+Xname_op('LOAD_ATTR', 105) # Index in name list
+Xdef_op('COMPARE_OP', 106) # Comparison operator
+Xname_op('IMPORT_NAME', 107) # Index in name list
+Xname_op('IMPORT_FROM', 108) # Index in name list
+X
+Xjrel_op('JUMP_FORWARD', 110) # Number of bytes to skip
+Xjrel_op('JUMP_IF_FALSE', 111) # ""
+Xjrel_op('JUMP_IF_TRUE', 112) # ""
+Xjabs_op('JUMP_ABSOLUTE', 113) # Target byte offset from beginning of code
+Xjrel_op('FOR_LOOP', 114) # Number of bytes to skip
+X
+Xjrel_op('SETUP_LOOP', 120) # Distance to target address
+Xjrel_op('SETUP_EXCEPT', 121) # ""
+Xjrel_op('SETUP_FINALLY', 122) # ""
+X
+Xdef_op('SET_LINENO', 127) # Current line number
+XSET_LINENO = 127
+EOF
+fi
+if test -s 'lib/lambda.py'
+then echo '*** I will not over-write existing file lib/lambda.py'
+else
+echo 'x - lib/lambda.py'
+sed 's/^X//' > 'lib/lambda.py' << 'EOF'
+X# A bit of Lambda Calculus illustrated in Python.
+X#
+X# This does not use Python's built-in 'eval' or 'exec' functions!
+X
+X
+X# Currying
+X#
+X# From a function with 2 args, f(x, y), and a value for the 1st arg,
+X# we can create a new function with one argument fx(y) = f(x, y).
+X# This is called "Currying" (after the idea's inventor, a Mr. Curry).
+X#
+X# To implement this we create a class member, of which fx is a method;
+X# f and x are stored as data attributes of the member.
+X
+Xclass _CurryClass():
+X def new(self, (f, x)):
+X self.f = f
+X self.x = x
+X return self
+X def fx(self, y):
+X return self.f(self.x, y)
+X
+Xdef CURRY(f, x):
+X # NB: f is not "simple": it has 2 arguments
+X return _CurryClass().new(f, x).fx
+X
+X
+X# Numbers in Lambda Calculus
+X#
+X# In the lambda calculus, natural numbers are represented by
+X# higher-order functions Ntimes(f, x) that yield f applied N
+X# times to x, e.g., Twice(f, x) = f(f(x)).
+X# As far as I understand, there is no difference in real lambda
+X# calculus between
+X# lambda f x : f(f(x))
+X# and
+X# lambda f : f o f # 'o' means function composition
+X# but in Python we have to write the first as Twice(f, x) and
+X# the second as twice(f).
+X
+Xdef Never(f, x): return x
+Xdef Once(f, x): return f(x)
+Xdef Twice(f, x): return f(f(x))
+Xdef Thrice(f, x): return f(f(f(x)))
+Xdef Fourfold(f, x): return f(f(f(f(x))))
+X# (etc.)
+X
+Xdef never(f): return CURRY(Never, f)
+Xdef once(f): return CURRY(Once, f)
+Xdef twice(f): return CURRY(Twice, f)
+Xdef thrice(f): return CURRY(Thrice, f)
+Xdef fourfold(f): return CURRY(Fourfold, f)
+X# (etc.)
+X
+X
+X# NB: actually 'ntimes' is less concrete than 'Ntimes', as
+X# 'ntimes' returns a function, while 'Ntimes' returns a value
+X# similar to what f(x) returns. 'Ntimes' can be derived
+X# from 'ntimes', as follows:
+X# def Ntimes(f, x): return ntimes(f)(x)
+X# but this doesn't help us since 'ntimes' can only be defined
+X# using Ntimes (or a trick like the one used by CURRY).
+X
+X
+X# Arithmetic in Lambda Calculus
+X#
+X# We can perform simple arithmetic on the un-curried versions, e.g.,
+X# Successor(Twice) = Thrice (2+1)
+X# Sum(Thrice, Twice) = Fivefold (3+2)
+X# Product(Thrice, Twice) = Sixfold (3*2)
+X# Power(Thrice, Twice) = Ninefold (3**2)
+X#
+X# First we define versions that need f and x arguments.
+X# They have funny argument forms so the final functions can
+X# use CURRY, which only works on functions of exactly 2 arguments.
+X
+Xdef SUCCESSOR(Ntimes, (f, x)): return f(Ntimes(f, x))
+Xdef SUCCESSOR(Ntimes, (f, x)): return Ntimes(f, f(x)) # Same effect
+Xdef SUM(Ntimes, (Mtimes, (f, x))): return Ntimes(f, Mtimes(f, x))
+Xdef PRODUCT(Ntimes, (Mtimes, (f, x))): return Ntimes(CURRY(Mtimes, f), x)
+Xdef POWER(Ntimes, (Mtimes, (f, x))):
+X return Mtimes(CURRY(CURRY, Ntimes), f)(x)
+X
+Xdef Successor(Ntimes): return CURRY(SUCCESSOR, Ntimes)
+Xdef Sum(Ntimes, Mtimes): return CURRY(CURRY(SUM, Ntimes), Mtimes)
+Xdef Product(Ntimes, Mtimes): return CURRY(CURRY(PRODUCT, Ntimes), Mtimes)
+Xdef Power(Ntimes, Mtimes): return CURRY(CURRY(POWER, Ntimes), Mtimes)
+X
+X
+X# Sorry, I don't have a clue on how to do subtraction or division...
+X
+X
+X# References
+X#
+X# All I know about lambda calculus is from Roger Penrose's
+X# The Emperor's New Mind, Chapter 2.
+X
+X
+X# P.S.: Here is a Lambda function in Python.
+X# It uses 'exec' and expects two strings to describe the arguments
+X# and the function expression. Example:
+X# lambda('x', 'x+1')
+X# defines the successor function.
+X
+Xdef lambda(args, expr):
+X if '\n' in args or '\n' in expr:
+X raise RuntimeError, 'lambda: no cheating!'
+X stmt = 'def func(' + args + '): return ' + expr + '\n'
+X print 'lambda:', stmt,
+X exec(stmt)
+X return func
+X
+X
+X# P.P.S.S.: Here is a way to construct Ntimes and ntimes directly.
+X# Example:
+X# GenericNtimes(4)
+X# is equivalent to Fourfold.
+X
+Xclass _GenericNtimesClass():
+X def new(self, n):
+X self.n = n
+X return self
+X def Ntimes(self, (f, x)):
+X n = self.n
+X while n > 0: x, n = f(x), n-1
+X return x
+X
+Xdef GenericNtimes(n):
+X return _GenericNtimesClass().new(n).Ntimes
+X
+X
+X# To construct any 'ntimes' function from the corresponding 'Ntimes',
+X# we use a trick as used by CURRY. For example,
+X# Ntimes2ntimes(Fourfold)
+X# yields a function equivalent to fourfold.
+X
+Xclass _Ntimes2ntimesClass():
+X def new(self, Ntimes):
+X self.Ntimes = Ntimes
+X return self
+X def ntimes(self, f):
+X return CURRY(self.Ntimes, f)
+X
+Xdef Ntimes2ntimes(Ntimes): return _Ntimes2ntimesClass().new(Ntimes).ntimes
+X
+X
+X# This allows us to construct generic 'ntimes' functions. Example:
+X# generic_ntimes(3)
+X# is the same as thrice.
+X
+Xdef generic_ntimes(n): return Ntimes2ntimes(GenericNtimes(n))
+EOF
+fi
+if test -s 'lib/tb.py'
+then echo '*** I will not over-write existing file lib/tb.py'
+else
+echo 'x - lib/tb.py'
+sed 's/^X//' > 'lib/tb.py' << 'EOF'
+X# Print tracebacks, with a dump of local variables.
+X# Also an interactive stack trace browser.
+X
+Ximport sys
+Xtry:
+X import mac
+X os = mac
+Xexcept NameError:
+X import posix
+X os = posix
+Xfrom stat import *
+Ximport string
+X
+Xdef br(): browser(sys.last_traceback)
+X
+Xdef tb(): printtb(sys.last_traceback)
+X
+Xdef browser(tb):
+X if not tb:
+X print 'No traceback.'
+X return
+X tblist = []
+X while tb:
+X tblist.append(tb)
+X tb = tb.tb_next
+X ptr = len(tblist)-1
+X tb = tblist[ptr]
+X while 1:
+X if tb <> tblist[ptr]:
+X tb = tblist[ptr]
+X print `ptr` + ':',
+X printtbheader(tb)
+X try:
+X line = raw_input('TB: ')
+X except KeyboardInterrupt:
+X print '\n[Interrupted]'
+X break
+X except EOFError:
+X print '\n[EOF]'
+X break
+X cmd = string.strip(line)
+X if cmd:
+X if cmd = 'quit':
+X break
+X elif cmd = 'list':
+X browserlist(tb)
+X elif cmd = 'up':
+X if ptr-1 >= 0: ptr = ptr-1
+X else: print 'Bottom of stack.'
+X elif cmd = 'down':
+X if ptr+1 < len(tblist): ptr = ptr+1
+X else: print 'Top of stack.'
+X elif cmd = 'locals':
+X printsymbols(tb.tb_frame.f_locals)
+X elif cmd = 'globals':
+X printsymbols(tb.tb_frame.f_globals)
+X elif cmd in ('?', 'help'):
+X browserhelp()
+X else:
+X browserexec(tb, cmd)
+X
+Xdef browserlist(tb):
+X filename = tb.tb_frame.f_code.co_filename
+X lineno = tb.tb_lineno
+X last = lineno
+X first = max(1, last-10)
+X for i in range(first, last+1):
+X if i = lineno: prefix = '***' + string.rjust(`i`, 4) + ':'
+X else: prefix = string.rjust(`i`, 7) + ':'
+X line = readfileline(filename, i)
+X if line[-1:] = '\n': line = line[:-1]
+X print prefix + line
+X
+Xdef browserexec(tb, cmd):
+X locals = tb.tb_frame.f_locals
+X globals = tb.tb_frame.f_globals
+X try:
+X exec(cmd+'\n', globals, locals)
+X except:
+X print '*** Exception:',
+X print sys.exc_type,
+X if sys.exc_value <> None:
+X print ':', sys.exc_value,
+X print
+X print 'Type help to get help.'
+X
+Xdef browserhelp():
+X print
+X print ' This is the traceback browser. Commands are:'
+X print ' up : move one level up in the call stack'
+X print ' down : move one level down in the call stack'
+X print ' locals : print all local variables at this level'
+X print ' globals : print all global variables at this level'
+X print ' list : list source code around the failure'
+X print ' help : print help (what you are reading now)'
+X print ' quit : back to command interpreter'
+X print ' Typing any other 1-line statement will execute it'
+X print ' using the current level\'s symbol tables'
+X print
+X
+Xdef printtb(tb):
+X while tb:
+X print1tb(tb)
+X tb = tb.tb_next
+X
+Xdef print1tb(tb):
+X printtbheader(tb)
+X if tb.tb_frame.f_locals is not tb.tb_frame.f_globals:
+X printsymbols(tb.tb_frame.f_locals)
+X
+Xdef printtbheader(tb):
+X filename = tb.tb_frame.f_code.co_filename
+X lineno = tb.tb_lineno
+X info = '"' + filename + '"(' + `lineno` + ')'
+X line = readfileline(filename, lineno)
+X if line:
+X info = info + ': ' + string.strip(line)
+X print info
+X
+Xdef printsymbols(d):
+X keys = d.keys()
+X keys.sort()
+X for name in keys:
+X print ' ' + string.ljust(name, 12) + ':',
+X printobject(d[name], 4)
+X print
+X
+Xdef printobject(v, maxlevel):
+X if v = None:
+X print 'None',
+X elif type(v) in (type(0), type(0.0)):
+X print v,
+X elif type(v) = type(''):
+X if len(v) > 20:
+X print `v[:17] + '...'`,
+X else:
+X print `v`,
+X elif type(v) = type(()):
+X print '(',
+X printlist(v, maxlevel)
+X print ')',
+X elif type(v) = type([]):
+X print '[',
+X printlist(v, maxlevel)
+X print ']',
+X elif type(v) = type({}):
+X print '{',
+X printdict(v, maxlevel)
+X print '}',
+X else:
+X print v,
+X
+Xdef printlist(v, maxlevel):
+X n = len(v)
+X if n = 0: return
+X if maxlevel <= 0:
+X print '...',
+X return
+X for i in range(min(6, n)):
+X printobject(v[i], maxlevel-1)
+X if i+1 < n: print ',',
+X if n > 6: print '...',
+X
+Xdef printdict(v, maxlevel):
+X keys = v.keys()
+X n = len(keys)
+X if n = 0: return
+X if maxlevel <= 0:
+X print '...',
+X return
+X keys.sort()
+X for i in range(min(6, n)):
+X key = keys[i]
+X print `key` + ':',
+X printobject(v[key], maxlevel-1)
+X if i+1 < n: print ',',
+X if n > 6: print '...',
+X
+X_filecache = {}
+X
+Xdef readfileline(filename, lineno):
+X try:
+X stat = os.stat(filename)
+X except os.error, msg:
+X print 'Cannot stat', filename, '--', msg
+X return ''
+X cache_ok = 0
+X if _filecache.has_key(filename):
+X cached_stat, lines = _filecache[filename]
+X if stat[ST_SIZE] = cached_stat[ST_SIZE] and \
+X stat[ST_MTIME] = cached_stat[ST_MTIME]:
+X cache_ok = 1
+X else:
+X print 'Stale cache entry for', filename
+X del _filecache[filename]
+X if not cache_ok:
+X lines = readfilelines(filename)
+X if not lines:
+X return ''
+X _filecache[filename] = stat, lines
+X if 0 <= lineno-1 < len(lines):
+X return lines[lineno-1]
+X else:
+X print 'Line number out of range, last line is', len(lines)
+X return ''
+X
+Xdef readfilelines(filename):
+X try:
+X fp = open(filename, 'r')
+X except:
+X print 'Cannot open', filename
+X return []
+X lines = []
+X while 1:
+X line = fp.readline()
+X if not line: break
+X lines.append(line)
+X if not lines:
+X print 'Empty file', filename
+X return lines
+EOF
+fi
+if test -s 'src/errors.c'
+then echo '*** I will not over-write existing file src/errors.c'
+else
+echo 'x - src/errors.c'
+sed 's/^X//' > 'src/errors.c' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/* Error handling -- see also run.c */
+X
+X/* New error handling interface.
+X
+X The following problem exists (existed): methods of built-in modules
+X are called with 'self' and 'args' arguments, but without a context
+X argument, so they have no way to raise a specific exception.
+X The same is true for the object implementations: no context argument.
+X The old convention was to set 'errno' and to return NULL.
+X The caller (usually call_function() in eval.c) detects the NULL
+X return value and then calls puterrno(ctx) to turn the errno value
+X into a true exception. Problems with this approach are:
+X - it used standard errno values to indicate Python-specific errors,
+X but this means that when such an error code is reported by a system
+X call (e.g., in module posix), the user gets a confusing message
+X - errno is a global variable, which makes extensions to a multi-
+X threading environment difficult; e.g., in IRIX, multi-threaded
+X programs must use the function oserror() instead of looking in errno
+X - there is no portable way to add new error numbers for specic
+X situations -- the value space for errno is reserved to the OS, yet
+X the way to turn module-specific errors into a module-specific
+X exception requires module-specific values for errno
+X - there is no way to add a more situation-specific message to an
+X error.
+X
+X The new interface solves all these problems. To return an error, a
+X built-in function calls err_set(exception), err_setval(exception,
+X value) or err_setstr(exception, string), and returns NULL. These
+X functions save the value for later use by puterrno(). To adapt this
+X scheme to a multi-threaded environment, only the implementation of
+X err_setval() has to be changed.
+X*/
+X
+X#include "allobjects.h"
+X
+X#include <errno.h>
+X#ifndef errno
+Xextern int errno;
+X#endif
+X
+X#include "errcode.h"
+X
+Xextern char *strerror PROTO((int));
+X
+X/* Last exception stored by err_setval() */
+X
+Xstatic object *last_exception;
+Xstatic object *last_exc_val;
+X
+Xvoid
+Xerr_setval(exception, value)
+X object *exception;
+X object *value;
+X{
+X XDECREF(last_exception);
+X XINCREF(exception);
+X last_exception = exception;
+X
+X XDECREF(last_exc_val);
+X XINCREF(value);
+X last_exc_val = value;
+X}
+X
+Xvoid
+Xerr_set(exception)
+X object *exception;
+X{
+X err_setval(exception, (object *)NULL);
+X}
+X
+Xvoid
+Xerr_setstr(exception, string)
+X object *exception;
+X char *string;
+X{
+X object *value = newstringobject(string);
+X err_setval(exception, value);
+X XDECREF(value);
+X}
+X
+Xint
+Xerr_occurred()
+X{
+X return last_exception != NULL;
+X}
+X
+Xvoid
+Xerr_get(p_exc, p_val)
+X object **p_exc;
+X object **p_val;
+X{
+X *p_exc = last_exception;
+X last_exception = NULL;
+X *p_val = last_exc_val;
+X last_exc_val = NULL;
+X}
+X
+Xvoid
+Xerr_clear()
+X{
+X XDECREF(last_exception);
+X last_exception = NULL;
+X XDECREF(last_exc_val);
+X last_exc_val = NULL;
+X}
+X
+X/* Convenience functions to set a type error exception and return 0 */
+X
+Xint
+Xerr_badarg()
+X{
+X err_setstr(TypeError, "illegal argument type for built-in operation");
+X return 0;
+X}
+X
+Xobject *
+Xerr_nomem()
+X{
+X err_set(MemoryError);
+X return NULL;
+X}
+X
+Xobject *
+Xerr_errno(exc)
+X object *exc;
+X{
+X object *v = newtupleobject(2);
+X if (v != NULL) {
+X settupleitem(v, 0, newintobject((long)errno));
+X settupleitem(v, 1, newstringobject(strerror(errno)));
+X }
+X err_setval(exc, v);
+X XDECREF(v);
+X return NULL;
+X}
+X
+Xvoid
+Xerr_badcall()
+X{
+X err_setstr(SystemError, "bad argument to internal function");
+X}
+X
+X/* Set the error appropriate to the given input error code (see errcode.h) */
+X
+Xvoid
+Xerr_input(err)
+X int err;
+X{
+X switch (err) {
+X case E_DONE:
+X case E_OK:
+X break;
+X case E_SYNTAX:
+X err_setstr(RuntimeError, "syntax error");
+X break;
+X case E_TOKEN:
+X err_setstr(RuntimeError, "illegal token");
+X break;
+X case E_INTR:
+X err_set(KeyboardInterrupt);
+X break;
+X case E_NOMEM:
+X err_nomem();
+X break;
+X case E_EOF:
+X err_set(EOFError);
+X break;
+X default:
+X err_setstr(RuntimeError, "unknown input error");
+X break;
+X }
+X}
+EOF
+fi
+if test -s 'src/mathmodule.c'
+then echo '*** I will not over-write existing file src/mathmodule.c'
+else
+echo 'x - src/mathmodule.c'
+sed 's/^X//' > 'src/mathmodule.c' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/* Math module -- standard C math library functions, pi and e */
+X
+X#include "allobjects.h"
+X
+X#include <errno.h>
+X#ifndef errno
+Xextern int errno;
+X#endif
+X
+X#include "modsupport.h"
+X
+X#include <math.h>
+X
+Xstatic int
+Xgetdoublearg(args, px)
+X register object *args;
+X double *px;
+X{
+X if (args == NULL)
+X return err_badarg();
+X if (is_floatobject(args)) {
+X *px = getfloatvalue(args);
+X return 1;
+X }
+X if (is_intobject(args)) {
+X *px = getintvalue(args);
+X return 1;
+X }
+X return err_badarg();
+X}
+X
+Xstatic int
+Xget2doublearg(args, px, py)
+X register object *args;
+X double *px, *py;
+X{
+X if (args == NULL || !is_tupleobject(args) || gettuplesize(args) != 2)
+X return err_badarg();
+X return getdoublearg(gettupleitem(args, 0), px) &&
+X getdoublearg(gettupleitem(args, 1), py);
+X}
+X
+Xstatic object *
+Xmath_1(args, func)
+X object *args;
+X double (*func) FPROTO((double));
+X{
+X double x;
+X if (!getdoublearg(args, &x))
+X return NULL;
+X errno = 0;
+X x = (*func)(x);
+X if (errno != 0)
+X return NULL;
+X else
+X return newfloatobject(x);
+X}
+X
+Xstatic object *
+Xmath_2(args, func)
+X object *args;
+X double (*func) FPROTO((double, double));
+X{
+X double x, y;
+X if (!get2doublearg(args, &x, &y))
+X return NULL;
+X errno = 0;
+X x = (*func)(x, y);
+X if (errno != 0)
+X return NULL;
+X else
+X return newfloatobject(x);
+X}
+X
+X#define FUNC1(stubname, func) \
+X static object * stubname(self, args) object *self, *args; { \
+X return math_1(args, func); \
+X }
+X
+X#define FUNC2(stubname, func) \
+X static object * stubname(self, args) object *self, *args; { \
+X return math_2(args, func); \
+X }
+X
+XFUNC1(math_acos, acos)
+XFUNC1(math_asin, asin)
+XFUNC1(math_atan, atan)
+XFUNC2(math_atan2, atan2)
+XFUNC1(math_ceil, ceil)
+XFUNC1(math_cos, cos)
+XFUNC1(math_cosh, cosh)
+XFUNC1(math_exp, exp)
+XFUNC1(math_fabs, fabs)
+XFUNC1(math_floor, floor)
+X#if 0
+X/* XXX This one is not in the Amoeba library yet, so what the heck... */
+XFUNC2(math_fmod, fmod)
+X#endif
+XFUNC1(math_log, log)
+XFUNC1(math_log10, log10)
+XFUNC2(math_pow, pow)
+XFUNC1(math_sin, sin)
+XFUNC1(math_sinh, sinh)
+XFUNC1(math_sqrt, sqrt)
+XFUNC1(math_tan, tan)
+XFUNC1(math_tanh, tanh)
+X
+X#if 0
+X/* What about these? */
+Xdouble frexp(double x, int *i);
+Xdouble ldexp(double x, int n);
+Xdouble modf(double x, double *i);
+X#endif
+X
+Xstatic struct methodlist math_methods[] = {
+X {"acos", math_acos},
+X {"asin", math_asin},
+X {"atan", math_atan},
+X {"atan2", math_atan2},
+X {"ceil", math_ceil},
+X {"cos", math_cos},
+X {"cosh", math_cosh},
+X {"exp", math_exp},
+X {"fabs", math_fabs},
+X {"floor", math_floor},
+X#if 0
+X {"fmod", math_fmod},
+X {"frexp", math_freqp},
+X {"ldexp", math_ldexp},
+X#endif
+X {"log", math_log},
+X {"log10", math_log10},
+X#if 0
+X {"modf", math_modf},
+X#endif
+X {"pow", math_pow},
+X {"sin", math_sin},
+X {"sinh", math_sinh},
+X {"sqrt", math_sqrt},
+X {"tan", math_tan},
+X {"tanh", math_tanh},
+X {NULL, NULL} /* sentinel */
+X};
+X
+Xvoid
+Xinitmath()
+X{
+X object *m, *d, *v;
+X
+X m = initmodule("math", math_methods);
+X d = getmoduledict(m);
+X dictinsert(d, "pi", v = newfloatobject(atan(1.0) * 4.0));
+X DECREF(v);
+X dictinsert(d, "e", v = newfloatobject(exp(1.0)));
+X DECREF(v);
+X}
+EOF
+fi
+if test -s 'src/sysmodule.c'
+then echo '*** I will not over-write existing file src/sysmodule.c'
+else
+echo 'x - src/sysmodule.c'
+sed 's/^X//' > 'src/sysmodule.c' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/* System module */
+X
+X/*
+XVarious bits of information used by the interpreter are collected in
+Xmodule 'sys'.
+XFunction member:
+X- exit(sts): call (C, POSIX) exit(sts)
+XData members:
+X- stdin, stdout, stderr: standard file objects
+X- modules: the table of modules (dictionary)
+X- path: module search path (list of strings)
+X- argv: script arguments (list of strings)
+X- ps1, ps2: optional primary and secondary prompts (strings)
+X*/
+X
+X#include "allobjects.h"
+X
+X#include "sysmodule.h"
+X#include "import.h"
+X#include "modsupport.h"
+X
+X/* Define delimiter used in $PYTHONPATH */
+X
+X#ifdef THINK_C
+X#define DELIM ' '
+X#endif
+X
+X#ifndef DELIM
+X#define DELIM ':'
+X#endif
+X
+Xstatic object *sysdict;
+X
+Xobject *
+Xsysget(name)
+X char *name;
+X{
+X return dictlookup(sysdict, name);
+X}
+X
+XFILE *
+Xsysgetfile(name, def)
+X char *name;
+X FILE *def;
+X{
+X FILE *fp = NULL;
+X object *v = sysget(name);
+X if (v != NULL)
+X fp = getfilefile(v);
+X if (fp == NULL)
+X fp = def;
+X return fp;
+X}
+X
+Xint
+Xsysset(name, v)
+X char *name;
+X object *v;
+X{
+X if (v == NULL)
+X return dictremove(sysdict, name);
+X else
+X return dictinsert(sysdict, name, v);
+X}
+X
+Xstatic object *
+Xsys_exit(self, args)
+X object *self;
+X object *args;
+X{
+X int sts;
+X if (!getintarg(args, &sts))
+X return NULL;
+X goaway(sts);
+X exit(sts); /* Just in case */
+X /* NOTREACHED */
+X}
+X
+Xstatic struct methodlist sys_methods[] = {
+X {"exit", sys_exit},
+X {NULL, NULL} /* sentinel */
+X};
+X
+Xstatic object *sysin, *sysout, *syserr;
+X
+Xvoid
+Xinitsys()
+X{
+X object *m = initmodule("sys", sys_methods);
+X sysdict = getmoduledict(m);
+X INCREF(sysdict);
+X /* NB keep an extra ref to the std files to avoid closing them
+X when the user deletes them */
+X /* XXX File objects should have a "don't close" flag instead */
+X sysin = newopenfileobject(stdin, "<stdin>", "r");
+X sysout = newopenfileobject(stdout, "<stdout>", "w");
+X syserr = newopenfileobject(stderr, "<stderr>", "w");
+X if (err_occurred())
+X fatal("can't create sys.std* file objects");
+X dictinsert(sysdict, "stdin", sysin);
+X dictinsert(sysdict, "stdout", sysout);
+X dictinsert(sysdict, "stderr", syserr);
+X dictinsert(sysdict, "modules", get_modules());
+X if (err_occurred())
+X fatal("can't insert sys.* objects in sys dict");
+X}
+X
+Xstatic object *
+Xmakepathobject(path, delim)
+X char *path;
+X int delim;
+X{
+X int i, n;
+X char *p;
+X object *v, *w;
+X
+X n = 1;
+X p = path;
+X while ((p = strchr(p, delim)) != NULL) {
+X n++;
+X p++;
+X }
+X v = newlistobject(n);
+X if (v == NULL)
+X return NULL;
+X for (i = 0; ; i++) {
+X p = strchr(path, delim);
+X if (p == NULL)
+X p = strchr(path, '\0'); /* End of string */
+X w = newsizedstringobject(path, (int) (p - path));
+X if (w == NULL) {
+X DECREF(v);
+X return NULL;
+X }
+X setlistitem(v, i, w);
+X if (*p == '\0')
+X break;
+X path = p+1;
+X }
+X return v;
+X}
+X
+Xvoid
+Xsetpythonpath(path)
+X char *path;
+X{
+X object *v;
+X if ((v = makepathobject(path, DELIM)) == NULL)
+X fatal("can't create sys.path");
+X if (sysset("path", v) != 0)
+X fatal("can't assign sys.path");
+X DECREF(v);
+X}
+X
+Xstatic object *
+Xmakeargvobject(argc, argv)
+X int argc;
+X char **argv;
+X{
+X object *av;
+X if (argc < 0 || argv == NULL)
+X argc = 0;
+X av = newlistobject(argc);
+X if (av != NULL) {
+X int i;
+X for (i = 0; i < argc; i++) {
+X object *v = newstringobject(argv[i]);
+X if (v == NULL) {
+X DECREF(av);
+X av = NULL;
+X break;
+X }
+X setlistitem(av, i, v);
+X }
+X }
+X return av;
+X}
+X
+Xvoid
+Xsetpythonargv(argc, argv)
+X int argc;
+X char **argv;
+X{
+X object *av = makeargvobject(argc, argv);
+X if (av == NULL)
+X fatal("no mem for sys.argv");
+X if (sysset("argv", av) != 0)
+X fatal("can't assign sys.argv");
+X DECREF(av);
+X}
+EOF
+fi
+if test -s 'src/timemodule.c'
+then echo '*** I will not over-write existing file src/timemodule.c'
+else
+echo 'x - src/timemodule.c'
+sed 's/^X//' > 'src/timemodule.c' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/* Time module */
+X
+X#include "allobjects.h"
+X
+X#include "modsupport.h"
+X
+X#include "sigtype.h"
+X
+X#include <signal.h>
+X#include <setjmp.h>
+X
+X#ifdef __STDC__
+X#include <time.h>
+X#else /* !__STDC__ */
+Xtypedef unsigned long time_t;
+Xextern time_t time();
+X#endif /* !__STDC__ */
+X
+X
+X/* Time methods */
+X
+Xstatic object *
+Xtime_time(self, args)
+X object *self;
+X object *args;
+X{
+X long secs;
+X if (!getnoarg(args))
+X return NULL;
+X secs = time((time_t *)NULL);
+X return newintobject(secs);
+X}
+X
+Xstatic jmp_buf sleep_intr;
+X
+Xstatic void
+Xsleep_catcher(sig)
+X int sig;
+X{
+X longjmp(sleep_intr, 1);
+X}
+X
+Xstatic object *
+Xtime_sleep(self, args)
+X object *self;
+X object *args;
+X{
+X int secs;
+X SIGTYPE (*sigsave)();
+X if (!getintarg(args, &secs))
+X return NULL;
+X if (setjmp(sleep_intr)) {
+X signal(SIGINT, sigsave);
+X err_set(KeyboardInterrupt);
+X return NULL;
+X }
+X sigsave = signal(SIGINT, SIG_IGN);
+X if (sigsave != (SIGTYPE (*)()) SIG_IGN)
+X signal(SIGINT, sleep_catcher);
+X sleep(secs);
+X signal(SIGINT, sigsave);
+X INCREF(None);
+X return None;
+X}
+X
+X#ifdef THINK_C
+X#define DO_MILLI
+X#endif /* THINK_C */
+X
+X#ifdef AMOEBA
+X#define DO_MILLI
+Xextern long sys_milli();
+X#define millitimer sys_milli
+X#endif /* AMOEBA */
+X
+X#ifdef BSD_TIME
+X#define DO_MILLI
+X#endif /* BSD_TIME */
+X
+X#ifdef DO_MILLI
+X
+Xstatic object *
+Xtime_millisleep(self, args)
+X object *self;
+X object *args;
+X{
+X long msecs;
+X SIGTYPE (*sigsave)();
+X if (!getlongarg(args, &msecs))
+X return NULL;
+X if (setjmp(sleep_intr)) {
+X signal(SIGINT, sigsave);
+X err_set(KeyboardInterrupt);
+X return NULL;
+X }
+X sigsave = signal(SIGINT, SIG_IGN);
+X if (sigsave != (SIGTYPE (*)()) SIG_IGN)
+X signal(SIGINT, sleep_catcher);
+X millisleep(msecs);
+X signal(SIGINT, sigsave);
+X INCREF(None);
+X return None;
+X}
+X
+Xstatic object *
+Xtime_millitimer(self, args)
+X object *self;
+X object *args;
+X{
+X long msecs;
+X extern long millitimer();
+X if (!getnoarg(args))
+X return NULL;
+X msecs = millitimer();
+X return newintobject(msecs);
+X}
+X
+X#endif /* DO_MILLI */
+X
+X
+Xstatic struct methodlist time_methods[] = {
+X#ifdef DO_MILLI
+X {"millisleep", time_millisleep},
+X {"millitimer", time_millitimer},
+X#endif /* DO_MILLI */
+X {"sleep", time_sleep},
+X {"time", time_time},
+X {NULL, NULL} /* sentinel */
+X};
+X
+X
+Xvoid
+Xinittime()
+X{
+X initmodule("time", time_methods);
+X}
+X
+X
+X#ifdef THINK_C
+X
+X#define MacTicks (* (long *)0x16A)
+X
+Xstatic
+Xsleep(msecs)
+X int msecs;
+X{
+X register long deadline;
+X
+X deadline = MacTicks + msecs * 60;
+X while (MacTicks < deadline) {
+X if (intrcheck())
+X sleep_catcher(SIGINT);
+X }
+X}
+X
+Xstatic
+Xmillisleep(msecs)
+X long msecs;
+X{
+X register long deadline;
+X
+X deadline = MacTicks + msecs * 3 / 50; /* msecs * 60 / 1000 */
+X while (MacTicks < deadline) {
+X if (intrcheck())
+X sleep_catcher(SIGINT);
+X }
+X}
+X
+Xstatic long
+Xmillitimer()
+X{
+X return MacTicks * 50 / 3; /* MacTicks * 1000 / 60 */
+X}
+X
+X#endif /* THINK_C */
+X
+X
+X#ifdef BSD_TIME
+X
+X#include <sys/types.h>
+X#include <sys/time.h>
+X
+Xstatic long
+Xmillitimer()
+X{
+X struct timeval t;
+X struct timezone tz;
+X if (gettimeofday(&t, &tz) != 0)
+X return -1;
+X return t.tv_sec*1000 + t.tv_usec/1000;
+X
+X}
+X
+Xstatic
+Xmillisleep(msecs)
+X long msecs;
+X{
+X struct timeval t;
+X t.tv_sec = msecs/1000;
+X t.tv_usec = (msecs%1000)*1000;
+X (void) select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t);
+X}
+X
+X#endif /* BSD_TIME */
+X
+EOF
+fi
+if test -s 'src/traceback.c'
+then echo '*** I will not over-write existing file src/traceback.c'
+else
+echo 'x - src/traceback.c'
+sed 's/^X//' > 'src/traceback.c' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/* Traceback implementation */
+X
+X#include "allobjects.h"
+X
+X#include "compile.h"
+X#include "frameobject.h"
+X#include "traceback.h"
+X#include "structmember.h"
+X
+Xtypedef struct _tracebackobject {
+X OB_HEAD
+X struct _tracebackobject *tb_next;
+X frameobject *tb_frame;
+X int tb_lasti;
+X int tb_lineno;
+X} tracebackobject;
+X
+X#define OFF(x) offsetof(tracebackobject, x)
+X
+Xstatic struct memberlist tb_memberlist[] = {
+X {"tb_next", T_OBJECT, OFF(tb_next)},
+X {"tb_frame", T_OBJECT, OFF(tb_frame)},
+X {"tb_lasti", T_INT, OFF(tb_lasti)},
+X {"tb_lineno", T_INT, OFF(tb_lineno)},
+X {NULL} /* Sentinel */
+X};
+X
+Xstatic object *
+Xtb_getattr(tb, name)
+X tracebackobject *tb;
+X char *name;
+X{
+X return getmember((char *)tb, tb_memberlist, name);
+X}
+X
+Xstatic void
+Xtb_dealloc(tb)
+X tracebackobject *tb;
+X{
+X XDECREF(tb->tb_next);
+X XDECREF(tb->tb_frame);
+X DEL(tb);
+X}
+X
+Xstatic typeobject Tracebacktype = {
+X OB_HEAD_INIT(&Typetype)
+X 0,
+X "traceback",
+X sizeof(tracebackobject),
+X 0,
+X tb_dealloc, /*tp_dealloc*/
+X 0, /*tp_print*/
+X tb_getattr, /*tp_getattr*/
+X 0, /*tp_setattr*/
+X 0, /*tp_compare*/
+X 0, /*tp_repr*/
+X 0, /*tp_as_number*/
+X 0, /*tp_as_sequence*/
+X 0, /*tp_as_mapping*/
+X};
+X
+X#define is_tracebackobject(v) ((v)->ob_type == &Tracebacktype)
+X
+Xstatic tracebackobject *
+Xnewtracebackobject(next, frame, lasti, lineno)
+X tracebackobject *next;
+X frameobject *frame;
+X int lasti, lineno;
+X{
+X tracebackobject *tb;
+X if ((next != NULL && !is_tracebackobject(next)) ||
+X frame == NULL || !is_frameobject(frame)) {
+X err_badcall();
+X return NULL;
+X }
+X tb = NEWOBJ(tracebackobject, &Tracebacktype);
+X if (tb != NULL) {
+X XINCREF(next);
+X tb->tb_next = next;
+X XINCREF(frame);
+X tb->tb_frame = frame;
+X tb->tb_lasti = lasti;
+X tb->tb_lineno = lineno;
+X }
+X return tb;
+X}
+X
+Xstatic tracebackobject *tb_current = NULL;
+X
+Xint
+Xtb_here(frame, lasti, lineno)
+X frameobject *frame;
+X int lasti;
+X int lineno;
+X{
+X tracebackobject *tb;
+X tb = newtracebackobject(tb_current, frame, lasti, lineno);
+X if (tb == NULL)
+X return -1;
+X XDECREF(tb_current);
+X tb_current = tb;
+X return 0;
+X}
+X
+Xobject *
+Xtb_fetch()
+X{
+X object *v;
+X v = (object *)tb_current;
+X tb_current = NULL;
+X return v;
+X}
+X
+Xint
+Xtb_store(v)
+X object *v;
+X{
+X if (v != NULL && !is_tracebackobject(v)) {
+X err_badcall();
+X return -1;
+X }
+X XDECREF(tb_current);
+X XINCREF(v);
+X tb_current = (tracebackobject *)v;
+X return 0;
+X}
+X
+Xstatic void
+Xtb_displayline(fp, filename, lineno)
+X FILE *fp;
+X char *filename;
+X int lineno;
+X{
+X FILE *xfp;
+X char buf[1000];
+X int i;
+X if (filename[0] == '<' && filename[strlen(filename)-1] == '>')
+X return;
+X xfp = fopen(filename, "r");
+X if (xfp == NULL) {
+X fprintf(fp, " (cannot open \"%s\")\n", filename);
+X return;
+X }
+X for (i = 0; i < lineno; i++) {
+X if (fgets(buf, sizeof buf, xfp) == NULL)
+X break;
+X }
+X if (i == lineno) {
+X char *p = buf;
+X while (*p == ' ' || *p == '\t')
+X p++;
+X fprintf(fp, " %s", p);
+X if (strchr(p, '\n') == NULL)
+X fprintf(fp, "\n");
+X }
+X fclose(xfp);
+X}
+X
+Xstatic void
+Xtb_printinternal(tb, fp)
+X tracebackobject *tb;
+X FILE *fp;
+X{
+X while (tb != NULL) {
+X if (intrcheck()) {
+X fprintf(fp, "[interrupted]\n");
+X break;
+X }
+X fprintf(fp, " File \"");
+X printobject(tb->tb_frame->f_code->co_filename, fp, PRINT_RAW);
+X fprintf(fp, "\", line %d\n", tb->tb_lineno);
+X tb_displayline(fp,
+X getstringvalue(tb->tb_frame->f_code->co_filename),
+X tb->tb_lineno);
+X tb = tb->tb_next;
+X }
+X}
+X
+Xint
+Xtb_print(v, fp)
+X object *v;
+X FILE *fp;
+X{
+X if (v == NULL)
+X return 0;
+X if (!is_tracebackobject(v)) {
+X err_badcall();
+X return -1;
+X }
+X sysset("last_traceback", v);
+X tb_printinternal((tracebackobject *)v, fp);
+X return 0;
+X}
+EOF
+fi
+echo 'Part 15 out of 21 of pack.out complete.'
+exit 0
diff --git a/shar/python-0.9.1-16-21.shar b/shar/python-0.9.1-16-21.shar
new file mode 100644
index 0000000..dc787e0
--- /dev/null
+++ b/shar/python-0.9.1-16-21.shar
@@ -0,0 +1,2495 @@
+: This is a shell archive.
+: Extract with 'sh this_file'.
+:
+: Extract part 01 first since it makes all directories
+echo 'Start of pack.out, part 16 out of 21:'
+if test -s 'demo/sgi/gl_panel/flying/materials.s'
+then echo '*** I will not over-write existing file demo/sgi/gl_panel/flying/materials.s'
+else
+echo 'x - demo/sgi/gl_panel/flying/materials.s'
+sed 's/^X//' > 'demo/sgi/gl_panel/flying/materials.s' << 'EOF'
+X;;; This file was automatically generated by the panel editor.
+X;;; If you read it into gnu emacs, it will automagically format itself.
+X
+X(panel (prop help creator:user-panel-help)
+X(prop user-panel #t)
+X(label "Materials")
+X(al (pnl_label (prop help creator:user-act-help)
+X(label "specular")
+X(x 4)
+X(y 0.5)
+X(downfunc move-then-resize)
+X)
+X(pnl_label (prop help creator:user-act-help)
+X(label "diffuse")
+X(x 4)
+X(y 4)
+X(downfunc move-then-resize)
+X)
+X(pnl_radio_button (name "m7")
+X(prop help creator:user-act-help)
+X(label "material 7")
+X(x 6.5)
+X(y 1.5)
+X(h 0.36)
+X(downfunc move-then-resize)
+X)
+X(pnl_radio_button (name "m9")
+X(prop help creator:user-act-help)
+X(label "material 9")
+X(x 6.5)
+X(y 0.5)
+X(h 0.36)
+X(downfunc move-then-resize)
+X)
+X(pnl_radio_button (name "m8")
+X(prop help creator:user-act-help)
+X(label "material 8")
+X(x 6.5)
+X(y 1)
+X(h 0.36)
+X(downfunc move-then-resize)
+X)
+X(pnl_radio_button (name "m6")
+X(prop help creator:user-act-help)
+X(label "material 6")
+X(x 6.5)
+X(y 2)
+X(h 0.36)
+X(downfunc move-then-resize)
+X)
+X(pnl_radio_button (name "m5")
+X(prop help creator:user-act-help)
+X(label "material 5")
+X(x 6.5)
+X(y 2.5)
+X(h 0.36)
+X(downfunc move-then-resize)
+X)
+X(pnl_radio_button (name "m4")
+X(prop help creator:user-act-help)
+X(label "material 4")
+X(x 6.5)
+X(y 3)
+X(h 0.36)
+X(downfunc move-then-resize)
+X)
+X(pnl_radio_button (name "m3")
+X(prop help creator:user-act-help)
+X(label "material 3")
+X(x 6.5)
+X(y 3.5)
+X(h 0.36)
+X(downfunc move-then-resize)
+X)
+X(pnl_radio_button (name "m2")
+X(prop help creator:user-act-help)
+X(label "material 2")
+X(x 6.5)
+X(y 4)
+X(h 0.36)
+X(downfunc move-then-resize)
+X)
+X(pnl_radio_button (name "m1")
+X(prop help creator:user-act-help)
+X(label "material 1")
+X(x 6.5)
+X(y 4.5)
+X(h 0.36)
+X(downfunc move-then-resize)
+X)
+X(pnl_filled_hslider (name "diffB")
+X(prop help creator:user-act-help)
+X(label "B")
+X(y 3.5)
+X(w 3.3)
+X(h 0.4)
+X(labeltype 0)
+X(downfunc move-then-resize)
+X)
+X(pnl_filled_hslider (name "diffG")
+X(prop help creator:user-act-help)
+X(label "G")
+X(y 4)
+X(w 3.3)
+X(h 0.4)
+X(labeltype 0)
+X(downfunc move-then-resize)
+X)
+X(pnl_filled_hslider (name "diffR")
+X(prop help creator:user-act-help)
+X(label "R")
+X(y 4.5)
+X(w 3.3)
+X(h 0.4)
+X(labeltype 0)
+X(downfunc move-then-resize)
+X)
+X(pnl_filled_hslider (name "specB")
+X(prop help creator:user-act-help)
+X(label "B")
+X(w 3.3)
+X(h 0.4)
+X(labeltype 0)
+X(downfunc move-then-resize)
+X)
+X(pnl_filled_hslider (name "specG")
+X(prop help creator:user-act-help)
+X(label "G")
+X(y 0.5)
+X(w 3.3)
+X(h 0.4)
+X(labeltype 0)
+X(downfunc move-then-resize)
+X)
+X(pnl_filled_hslider (name "specR")
+X(prop help creator:user-act-help)
+X(label "R")
+X(y 1)
+X(w 3.3)
+X(h 0.4)
+X(labeltype 0)
+X(downfunc move-then-resize)
+X)
+X(pnl_filled_hslider (name "shine")
+X(prop help creator:user-act-help)
+X(label "shininess")
+X(y 2.25)
+X(w 3.3)
+X(h 0.4)
+X(labeltype 0)
+X(downfunc move-then-resize)
+X)
+X)
+X)
+X;;; Local Variables:
+X;;; mode: scheme
+X;;; eval: (save-excursion (goto-char (point-min)) (kill-line 3))
+X;;; eval: (save-excursion (goto-char (point-min)) (replace-regexp "[ \n]*)" ")"))
+X;;; eval: (indent-region (point-min) (point-max) nil)
+X;;; eval: (progn (kill-line -3) (delete-backward-char 1) (save-buffer))
+X;;; End:
+EOF
+fi
+if test -s 'src/config.c'
+then echo '*** I will not over-write existing file src/config.c'
+else
+echo 'x - src/config.c'
+sed 's/^X//' > 'src/config.c' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/* Configurable Python configuration file */
+X
+X#include <stdio.h>
+X
+X#ifdef USE_STDWIN
+X#include <stdwin.h>
+X
+Xstatic int use_stdwin;
+X#endif
+X
+X/*ARGSUSED*/
+Xvoid
+Xinitargs(p_argc, p_argv)
+X int *p_argc;
+X char ***p_argv;
+X{
+X#ifdef USE_STDWIN
+X extern char *getenv();
+X char *display;
+X
+X /* Ignore an initial argument of '-s', for backward compatibility */
+X if (*p_argc > 1 && strcmp((*p_argv)[1], "-s") == 0) {
+X (*p_argv)[1] = (*p_argv)[0];
+X (*p_argc)--, (*p_argv)++;
+X }
+X
+X /* Assume we have to initialize stdwin if either of the following
+X conditions holds:
+X - the environment variable $DISPLAY is set
+X - there is an argument "-display" somewhere
+X */
+X
+X display = getenv("DISPLAY");
+X if (display != 0)
+X use_stdwin = 1;
+X else {
+X int i;
+X /* Scan through the arguments looking for "-display" */
+X for (i = 1; i < *p_argc; i++) {
+X if (strcmp((*p_argv)[i], "-display") == 0) {
+X use_stdwin = 1;
+X break;
+X }
+X }
+X }
+X
+X if (use_stdwin)
+X wargs(p_argc, p_argv);
+X#endif
+X}
+X
+Xvoid
+Xinitcalls()
+X{
+X}
+X
+Xvoid
+Xdonecalls()
+X{
+X#ifdef USE_STDWIN
+X if (use_stdwin)
+X wdone();
+X#endif
+X#ifdef USE_AUDIO
+X asa_done();
+X#endif
+X}
+X
+X#ifdef USE_STDWIN
+Xstatic void
+Xmaybeinitstdwin()
+X{
+X if (use_stdwin)
+X initstdwin();
+X else
+X fprintf(stderr,
+X "No $DISPLAY nor -display arg -- stdwin not available\n");
+X}
+X#endif
+X
+X#ifndef PYTHONPATH
+X#define PYTHONPATH ".:/usr/local/lib/python"
+X#endif
+X
+Xextern char *getenv();
+X
+Xchar *
+Xgetpythonpath()
+X{
+X char *path = getenv("PYTHONPATH");
+X if (path == 0)
+X path = PYTHONPATH;
+X return path;
+X}
+X
+X
+X/* Table of built-in modules.
+X These are initialized when first imported. */
+X
+X/* Standard modules */
+Xextern void inittime();
+Xextern void initmath();
+Xextern void initregexp();
+Xextern void initposix();
+X#ifdef USE_AUDIO
+Xextern void initaudio();
+X#endif
+X#ifdef USE_AMOEBA
+Xextern void initamoeba();
+X#endif
+X#ifdef USE_GL
+Xextern void initgl();
+X#ifdef USE_PANEL
+Xextern void initpanel();
+X#endif
+X#endif
+X#ifdef USE_STDWIN
+Xextern void maybeinitstdwin();
+X#endif
+X
+Xstruct {
+X char *name;
+X void (*initfunc)();
+X} inittab[] = {
+X
+X /* Standard modules */
+X
+X {"time", inittime},
+X {"math", initmath},
+X {"regexp", initregexp},
+X {"posix", initposix},
+X
+X
+X /* Optional modules */
+X
+X#ifdef USE_AUDIO
+X {"audio", initaudio},
+X#endif
+X
+X#ifdef USE_AMOEBA
+X {"amoeba", initamoeba},
+X#endif
+X
+X#ifdef USE_GL
+X {"gl", initgl},
+X#ifdef USE_PANEL
+X {"pnl", initpanel},
+X#endif
+X#endif
+X
+X#ifdef USE_STDWIN
+X {"stdwin", maybeinitstdwin},
+X#endif
+X
+X {0, 0} /* Sentinel */
+X};
+EOF
+fi
+if test -s 'src/frameobject.c'
+then echo '*** I will not over-write existing file src/frameobject.c'
+else
+echo 'x - src/frameobject.c'
+sed 's/^X//' > 'src/frameobject.c' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/* Frame object implementation */
+X
+X#include "allobjects.h"
+X
+X#include "compile.h"
+X#include "frameobject.h"
+X#include "opcode.h"
+X#include "structmember.h"
+X
+X#define OFF(x) offsetof(frameobject, x)
+X
+Xstatic struct memberlist frame_memberlist[] = {
+X {"f_back", T_OBJECT, OFF(f_back)},
+X {"f_code", T_OBJECT, OFF(f_code)},
+X {"f_globals", T_OBJECT, OFF(f_globals)},
+X {"f_locals", T_OBJECT, OFF(f_locals)},
+X {NULL} /* Sentinel */
+X};
+X
+Xstatic object *
+Xframe_getattr(f, name)
+X frameobject *f;
+X char *name;
+X{
+X return getmember((char *)f, frame_memberlist, name);
+X}
+X
+Xstatic void
+Xframe_dealloc(f)
+X frameobject *f;
+X{
+X XDECREF(f->f_back);
+X XDECREF(f->f_code);
+X XDECREF(f->f_globals);
+X XDECREF(f->f_locals);
+X XDEL(f->f_valuestack);
+X XDEL(f->f_blockstack);
+X DEL(f);
+X}
+X
+Xtypeobject Frametype = {
+X OB_HEAD_INIT(&Typetype)
+X 0,
+X "frame",
+X sizeof(frameobject),
+X 0,
+X frame_dealloc, /*tp_dealloc*/
+X 0, /*tp_print*/
+X frame_getattr, /*tp_getattr*/
+X 0, /*tp_setattr*/
+X 0, /*tp_compare*/
+X 0, /*tp_repr*/
+X 0, /*tp_as_number*/
+X 0, /*tp_as_sequence*/
+X 0, /*tp_as_mapping*/
+X};
+X
+Xframeobject *
+Xnewframeobject(back, code, globals, locals, nvalues, nblocks)
+X frameobject *back;
+X codeobject *code;
+X object *globals;
+X object *locals;
+X int nvalues;
+X int nblocks;
+X{
+X frameobject *f;
+X if ((back != NULL && !is_frameobject(back)) ||
+X code == NULL || !is_codeobject(code) ||
+X globals == NULL || !is_dictobject(globals) ||
+X locals == NULL || !is_dictobject(locals) ||
+X nvalues < 0 || nblocks < 0) {
+X err_badcall();
+X return NULL;
+X }
+X f = NEWOBJ(frameobject, &Frametype);
+X if (f != NULL) {
+X if (back)
+X INCREF(back);
+X f->f_back = back;
+X INCREF(code);
+X f->f_code = code;
+X INCREF(globals);
+X f->f_globals = globals;
+X INCREF(locals);
+X f->f_locals = locals;
+X f->f_valuestack = NEW(object *, nvalues+1);
+X f->f_blockstack = NEW(block, nblocks+1);
+X f->f_nvalues = nvalues;
+X f->f_nblocks = nblocks;
+X f->f_iblock = 0;
+X if (f->f_valuestack == NULL || f->f_blockstack == NULL) {
+X err_nomem();
+X DECREF(f);
+X f = NULL;
+X }
+X }
+X return f;
+X}
+X
+X/* Block management */
+X
+Xvoid
+Xsetup_block(f, type, handler, level)
+X frameobject *f;
+X int type;
+X int handler;
+X int level;
+X{
+X block *b;
+X if (f->f_iblock >= f->f_nblocks) {
+X fprintf(stderr, "XXX block stack overflow\n");
+X abort();
+X }
+X b = &f->f_blockstack[f->f_iblock++];
+X b->b_type = type;
+X b->b_level = level;
+X b->b_handler = handler;
+X}
+X
+Xblock *
+Xpop_block(f)
+X frameobject *f;
+X{
+X block *b;
+X if (f->f_iblock <= 0) {
+X fprintf(stderr, "XXX block stack underflow\n");
+X abort();
+X }
+X b = &f->f_blockstack[--f->f_iblock];
+X return b;
+X}
+EOF
+fi
+if test -s 'src/metagrammar.c'
+then echo '*** I will not over-write existing file src/metagrammar.c'
+else
+echo 'x - src/metagrammar.c'
+sed 's/^X//' > 'src/metagrammar.c' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X#include "pgenheaders.h"
+X#include "metagrammar.h"
+X#include "grammar.h"
+X#include "pgen.h"
+Xstatic arc arcs_0_0[3] = {
+X {2, 0},
+X {3, 0},
+X {4, 1},
+X};
+Xstatic arc arcs_0_1[1] = {
+X {0, 1},
+X};
+Xstatic state states_0[2] = {
+X {3, arcs_0_0},
+X {1, arcs_0_1},
+X};
+Xstatic arc arcs_1_0[1] = {
+X {5, 1},
+X};
+Xstatic arc arcs_1_1[1] = {
+X {6, 2},
+X};
+Xstatic arc arcs_1_2[1] = {
+X {7, 3},
+X};
+Xstatic arc arcs_1_3[1] = {
+X {3, 4},
+X};
+Xstatic arc arcs_1_4[1] = {
+X {0, 4},
+X};
+Xstatic state states_1[5] = {
+X {1, arcs_1_0},
+X {1, arcs_1_1},
+X {1, arcs_1_2},
+X {1, arcs_1_3},
+X {1, arcs_1_4},
+X};
+Xstatic arc arcs_2_0[1] = {
+X {8, 1},
+X};
+Xstatic arc arcs_2_1[2] = {
+X {9, 0},
+X {0, 1},
+X};
+Xstatic state states_2[2] = {
+X {1, arcs_2_0},
+X {2, arcs_2_1},
+X};
+Xstatic arc arcs_3_0[1] = {
+X {10, 1},
+X};
+Xstatic arc arcs_3_1[2] = {
+X {10, 1},
+X {0, 1},
+X};
+Xstatic state states_3[2] = {
+X {1, arcs_3_0},
+X {2, arcs_3_1},
+X};
+Xstatic arc arcs_4_0[2] = {
+X {11, 1},
+X {13, 2},
+X};
+Xstatic arc arcs_4_1[1] = {
+X {7, 3},
+X};
+Xstatic arc arcs_4_2[3] = {
+X {14, 4},
+X {15, 4},
+X {0, 2},
+X};
+Xstatic arc arcs_4_3[1] = {
+X {12, 4},
+X};
+Xstatic arc arcs_4_4[1] = {
+X {0, 4},
+X};
+Xstatic state states_4[5] = {
+X {2, arcs_4_0},
+X {1, arcs_4_1},
+X {3, arcs_4_2},
+X {1, arcs_4_3},
+X {1, arcs_4_4},
+X};
+Xstatic arc arcs_5_0[3] = {
+X {5, 1},
+X {16, 1},
+X {17, 2},
+X};
+Xstatic arc arcs_5_1[1] = {
+X {0, 1},
+X};
+Xstatic arc arcs_5_2[1] = {
+X {7, 3},
+X};
+Xstatic arc arcs_5_3[1] = {
+X {18, 1},
+X};
+Xstatic state states_5[4] = {
+X {3, arcs_5_0},
+X {1, arcs_5_1},
+X {1, arcs_5_2},
+X {1, arcs_5_3},
+X};
+Xstatic dfa dfas[6] = {
+X {256, "MSTART", 0, 2, states_0,
+X "\070\000\000"},
+X {257, "RULE", 0, 5, states_1,
+X "\040\000\000"},
+X {258, "RHS", 0, 2, states_2,
+X "\040\010\003"},
+X {259, "ALT", 0, 2, states_3,
+X "\040\010\003"},
+X {260, "ITEM", 0, 5, states_4,
+X "\040\010\003"},
+X {261, "ATOM", 0, 4, states_5,
+X "\040\000\003"},
+X};
+Xstatic label labels[19] = {
+X {0, "EMPTY"},
+X {256, 0},
+X {257, 0},
+X {4, 0},
+X {0, 0},
+X {1, 0},
+X {11, 0},
+X {258, 0},
+X {259, 0},
+X {18, 0},
+X {260, 0},
+X {9, 0},
+X {10, 0},
+X {261, 0},
+X {16, 0},
+X {14, 0},
+X {3, 0},
+X {7, 0},
+X {8, 0},
+X};
+Xstatic grammar gram = {
+X 6,
+X dfas,
+X {19, labels},
+X 256
+X};
+X
+Xgrammar *
+Xmeta_grammar()
+X{
+X return &gram;
+X}
+EOF
+fi
+if test -s 'src/methodobject.c'
+then echo '*** I will not over-write existing file src/methodobject.c'
+else
+echo 'x - src/methodobject.c'
+sed 's/^X//' > 'src/methodobject.c' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/* Method object implementation */
+X
+X#include "allobjects.h"
+X
+X#include "token.h"
+X
+Xtypedef struct {
+X OB_HEAD
+X char *m_name;
+X method m_meth;
+X object *m_self;
+X} methodobject;
+X
+Xobject *
+Xnewmethodobject(name, meth, self)
+X char *name; /* static string */
+X method meth;
+X object *self;
+X{
+X methodobject *op = NEWOBJ(methodobject, &Methodtype);
+X if (op != NULL) {
+X op->m_name = name;
+X op->m_meth = meth;
+X if (self != NULL)
+X INCREF(self);
+X op->m_self = self;
+X }
+X return (object *)op;
+X}
+X
+Xmethod
+Xgetmethod(op)
+X object *op;
+X{
+X if (!is_methodobject(op)) {
+X err_badcall();
+X return NULL;
+X }
+X return ((methodobject *)op) -> m_meth;
+X}
+X
+Xobject *
+Xgetself(op)
+X object *op;
+X{
+X if (!is_methodobject(op)) {
+X err_badcall();
+X return NULL;
+X }
+X return ((methodobject *)op) -> m_self;
+X}
+X
+X/* Methods (the standard built-in methods, that is) */
+X
+Xstatic void
+Xmeth_dealloc(m)
+X methodobject *m;
+X{
+X if (m->m_self != NULL)
+X DECREF(m->m_self);
+X free((char *)m);
+X}
+X
+Xstatic void
+Xmeth_print(m, fp, flags)
+X methodobject *m;
+X FILE *fp;
+X int flags;
+X{
+X if (m->m_self == NULL)
+X fprintf(fp, "<built-in function '%s'>", m->m_name);
+X else
+X fprintf(fp, "<built-in method '%s' of some %s object>",
+X m->m_name, m->m_self->ob_type->tp_name);
+X}
+X
+Xstatic object *
+Xmeth_repr(m)
+X methodobject *m;
+X{
+X char buf[200];
+X if (m->m_self == NULL)
+X sprintf(buf, "<built-in function '%.80s'>", m->m_name);
+X else
+X sprintf(buf,
+X "<built-in method '%.80s' of some %.80s object>",
+X m->m_name, m->m_self->ob_type->tp_name);
+X return newstringobject(buf);
+X}
+X
+Xtypeobject Methodtype = {
+X OB_HEAD_INIT(&Typetype)
+X 0,
+X "method",
+X sizeof(methodobject),
+X 0,
+X meth_dealloc, /*tp_dealloc*/
+X meth_print, /*tp_print*/
+X 0, /*tp_getattr*/
+X 0, /*tp_setattr*/
+X 0, /*tp_compare*/
+X meth_repr, /*tp_repr*/
+X 0, /*tp_as_number*/
+X 0, /*tp_as_sequence*/
+X 0, /*tp_as_mapping*/
+X};
+X
+X/* Find a method in a module's method table.
+X Usually called from an object's getattr method. */
+X
+Xobject *
+Xfindmethod(ml, op, name)
+X struct methodlist *ml;
+X object *op;
+X char *name;
+X{
+X for (; ml->ml_name != NULL; ml++) {
+X if (strcmp(name, ml->ml_name) == 0)
+X return newmethodobject(ml->ml_name, ml->ml_meth, op);
+X }
+X err_setstr(NameError, name);
+X return NULL;
+X}
+EOF
+fi
+if test -s 'src/moduleobject.c'
+then echo '*** I will not over-write existing file src/moduleobject.c'
+else
+echo 'x - src/moduleobject.c'
+sed 's/^X//' > 'src/moduleobject.c' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/* Module object implementation */
+X
+X#include "allobjects.h"
+X
+Xtypedef struct {
+X OB_HEAD
+X object *md_name;
+X object *md_dict;
+X} moduleobject;
+X
+Xobject *
+Xnewmoduleobject(name)
+X char *name;
+X{
+X moduleobject *m = NEWOBJ(moduleobject, &Moduletype);
+X if (m == NULL)
+X return NULL;
+X m->md_name = newstringobject(name);
+X m->md_dict = newdictobject();
+X if (m->md_name == NULL || m->md_dict == NULL) {
+X DECREF(m);
+X return NULL;
+X }
+X return (object *)m;
+X}
+X
+Xobject *
+Xgetmoduledict(m)
+X object *m;
+X{
+X if (!is_moduleobject(m)) {
+X err_badcall();
+X return NULL;
+X }
+X return ((moduleobject *)m) -> md_dict;
+X}
+X
+Xchar *
+Xgetmodulename(m)
+X object *m;
+X{
+X if (!is_moduleobject(m)) {
+X err_badarg();
+X return NULL;
+X }
+X return getstringvalue(((moduleobject *)m) -> md_name);
+X}
+X
+X/* Methods */
+X
+Xstatic void
+Xmodule_dealloc(m)
+X moduleobject *m;
+X{
+X if (m->md_name != NULL)
+X DECREF(m->md_name);
+X if (m->md_dict != NULL)
+X DECREF(m->md_dict);
+X free((char *)m);
+X}
+X
+Xstatic void
+Xmodule_print(m, fp, flags)
+X moduleobject *m;
+X FILE *fp;
+X int flags;
+X{
+X fprintf(fp, "<module '%s'>", getstringvalue(m->md_name));
+X}
+X
+Xstatic object *
+Xmodule_repr(m)
+X moduleobject *m;
+X{
+X char buf[100];
+X sprintf(buf, "<module '%.80s'>", getstringvalue(m->md_name));
+X return newstringobject(buf);
+X}
+X
+Xstatic object *
+Xmodule_getattr(m, name)
+X moduleobject *m;
+X char *name;
+X{
+X object *res;
+X if (strcmp(name, "__dict__") == 0) {
+X INCREF(m->md_dict);
+X return m->md_dict;
+X }
+X if (strcmp(name, "__name__") == 0) {
+X INCREF(m->md_name);
+X return m->md_name;
+X }
+X res = dictlookup(m->md_dict, name);
+X if (res == NULL)
+X err_setstr(NameError, name);
+X else
+X INCREF(res);
+X return res;
+X}
+X
+Xstatic int
+Xmodule_setattr(m, name, v)
+X moduleobject *m;
+X char *name;
+X object *v;
+X{
+X if (strcmp(name, "__dict__") == 0 || strcmp(name, "__name__") == 0) {
+X err_setstr(NameError, "can't assign to reserved member name");
+X return -1;
+X }
+X if (v == NULL)
+X return dictremove(m->md_dict, name);
+X else
+X return dictinsert(m->md_dict, name, v);
+X}
+X
+Xtypeobject Moduletype = {
+X OB_HEAD_INIT(&Typetype)
+X 0, /*ob_size*/
+X "module", /*tp_name*/
+X sizeof(moduleobject), /*tp_size*/
+X 0, /*tp_itemsize*/
+X module_dealloc, /*tp_dealloc*/
+X module_print, /*tp_print*/
+X module_getattr, /*tp_getattr*/
+X module_setattr, /*tp_setattr*/
+X 0, /*tp_compare*/
+X module_repr, /*tp_repr*/
+X};
+EOF
+fi
+if test -s 'src/opcode.h'
+then echo '*** I will not over-write existing file src/opcode.h'
+else
+echo 'x - src/opcode.h'
+sed 's/^X//' > 'src/opcode.h' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/* Instruction opcodes for compiled code */
+X
+X#define STOP_CODE 0
+X#define POP_TOP 1
+X#define ROT_TWO 2
+X#define ROT_THREE 3
+X#define DUP_TOP 4
+X
+X#define UNARY_POSITIVE 10
+X#define UNARY_NEGATIVE 11
+X#define UNARY_NOT 12
+X#define UNARY_CONVERT 13
+X#define UNARY_CALL 14
+X
+X#define BINARY_MULTIPLY 20
+X#define BINARY_DIVIDE 21
+X#define BINARY_MODULO 22
+X#define BINARY_ADD 23
+X#define BINARY_SUBTRACT 24
+X#define BINARY_SUBSCR 25
+X#define BINARY_CALL 26
+X
+X#define SLICE 30
+X/* Also uses 31-33 */
+X
+X#define STORE_SLICE 40
+X/* Also uses 41-43 */
+X
+X#define DELETE_SLICE 50
+X/* Also uses 51-53 */
+X
+X#define STORE_SUBSCR 60
+X#define DELETE_SUBSCR 61
+X
+X#define PRINT_EXPR 70
+X#define PRINT_ITEM 71
+X#define PRINT_NEWLINE 72
+X
+X#define BREAK_LOOP 80
+X#define RAISE_EXCEPTION 81
+X#define LOAD_LOCALS 82
+X#define RETURN_VALUE 83
+X#define REQUIRE_ARGS 84
+X#define REFUSE_ARGS 85
+X#define BUILD_FUNCTION 86
+X#define POP_BLOCK 87
+X#define END_FINALLY 88
+X#define BUILD_CLASS 89
+X
+X#define HAVE_ARGUMENT 90 /* Opcodes from here have an argument: */
+X
+X#define STORE_NAME 90 /* Index in name list */
+X#define DELETE_NAME 91 /* "" */
+X#define UNPACK_TUPLE 92 /* Number of tuple items */
+X#define UNPACK_LIST 93 /* Number of list items */
+X/* unused: 94 */
+X#define STORE_ATTR 95 /* Index in name list */
+X#define DELETE_ATTR 96 /* "" */
+X
+X#define LOAD_CONST 100 /* Index in const list */
+X#define LOAD_NAME 101 /* Index in name list */
+X#define BUILD_TUPLE 102 /* Number of tuple items */
+X#define BUILD_LIST 103 /* Number of list items */
+X#define BUILD_MAP 104 /* Always zero for now */
+X#define LOAD_ATTR 105 /* Index in name list */
+X#define COMPARE_OP 106 /* Comparison operator */
+X#define IMPORT_NAME 107 /* Index in name list */
+X#define IMPORT_FROM 108 /* Index in name list */
+X
+X#define JUMP_FORWARD 110 /* Number of bytes to skip */
+X#define JUMP_IF_FALSE 111 /* "" */
+X#define JUMP_IF_TRUE 112 /* "" */
+X#define JUMP_ABSOLUTE 113 /* Target byte offset from beginning of code */
+X#define FOR_LOOP 114 /* Number of bytes to skip */
+X
+X#define SETUP_LOOP 120 /* Target address (absolute) */
+X#define SETUP_EXCEPT 121 /* "" */
+X#define SETUP_FINALLY 122 /* "" */
+X
+X#define SET_LINENO 127 /* Current line number */
+X
+X/* Comparison operator codes (argument to COMPARE_OP) */
+Xenum cmp_op {LT, LE, EQ, NE, GT, GE, IN, NOT_IN, IS, IS_NOT, EXC_MATCH, BAD};
+X
+X#define HAS_ARG(op) ((op) >= HAVE_ARGUMENT)
+EOF
+fi
+if test -s 'src/parsetok.c'
+then echo '*** I will not over-write existing file src/parsetok.c'
+else
+echo 'x - src/parsetok.c'
+sed 's/^X//' > 'src/parsetok.c' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/* Parser-tokenizer link implementation */
+X
+X#include "pgenheaders.h"
+X#include "tokenizer.h"
+X#include "node.h"
+X#include "grammar.h"
+X#include "parser.h"
+X#include "parsetok.h"
+X#include "errcode.h"
+X
+X
+X/* Forward */
+Xstatic int parsetok PROTO((struct tok_state *, grammar *, int, node **));
+X
+X
+X/* Parse input coming from a string. Return error code, print some errors. */
+X
+Xint
+Xparsestring(s, g, start, n_ret)
+X char *s;
+X grammar *g;
+X int start;
+X node **n_ret;
+X{
+X struct tok_state *tok = tok_setups(s);
+X int ret;
+X
+X if (tok == NULL) {
+X fprintf(stderr, "no mem for tok_setups\n");
+X return E_NOMEM;
+X }
+X ret = parsetok(tok, g, start, n_ret);
+X if (ret == E_TOKEN || ret == E_SYNTAX) {
+X fprintf(stderr, "String parsing error at line %d\n",
+X tok->lineno);
+X }
+X tok_free(tok);
+X return ret;
+X}
+X
+X
+X/* Parse input coming from a file. Return error code, print some errors. */
+X
+Xint
+Xparsefile(fp, filename, g, start, ps1, ps2, n_ret)
+X FILE *fp;
+X char *filename;
+X grammar *g;
+X int start;
+X char *ps1, *ps2;
+X node **n_ret;
+X{
+X struct tok_state *tok = tok_setupf(fp, ps1, ps2);
+X int ret;
+X
+X if (tok == NULL) {
+X fprintf(stderr, "no mem for tok_setupf\n");
+X return E_NOMEM;
+X }
+X ret = parsetok(tok, g, start, n_ret);
+X if (ret == E_TOKEN || ret == E_SYNTAX) {
+X char *p;
+X fprintf(stderr, "Parsing error: file %s, line %d:\n",
+X filename, tok->lineno);
+X *tok->inp = '\0';
+X if (tok->inp > tok->buf && tok->inp[-1] == '\n')
+X tok->inp[-1] = '\0';
+X fprintf(stderr, "%s\n", tok->buf);
+X for (p = tok->buf; p < tok->cur; p++) {
+X if (*p == '\t')
+X putc('\t', stderr);
+X else
+X putc(' ', stderr);
+X }
+X fprintf(stderr, "^\n");
+X }
+X tok_free(tok);
+X return ret;
+X}
+X
+X
+X/* Parse input coming from the given tokenizer structure.
+X Return error code. */
+X
+Xstatic int
+Xparsetok(tok, g, start, n_ret)
+X struct tok_state *tok;
+X grammar *g;
+X int start;
+X node **n_ret;
+X{
+X parser_state *ps;
+X int ret;
+X
+X if ((ps = newparser(g, start)) == NULL) {
+X fprintf(stderr, "no mem for new parser\n");
+X return E_NOMEM;
+X }
+X
+X for (;;) {
+X char *a, *b;
+X int type;
+X int len;
+X char *str;
+X
+X type = tok_get(tok, &a, &b);
+X if (type == ERRORTOKEN) {
+X ret = tok->done;
+X break;
+X }
+X len = b - a;
+X str = NEW(char, len + 1);
+X if (str == NULL) {
+X fprintf(stderr, "no mem for next token\n");
+X ret = E_NOMEM;
+X break;
+X }
+X strncpy(str, a, len);
+X str[len] = '\0';
+X ret = addtoken(ps, (int)type, str, tok->lineno);
+X if (ret != E_OK) {
+X if (ret == E_DONE) {
+X *n_ret = ps->p_tree;
+X ps->p_tree = NULL;
+X }
+X else if (tok->lineno <= 1 && tok->done == E_EOF)
+X ret = E_EOF;
+X break;
+X }
+X }
+X
+X delparser(ps);
+X return ret;
+X}
+EOF
+fi
+if test -s 'src/pgenmain.c'
+then echo '*** I will not over-write existing file src/pgenmain.c'
+else
+echo 'x - src/pgenmain.c'
+sed 's/^X//' > 'src/pgenmain.c' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/* Parser generator main program */
+X
+X/* This expects a filename containing the grammar as argv[1] (UNIX)
+X or asks the console for such a file name (THINK C).
+X It writes its output on two files in the current directory:
+X - "graminit.c" gets the grammar as a bunch of initialized data
+X - "graminit.h" gets the grammar's non-terminals as #defines.
+X Error messages and status info during the generation process are
+X written to stdout, or sometimes to stderr. */
+X
+X#include "pgenheaders.h"
+X#include "grammar.h"
+X#include "node.h"
+X#include "parsetok.h"
+X#include "pgen.h"
+X
+Xint debugging;
+X
+X/* Forward */
+Xgrammar *getgrammar PROTO((char *filename));
+X#ifdef THINK_C
+Xint main PROTO((int, char **));
+Xchar *askfile PROTO((void));
+X#endif
+X
+Xint
+Xmain(argc, argv)
+X int argc;
+X char **argv;
+X{
+X grammar *g;
+X node *n;
+X FILE *fp;
+X char *filename;
+X
+X#ifdef THINK_C
+X filename = askfile();
+X#else
+X if (argc != 2) {
+X fprintf(stderr, "usage: %s grammar\n", argv[0]);
+X exit(2);
+X }
+X filename = argv[1];
+X#endif
+X g = getgrammar(filename);
+X fp = fopen("graminit.c", "w");
+X if (fp == NULL) {
+X perror("graminit.c");
+X exit(1);
+X }
+X printf("Writing graminit.c ...\n");
+X printgrammar(g, fp);
+X fclose(fp);
+X fp = fopen("graminit.h", "w");
+X if (fp == NULL) {
+X perror("graminit.h");
+X exit(1);
+X }
+X printf("Writing graminit.h ...\n");
+X printnonterminals(g, fp);
+X fclose(fp);
+X exit(0);
+X}
+X
+Xgrammar *
+Xgetgrammar(filename)
+X char *filename;
+X{
+X FILE *fp;
+X node *n;
+X grammar *g0, *g;
+X
+X fp = fopen(filename, "r");
+X if (fp == NULL) {
+X perror(filename);
+X exit(1);
+X }
+X g0 = meta_grammar();
+X n = NULL;
+X parsefile(fp, filename, g0, g0->g_start, (char *)NULL, (char *)NULL, &n);
+X fclose(fp);
+X if (n == NULL) {
+X fprintf(stderr, "Parsing error.\n");
+X exit(1);
+X }
+X g = pgen(n);
+X if (g == NULL) {
+X printf("Bad grammar.\n");
+X exit(1);
+X }
+X return g;
+X}
+X
+X#ifdef THINK_C
+Xchar *
+Xaskfile()
+X{
+X char buf[256];
+X static char name[256];
+X printf("Input file name: ");
+X if (fgets(buf, sizeof buf, stdin) == NULL) {
+X printf("EOF\n");
+X exit(1);
+X }
+X /* XXX The (unsigned char *) case is needed by THINK C 3.0 */
+X if (sscanf(/*(unsigned char *)*/buf, " %s ", name) != 1) {
+X printf("No file\n");
+X exit(1);
+X }
+X return name;
+X}
+X#endif
+X
+Xvoid
+Xfatal(msg)
+X char *msg;
+X{
+X fprintf(stderr, "pgen: FATAL ERROR: %s\n", msg);
+X exit(1);
+X}
+X
+X/* XXX TO DO:
+X - check for duplicate definitions of names (instead of fatal err)
+X*/
+EOF
+fi
+if test -s 'src/printgrammar.c'
+then echo '*** I will not over-write existing file src/printgrammar.c'
+else
+echo 'x - src/printgrammar.c'
+sed 's/^X//' > 'src/printgrammar.c' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/* Print a bunch of C initializers that represent a grammar */
+X
+X#include "pgenheaders.h"
+X#include "grammar.h"
+X
+X/* Forward */
+Xstatic void printarcs PROTO((int, dfa *, FILE *));
+Xstatic void printstates PROTO((grammar *, FILE *));
+Xstatic void printdfas PROTO((grammar *, FILE *));
+Xstatic void printlabels PROTO((grammar *, FILE *));
+X
+Xvoid
+Xprintgrammar(g, fp)
+X grammar *g;
+X FILE *fp;
+X{
+X fprintf(fp, "#include \"pgenheaders.h\"\n");
+X fprintf(fp, "#include \"grammar.h\"\n");
+X printdfas(g, fp);
+X printlabels(g, fp);
+X fprintf(fp, "grammar gram = {\n");
+X fprintf(fp, "\t%d,\n", g->g_ndfas);
+X fprintf(fp, "\tdfas,\n");
+X fprintf(fp, "\t{%d, labels},\n", g->g_ll.ll_nlabels);
+X fprintf(fp, "\t%d\n", g->g_start);
+X fprintf(fp, "};\n");
+X}
+X
+Xvoid
+Xprintnonterminals(g, fp)
+X grammar *g;
+X FILE *fp;
+X{
+X dfa *d;
+X int i;
+X
+X d = g->g_dfa;
+X for (i = g->g_ndfas; --i >= 0; d++)
+X fprintf(fp, "#define %s %d\n", d->d_name, d->d_type);
+X}
+X
+Xstatic void
+Xprintarcs(i, d, fp)
+X int i;
+X dfa *d;
+X FILE *fp;
+X{
+X arc *a;
+X state *s;
+X int j, k;
+X
+X s = d->d_state;
+X for (j = 0; j < d->d_nstates; j++, s++) {
+X fprintf(fp, "static arc arcs_%d_%d[%d] = {\n",
+X i, j, s->s_narcs);
+X a = s->s_arc;
+X for (k = 0; k < s->s_narcs; k++, a++)
+X fprintf(fp, "\t{%d, %d},\n", a->a_lbl, a->a_arrow);
+X fprintf(fp, "};\n");
+X }
+X}
+X
+Xstatic void
+Xprintstates(g, fp)
+X grammar *g;
+X FILE *fp;
+X{
+X state *s;
+X dfa *d;
+X int i, j;
+X
+X d = g->g_dfa;
+X for (i = 0; i < g->g_ndfas; i++, d++) {
+X printarcs(i, d, fp);
+X fprintf(fp, "static state states_%d[%d] = {\n",
+X i, d->d_nstates);
+X s = d->d_state;
+X for (j = 0; j < d->d_nstates; j++, s++)
+X fprintf(fp, "\t{%d, arcs_%d_%d},\n",
+X s->s_narcs, i, j);
+X fprintf(fp, "};\n");
+X }
+X}
+X
+Xstatic void
+Xprintdfas(g, fp)
+X grammar *g;
+X FILE *fp;
+X{
+X dfa *d;
+X int i, j;
+X
+X printstates(g, fp);
+X fprintf(fp, "static dfa dfas[%d] = {\n", g->g_ndfas);
+X d = g->g_dfa;
+X for (i = 0; i < g->g_ndfas; i++, d++) {
+X fprintf(fp, "\t{%d, \"%s\", %d, %d, states_%d,\n",
+X d->d_type, d->d_name, d->d_initial, d->d_nstates, i);
+X fprintf(fp, "\t \"");
+X for (j = 0; j < NBYTES(g->g_ll.ll_nlabels); j++)
+X fprintf(fp, "\\%03o", d->d_first[j] & 0xff);
+X fprintf(fp, "\"},\n");
+X }
+X fprintf(fp, "};\n");
+X}
+X
+Xstatic void
+Xprintlabels(g, fp)
+X grammar *g;
+X FILE *fp;
+X{
+X label *l;
+X int i;
+X
+X fprintf(fp, "static label labels[%d] = {\n", g->g_ll.ll_nlabels);
+X l = g->g_ll.ll_label;
+X for (i = g->g_ll.ll_nlabels; --i >= 0; l++) {
+X if (l->lb_str == NULL)
+X fprintf(fp, "\t{%d, 0},\n", l->lb_type);
+X else
+X fprintf(fp, "\t{%d, \"%s\"},\n",
+X l->lb_type, l->lb_str);
+X }
+X fprintf(fp, "};\n");
+X}
+EOF
+fi
+if test -s 'src/regsub.c'
+then echo '*** I will not over-write existing file src/regsub.c'
+else
+echo 'x - src/regsub.c'
+sed 's/^X//' > 'src/regsub.c' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/*
+X * regsub
+X *
+X * Copyright (c) 1986 by University of Toronto.
+X * Written by Henry Spencer. Not derived from licensed software.
+X#ifdef MULTILINE
+X * Changed by Guido van Rossum, CWI, Amsterdam
+X * for multi-line support.
+X#endif
+X *
+X * Permission is granted to anyone to use this software for any
+X * purpose on any computer system, and to redistribute it freely,
+X * subject to the following restrictions:
+X *
+X * 1. The author is not responsible for the consequences of use of
+X * this software, no matter how awful, even if they arise
+X * from defects in it.
+X *
+X * 2. The origin of this software must not be misrepresented, either
+X * by explicit claim or by omission.
+X *
+X * 3. Altered versions must be plainly marked as such, and must not
+X * be misrepresented as being the original software.
+X */
+X#include <stdio.h>
+X#include "regexp.h"
+X#include "regmagic.h"
+X
+X#ifndef CHARBITS
+X#define UCHARAT(p) ((int)*(unsigned char *)(p))
+X#else
+X#define UCHARAT(p) ((int)*(p)&CHARBITS)
+X#endif
+X
+X/*
+X - regsub - perform substitutions after a regexp match
+X */
+Xvoid
+Xregsub(prog, source, dest)
+Xregexp *prog;
+Xchar *source;
+Xchar *dest;
+X{
+X register char *src;
+X register char *dst;
+X register char c;
+X register int no;
+X register int len;
+X extern char *strncpy();
+X
+X if (prog == NULL || source == NULL || dest == NULL) {
+X regerror("NULL parm to regsub");
+X return;
+X }
+X if (UCHARAT(prog->program) != MAGIC) {
+X regerror("damaged regexp fed to regsub");
+X return;
+X }
+X
+X src = source;
+X dst = dest;
+X while ((c = *src++) != '\0') {
+X if (c == '&')
+X no = 0;
+X else if (c == '\\' && '0' <= *src && *src <= '9')
+X no = *src++ - '0';
+X else
+X no = -1;
+X
+X if (no < 0) { /* Ordinary character. */
+X if (c == '\\' && (*src == '\\' || *src == '&'))
+X c = *src++;
+X#ifdef MULTILINE
+X else if (c == '\\' && *src == 'n') {
+X c = '\n';
+X src++;
+X }
+X#endif
+X *dst++ = c;
+X } else if (prog->startp[no] != NULL && prog->endp[no] != NULL) {
+X len = prog->endp[no] - prog->startp[no];
+X (void) strncpy(dst, prog->startp[no], len);
+X dst += len;
+X if (len != 0 && *(dst-1) == '\0') { /* strncpy hit NUL. */
+X regerror("damaged match string");
+X return;
+X }
+X }
+X }
+X *dst++ = '\0';
+X}
+EOF
+fi
+if test -s 'src/sc_errors.c'
+then echo '*** I will not over-write existing file src/sc_errors.c'
+else
+echo 'x - src/sc_errors.c'
+sed 's/^X//' > 'src/sc_errors.c' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X
+X#include <stdio.h>
+X
+X#include "PROTO.h"
+X#include "object.h"
+X#include "errors.h"
+X#include "sc_errors.h"
+X#include "stringobject.h"
+X#include "tupleobject.h"
+X
+Xobject *
+Xerr_scerr(sc_errno)
+X int sc_errno;
+X{
+X switch(sc_errno) {
+X
+X case NoBufSize:
+X err_setstr(StubcodeError, "Stubcode didn't start with BufSize");
+X break;
+X
+X case TwoBufSize:
+X err_setstr(StubcodeError, "Stubcode can't have more then one BufSize");
+X break;
+X
+X case ElementIsNull:
+X err_setstr(StubcodeError, "Trying to access an NIL object");
+X break;
+X
+X case StackOverflow:
+X err_setstr(StubcodeError, "Stack overflow");
+X return NULL;
+X
+X case StackUnderflow:
+X err_setstr(StubcodeError, "Stack underflow");
+X return NULL;
+X
+X case NoEndLoop:
+X err_setstr(StubcodeError, "LoopXXX with no EndLoop");
+X return NULL;
+X
+X case BufferOverflow:
+X err_setstr(StubcodeError, "Buffer overflow");
+X return NULL;
+X
+X }
+X return NULL;
+X}
+X
+Xerr_scerrset(sc_errno, value, instr)
+X int sc_errno;
+X object *value;
+X char *instr;
+X{
+X object *str, *str1, *t;
+X
+X if ((t = newtupleobject(3)) == NULL) {
+X return -1;
+X }
+X if ((str = newstringobject(instr)) == NULL) {
+X return -1;
+X }
+X if (settupleitem(t, 2, str) != 0) {
+X return -1;
+X }
+X INCREF(value);
+X if (settupleitem(t, 1, value) != 0) {
+X DECREF(t);
+X return -1;
+X }
+X switch(sc_errno) {
+X
+X case TypeFailure:
+X if ((str1 = newstringobject("Unexpected type")) == NULL) {
+X DECREF(t);
+X return -1;
+X }
+X break;
+X
+X case RangeError:
+X if ((str1 = newstringobject("Value out of range")) == NULL) {
+X DECREF(t);
+X return -1;
+X }
+X break;
+X
+X case SizeError:
+X if ((str1 = newstringobject("Value doesn't have the right size")) == NULL) {
+X DECREF(t);
+X return -1;
+X }
+X break;
+X
+X case FlagError:
+X if ((str1 = newstringobject("Illegal flag value")) == NULL) {
+X DECREF(t);
+X return -1;
+X }
+X break;
+X
+X case TransError:
+X if ((str1 = newstringobject("hdr.h_status != 0")) == NULL) {
+X DECREF(t);
+X return -1;
+X }
+X break;
+X
+X default:
+X if ((str1 = newstringobject("sc_errno not found")) == NULL) {
+X DECREF(t);
+X return -1;
+X }
+X break;
+X }
+X if (settupleitem(t, 0, str1) != 0) {
+X DECREF(t);
+X return -1;
+X }
+X err_setval(StubcodeError, t);
+X DECREF(t);
+X return -1;
+X}
+EOF
+fi
+if test -s 'src/sc_global.h'
+then echo '*** I will not over-write existing file src/sc_global.h'
+else
+echo 'x - src/sc_global.h'
+sed 's/^X//' > 'src/sc_global.h' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X
+X/*
+X** This file contains the data used in Ail, Python and sc2txt.
+X**
+X** If you want to add an instuction to the instructions just define
+X** it here and add the instruction in the function sc_interpreter in
+X** the file sc_interpreter.c in the switch. You also have to make a
+X** new function with the name x{instruction_name} in the file
+X** sc_interpreter.
+X*/
+X
+X/*
+X** When you want to change the types of the opcode or the operand
+X** you maybe need to adjust the options to mypf. And the defines :
+X** SwapOpcode, SwapOperand.
+X*/
+X
+Xtypedef unsigned char TscOpcode;
+Xtypedef long TscOperand;
+X
+X#define SC_MAGIC 0x19901991
+X
+X#define SwapOpcode(x) x = x
+X#define SwapOperand(l) ((l))=(((((l))>>24)&0xFF)|((((l))>>8)&0xFF00)|((((l))<<8)&0xFF0000)|((((l))<<24)&0xFF000000))
+X
+X#define STKSIZE 256
+X
+X#define OPERAND 0x80
+X#define FLAGS 0x40
+X
+X/*
+X** The headerfields. The value of the flag is the index of the fields
+X** array from the file mhdr.c plus one
+X*/
+X
+X#define H_EXTRA 0x00000001
+X#define H_SIZE 0x00000002
+X#define H_OFFSET 0x00000003
+X#define H_PORT 0x00000004
+X#define H_PRIV 0x00000005
+X#define PSEUDOFIELD 0x00000006
+X#define ALL_FIELDS 0x000000ff
+X
+X/*
+X** The specefiers for the integers
+X*/
+X
+X#define NOSIGN 0x00000100
+X#define INT32 0x00000200
+X#define ALLTYPES 0xffffff00
+X
+X/*
+X** The opcode with no operand
+X*/
+X
+X#define ListS 0x00
+X#define PutVS 0x01
+X#define GetVS 0x02
+X#define StringS 0x03
+X#define Equal 0x04
+X#define NoArgs 0x05
+X
+X/*
+X * Between 0x10 and 0x3f there is space for predefined marshal
+X * and unmarshal functions or macros that do not have an operand
+X */
+X
+X#define MarshTC 0x10
+X#define UnMarshTC 0x11
+X
+X/*
+X** The opcode with a number as operand
+X*/
+X
+X#define BufSize 0x80
+X#define Trans 0x81
+X#define TTupleS 0x82
+X#define Unpack 0x83
+X#define PutFS 0x84
+X#define TStringSeq 0x85
+X#define TStringSlt 0x86
+X#define TListSeq 0x87
+X#define TListSlt 0x88
+X#define LoopPut 0x89
+X#define EndLoop 0x8a
+X#define Dup 0x8b
+X#define Pop 0x8c
+X#define Align 0x8d
+X#define Pack 0x8e
+X#define LoopGet 0x8f
+X#define GetFS 0x90
+X#define PushI 0x91
+X
+X/*
+X** Between 0xa0 and 0xbf there is space for predefined marshal
+X** and unmarshal functions or macros with a numberas operand
+X*/
+X
+X
+X/*
+X** The opcodes with flags as operand
+X*/
+X
+X#define AilWord 0xc0
+X#define PutI 0xc1
+X#define PutC 0xc2
+X#define GetI 0xc3
+X#define GetC 0xc4
+X
+X/*
+X** Between 0xe0 and 0xff there is space for predefined marshal
+X** and unmarshal functions or macros with flags as operand
+X*/
+EOF
+fi
+if test -s 'src/scdbg.c'
+then echo '*** I will not over-write existing file src/scdbg.c'
+else
+echo 'x - src/scdbg.c'
+sed 's/^X//' > 'src/scdbg.c' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X
+X#include "sc_global.h"
+X
+Xvoid xPrintNum(Num)
+XTscOperand Num;
+X{
+X
+X printf(" %ld",(long)Num);
+X}
+X
+Xvoid xPrintFlags(Flags)
+XTscOperand Flags;
+X{
+Xlong x;
+X
+X x = (long)Flags;
+X x = x & 0x0000000F;
+X if (x == H_EXTRA) printf(" h_extra");
+X if (x == H_SIZE) printf(" h_size");
+X if (x == H_OFFSET) printf(" h_offset");
+X if (x == H_PORT) printf(" h_port");
+X if (x == H_PRIV) printf(" h_priv");
+X if (x == PSEUDOFIELD) printf(" h_port and h_priv");
+X x = (long)Flags;
+X if (x & NOSIGN) printf(" unsigned");
+X if (x & INT32) printf(" int32");
+X}
+X
+Xvoid xPrintCode(Opcode)
+XTscOpcode Opcode;
+X{
+X
+X switch (Opcode) {
+X
+X case BufSize: printf("BufSize");
+X break;
+X
+X case Trans: printf("Trans");
+X break;
+X
+X case TTupleS: printf("TTupleS");
+X break;
+X
+X case Unpack: printf("Unpack");
+X break;
+X
+X case AilWord: printf("AilWord");
+X break;
+X
+X case ListS: printf("ListS");
+X break;
+X
+X case StringS: printf("StringS");
+X break;
+X
+X case PutFS: printf("PutFS");
+X break;
+X
+X case TStringSeq: printf("TStringSeq");
+X break;
+X
+X case TStringSlt: printf("TStringSlt");
+X break;
+X
+X case PutVS: printf("PutVS");
+X break;
+X
+X case TListSeq: printf("TListSeq");
+X break;
+X
+X case TListSlt: printf("TListSlt");
+X break;
+X
+X case LoopPut: printf("LoopPut");
+X break;
+X
+X case EndLoop: printf("EndLoop");
+X break;
+X
+X case PutI: printf("PutI");
+X break;
+X
+X case PutC: printf("PutC");
+X break;
+X
+X case Dup: printf("Dup");
+X break;
+X
+X case Pop: printf("Pop");
+X break;
+X
+X case Align: printf("Align");
+X break;
+X
+X case Pack: printf("Pack");
+X break;
+X
+X case GetVS: printf("GetVS");
+X break;
+X
+X case LoopGet: printf("LoopGet");
+X break;
+X
+X case GetFS: printf("GetFS");
+X break;
+X
+X case GetI: printf("GetI");
+X break;
+X
+X case GetC: printf("GetC");
+X break;
+X
+X case PushI: printf("PushI");
+X break;
+X
+X case MarshTC: printf("MarshTC");
+X break;
+X
+X case UnMarshTC: printf("UnMarshTC");
+X break;
+X
+X case Equal: printf("Equal");
+X break;
+X
+X default: printf("Unknown opcode %04x",(int)Opcode);
+X break;
+X }
+X}
+EOF
+fi
+if test -s 'src/structmember.c'
+then echo '*** I will not over-write existing file src/structmember.c'
+else
+echo 'x - src/structmember.c'
+sed 's/^X//' > 'src/structmember.c' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/* Map C struct members to Python object attributes */
+X
+X#include "allobjects.h"
+X
+X#include "structmember.h"
+X
+Xobject *
+Xgetmember(addr, mlist, name)
+X char *addr;
+X struct memberlist *mlist;
+X char *name;
+X{
+X struct memberlist *l;
+X
+X for (l = mlist; l->name != NULL; l++) {
+X if (strcmp(l->name, name) == 0) {
+X object *v;
+X addr += l->offset;
+X switch (l->type) {
+X case T_SHORT:
+X v = newintobject((long) *(short*)addr);
+X break;
+X case T_INT:
+X v = newintobject((long) *(int*)addr);
+X break;
+X case T_LONG:
+X v = newintobject(*(long*)addr);
+X break;
+X case T_FLOAT:
+X v = newfloatobject((double)*(float*)addr);
+X break;
+X case T_DOUBLE:
+X v = newfloatobject(*(double*)addr);
+X break;
+X case T_STRING:
+X if (*(char**)addr == NULL) {
+X INCREF(None);
+X v = None;
+X }
+X else
+X v = newstringobject(*(char**)addr);
+X break;
+X case T_OBJECT:
+X v = *(object **)addr;
+X if (v == NULL)
+X v = None;
+X INCREF(v);
+X break;
+X default:
+X err_setstr(SystemError, "bad memberlist type");
+X v = NULL;
+X }
+X return v;
+X }
+X }
+X
+X err_setstr(NameError, name);
+X return NULL;
+X}
+X
+Xint
+Xsetmember(addr, mlist, name, v)
+X char *addr;
+X struct memberlist *mlist;
+X char *name;
+X object *v;
+X{
+X struct memberlist *l;
+X
+X for (l = mlist; l->name != NULL; l++) {
+X if (strcmp(l->name, name) == 0) {
+X if (l->readonly || l->type == T_STRING) {
+X err_setstr(RuntimeError, "readonly attribute");
+X return -1;
+X }
+X addr += l->offset;
+X switch (l->type) {
+X case T_SHORT:
+X if (!is_intobject(v)) {
+X err_badarg();
+X return -1;
+X }
+X *(short*)addr = getintvalue(v);
+X break;
+X case T_INT:
+X if (!is_intobject(v)) {
+X err_badarg();
+X return -1;
+X }
+X *(int*)addr = getintvalue(v);
+X break;
+X case T_LONG:
+X if (!is_intobject(v)) {
+X err_badarg();
+X return -1;
+X }
+X *(long*)addr = getintvalue(v);
+X break;
+X case T_FLOAT:
+X if (is_intobject(v))
+X *(float*)addr = getintvalue(v);
+X else if (is_floatobject(v))
+X *(float*)addr = getfloatvalue(v);
+X else {
+X err_badarg();
+X return -1;
+X }
+X break;
+X case T_DOUBLE:
+X if (is_intobject(v))
+X *(double*)addr = getintvalue(v);
+X else if (is_floatobject(v))
+X *(double*)addr = getfloatvalue(v);
+X else {
+X err_badarg();
+X return -1;
+X }
+X break;
+X case T_OBJECT:
+X XDECREF(*(object **)addr);
+X XINCREF(v);
+X *(object **)addr = v;
+X break;
+X default:
+X err_setstr(SystemError, "bad memberlist type");
+X return -1;
+X }
+X return 0;
+X }
+X }
+X
+X err_setstr(NameError, name);
+X return -1;
+X}
+EOF
+fi
+if test -s 'src/xxobject.c'
+then echo '*** I will not over-write existing file src/xxobject.c'
+else
+echo 'x - src/xxobject.c'
+sed 's/^X//' > 'src/xxobject.c' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/* Use this file as a template to start implementing a new object type.
+X If your objects will be called foobar, start by copying this file to
+X foobarobject.c, changing all occurrences of xx to foobar and all
+X occurrences of Xx by Foobar. You will probably want to delete all
+X references to 'x_attr' and add your own types of attributes
+X instead. Maybe you want to name your local variables other than
+X 'xp'. If your object type is needed in other files, you'll have to
+X create a file "foobarobject.h"; see intobject.h for an example. */
+X
+X
+X/* Xx objects */
+X
+X#include "allobjects.h"
+X
+Xtypedef struct {
+X OB_HEAD
+X object *x_attr; /* Attributes dictionary */
+X} xxobject;
+X
+Xextern typeobject Xxtype; /* Really static, forward */
+X
+X#define is_xxobject(v) ((v)->ob_type == &Xxtype)
+X
+Xstatic xxobject *
+Xnewxxobject(arg)
+X object *arg;
+X{
+X xxobject *xp;
+X xp = NEWOBJ(xxobject, &Xxtype);
+X if (xp == NULL)
+X return NULL;
+X xp->x_attr = NULL;
+X return xp;
+X}
+X
+X/* Xx methods */
+X
+Xstatic void
+Xxx_dealloc(xp)
+X xxobject *xp;
+X{
+X XDECREF(xp->x_attr);
+X DEL(xp);
+X}
+X
+Xstatic object *
+Xxx_demo(self, args)
+X xxobject *self;
+X object *args;
+X{
+X if (!getnoarg(args))
+X return NULL;
+X INCREF(None);
+X return None;
+X}
+X
+Xstatic struct methodlist xx_methods[] = {
+X "demo", xx_demo,
+X {NULL, NULL} /* sentinel */
+X};
+X
+Xstatic object *
+Xxx_getattr(xp, name)
+X xxobject *xp;
+X char *name;
+X{
+X if (xp->x_attr != NULL) {
+X object *v = dictlookup(xp->x_attr, name);
+X if (v != NULL) {
+X INCREF(v);
+X return v;
+X }
+X }
+X return findmethod(xx_methods, (object *)xp, name);
+X}
+X
+Xstatic int
+Xxx_setattr(xp, name, v)
+X xxobject *xp;
+X char *name;
+X object *v;
+X{
+X if (xp->x_attr == NULL) {
+X xp->x_attr = newdictobject();
+X if (xp->x_attr == NULL)
+X return -1;
+X }
+X if (v == NULL)
+X return dictremove(xp->x_attr, name);
+X else
+X return dictinsert(xp->x_attr, name, v);
+X}
+X
+Xstatic typeobject Xxtype = {
+X OB_HEAD_INIT(&Typetype)
+X 0, /*ob_size*/
+X "xx", /*tp_name*/
+X sizeof(xxobject), /*tp_size*/
+X 0, /*tp_itemsize*/
+X /* methods */
+X xx_dealloc, /*tp_dealloc*/
+X 0, /*tp_print*/
+X xx_getattr, /*tp_getattr*/
+X xx_setattr, /*tp_setattr*/
+X 0, /*tp_compare*/
+X 0, /*tp_repr*/
+X};
+EOF
+fi
+echo 'Part 16 out of 21 of pack.out complete.'
+exit 0
diff --git a/shar/python-0.9.1-17-21.shar b/shar/python-0.9.1-17-21.shar
new file mode 100644
index 0000000..1ab184e
--- /dev/null
+++ b/shar/python-0.9.1-17-21.shar
@@ -0,0 +1,2464 @@
+: This is a shell archive.
+: Extract with 'sh this_file'.
+:
+: Extract part 01 first since it makes all directories
+echo 'Start of pack.out, part 17 out of 21:'
+if test -s 'demo/sgi/gl/nurbs.py'
+then echo '*** I will not over-write existing file demo/sgi/gl/nurbs.py'
+else
+echo 'x - demo/sgi/gl/nurbs.py'
+sed 's/^X//' > 'demo/sgi/gl/nurbs.py' << 'EOF'
+X#! /ufs/guido/bin/sgi/python
+X
+X# Rotate a 3D surface created using NURBS.
+X#
+X# Press left mouse button to toggle surface trimming.
+X# Press ESC to quit.
+X#
+X# See the GL manual for an explanation of NURBS.
+X
+Xfrom gl import *
+Xfrom GL import *
+Xfrom DEVICE import *
+X
+XTRUE = 1
+XFALSE = 0
+XORDER = 4
+X
+Xidmat = [1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1]
+X
+Xsurfknots = [-1, -1, -1, -1, 1, 1, 1, 1]
+X
+Xdef make_ctlpoints():
+X c = []
+X #
+X ci = []
+X ci.append(-2.5, -3.7, 1.0)
+X ci.append(-1.5, -3.7, 3.0)
+X ci.append(1.5, -3.7, -2.5)
+X ci.append(2.5, -3.7, -0.75)
+X c.append(ci)
+X #
+X ci = []
+X ci.append(-2.5, -2.0, 3.0)
+X ci.append(-1.5, -2.0, 4.0)
+X ci.append(1.5, -2.0, -3.0)
+X ci.append(2.5, -2.0, 0.0)
+X c.append(ci)
+X #
+X ci = []
+X ci.append(-2.5, 2.0, 1.0)
+X ci.append(-1.5, 2.0, 0.0)
+X ci.append(1.5, 2.0, -1.0)
+X ci.append(2.5, 2.0, 2.0)
+X c.append(ci)
+X #
+X ci = []
+X ci.append(-2.5, 2.7, 1.25)
+X ci.append(-1.5, 2.7, 0.1)
+X ci.append(1.5, 2.7, -0.6)
+X ci.append(2.5, 2.7, 0.2)
+X c.append(ci)
+X #
+X return c
+X
+Xctlpoints = make_ctlpoints()
+X
+Xtrimknots = [0., 0., 0., 1., 1., 2., 2., 3., 3., 4., 4., 4.]
+X
+Xdef make_trimpoints():
+X c = []
+X c.append(1.0, 0.0, 1.0)
+X c.append(1.0, 1.0, 1.0)
+X c.append(0.0, 2.0, 2.0)
+X c.append(-1.0, 1.0, 1.0)
+X c.append(-1.0, 0.0, 1.0)
+X c.append(-1.0, -1.0, 1.0)
+X c.append(0.0, -2.0, 2.0)
+X c.append(1.0, -1.0, 1.0)
+X c.append(1.0, 0.0, 1.0)
+X return c
+X
+Xtrimpoints = make_trimpoints()
+X
+Xdef main():
+X init_windows()
+X setup_queue()
+X make_lights()
+X init_view()
+X #
+X set_scene()
+X setnurbsproperty( N_ERRORCHECKING, 1.0 )
+X setnurbsproperty( N_PIXEL_TOLERANCE, 50.0 )
+X trim_flag = 0
+X draw_trim_surface(trim_flag)
+X #
+X while 1:
+X while qtest():
+X dev, val = qread()
+X if dev = ESCKEY:
+X return
+X elif dev = WINQUIT:
+X dglclose(-1) # this for DGL only
+X return
+X elif dev = REDRAW:
+X reshapeviewport()
+X set_scene()
+X draw_trim_surface(trim_flag)
+X elif dev = LEFTMOUSE:
+X if val:
+X trim_flag = (not trim_flag)
+X set_scene()
+X draw_trim_surface(trim_flag)
+X
+Xdef init_windows():
+X foreground()
+X #prefposition(0, 500, 0, 500)
+X wid = winopen('nurbs')
+X wintitle('NURBS Surface')
+X doublebuffer()
+X RGBmode()
+X gconfig()
+X lsetdepth(0x000, 0x7fffff)
+X zbuffer( TRUE )
+X
+Xdef setup_queue():
+X qdevice(ESCKEY)
+X qdevice(REDRAW)
+X qdevice(RIGHTMOUSE)
+X qdevice(WINQUIT)
+X qdevice(LEFTMOUSE) #trimming
+X
+Xdef init_view():
+X mmode(MPROJECTION)
+X ortho( -4., 4., -4., 4., -4., 4. )
+X #
+X mmode(MVIEWING)
+X loadmatrix(idmat)
+X #
+X lmbind(MATERIAL, 1)
+X
+Xdef set_scene():
+X lmbind(MATERIAL, 0)
+X RGBcolor(150,150,150)
+X lmbind(MATERIAL, 1)
+X clear()
+X zclear()
+X #
+X rotate( 100, 'y' )
+X rotate( 100, 'z' )
+X
+Xdef draw_trim_surface(trim_flag):
+X bgnsurface()
+X nurbssurface(surfknots, surfknots, ctlpoints, ORDER, ORDER, N_XYZ)
+X if trim_flag:
+X bgntrim()
+X nurbscurve(trimknots, trimpoints, ORDER-1, N_STW)
+X endtrim()
+X endsurface()
+X swapbuffers()
+X
+Xdef make_lights():
+X lmdef(DEFLMODEL,1,[])
+X lmdef(DEFLIGHT,1,[])
+X #
+X # define material #1
+X #
+X a = []
+X a = a + [EMISSION, 0.0, 0.0, 0.0]
+X a = a + [AMBIENT, 0.1, 0.1, 0.1]
+X a = a + [DIFFUSE, 0.6, 0.3, 0.3]
+X a = a + [SPECULAR, 0.0, 0.6, 0.0]
+X a = a + [SHININESS, 2.0]
+X a = a + [LMNULL]
+X lmdef(DEFMATERIAL, 1, a)
+X #
+X # turn on lighting
+X #
+X lmbind(LIGHT0, 1)
+X lmbind(LMODEL, 1)
+X
+Xmain()
+EOF
+chmod +x 'demo/sgi/gl/nurbs.py'
+fi
+if test -s 'demo/sgi/gl/zrgb.py'
+then echo '*** I will not over-write existing file demo/sgi/gl/zrgb.py'
+else
+echo 'x - demo/sgi/gl/zrgb.py'
+sed 's/^X//' > 'demo/sgi/gl/zrgb.py' << 'EOF'
+X#! /ufs/guido/bin/sgi/python
+X
+X# zrgb (Requires Z buffer.)
+X#
+X# This program demostrates zbuffering 3 intersecting RGB polygons while
+X# in doublebuffer mode where, movement of the mouse with the LEFTMOUSE
+X# button depressed will, rotate the 3 polygons. This is done by compound
+X# rotations allowing continuous screen-oriented rotations.
+X#
+X# Press the "Esc" key to exit.
+X
+Xfrom gl import *
+Xfrom GL import *
+Xfrom DEVICE import *
+X
+X
+Xobjmat=[1.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,1.0]
+X
+Xidmat=[1.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,1.0]
+X
+Xdef main() :
+X #
+X # old and new mouse position
+X #
+X #
+X mode = 0
+X omx = 0
+X mx = 0
+X omy = 0
+X my = 0
+X #
+X initialize ()
+X #
+X draw_scene (objmat)
+X #
+X while (1) :
+X #
+X dev, val = qread()
+X #
+X if dev = ESCKEY :
+X if val :
+X break
+X # exit when key is going up, not down
+X # this avoids the scenario where a window
+X # underneath this program's window
+X # would otherwise "eat up" the up-
+X # event of the Esc key being released
+X return
+X #
+X elif dev = REDRAW :
+X reshapeviewport()
+X draw_scene(objmat)
+X #
+X elif dev = LEFTMOUSE:
+X omx = mx
+X omy = my
+X if val :
+X mode = 1
+X else :
+X mode = 0
+X elif dev = MOUSEX :
+X omx = mx
+X mx = val
+X #print omx, mx
+X objmat = update_scene(objmat,mx,my,omx,omy,mode)
+X #
+X elif dev = MOUSEY :
+X omy = my
+X my = val
+X #print omy, my
+X objmat = update_scene(objmat,mx,my,omx,omy,mode)
+X #
+X
+X
+Xdef initialize () :
+X #
+X foreground ()
+X keepaspect(5, 4)
+X w = winopen('Zbuffered RGB')
+X #
+X doublebuffer()
+X RGBmode()
+X gconfig()
+X zbuffer(1)
+X lsetdepth(0x0, 0x7FFFFF)
+X #
+X qdevice(ESCKEY)
+X qdevice(LEFTMOUSE)
+X qdevice(MOUSEX)
+X qdevice(MOUSEY)
+X
+Xdef update_scene (mat, mx, my, omx, omy, mode) :
+X #
+X if mode = 1 :
+X mat = orient(mat, mx, my, omx, omy)
+X draw_scene(mat)
+X return mat
+X
+Xdef orient (mat, mx, my, omx, omy) :
+X #
+X #
+X pushmatrix()
+X loadmatrix(idmat)
+X #
+X if mx - omx : rot (float (mx - omx), 'y')
+X if omy - my : rot (float (omy - my), 'x')
+X #
+X multmatrix(mat)
+X mat = getmatrix()
+X #
+X #
+X popmatrix()
+X #
+X return mat
+X
+Xdef draw_scene (mat) :
+X RGBcolor(40, 100, 200)
+X clear()
+X zclear()
+X #
+X perspective(400, 1.25, 30.0, 60.0)
+X translate(0.0, 0.0, -40.0)
+X multmatrix(mat)
+X #
+X # skews original view to show all polygons
+X #
+X rotate(-580, 'y')
+X draw_polys()
+X #
+X swapbuffers()
+X
+Xpolygon1 = [(-10.0,-10.0,0.0),(10.0,-10.0,0.0),(-10.0,10.0,0.0)]
+X
+Xpolygon2 = [(0.0,-10.0,-10.0),(0.0,-10.0,10.0),(0.0,5.0,-10.0)]
+X
+Xpolygon3 = [(-10.0,6.0,4.0),(-10.0,3.0,4.0),(4.0,-9.0,-10.0),(4.0,-6.0,-10.0)]
+X
+Xdef draw_polys():
+X bgnpolygon()
+X cpack(0x0)
+X v3f(polygon1[0])
+X cpack(0x007F7F7F)
+X v3f(polygon1[1])
+X cpack(0x00FFFFFF)
+X v3f(polygon1[2])
+X endpolygon()
+X #
+X bgnpolygon()
+X cpack(0x0000FFFF)
+X v3f(polygon2[0])
+X cpack(0x007FFF00)
+X v3f(polygon2[1])
+X cpack(0x00FF0000)
+X v3f(polygon2[2])
+X endpolygon()
+X #
+X bgnpolygon()
+X cpack(0x0000FFFF)
+X v3f(polygon3[0])
+X cpack(0x00FF00FF)
+X v3f(polygon3[1])
+X cpack(0x00FF0000)
+X v3f(polygon3[2])
+X cpack(0x00FF00FF)
+X v3f(polygon3[3])
+X endpolygon()
+X
+X
+Xmain ()
+EOF
+chmod +x 'demo/sgi/gl/zrgb.py'
+fi
+if test -s 'demo/sgi/gl_panel/flying/flying.s'
+then echo '*** I will not over-write existing file demo/sgi/gl_panel/flying/flying.s'
+else
+echo 'x - demo/sgi/gl_panel/flying/flying.s'
+sed 's/^X//' > 'demo/sgi/gl_panel/flying/flying.s' << 'EOF'
+X;;; This file was automatically generated by the panel editor.
+X;;; If you read it into gnu emacs, it will automagically format itself.
+X
+X(panel (prop help creator:user-panel-help)
+X(prop user-panel #t)
+X(label "flying objects")
+X(al (pnl_toggle_button (name "table")
+X(prop help creator:user-act-help)
+X(label "table")
+X(x 4.75)
+X(y 0.25)
+X(downfunc move-then-resize)
+X)
+X(pnl_toggle_button (name "pyramid")
+X(prop help creator:user-act-help)
+X(label "pyramid")
+X(x 4.75)
+X(y 0.75)
+X(downfunc move-then-resize)
+X)
+X(pnl_toggle_button (name "glass")
+X(prop help creator:user-act-help)
+X(label "glass")
+X(x 4.75)
+X(y 1.25)
+X(downfunc move-then-resize)
+X)
+X(pnl_toggle_button (name "diamond")
+X(prop help creator:user-act-help)
+X(label "diamond")
+X(x 4.75)
+X(y 1.75)
+X(downfunc move-then-resize)
+X)
+X(pnl_toggle_button (name "disk")
+X(prop help creator:user-act-help)
+X(label "disk")
+X(x 4.75)
+X(y 2.25)
+X(downfunc move-then-resize)
+X)
+X(pnl_toggle_button (name "icecream")
+X(prop help creator:user-act-help)
+X(label "ice cream")
+X(x 4.75)
+X(y 2.75)
+X(downfunc move-then-resize)
+X)
+X(pnl_toggle_button (name "cube")
+X(prop help creator:user-act-help)
+X(label "cube")
+X(x 4.75)
+X(y 3.25)
+X(val 1)
+X(downfunc move-then-resize)
+X)
+X(pnl_toggle_button (name "cylinder")
+X(prop help creator:user-act-help)
+X(label "cylinder")
+X(x 4.75)
+X(y 3.75)
+X(downfunc move-then-resize)
+X)
+X(pnl_toggle_button (name "sphere")
+X(prop help creator:user-act-help)
+X(label "sphere")
+X(x 4.75)
+X(y 4.25)
+X(downfunc move-then-resize)
+X)
+X(pnl_button (name "quit")
+X(prop help creator:user-act-help)
+X(label "quit")
+X(x 0.25)
+X(y 2.25)
+X(w 1.3)
+X(h 0.65)
+X(labeltype 16)
+X(downfunc move-then-resize)
+X)
+X(pnl_button (name "showall")
+X(prop help creator:user-act-help)
+X(label "show all")
+X(x 3.75)
+X(y 3.75)
+X(labeltype 8)
+X(downfunc move-then-resize)
+X)
+X(pnl_button (name "shownone")
+X(prop help creator:user-act-help)
+X(label "show none")
+X(x 3.75)
+X(y 3.25)
+X(labeltype 8)
+X(downfunc move-then-resize)
+X)
+X(pnl_radio_button (name "wire")
+X(prop end-of-group #t)
+X(prop help creator:user-act-help)
+X(label "wire frame")
+X(x 0.25)
+X(y 4.5)
+X(h 0.36)
+X(downfunc move-then-resize)
+X)
+X(pnl_radio_button (name "filled")
+X(prop help creator:user-act-help)
+X(label "filled")
+X(x 0.25)
+X(y 4)
+X(h 0.36)
+X(val 1)
+X(downfunc move-then-resize)
+X)
+X(pnl_radio_button (name "flat")
+X(prop end-of-group #t)
+X(prop help creator:user-act-help)
+X(label "flat shaded")
+X(x 0.25)
+X(y 0.5)
+X(h 0.36)
+X(downfunc move-then-resize)
+X)
+X(pnl_radio_button (name "gouraud")
+X(prop help creator:user-act-help)
+X(label "gouraud shaded")
+X(x 0.25)
+X(h 0.36)
+X(val 1)
+X(downfunc move-then-resize)
+X)
+X)
+X)
+X;;; Local Variables:
+X;;; mode: scheme
+X;;; eval: (save-excursion (goto-char (point-min)) (kill-line 3))
+X;;; eval: (save-excursion (goto-char (point-min)) (replace-regexp "[ \n]*)" ")"))
+X;;; eval: (indent-region (point-min) (point-max) nil)
+X;;; eval: (progn (kill-line -3) (delete-backward-char 1) (save-buffer))
+X;;; End:
+EOF
+fi
+if test -s 'demo/sgi/gl_panel/flying/objectdef.py'
+then echo '*** I will not over-write existing file demo/sgi/gl_panel/flying/objectdef.py'
+else
+echo 'x - demo/sgi/gl_panel/flying/objectdef.py'
+sed 's/^X//' > 'demo/sgi/gl_panel/flying/objectdef.py' << 'EOF'
+Xfrom math import *
+Xfrom objdict import *
+Xfrom gl import *
+X
+XFUZZY = 0.00001
+X
+X# first try - brute force method (ala M.Overmars...)
+X
+Xdef makespinobject (smooth,rot,n,x1,z1,nx1,nz1,x2,z2,nx2,nz2) :
+X object = []
+X dth = 2.0 * pi / float (rot)
+X for i in range (0, n) :
+X for j in range (0, rot) :
+X th = dth * float (j)
+X #
+X if smooth = 1:
+X a1 = th
+X a2 =th+dth
+X else :
+X a1 = th + dth / 2.0
+X a2 = th + dth / 2.0
+X #
+X v0 = (x1[i]*sin(th),x1[i]*cos(th),z1[i])
+X n0 = (nx1[i]*sin(a1),nx1[i]*cos(a1),nz1[i])
+X #
+X v1 = (x1[i]*sin(th+dth),x1[i]*cos(th+dth),z1[i])
+X n1 = (nx1[i]*sin(a2), nx1[i]*cos(a2), nz1[i])
+X #
+X v2 = (x2[i]*sin(th+dth),x2[i]*cos(th+dth),z2[i])
+X n2 = (nx2[i]*sin(a2), nx2[i]*cos(a2), nz2[i])
+X #
+X v3 = (x2[i]*sin(th), x2[i]*cos(th), z2[i])
+X n3 = (nx2[i]*sin(a1), nx2[i]*cos(a1), nz2[i])
+X #
+X patch = ((v0,n0), (v1,n1), (v2,n2), (v3,n3))
+X #patch = ((n0,v0), (n1,v1), (n2,v2), (n3,v3))
+X #
+X if x1[i] < FUZZY :
+X patch = patch[1:]
+X #
+X object.append (patch)
+X #
+X return object
+X
+Xdef makesphere (n):
+X asin = []
+X acos = []
+X for i in range (0, n-1):
+X asin.append (sin((pi/float (n))*(1.0+float (i))))
+X acos.append(cos((pi/float (n))*(1.0+float (i))))
+X #
+X x1 = [0.0] + asin
+X z1 = [1.0] + acos
+X nx1 = [0.0] + asin
+X nz1 = [1.0] + acos
+X #
+X x2 = asin + [0.0]
+X z2 = acos + [-1.0]
+X nx2 = asin + [0.0]
+X nz2 = acos + [-1.0]
+X #
+X return makespinobject (1,2*n,n,x1,z1,nx1,nz1,x2,z2,nx2,nz2)
+X
+Xdef makecylinder(n) :
+X x1 = [0.0, 1.0, 1.0]
+X nx1 = [0.0, 1.0, 0.0]
+X z1 = [1.0, 1.0, -1.0]
+X nz1 = [1.0, 0.0, -1.0]
+X #
+X z2 = [1.0, -1.0, -1.0]
+X nz2 = [1.0, 0.0, -1.0]
+X x2 = [1.0, 1.0, 0.0]
+X nx2 = [0.0, 1.0, 0.0]
+X #
+X return makespinobject(1,2*n,3,x1,z1,nx1,nz1,x2,z2,nx2,nz2)
+X
+Xdef makecone(n) :
+X x1 = [0.0, 1.0, 1.0]
+X nx1 = [2.0/sqrt(5.0), 0.0, 0.0]
+X z1 = [1.0, -1.0, -1.0]
+X nz1 = [1.0/sqrt(5.0), -1.0, -1.0]
+X #
+X x2 = [1.0, 0.0, 0.0]
+X nx2 = [2.0/sqrt(5.0), 0.0, 0.0]
+X nz2 = [1.0/sqrt(5.0), -1.0, -1.0]
+X z2 = [-1.0, -1.0, -1.0]
+X #
+X return makespinobject(1,2*n,2,x1,z1,nx1,nz1,x2,z2,nx2,nz2)
+X
+Xdef makecube() :
+X x1 = [0.0, sqrt(2.0), sqrt (2.0)]
+X nx1 = [0.0, 1.0, 0.0]
+X z1 = [1.0, 1.0, -1.0]
+X nz1 = [1.0, 0.0, -1.0]
+X #
+X x2 = [sqrt(2.0), sqrt(2.0), 0.0]
+X nx2 = [0.0, 1.0, 0.0]
+X z2 = [1.0, -1.0, -1.0]
+X nz2 = [1.0, 0.0, -1.0]
+X #
+X return makespinobject(0,4,3,x1,z1,nx1,nz1,x2,z2,nx2,nz2)
+X
+X
+Xdef makepyramid() :
+X x1 = [0.0, sqrt(2.0), 0.0]
+X nx1 = [2.0 / sqrt(5.0), 0.0, 0.0]
+X z1 = [1.0, -1.0, 0.0]
+X nz1 = [1.0 / sqrt(5.0), -1.0, 0.0]
+X #
+X x2 = [sqrt(2.0), 0.0, 0.0]
+X nx2 = [2.0 / sqrt(5.0), 0.0, 0.0]
+X z2 = [-1.0, -1.0, -1.0]
+X nz2 = [1.0/sqrt(5.0), -1.0, 0.0]
+X #
+X return makespinobject(0,4,3,x1,z1,nx1,nz1,x2,z2,nx2,nz2)
+X
+Xdef makeobjects () :
+X cube = makecube()
+X sphere = makesphere (6)
+X cylinder = makecylinder (6)
+X cone = makecone (6)
+X pyramid = makepyramid ()
+X #
+X odict = {}
+X odict ['cube'] = cube
+X odict ['pyramid'] = pyramid
+X odict ['sphere'] = sphere
+X odict ['cylinder'] = cylinder
+X odict ['cone'] = cone
+X odict ['diamond'] = cube
+X odict ['disk'] = sphere
+X #
+X return odict
+X
+X
+Xrenderfuncs = [bgnpolygon, endpolygon]
+X
+Xdef putFunc (funcs) :
+X renderfuncs [:] = funcs
+X
+Xdef drawobject (obj) :
+X #
+X for patch in obj :
+X renderfuncs[0] ()
+X vnarray (patch)
+X renderfuncs[1] ()
+X
+EOF
+fi
+if test -s 'lib/Split.py'
+then echo '*** I will not over-write existing file lib/Split.py'
+else
+echo 'x - lib/Split.py'
+sed 's/^X//' > 'lib/Split.py' << 'EOF'
+X# Generic Split implementation.
+X# Use as a base class for other splits.
+X# Derived classes should at least implement the methods that call
+X# unimpl() below: minsize(), getbounds() and setbounds().
+X
+XError = 'Split.Error' # Exception
+X
+Ximport rect
+Xfrom util import remove
+X
+Xclass Split():
+X #
+X # Calls from creator
+X # NB derived classes may add parameters to create()
+X #
+X def create(self, parent):
+X parent.addchild(self)
+X self.parent = parent
+X self.children = []
+X self.mouse_interest = []
+X self.timer_interest = []
+X self.mouse_focus = 0
+X return self
+X #
+X # Downcalls from parent to child
+X #
+X def destroy(self):
+X self.parent = None
+X for child in self.children:
+X child.destroy()
+X del self.children[:]
+X del self.mouse_interest[:]
+X del self.timer_interest[:]
+X self.mouse_focus = None
+X #
+X def minsize(self, m): return unimpl()
+X def getbounds(self): return unimpl()
+X def setbounds(self, bounds): unimpl()
+X #
+X def draw(self, d_detail):
+X # (Could avoid calls to children outside the area)
+X for child in self.children:
+X child.draw(d_detail)
+X #
+X # Downcalls only made after certain upcalls
+X #
+X def mouse_down(self, detail):
+X if self.mouse_focus:
+X self.mouse_focus.mouse_down(detail)
+X p = detail[0]
+X for child in self.mouse_interest:
+X if rect.pointinrect(p, child.getbounds()):
+X self.mouse_focus = child
+X child.mouse_down(detail)
+X def mouse_move(self, detail):
+X if self.mouse_focus:
+X self.mouse_focus.mouse_move(detail)
+X def mouse_up(self, detail):
+X if self.mouse_focus:
+X self.mouse_focus.mouse_up(detail)
+X self.mouse_focus = 0
+X #
+X def timer(self):
+X for child in self.timer_interest:
+X child.timer()
+X #
+X # Upcalls from child to parent
+X #
+X def addchild(self, child):
+X if child in self.children:
+X raise Error, 'addchild: child already inlist'
+X self.children.append(child)
+X def delchild(self, child):
+X if child not in self.children:
+X raise Error, 'delchild: child not in list'
+X remove(child, self.children)
+X if child in self.mouse_interest:
+X remove(child, self.mouse_interest)
+X if child in self.timer_interest:
+X remove(child, self.timer_interest)
+X if child = self.mouse_focus:
+X self.mouse_focus = 0
+X #
+X def need_mouse(self, child):
+X if child not in self.mouse_interest:
+X self.mouse_interest.append(child)
+X self.parent.need_mouse(self)
+X def no_mouse(self, child):
+X if child in self.mouse_interest:
+X remove(child, self.mouse_interest)
+X if not self.mouse_interest:
+X self.parent.no_mouse(self)
+X #
+X def need_timer(self, child):
+X if child not in self.timer_interest:
+X self.timer_interest.append(child)
+X self.parent.need_timer(self)
+X def no_timer(self, child):
+X if child in self.timer_interest:
+X remove(child, self.timer_interest)
+X if not self.timer_interest:
+X self.parent.no_timer(self)
+X #
+X # The rest are transparent:
+X #
+X def begindrawing(self):
+X return self.parent.begindrawing()
+X def beginmeasuring(self):
+X return self.parent.beginmeasuring()
+X #
+X def change(self, area):
+X self.parent.change(area)
+X def scroll(self, area_vector):
+X self.parent.scroll(area_vector)
+X def settimer(self, itimer):
+X self.parent.settimer(itimer)
+EOF
+fi
+if test -s 'lib/WindowParent.py'
+then echo '*** I will not over-write existing file lib/WindowParent.py'
+else
+echo 'x - lib/WindowParent.py'
+sed 's/^X//' > 'lib/WindowParent.py' << 'EOF'
+X# A 'WindowParent' is the only module that uses real stdwin functionality.
+X# It is the root of the tree.
+X# It should have exactly one child when realized.
+X
+Ximport stdwin
+Xfrom stdwinevents import *
+X
+Xfrom TransParent import ManageOneChild
+X
+XError = 'WindowParent.Error' # Exception
+X
+Xclass WindowParent() = ManageOneChild():
+X #
+X def create(self, (title, size)):
+X self.title = title
+X self.size = size # (width, height)
+X self._reset()
+X return self
+X #
+X def _reset(self):
+X self.child = 0
+X self.win = 0
+X self.itimer = 0
+X self.do_mouse = 0
+X self.do_timer = 0
+X #
+X def destroy(self):
+X if self.child: self.child.destroy()
+X self._reset()
+X #
+X def need_mouse(self, child): self.do_mouse = 1
+X def no_mouse(self, child): self.do_mouse = 0
+X #
+X def need_timer(self, child): self.do_timer = 1
+X def no_timer(self, child): self.do_timer = 0
+X #
+X def realize(self):
+X if self.win:
+X raise Error, 'realize(): called twice'
+X if not self.child:
+X raise Error, 'realize(): no child'
+X size = self.child.minsize(self.beginmeasuring())
+X self.size = max(self.size[0], size[0]), \
+X max(self.size[1], size[1])
+X #stdwin.setdefwinsize(self.size)
+X # XXX Compensate stdwin bug:
+X stdwin.setdefwinsize(self.size[0]+4, self.size[1]+2)
+X self.win = stdwin.open(self.title)
+X if self.itimer:
+X self.win.settimer(self.itimer)
+X bounds = (0, 0), self.win.getwinsize()
+X self.child.setbounds(bounds)
+X #
+X def beginmeasuring(self):
+X # Return something with which a child can measure text
+X if self.win:
+X return self.win.begindrawing()
+X else:
+X return stdwin
+X #
+X def begindrawing(self):
+X if self.win:
+X return self.win.begindrawing()
+X else:
+X raise Error, 'begindrawing(): not realized yet'
+X #
+X def change(self, area):
+X if self.win:
+X self.win.change(area)
+X #
+X def scroll(self, args):
+X if self.win:
+X self.win.scroll(args)
+X #
+X def settimer(self, itimer):
+X if self.win:
+X self.win.settimer(itimer)
+X else:
+X self.itimer = itimer
+X #
+X # Only call dispatch if we have a child
+X #
+X def dispatch(self, (type, win, detail)):
+X if win <> self.win:
+X return
+X elif type = WE_DRAW:
+X d = self.win.begindrawing()
+X self.child.draw(d, detail)
+X elif type = WE_MOUSE_DOWN:
+X if self.do_mouse: self.child.mouse_down(detail)
+X elif type = WE_MOUSE_MOVE:
+X if self.do_mouse: self.child.mouse_move(detail)
+X elif type = WE_MOUSE_UP:
+X if self.do_mouse: self.child.mouse_up(detail)
+X elif type = WE_TIMER:
+X if self.do_timer: self.child.timer()
+X elif type = WE_SIZE:
+X self.win.change((0, 0), (10000, 10000)) # XXX
+X bounds = (0, 0), self.win.getwinsize()
+X self.child.setbounds(bounds)
+X #
+EOF
+fi
+if test -s 'lib/gwin.py'
+then echo '*** I will not over-write existing file lib/gwin.py'
+else
+echo 'x - lib/gwin.py'
+sed 's/^X//' > 'lib/gwin.py' << 'EOF'
+X# Module 'gwin'
+X# Generic stdwin windows
+X
+X# This is used as a base class from which to derive other window types.
+X# The mainloop() function here is an event dispatcher for all window types.
+X
+Ximport stdwin
+Xfrom stdwinevents import *
+X
+X# XXX Old version of stdwinevents, should go
+Ximport stdwinsupport
+XS = stdwinsupport # Shorthand
+X
+Xwindows = [] # List of open windows
+X
+X
+X# Open a window
+X
+Xdef open(title): # Open a generic window
+X w = stdwin.open(title)
+X stdwin.setdefwinsize(0, 0)
+X # Set default event handlers
+X w.draw = nop
+X w.char = nop
+X w.mdown = nop
+X w.mmove = nop
+X w.mup = nop
+X w.m2down = m2down
+X w.m2up = m2up
+X w.size = nop
+X w.move = nop
+X w.activate = w.deactivate = nop
+X w.timer = nop
+X # default command handlers
+X w.close = close
+X w.tab = tab
+X w.enter = enter
+X w.backspace = backspace
+X w.arrow = arrow
+X w.kleft = w.kup = w.kright = w.kdown = nop
+X windows.append(w)
+X return w
+X
+X
+X# Generic event dispatching
+X
+Xdef mainloop(): # Handle events until no windows left
+X while windows:
+X treatevent(stdwin.getevent())
+X
+Xdef treatevent(e): # Handle a stdwin event
+X type, w, detail = e
+X if type = S.we_draw:
+X w.draw(w, detail)
+X elif type = S.we_menu:
+X m, item = detail
+X m.action[item](w, m, item)
+X elif type = S.we_command:
+X treatcommand(w, detail)
+X elif type = S.we_char:
+X w.char(w, detail)
+X elif type = S.we_mouse_down:
+X if detail[1] > 1: w.m2down(w, detail)
+X else: w.mdown(w, detail)
+X elif type = S.we_mouse_move:
+X w.mmove(w, detail)
+X elif type = S.we_mouse_up:
+X if detail[1] > 1: w.m2up(w, detail)
+X else: w.mup(w, detail)
+X elif type = S.we_size:
+X w.size(w, w.getwinsize())
+X elif type = S.we_activate:
+X w.activate(w)
+X elif type = S.we_deactivate:
+X w.deactivate(w)
+X elif type = S.we_move:
+X w.move(w)
+X elif type = S.we_timer:
+X w.timer(w)
+X elif type = WE_CLOSE:
+X w.close(w)
+X
+Xdef treatcommand(w, type): # Handle a we_command event
+X if type = S.wc_close:
+X w.close(w)
+X elif type = S.wc_return:
+X w.enter(w)
+X elif type = S.wc_tab:
+X w.tab(w)
+X elif type = S.wc_backspace:
+X w.backspace(w)
+X elif type in (S.wc_left, S.wc_up, S.wc_right, S.wc_down):
+X w.arrow(w, type)
+X
+X
+X# Methods
+X
+Xdef close(w): # Close method
+X for i in range(len(windows)):
+X if windows[i] is w:
+X del windows[i]
+X break
+X
+Xdef arrow(w, detail): # Arrow key method
+X if detail = S.wc_left:
+X w.kleft(w)
+X elif detail = S.wc_up:
+X w.kup(w)
+X elif detail = S.wc_right:
+X w.kright(w)
+X elif detail = S.wc_down:
+X w.kdown(w)
+X
+X
+X# Trivial methods
+X
+Xdef tab(w): w.char(w, '\t')
+Xdef enter(w): w.char(w, '\n') # 'return' is a Python reserved word
+Xdef backspace(w): w.char(w, '\b')
+Xdef m2down(w, detail): w.mdown(w, detail)
+Xdef m2up(w, detail): w.mup(w, detail)
+Xdef nop(args): pass
+EOF
+fi
+if test -s 'lib/panelparser.py'
+then echo '*** I will not over-write existing file lib/panelparser.py'
+else
+echo 'x - lib/panelparser.py'
+sed 's/^X//' > 'lib/panelparser.py' << 'EOF'
+X# Module 'parser'
+X#
+X# Parse S-expressions output by the Panel Editor
+X# (which is written in Scheme so it can't help writing S-expressions).
+X#
+X# See notes at end of file.
+X
+X
+Xwhitespace = ' \t\n'
+Xoperators = '()\''
+Xseparators = operators + whitespace + ';' + '"'
+X
+X
+X# Tokenize a string.
+X# Return a list of tokens (strings).
+X#
+Xdef tokenize_string(s):
+X tokens = []
+X while s:
+X c = s[:1]
+X if c in whitespace:
+X s = s[1:]
+X elif c = ';':
+X s = ''
+X elif c = '"':
+X n = len(s)
+X i = 1
+X while i < n:
+X c = s[i]
+X i = i+1
+X if c = '"': break
+X if c = '\\': i = i+1
+X tokens.append(s[:i])
+X s = s[i:]
+X elif c in operators:
+X tokens.append(c)
+X s = s[1:]
+X else:
+X n = len(s)
+X i = 1
+X while i < n:
+X if s[i] in separators: break
+X i = i+1
+X tokens.append(s[:i])
+X s = s[i:]
+X return tokens
+X
+X
+X# Tokenize a whole file (given as file object, not as file name).
+X# Return a list of tokens (strings).
+X#
+Xdef tokenize_file(fp):
+X tokens = []
+X while 1:
+X line = fp.readline()
+X if not line: break
+X tokens = tokens + tokenize_string(line)
+X return tokens
+X
+X
+X# Exception raised by parse_exr.
+X#
+Xsyntax_error = 'syntax error'
+X
+X
+X# Parse an S-expression.
+X# Input is a list of tokens as returned by tokenize_*().
+X# Return a pair (expr, tokens)
+X# where expr is a list representing the s-expression,
+X# and tokens contains the remaining tokens.
+X# May raise syntax_error.
+X#
+Xdef parse_expr(tokens):
+X if (not tokens) or tokens[0] <> '(':
+X raise syntax_error, 'expected "("'
+X tokens = tokens[1:]
+X expr = []
+X while 1:
+X if not tokens:
+X raise syntax_error, 'missing ")"'
+X if tokens[0] = ')':
+X return expr, tokens[1:]
+X elif tokens[0] = '(':
+X subexpr, tokens = parse_expr(tokens)
+X expr.append(subexpr)
+X else:
+X expr.append(tokens[0])
+X tokens = tokens[1:]
+X
+X
+X# Parse a file (given as file object, not as file name).
+X# Return a list of parsed S-expressions found at the top level.
+X#
+Xdef parse_file(fp):
+X tokens = tokenize_file(fp)
+X exprlist = []
+X while tokens:
+X expr, tokens = parse_expr(tokens)
+X exprlist.append(expr)
+X return exprlist
+X
+X
+X# EXAMPLE:
+X#
+X# The input
+X# '(hip (hop hur-ray))'
+X#
+X# passed to tokenize_string() returns the token list
+X# ['(', 'hip', '(', 'hop', 'hur-ray', ')', ')']
+X#
+X# When this is passed to parse_expr() it returns the expression
+X# ['hip', ['hop', 'hur-ray']]
+X# plus an empty token list (because there are no tokens left.
+X#
+X# When a file containing the example is passed to parse_file() it returns
+X# a list whose only element is the output of parse_expr() above:
+X# [['hip', ['hop', 'hur-ray']]]
+X
+X
+X# TOKENIZING:
+X#
+X# Comments start with semicolon (;) and continue till the end of the line.
+X#
+X# Tokens are separated by whitespace, except the following characters
+X# always form a separate token (outside strings):
+X# ( ) '
+X# Strings are enclosed in double quotes (") and backslash (\) is used
+X# as escape character in strings.
+EOF
+fi
+if test -s 'lib/path.py'
+then echo '*** I will not over-write existing file lib/path.py'
+else
+echo 'x - lib/path.py'
+sed 's/^X//' > 'lib/path.py' << 'EOF'
+X# Module 'path' -- common operations on POSIX pathnames
+X
+Ximport posix
+Ximport stat
+X
+X
+X# Intelligent pathname concatenation.
+X# Inserts a '/' unless the first part is empty or already ends in '/'.
+X# Ignores the first part altogether if the second part is absolute
+X# (begins with '/').
+X#
+Xdef cat(a, b):
+X if b[:1] = '/': return b
+X if a = '' or a[-1:] = '/': return a + b
+X return a + '/' + b
+X
+X
+X# Split a path in head (empty or ending in '/') and tail (no '/').
+X# The tail will be empty if the path ends in '/'.
+X#
+Xdef split(p):
+X head, tail = '', ''
+X for c in p:
+X tail = tail + c
+X if c = '/':
+X head, tail = head + tail, ''
+X return head, tail
+X
+X
+X# Return the tail (basename) part of a path.
+X#
+Xdef basename(p):
+X return split(p)[1]
+X
+X
+X# Return the longest prefix of all list elements.
+X#
+Xdef commonprefix(m):
+X if not m: return ''
+X prefix = m[0]
+X for item in m:
+X for i in range(len(prefix)):
+X if prefix[:i+1] <> item[:i+1]:
+X prefix = prefix[:i]
+X if i = 0: return ''
+X break
+X return prefix
+X
+X
+X# Does a file/directory exist?
+X#
+Xdef exists(path):
+X try:
+X st = posix.stat(path)
+X except posix.error:
+X return 0
+X return 1
+X
+X
+X# Is a path a posix directory?
+X#
+Xdef isdir(path):
+X try:
+X st = posix.stat(path)
+X except posix.error:
+X return 0
+X return stat.S_ISDIR(st[stat.ST_MODE])
+X
+X
+X# Is a path a symbolic link?
+X# This will always return false on systems where posix.lstat doesn't exist.
+X#
+Xdef islink(path):
+X try:
+X st = posix.lstat(path)
+X except (posix.error, NameError):
+X return 0
+X return stat.S_ISLNK(st[stat.ST_MODE])
+X
+X
+X_mounts = []
+X
+Xdef _getmounts():
+X import commands, string
+X mounts = []
+X data = commands.getoutput('/etc/mount')
+X lines = string.splitfields(data, '\n')
+X for line in lines:
+X words = string.split(line)
+X if len(words) >= 3 and words[1] = 'on':
+X mounts.append(words[2])
+X return mounts
+X
+X
+X# Is a path a mount point?
+X# This only works for normalized, absolute paths,
+X# and only if the mount table as printed by /etc/mount is correct.
+X# Sorry.
+X#
+Xdef ismount(path):
+X if not _mounts:
+X _mounts[:] = _getmounts()
+X return path in _mounts
+X
+X
+X# Directory tree walk.
+X# For each directory under top (including top itself),
+X# func(arg, dirname, filenames) is called, where dirname
+X# is the name of the directory and filenames is the list of
+X# files (and subdirectories etc.) in the directory.
+X# func may modify the filenames list, to implement a filter,
+X# or to impose a different order of visiting.
+X#
+Xdef walk(top, func, arg):
+X try:
+X names = posix.listdir(top)
+X except posix.error:
+X return
+X func(arg, top, names)
+X exceptions = ('.', '..')
+X for name in names:
+X if name not in exceptions:
+X name = cat(top, name)
+X if isdir(name):
+X walk(name, func, arg)
+EOF
+fi
+if test -s 'lib/string.py'
+then echo '*** I will not over-write existing file lib/string.py'
+else
+echo 'x - lib/string.py'
+sed 's/^X//' > 'lib/string.py' << 'EOF'
+X# module 'string' -- A collection of string operations
+X
+X# XXX Some of these operations are incredibly slow and should be built in
+X
+X# Some strings for ctype-style character classification
+Xwhitespace = ' \t\n'
+Xlowercase = 'abcdefghijklmnopqrstuvwxyz'
+Xuppercase = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+Xletters = lowercase + uppercase
+Xdigits = '0123456789'
+Xhexdigits = digits + 'abcdef' + 'ABCDEF'
+Xoctdigits = '01234567'
+X
+X# Case conversion helpers
+X_caseswap = {}
+Xfor i in range(26):
+X _caseswap[lowercase[i]] = uppercase[i]
+X _caseswap[uppercase[i]] = lowercase[i]
+Xdel i
+X
+X# convert UPPER CASE letters to lower case
+Xdef lower(s):
+X res = ''
+X for c in s:
+X if 'A' <= c <= 'Z': c = _caseswap[c]
+X res = res + c
+X return res
+X
+X# Convert lower case letters to UPPER CASE
+Xdef upper(s):
+X res = ''
+X for c in s:
+X if 'a' <= c <= 'z': c = _caseswap[c]
+X res = res + c
+X return res
+X
+X# Swap lower case letters and UPPER CASE
+Xdef swapcase(s):
+X res = ''
+X for c in s:
+X if 'a' <= c <= 'z' or 'A' <= c <= 'Z': c = _caseswap[c]
+X res = res + c
+X return res
+X
+X# Strip leading and trailing tabs and spaces
+Xdef strip(s):
+X i, j = 0, len(s)
+X while i < j and s[i] in whitespace: i = i+1
+X while i < j and s[j-1] in whitespace: j = j-1
+X return s[i:j]
+X
+X# Split a string into a list of space/tab-separated words
+X# NB: split(s) is NOT the same as splitfields(s, ' ')!
+Xdef split(s):
+X res = []
+X i, n = 0, len(s)
+X while i < n:
+X while i < n and s[i] in whitespace: i = i+1
+X if i = n: break
+X j = i
+X while j < n and s[j] not in whitespace: j = j+1
+X res.append(s[i:j])
+X i = j
+X return res
+X
+X# Split a list into fields separated by a given string
+X# NB: splitfields(s, ' ') is NOT the same as split(s)!
+Xdef splitfields(s, sep):
+X res = []
+X ns = len(s)
+X nsep = len(sep)
+X i = j = 0
+X while j+nsep <= ns:
+X if s[j:j+nsep] = sep:
+X res.append(s[i:j])
+X i = j = j + nsep
+X else:
+X j = j + 1
+X res.append(s[i:])
+X return res
+X
+X# Find substring
+Xindex_error = 'substring not found in string.index'
+Xdef index(s, sub):
+X n = len(sub)
+X for i in range(len(s) + 1 - n):
+X if sub = s[i:i+n]: return i
+X raise index_error, (s, sub)
+X
+X# Convert string to integer
+Xatoi_error = 'non-numeric argument to string.atoi'
+Xdef atoi(str):
+X s = str
+X if s[:1] in '+-': s = s[1:]
+X if not s: raise atoi_error, str
+X for c in s:
+X if c not in digits: raise atoi_error, str
+X return eval(str)
+X
+X# Left-justify a string
+Xdef ljust(s, width):
+X n = len(s)
+X if n >= width: return s
+X return s + ' '*(width-n)
+X
+X# Right-justify a string
+Xdef rjust(s, width):
+X n = len(s)
+X if n >= width: return s
+X return ' '*(width-n) + s
+X
+X# Center a string
+Xdef center(s, width):
+X n = len(s)
+X if n >= width: return s
+X return ' '*((width-n)/2) + s + ' '*(width -(width-n)/2)
+X
+X# Zero-fill a number, e.g., (12, 3) --> '012' and (-3, 3) --> '-03'
+X# Decadent feature: the argument may be a string or a number
+X# (Use of this is deprecated; it should be a string as with ljust c.s.)
+Xdef zfill(x, width):
+X if type(x) = type(''): s = x
+X else: s = `x`
+X n = len(s)
+X if n >= width: return s
+X sign = ''
+X if s[0] = '-':
+X sign, s = '-', s[1:]
+X return sign + '0'*(width-n) + s
+EOF
+fi
+if test -s 'src/Grammar'
+then echo '*** I will not over-write existing file src/Grammar'
+else
+echo 'x - src/Grammar'
+sed 's/^X//' > 'src/Grammar' << 'EOF'
+X# Grammar for Python, version 4
+X
+X# Changes compared to version 3:
+X# Removed 'dir' statement.
+X# Function call argument is a testlist instead of exprlist.
+X
+X# Changes compared to version 2:
+X# The syntax of Boolean operations is changed to use more
+X# conventional priorities: or < and < not.
+X
+X# Changes compared to version 1:
+X# modules and scripts are unified;
+X# 'quit' is gone (use ^D);
+X# empty_stmt is gone, replaced by explicit NEWLINE where appropriate;
+X# 'import' and 'def' aren't special any more;
+X# added 'from' NAME option on import clause, and '*' to import all;
+X# added class definition.
+X
+X# Start symbols for the grammar:
+X# single_input is a single interactive statement;
+X# file_input is a module or sequence of commands read from an input file;
+X# expr_input is the input for the input() function;
+X# eval_input is the input for the eval() function.
+X
+X# NB: compound_stmt in single_input is followed by extra NEWLINE!
+Xsingle_input: NEWLINE | simple_stmt | compound_stmt NEWLINE
+Xfile_input: (NEWLINE | stmt)* ENDMARKER
+Xexpr_input: testlist NEWLINE
+Xeval_input: testlist ENDMARKER
+X
+Xfuncdef: 'def' NAME parameters ':' suite
+Xparameters: '(' [fplist] ')'
+Xfplist: fpdef (',' fpdef)*
+Xfpdef: NAME | '(' fplist ')'
+X
+Xstmt: simple_stmt | compound_stmt
+Xsimple_stmt: expr_stmt | print_stmt | pass_stmt | del_stmt | flow_stmt | import_stmt
+Xexpr_stmt: (exprlist '=')* exprlist NEWLINE
+X# For assignments, additional restrictions enforced by the interpreter
+Xprint_stmt: 'print' (test ',')* [test] NEWLINE
+Xdel_stmt: 'del' exprlist NEWLINE
+Xpass_stmt: 'pass' NEWLINE
+Xflow_stmt: break_stmt | return_stmt | raise_stmt
+Xbreak_stmt: 'break' NEWLINE
+Xreturn_stmt: 'return' [testlist] NEWLINE
+Xraise_stmt: 'raise' expr [',' expr] NEWLINE
+Ximport_stmt: 'import' NAME (',' NAME)* NEWLINE | 'from' NAME 'import' ('*' | NAME (',' NAME)*) NEWLINE
+Xcompound_stmt: if_stmt | while_stmt | for_stmt | try_stmt | funcdef | classdef
+Xif_stmt: 'if' test ':' suite ('elif' test ':' suite)* ['else' ':' suite]
+Xwhile_stmt: 'while' test ':' suite ['else' ':' suite]
+Xfor_stmt: 'for' exprlist 'in' exprlist ':' suite ['else' ':' suite]
+Xtry_stmt: 'try' ':' suite (except_clause ':' suite)* ['finally' ':' suite]
+Xexcept_clause: 'except' [expr [',' expr]]
+Xsuite: simple_stmt | NEWLINE INDENT NEWLINE* (stmt NEWLINE*)+ DEDENT
+X
+Xtest: and_test ('or' and_test)*
+Xand_test: not_test ('and' not_test)*
+Xnot_test: 'not' not_test | comparison
+Xcomparison: expr (comp_op expr)*
+Xcomp_op: '<'|'>'|'='|'>' '='|'<' '='|'<' '>'|'in'|'not' 'in'|'is'|'is' 'not'
+Xexpr: term (('+'|'-') term)*
+Xterm: factor (('*'|'/'|'%') factor)*
+Xfactor: ('+'|'-') factor | atom trailer*
+Xatom: '(' [testlist] ')' | '[' [testlist] ']' | '{' '}' | '`' testlist '`' | NAME | NUMBER | STRING
+Xtrailer: '(' [testlist] ')' | '[' subscript ']' | '.' NAME
+Xsubscript: expr | [expr] ':' [expr]
+Xexprlist: expr (',' expr)* [',']
+Xtestlist: test (',' test)* [',']
+X
+Xclassdef: 'class' NAME parameters ['=' baselist] ':' suite
+Xbaselist: atom arguments (',' atom arguments)*
+Xarguments: '(' [testlist] ')'
+EOF
+fi
+if test -s 'src/firstsets.c'
+then echo '*** I will not over-write existing file src/firstsets.c'
+else
+echo 'x - src/firstsets.c'
+sed 's/^X//' > 'src/firstsets.c' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/* Computation of FIRST stets */
+X
+X#include "pgenheaders.h"
+X#include "grammar.h"
+X#include "token.h"
+X
+Xextern int debugging;
+X
+X/* Forward */
+Xstatic void calcfirstset PROTO((grammar *, dfa *));
+X
+Xvoid
+Xaddfirstsets(g)
+X grammar *g;
+X{
+X int i;
+X dfa *d;
+X
+X printf("Adding FIRST sets ...\n");
+X for (i = 0; i < g->g_ndfas; i++) {
+X d = &g->g_dfa[i];
+X if (d->d_first == NULL)
+X calcfirstset(g, d);
+X }
+X}
+X
+Xstatic void
+Xcalcfirstset(g, d)
+X grammar *g;
+X dfa *d;
+X{
+X int i, j;
+X state *s;
+X arc *a;
+X int nsyms;
+X int *sym;
+X int nbits;
+X static bitset dummy;
+X bitset result;
+X int type;
+X dfa *d1;
+X label *l0;
+X
+X if (debugging)
+X printf("Calculate FIRST set for '%s'\n", d->d_name);
+X
+X if (dummy == NULL)
+X dummy = newbitset(1);
+X if (d->d_first == dummy) {
+X fprintf(stderr, "Left-recursion for '%s'\n", d->d_name);
+X return;
+X }
+X if (d->d_first != NULL) {
+X fprintf(stderr, "Re-calculating FIRST set for '%s' ???\n",
+X d->d_name);
+X }
+X d->d_first = dummy;
+X
+X l0 = g->g_ll.ll_label;
+X nbits = g->g_ll.ll_nlabels;
+X result = newbitset(nbits);
+X
+X sym = NEW(int, 1);
+X if (sym == NULL)
+X fatal("no mem for new sym in calcfirstset");
+X nsyms = 1;
+X sym[0] = findlabel(&g->g_ll, d->d_type, (char *)NULL);
+X
+X s = &d->d_state[d->d_initial];
+X for (i = 0; i < s->s_narcs; i++) {
+X a = &s->s_arc[i];
+X for (j = 0; j < nsyms; j++) {
+X if (sym[j] == a->a_lbl)
+X break;
+X }
+X if (j >= nsyms) { /* New label */
+X RESIZE(sym, int, nsyms + 1);
+X if (sym == NULL)
+X fatal("no mem to resize sym in calcfirstset");
+X sym[nsyms++] = a->a_lbl;
+X type = l0[a->a_lbl].lb_type;
+X if (ISNONTERMINAL(type)) {
+X d1 = finddfa(g, type);
+X if (d1->d_first == dummy) {
+X fprintf(stderr,
+X "Left-recursion below '%s'\n",
+X d->d_name);
+X }
+X else {
+X if (d1->d_first == NULL)
+X calcfirstset(g, d1);
+X mergebitset(result, d1->d_first, nbits);
+X }
+X }
+X else if (ISTERMINAL(type)) {
+X addbit(result, a->a_lbl);
+X }
+X }
+X }
+X d->d_first = result;
+X if (debugging) {
+X printf("FIRST set for '%s': {", d->d_name);
+X for (i = 0; i < nbits; i++) {
+X if (testbit(result, i))
+X printf(" %s", labelrepr(&l0[i]));
+X }
+X printf(" }\n");
+X }
+X}
+EOF
+fi
+if test -s 'src/frameobject.h'
+then echo '*** I will not over-write existing file src/frameobject.h'
+else
+echo 'x - src/frameobject.h'
+sed 's/^X//' > 'src/frameobject.h' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/* Frame object interface */
+X
+Xtypedef struct {
+X int b_type; /* what kind of block this is */
+X int b_handler; /* where to jump to find handler */
+X int b_level; /* value stack level to pop to */
+X} block;
+X
+Xtypedef struct _frame {
+X OB_HEAD
+X struct _frame *f_back; /* previous frame, or NULL */
+X codeobject *f_code; /* code segment */
+X object *f_globals; /* global symbol table (dictobject) */
+X object *f_locals; /* local symbol table (dictobject) */
+X object **f_valuestack; /* malloc'ed array */
+X block *f_blockstack; /* malloc'ed array */
+X int f_nvalues; /* size of f_valuestack */
+X int f_nblocks; /* size of f_blockstack */
+X int f_iblock; /* index in f_blockstack */
+X} frameobject;
+X
+X
+X/* Standard object interface */
+X
+Xextern typeobject Frametype;
+X
+X#define is_frameobject(op) ((op)->ob_type == &Frametype)
+X
+Xframeobject * newframeobject PROTO(
+X (frameobject *, codeobject *, object *, object *, int, int));
+X
+X
+X/* The rest of the interface is specific for frame objects */
+X
+X/* List access macros */
+X
+X#ifdef NDEBUG
+X#define GETITEM(v, i) GETLISTITEM((listobject *)(v), (i))
+X#define GETITEMNAME(v, i) GETSTRINGVALUE((stringobject *)GETITEM((v), (i)))
+X#else
+X#define GETITEM(v, i) getlistitem((v), (i))
+X#define GETITEMNAME(v, i) getstringvalue(getlistitem((v), (i)))
+X#endif
+X
+X#define GETUSTRINGVALUE(s) ((unsigned char *)GETSTRINGVALUE(s))
+X
+X/* Code access macros */
+X
+X#define Getconst(f, i) (GETITEM((f)->f_code->co_consts, (i)))
+X#define Getname(f, i) (GETITEMNAME((f)->f_code->co_names, (i)))
+X
+X
+X/* Block management functions */
+X
+Xvoid setup_block PROTO((frameobject *, int, int, int));
+Xblock *pop_block PROTO((frameobject *));
+EOF
+fi
+if test -s 'src/funcobject.c'
+then echo '*** I will not over-write existing file src/funcobject.c'
+else
+echo 'x - src/funcobject.c'
+sed 's/^X//' > 'src/funcobject.c' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/* Function object implementation */
+X
+X#include "allobjects.h"
+X
+X#include "structmember.h"
+X
+Xtypedef struct {
+X OB_HEAD
+X object *func_code;
+X object *func_globals;
+X} funcobject;
+X
+Xobject *
+Xnewfuncobject(code, globals)
+X object *code;
+X object *globals;
+X{
+X funcobject *op = NEWOBJ(funcobject, &Functype);
+X if (op != NULL) {
+X INCREF(code);
+X op->func_code = code;
+X INCREF(globals);
+X op->func_globals = globals;
+X }
+X return (object *)op;
+X}
+X
+Xobject *
+Xgetfunccode(op)
+X object *op;
+X{
+X if (!is_funcobject(op)) {
+X err_badcall();
+X return NULL;
+X }
+X return ((funcobject *) op) -> func_code;
+X}
+X
+Xobject *
+Xgetfuncglobals(op)
+X object *op;
+X{
+X if (!is_funcobject(op)) {
+X err_badcall();
+X return NULL;
+X }
+X return ((funcobject *) op) -> func_globals;
+X}
+X
+X/* Methods */
+X
+X#define OFF(x) offsetof(funcobject, x)
+X
+Xstatic struct memberlist func_memberlist[] = {
+X {"func_code", T_OBJECT, OFF(func_code)},
+X {"func_globals",T_OBJECT, OFF(func_globals)},
+X {NULL} /* Sentinel */
+X};
+X
+Xstatic object *
+Xfunc_getattr(op, name)
+X funcobject *op;
+X char *name;
+X{
+X return getmember((char *)op, func_memberlist, name);
+X}
+X
+Xstatic void
+Xfunc_dealloc(op)
+X funcobject *op;
+X{
+X DECREF(op->func_code);
+X DECREF(op->func_globals);
+X DEL(op);
+X}
+X
+Xtypeobject Functype = {
+X OB_HEAD_INIT(&Typetype)
+X 0,
+X "function",
+X sizeof(funcobject),
+X 0,
+X func_dealloc, /*tp_dealloc*/
+X 0, /*tp_print*/
+X func_getattr, /*tp_getattr*/
+X 0, /*tp_setattr*/
+X 0, /*tp_compare*/
+X 0, /*tp_repr*/
+X};
+EOF
+fi
+if test -s 'src/grammar.h'
+then echo '*** I will not over-write existing file src/grammar.h'
+else
+echo 'x - src/grammar.h'
+sed 's/^X//' > 'src/grammar.h' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/* Grammar interface */
+X
+X#include "bitset.h" /* Sigh... */
+X
+X/* A label of an arc */
+X
+Xtypedef struct _label {
+X int lb_type;
+X char *lb_str;
+X} label;
+X
+X#define EMPTY 0 /* Label number 0 is by definition the empty label */
+X
+X/* A list of labels */
+X
+Xtypedef struct _labellist {
+X int ll_nlabels;
+X label *ll_label;
+X} labellist;
+X
+X/* An arc from one state to another */
+X
+Xtypedef struct _arc {
+X short a_lbl; /* Label of this arc */
+X short a_arrow; /* State where this arc goes to */
+X} arc;
+X
+X/* A state in a DFA */
+X
+Xtypedef struct _state {
+X int s_narcs;
+X arc *s_arc; /* Array of arcs */
+X
+X /* Optional accelerators */
+X int s_lower; /* Lowest label index */
+X int s_upper; /* Highest label index */
+X int *s_accel; /* Accelerator */
+X int s_accept; /* Nonzero for accepting state */
+X} state;
+X
+X/* A DFA */
+X
+Xtypedef struct _dfa {
+X int d_type; /* Non-terminal this represents */
+X char *d_name; /* For printing */
+X int d_initial; /* Initial state */
+X int d_nstates;
+X state *d_state; /* Array of states */
+X bitset d_first;
+X} dfa;
+X
+X/* A grammar */
+X
+Xtypedef struct _grammar {
+X int g_ndfas;
+X dfa *g_dfa; /* Array of DFAs */
+X labellist g_ll;
+X int g_start; /* Start symbol of the grammar */
+X int g_accel; /* Set if accelerators present */
+X} grammar;
+X
+X/* FUNCTIONS */
+X
+Xgrammar *newgrammar PROTO((int start));
+Xdfa *adddfa PROTO((grammar *g, int type, char *name));
+Xint addstate PROTO((dfa *d));
+Xvoid addarc PROTO((dfa *d, int from, int to, int lbl));
+Xdfa *finddfa PROTO((grammar *g, int type));
+Xchar *typename PROTO((grammar *g, int lbl));
+X
+Xint addlabel PROTO((labellist *ll, int type, char *str));
+Xint findlabel PROTO((labellist *ll, int type, char *str));
+Xchar *labelrepr PROTO((label *lb));
+Xvoid translatelabels PROTO((grammar *g));
+X
+Xvoid addfirstsets PROTO((grammar *g));
+X
+Xvoid addaccellerators PROTO((grammar *g));
+X
+Xvoid printgrammar PROTO((grammar *g, FILE *fp));
+Xvoid printnonterminals PROTO((grammar *g, FILE *fp));
+EOF
+fi
+if test -s 'src/intobject.h'
+then echo '*** I will not over-write existing file src/intobject.h'
+else
+echo 'x - src/intobject.h'
+sed 's/^X//' > 'src/intobject.h' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/* Integer object interface */
+X
+X/*
+X123456789-123456789-123456789-123456789-123456789-123456789-123456789-12
+X
+Xintobject represents a (long) integer. This is an immutable object;
+Xan integer cannot change its value after creation.
+X
+XThere are functions to create new integer objects, to test an object
+Xfor integer-ness, and to get the integer value. The latter functions
+Xreturns -1 and sets errno to EBADF if the object is not an intobject.
+XNone of the functions should be applied to nil objects.
+X
+XThe type intobject is (unfortunately) exposed bere so we can declare
+XTrueObject and FalseObject below; don't use this.
+X*/
+X
+Xtypedef struct {
+X OB_HEAD
+X long ob_ival;
+X} intobject;
+X
+Xextern typeobject Inttype;
+X
+X#define is_intobject(op) ((op)->ob_type == &Inttype)
+X
+Xextern object *newintobject PROTO((long));
+Xextern long getintvalue PROTO((object *));
+X
+X
+X/*
+X123456789-123456789-123456789-123456789-123456789-123456789-123456789-12
+X
+XFalse and True are special intobjects used by Boolean expressions.
+XAll values of type Boolean must point to either of these; but in
+Xcontexts where integers are required they are integers (valued 0 and 1).
+XHope these macros don't conflict with other people's.
+X
+XDon't forget to apply INCREF() when returning True or False!!!
+X*/
+X
+Xextern intobject FalseObject, TrueObject; /* Don't use these directly */
+X
+X#define False ((object *) &FalseObject)
+X#define True ((object *) &TrueObject)
+X
+X/* Macro, trading safety for speed */
+X#define GETINTVALUE(op) ((op)->ob_ival)
+EOF
+fi
+if test -s 'src/intrcheck.c'
+then echo '*** I will not over-write existing file src/intrcheck.c'
+else
+echo 'x - src/intrcheck.c'
+sed 's/^X//' > 'src/intrcheck.c' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/* Check for interrupts */
+X
+X#ifdef MSDOS
+X
+X/* This might work for MS-DOS (untested though): */
+X
+Xvoid
+Xinitintr()
+X{
+X}
+X
+Xint
+Xintrcheck()
+X{
+X int interrupted = 0;
+X while (kbhit()) {
+X if (getch() == '\003')
+X interrupted = 1;
+X }
+X return interrupted;
+X}
+X
+X#define OK
+X
+X#endif
+X
+X
+X#ifdef THINK_C
+X
+X/* This is for THINK C 4.0.
+X For 3.0, you may have to remove the signal stuff. */
+X
+X#include <MacHeaders>
+X#include <signal.h>
+X#include "sigtype.h"
+X
+Xstatic int interrupted;
+X
+Xstatic SIGTYPE
+Xintcatcher(sig)
+X int sig;
+X{
+X interrupted = 1;
+X signal(SIGINT, intcatcher);
+X}
+X
+Xvoid
+Xinitintr()
+X{
+X if (signal(SIGINT, SIG_IGN) != SIG_IGN)
+X signal(SIGINT, intcatcher);
+X}
+X
+Xint
+Xintrcheck()
+X{
+X register EvQElPtr q;
+X
+X /* This is like THINK C 4.0's <console.h>.
+X I'm not sure why FlushEvents must be called from asm{}. */
+X for (q = (EvQElPtr)EventQueue.qHead; q; q = (EvQElPtr)q->qLink) {
+X if (q->evtQWhat == keyDown &&
+X (char)q->evtQMessage == '.' &&
+X (q->evtQModifiers & cmdKey) != 0) {
+X
+X asm {
+X moveq #keyDownMask,d0
+X _FlushEvents
+X }
+X interrupted = 1;
+X break;
+X }
+X }
+X if (interrupted) {
+X interrupted = 0;
+X return 1;
+X }
+X return 0;
+X}
+X
+X#define OK
+X
+X#endif /* THINK_C */
+X
+X
+X#ifndef OK
+X
+X/* Default version -- for real operating systems and for Standard C */
+X
+X#include <stdio.h>
+X#include <signal.h>
+X#include "sigtype.h"
+X
+Xstatic int interrupted;
+X
+Xstatic SIGTYPE
+Xintcatcher(sig)
+X int sig;
+X{
+X interrupted = 1;
+X signal(SIGINT, intcatcher);
+X}
+X
+Xvoid
+Xinitintr()
+X{
+X if (signal(SIGINT, SIG_IGN) != SIG_IGN)
+X signal(SIGINT, intcatcher);
+X}
+X
+Xint
+Xintrcheck()
+X{
+X if (!interrupted)
+X return 0;
+X interrupted = 0;
+X return 1;
+X}
+X
+X#endif /* !OK */
+EOF
+fi
+if test -s 'src/profmain.c'
+then echo '*** I will not over-write existing file src/profmain.c'
+else
+echo 'x - src/profmain.c'
+sed 's/^X//' > 'src/profmain.c' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X#include <stdio.h>
+X#include "string.h"
+X
+X#include "PROTO.h"
+X#include "grammar.h"
+X#include "node.h"
+X#include "parsetok.h"
+X#include "graminit.h"
+X#include "tokenizer.h"
+X#include "errcode.h"
+X#include "malloc.h"
+X
+Xextern int _profile;
+X
+Xextern grammar gram; /* From graminit.c */
+X
+Xint debugging = 1;
+X
+XFILE *getopenfile()
+X{
+X char buf[256];
+X char *p;
+X FILE *fp;
+X for (;;) {
+X fprintf(stderr, "File name: ");
+X if (fgets(buf, sizeof buf, stdin) == NULL) {
+X fprintf(stderr, "EOF\n");
+X exit(1);
+X }
+X p = strchr(buf, '\n');
+X if (p != NULL)
+X *p = '\0';
+X if ((fp = fopen(buf, "r")) != NULL)
+X break;
+X fprintf(stderr, "Sorry, try again.\n");
+X }
+X return fp;
+X}
+X
+Xmain()
+X{
+X FILE *fp;
+X _profile = 0;
+X fp = getopenfile();
+X#if 0
+X askgo("Start tokenizing");
+X runtokenizer(fp);
+X fseek(fp, 0L, 0);
+X#endif
+X if (!gram.g_accel)
+X addaccelerators(&gram);
+X askgo("Start parsing");
+X _profile = 1;
+X runparser(fp);
+X _profile = 0;
+X freopen("prof.out", "w", stdout);
+X DumpProfile();
+X fflush(stdout);
+X exit(0);
+X}
+X
+Xstatic int
+Xruntokenizer(fp)
+X FILE *fp;
+X{
+X struct tok_state *tok;
+X tok = tok_setupf(fp, "Tokenizing", ".");
+X for (;;) {
+X char *a, *b;
+X register char *str;
+X register int len;
+X (void) tok_get(tok, &a, &b);
+X if (tok->done != E_OK)
+X break;
+X len = b - a;
+X str = NEW(char, len + 1);
+X if (str == NULL) {
+X fprintf(stderr, "no mem for next token");
+X break;
+X }
+X strncpy(str, a, len);
+X str[len] = '\0';
+X }
+X fprintf(stderr, "done (%d)\n", tok->done);
+X}
+X
+Xstatic
+Xrunparser(fp, start)
+X FILE *fp;
+X{
+X node *n;
+X int ret;
+X ret = parsefile(fp, &gram, module_input, "Parsing", ".", &n);
+X fprintf(stderr, "done (%d)\n", ret);
+X#if 0
+X _profile = 0;
+X if (ret == E_DONE)
+X listtree(n);
+X#endif
+X}
+X
+Xstatic int
+Xaskgo(prompt)
+X char *prompt;
+X{
+X char buf[256];
+X fprintf(stderr, "%s: hit return when ready: ", prompt);
+X fgets(buf, sizeof buf, stdin);
+X}
+EOF
+fi
+if test -s 'src/strtol.c'
+then echo '*** I will not over-write existing file src/strtol.c'
+else
+echo 'x - src/strtol.c'
+sed 's/^X//' > 'src/strtol.c' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/*
+X** strtol
+X** This is a general purpose routine for converting
+X** an ascii string to an integer in an arbitrary base.
+X** Leading white space is ignored, if 'base' is zero
+X** it looks for a leading 0, 0x or 0X to tell which
+X** base. If these are absent it defaults to 10.
+X** Base must be between 0 and 36.
+X** If 'ptr' is non-NULL it will contain a pointer to
+X** the end of the scan.
+X** Errors due to bad pointers will probably result in
+X** exceptions - we don't check for them.
+X*/
+X
+X#include "ctype.h"
+X
+Xlong
+Xstrtol(str, ptr, base)
+Xregister char * str;
+Xchar ** ptr;
+Xint base;
+X{
+X register long result; /* return value of the function */
+X register int c; /* current input character */
+X int minus; /* true if a leading minus was found */
+X
+X result = 0;
+X minus = 0;
+X
+X/* catch silly bases */
+X if (base < 0 || base > 36)
+X {
+X if (ptr)
+X *ptr = str;
+X return result;
+X }
+X
+X/* skip leading white space */
+X while (*str && isspace(*str))
+X str++;
+X
+X/* check for optional leading minus sign */
+X if (*str == '-')
+X {
+X minus = 1;
+X str++;
+X }
+X
+X/* check for leading 0 or 0x for auto-base or base 16 */
+X switch (base)
+X {
+X case 0: /* look for leading 0, 0x or 0X */
+X if (*str == '0')
+X {
+X str++;
+X if (*str == 'x' || *str == 'X')
+X {
+X str++;
+X base = 16;
+X }
+X else
+X base = 8;
+X }
+X else
+X base = 10;
+X break;
+X
+X case 16: /* skip leading 0x or 0X */
+X if (*str == '0' && (*(str+1) == 'x' || *(str+1) == 'X'))
+X str += 2;
+X break;
+X }
+X
+X/* do the conversion */
+X while (c = *str)
+X {
+X if (isdigit(c) && c - '0' < base)
+X c -= '0';
+X else
+X {
+X if (isupper(c))
+X c = tolower(c);
+X if (c >= 'a' && c <= 'z')
+X c -= 'a' - 10;
+X else /* non-"digit" character */
+X break;
+X if (c >= base) /* non-"digit" character */
+X break;
+X }
+X result = result * base + c;
+X str++;
+X }
+X
+X/* set pointer to point to the last character scanned */
+X if (ptr)
+X *ptr = str;
+X return minus ? -result : result;
+X}
+EOF
+fi
+echo 'Part 17 out of 21 of pack.out complete.'
+exit 0
diff --git a/shar/python-0.9.1-18-21.shar b/shar/python-0.9.1-18-21.shar
new file mode 100644
index 0000000..6b566e7
--- /dev/null
+++ b/shar/python-0.9.1-18-21.shar
@@ -0,0 +1,2268 @@
+: This is a shell archive.
+: Extract with 'sh this_file'.
+:
+: Extract part 01 first since it makes all directories
+echo 'Start of pack.out, part 18 out of 21:'
+if test -s 'demo/sgi/gl/backface.py'
+then echo '*** I will not over-write existing file demo/sgi/gl/backface.py'
+else
+echo 'x - demo/sgi/gl/backface.py'
+sed 's/^X//' > 'demo/sgi/gl/backface.py' << 'EOF'
+X#! /ufs/guido/bin/sgi/python
+X
+X# backface
+X#
+X# draw a cube that can run with backface() turned on or off.
+X# cube is moved when LEFTMOUSE is pressed and mouse itself is moved.
+X
+Xfrom gl import *
+Xfrom DEVICE import *
+Xfrom GL import *
+X
+XCUBE_SIZE = 200.0
+XCUBE_OBJ = 1
+X
+Xdef main () :
+X #
+X x = 0
+X y = 0
+X moveit = 0
+X #
+X initialize()
+X #
+X while (1) :
+X #
+X while (qtest()) :
+X dev, val = qread()
+X #
+X if dev = ESCKEY :
+X backface(0)
+X return
+X #
+X elif dev = REDRAW :
+X reshapeviewport()
+X drawcube(x,y)
+X #
+X elif dev = LEFTMOUSE :
+X #
+X # LEFTMOUSE down
+X moveit = val
+X #
+X elif dev = BKEY :
+X backface(1)
+X drawcube(x,y)
+X #
+X elif dev = FKEY :
+X backface(0)
+X drawcube(x,y)
+X #
+X if moveit :
+X x = getvaluator(MOUSEX)
+X y = getvaluator(MOUSEY)
+X drawcube(x,y)
+X
+X
+Xdef initialize () :
+X foreground ()
+X keepaspect (1, 1)
+X gid = winopen('backface')
+X winset(gid)
+X winconstraints()
+X #
+X doublebuffer()
+X gconfig()
+X shademodel(FLAT)
+X #
+X ortho(-1024.0, 1024.0, -1024.0, 1024.0, -1024.0, 1024.0)
+X #
+X qdevice(ESCKEY)
+X qdevice(REDRAW)
+X qdevice(LEFTMOUSE)
+X qdevice(BKEY)
+X qdevice(FKEY)
+X qenter(REDRAW,gid)
+X #
+X backface(1)
+X
+X#
+X# define a cube
+Xdef cube () :
+X #
+X # front face
+X pushmatrix()
+X translate(0.0,0.0,CUBE_SIZE)
+X color(RED)
+X rectf(-CUBE_SIZE,-CUBE_SIZE,CUBE_SIZE,CUBE_SIZE)
+X popmatrix()
+X #
+X # right face
+X pushmatrix()
+X translate(CUBE_SIZE, 0.0, 0.0)
+X rotate(900, 'y')
+X color(GREEN)
+X rectf(-CUBE_SIZE,-CUBE_SIZE,CUBE_SIZE,CUBE_SIZE)
+X popmatrix()
+X #
+X # back face
+X pushmatrix()
+X translate(0.0, 0.0, -CUBE_SIZE)
+X rotate(1800, 'y')
+X color(BLUE)
+X rectf(-CUBE_SIZE,-CUBE_SIZE,CUBE_SIZE,CUBE_SIZE)
+X popmatrix()
+X #
+X # left face
+X pushmatrix()
+X translate(-CUBE_SIZE, 0.0, 0.0)
+X rotate(-900, 'y')
+X color(CYAN)
+X rectf(-CUBE_SIZE,-CUBE_SIZE,CUBE_SIZE,CUBE_SIZE)
+X popmatrix()
+X #
+X # top face
+X pushmatrix()
+X translate(0.0, CUBE_SIZE, 0.0)
+X rotate(-900, 'x')
+X color(MAGENTA)
+X rectf(-CUBE_SIZE,-CUBE_SIZE,CUBE_SIZE,CUBE_SIZE)
+X popmatrix()
+X #
+X # bottom face
+X pushmatrix()
+X translate(0.0, -CUBE_SIZE, 0.0)
+X rotate(900, 'x')
+X color(YELLOW)
+X rectf(-CUBE_SIZE,-CUBE_SIZE,CUBE_SIZE,CUBE_SIZE)
+X popmatrix()
+X
+Xdef drawcube(x,y) :
+X #
+X pushmatrix()
+X rotate(2*x, 'x')
+X rotate(2*y, 'y')
+X color(BLACK)
+X clear()
+X cube()
+X popmatrix()
+X swapbuffers()
+X
+X
+Xmain ()
+EOF
+chmod +x 'demo/sgi/gl/backface.py'
+fi
+if test -s 'demo/sgi/gl/mclock.doc'
+then echo '*** I will not over-write existing file demo/sgi/gl/mclock.doc'
+else
+echo 'x - demo/sgi/gl/mclock.doc'
+sed 's/^X//' > 'demo/sgi/gl/mclock.doc' << 'EOF'
+XNewsgroups: cwi.sgi
+XSubject: Re: new clock
+XDistribution: cwi.sgi
+XReferences: <[email protected]>
+X
+XLast week I wrote:
+X
+X>For your enjoyment I have implemented a colorful clock.
+X
+XThe clock has now been extended with some new facilities: a menu, an
+Xalarm and a gong. These may require some explanation beyond what's in
+Xthe usage message.
+X
+XMenu
+X----
+XThe right mouse button now pops up a menu that allows you to turn the
+Xseconds hand on or off and to switch the alarm off.
+X
+XAlarm
+X-----
+X
+XThe left and middle buttons set the alarm. When it is on, the alarm
+Xtime is displayed as a time on a 24 hour clock in the bottom left
+Xcorner. It is also indicated by two red triangles, corresponding to the
+Xlittle (hours) and big (minutes) hand. These hands can be moved around:
+Xthe left mouse button moves the minutes hand, the middle button moves
+Xthe hourds hand. Watch out for differences of twelve hours (always
+Xcheck the digital display); these can be corrected by dragging the hours
+Xhand once around the dial.
+X
+XWhen the alarm goes off, two things happen: a shell command specified on
+Xthe command line with the -a option is executed (in the background), and
+Xthe clock's colors change every two seconds, for five minutes. You can
+Xalso turn the alarm off by using the menu accessible through the right
+Xmouse button.
+X
+XThere is no default command for the -a option; if it is not specified,
+Xonly the changing of the colors happens. If you have an 8 ohm speaker
+Xconnected to the audio output of your Personal Iris, a suitable command
+Xwould be:
+X
+X mclock -a '/ufs/guido/bin/sgi/play /ufs/guido/lib/sounds/alarm'
+X
+XGong
+X----
+X
+XSome people like a clock that makes noises every hour, or even more
+Xoften. This is supported by the -g and -G options. With -g you specify
+Xa shell command to be executed to sound the gong; with -G you can
+Xspecify the interval between gong calls, in seconds (default is one hour).
+XThe shell command is executed in the background. It is given two
+Xarguments: the hours (on a 24 hour clock!) and the minutes. The
+Xexecutable Python script /ufs/guido/bin/sgi/chime is a suitable example.
+XAgain, this only works if you have installed a speaker (I bet 8 ohm
+Xspeakers are going to be in demand!)
+X
+X--
+XGuido van Rossum, Centre for Mathematics and Computer Science (CWI), Amsterdam
[email protected] or ..!hp4nl!cwi.nl!guido or guido%[email protected]
+X"A thing of beauty is a joy till sunrise"
+EOF
+fi
+if test -s 'demo/sgi/gl/mixing.py'
+then echo '*** I will not over-write existing file demo/sgi/gl/mixing.py'
+else
+echo 'x - demo/sgi/gl/mixing.py'
+sed 's/^X//' > 'demo/sgi/gl/mixing.py' << 'EOF'
+X#! /ufs/guido/bin/sgi/python
+X
+X# Use Gouraud shading to mix colors. Requires Z-buffer.
+X# It changes the color assignments so fast that you see white.
+X# Left button pauses, middle rotates the square. ESC to quit.
+X# Experiment with a larger window (too slow) or smaller window (really white).
+X
+Xfrom GL import *
+Xfrom gl import *
+Ximport DEVICE
+Xfrom math import *
+X
+X#
+X# tekenvlak : draw a square. with bgnpolygon
+X#
+Xdef tekenvlak (vc) :
+X bgnpolygon()
+X #vcarray (vc)
+X for i in vc :
+X c3f (i[1])
+X v3f (i[0])
+X endpolygon()
+X
+X#
+X# tekendoos : draw a box
+X#
+Xdef tekendoos (col) :
+X v = [(-5.0,0.0,0.0),(0.0,5.0,0.0),(5.0,0.0,0.0),(0.0,-5.0,0.0)]
+X vc = [(v[0],col[0]),(v[1],col[1]),(v[2],col[2]),(v[3],col[1])]
+X tekenvlak (vc)
+X
+X#
+X# initialize gl
+X#
+Xdef initgl () :
+X #
+X # open window
+X #
+X foreground ()
+X keepaspect (1, 1)
+X prefposition (100, 500, 100, 500)
+X w = winopen ('PYTHON RGB')
+X keepaspect (1, 1)
+X winconstraints()
+X #
+X # configure pipeline (2buf, GOURAUD and RGBmode)
+X #
+X doublebuffer ()
+X zbuffer (1)
+X shademodel (GOURAUD)
+X RGBmode ()
+X gconfig ()
+X #
+X # set viewing
+X #
+X perspective (900, 1, 1.0, 10.0)
+X polarview (10.0, 0, 0, 0)
+X #
+X # ask for the REDRAW and ESCKEY events
+X #
+X qdevice(DEVICE.MOUSE2)
+X qdevice(DEVICE.MOUSE3)
+X qdevice(DEVICE.REDRAW)
+X qdevice(DEVICE.ESCKEY)
+X
+X
+X#
+X# the color black
+X#
+Xblack = 0
+X#
+X# GoForIT : use 2buf to redraw the object 2n times. index i is used as
+X# the (smoothly changing) rotation angle
+X#
+Xdef GoForIt(i) :
+X col = [(255.0,0.0,0.0), (0.0,255.0,0.0), (0.0,0.0,255.0)]
+X twist = 0
+X freeze = 1
+X while 1 :
+X if freeze <> 0 :
+X col[0],col[1],col[2] = col[1],col[2],col[0]
+X #
+X # clear z-buffer and clear background to light-blue
+X #
+X zclear()
+X cpack (black)
+X clear()
+X #
+X tekendoos (col)
+X #
+X swapbuffers()
+X #
+X if qtest() <> 0 :
+X dev, val = qread()
+X if dev = DEVICE.ESCKEY :
+X break
+X elif dev = DEVICE.REDRAW :
+X reshapeviewport ()
+X elif dev = DEVICE.MOUSE2 and val <> 0 :
+X twist = twist + 30
+X perspective (900, 1, 1.0, 10.0)
+X polarview (10.0, 0, 0, twist)
+X elif dev = DEVICE.MOUSE3 and val <> 0 :
+X freeze = 1 - freeze
+X
+X
+X# the main program
+X#
+Xdef main () :
+X initgl ()
+X GoForIt (0)
+X
+X#
+X# exec main
+X#
+Xmain ()
+EOF
+chmod +x 'demo/sgi/gl/mixing.py'
+fi
+if test -s 'demo/sgi/gl_panel/twoview/observer.s'
+then echo '*** I will not over-write existing file demo/sgi/gl_panel/twoview/observer.s'
+else
+echo 'x - demo/sgi/gl_panel/twoview/observer.s'
+sed 's/^X//' > 'demo/sgi/gl_panel/twoview/observer.s' << 'EOF'
+X;;; This file was automatically generated by the panel editor.
+X;;; If you read it into gnu emacs, it will automagically format itself.
+X
+X(panel (prop help creator:user-panel-help)
+X(prop user-panel #t)
+X(label "Observer Control")
+X(x 876)
+X(y 10)
+X(al (pnl_right_arrow_button (name "right")
+X(prop help creator:user-act-help)
+X(x 3.2)
+X(y 2.09)
+X(downfunc move-then-resize)
+X)
+X(pnl_up_double_arrow_button (name "fast_forward")
+X(prop help creator:user-act-help)
+X(label "step forward")
+X(x 2.66)
+X(y 3.13)
+X(h 0.45)
+X(labeltype 4)
+X(downfunc move-then-resize)
+X)
+X(pnl_up_arrow_button (name "forward")
+X(prop help creator:user-act-help)
+X(x 2.66)
+X(y 2.64)
+X(downfunc move-then-resize)
+X)
+X(pnl_down_arrow_button (name "reverse")
+X(prop help creator:user-act-help)
+X(x 2.66)
+X(y 1.49)
+X(h 0.45)
+X(labeltype 12)
+X(downfunc move-then-resize)
+X)
+X(pnl_down_double_arrow_button (name "fast_reverse")
+X(prop help creator:user-act-help)
+X(label "step back")
+X(x 2.66)
+X(y 1)
+X(labeltype 12)
+X(downfunc move-then-resize)
+X)
+X(pnl_left_arrow_button (name "left")
+X(prop help creator:user-act-help)
+X(x 2.11)
+X(y 2.09)
+X(downfunc move-then-resize)
+X)
+X(pnl_right_double_arrow_button (name "fast_right")
+X(prop help creator:user-act-help)
+X(label "turn right")
+X(x 3.75)
+X(y 2.09)
+X(downfunc move-then-resize)
+X)
+X(pnl_left_double_arrow_button (name "fast_left")
+X(prop help creator:user-act-help)
+X(label "turn left")
+X(x 1.57)
+X(y 2.09)
+X(labeltype 8)
+X(downfunc move-then-resize)
+X)
+X(pnl_vslider (name "ypos")
+X(prop help creator:user-act-help)
+X(x 6.25)
+X(y 1)
+X(w 0.4)
+X(h 2.9)
+X(val 0.0758)
+X(downfunc move-then-resize)
+X)
+X(pnl_down_arrow_button (name "down")
+X(prop help creator:user-act-help)
+X(label "eye height")
+X(x 6.25)
+X(y 0.5)
+X(labeltype 12)
+X(downfunc move-then-resize)
+X)
+X(pnl_up_arrow_button (name "up")
+X(prop help creator:user-act-help)
+X(x 6.25)
+X(y 4)
+X(downfunc move-then-resize)
+X)
+X)
+X)
+X;;; Local Variables:
+X;;; mode: scheme
+X;;; eval: (save-excursion (goto-char (point-min)) (kill-line 3))
+X;;; eval: (save-excursion (goto-char (point-min)) (replace-regexp "[ \n]*)" ")"))
+X;;; eval: (indent-region (point-min) (point-max) nil)
+X;;; eval: (progn (kill-line -3) (delete-backward-char 1) (save-buffer))
+X;;; End:
+EOF
+fi
+if test -s 'lib/CSplit.py'
+then echo '*** I will not over-write existing file lib/CSplit.py'
+else
+echo 'x - lib/CSplit.py'
+sed 's/^X//' > 'lib/CSplit.py' << 'EOF'
+X# A CSplit is a Clock-shaped split: the children are grouped in a circle.
+X# The numbering is a little different from a real clock: the 12 o'clock
+X# position is called 0, not 12. This is a little easier since Python
+X# usually counts from zero. (BTW, there needn't be exactly 12 children.)
+X
+X
+Xfrom math import pi, sin, cos
+Xfrom Split import Split
+X
+Xclass CSplit() = Split():
+X #
+X def minsize(self, m):
+X # Since things look best if the children are spaced evenly
+X # along the circle (and often all children have the same
+X # size anyway) we compute the max child size and assume
+X # this is each child's size.
+X width, height = 0, 0
+X for child in self.children:
+X wi, he = child.minsize(m)
+X width = max(width, wi)
+X height = max(height, he)
+X # In approximation, the diameter of the circle we need is
+X # (diameter of box) * (#children) / pi.
+X # We approximate pi by 3 (so we slightly overestimate
+X # our minimal size requirements -- not so bad).
+X # Because the boxes stick out of the circle we add the
+X # box size to each dimension.
+X # Because we really deal with ellipses, do everything
+X # separate in each dimension.
+X n = len(self.children)
+X return width + (width*n + 2)/3, height + (height*n + 2)/3
+X #
+X def getbounds(self):
+X return self.bounds
+X #
+X def setbounds(self, bounds):
+X self.bounds = bounds
+X # Place the children. This involves some math.
+X # Compute center positions for children as if they were
+X # ellipses with a diameter about 1/N times the
+X # circumference of the big ellipse.
+X # (There is some rounding involved to make it look
+X # reasonable for small and large N alike.)
+X # XXX One day Python will have automatic conversions...
+X n = len(self.children)
+X fn = float(n)
+X if n = 0: return
+X (left, top), (right, bottom) = bounds
+X width, height = right-left, bottom-top
+X child_width, child_height = width*3/(n+4), height*3/(n+4)
+X half_width, half_height = \
+X float(width-child_width)/2.0, \
+X float(height-child_height)/2.0
+X center_h, center_v = center = (left+right)/2, (top+bottom)/2
+X fch, fcv = float(center_h), float(center_v)
+X alpha = 2.0 * pi / fn
+X for i in range(n):
+X child = self.children[i]
+X fi = float(i)
+X fh, fv = \
+X fch + half_width*sin(fi*alpha), \
+X fcv - half_height*cos(fi*alpha)
+X left, top = \
+X int(fh) - child_width/2, \
+X int(fv) - child_height/2
+X right, bottom = \
+X left + child_width, \
+X top + child_height
+X child.setbounds((left, top), (right, bottom))
+X #
+EOF
+fi
+if test -s 'lib/TransParent.py'
+then echo '*** I will not over-write existing file lib/TransParent.py'
+else
+echo 'x - lib/TransParent.py'
+sed 's/^X//' > 'lib/TransParent.py' << 'EOF'
+X# A class that sits transparently between a parent and one child.
+X# First create the parent, then this thing, then the child.
+X# Use this as a base class for objects that are almost transparent.
+X# Don't use as a base class for parents with multiple children.
+X
+XError = 'TransParent.Error' # Exception
+X
+Xclass ManageOneChild():
+X #
+X # Upcalls shared with other single-child parents
+X #
+X def addchild(self, child):
+X if self.child:
+X raise Error, 'addchild: one child only'
+X if not child:
+X raise Error, 'addchild: bad child'
+X self.child = child
+X #
+X def delchild(self, child):
+X if not self.child:
+X raise Error, 'delchild: no child'
+X if child <> self.child:
+X raise Error, 'delchild: not my child'
+X self.child = 0
+X
+Xclass TransParent() = ManageOneChild():
+X #
+X # Calls from creator
+X # NB derived classes may add parameters to create()
+X #
+X def create(self, parent):
+X parent.addchild(self)
+X self.parent = parent
+X self.child = 0 # No child yet
+X #
+X # Downcalls from parent to child
+X #
+X def destroy(self):
+X del self.parent
+X if self.child: self.child.destroy()
+X del self.child
+X #
+X def minsize(self, m):
+X if not self.child:
+X return 0, 0
+X else:
+X return self.child.minsize(m)
+X def getbounds(self, bounds):
+X if not self.child:
+X raise Error, 'getbounds w/o child'
+X else:
+X return self.child.getbounds()
+X def setbounds(self, bounds):
+X if not self.child:
+X raise Error, 'setbounds w/o child'
+X else:
+X self.child.setbounds(bounds)
+X def draw(self, args):
+X if self.child:
+X self.child.draw(args)
+X #
+X # Downcalls only made after certain upcalls
+X #
+X def mouse_down(self, detail):
+X if self.child: self.child.mouse_down(detail)
+X def mouse_move(self, detail):
+X if self.child: self.child.mouse_move(detail)
+X def mouse_up(self, detail):
+X if self.child: self.child.mouse_up(detail)
+X #
+X def timer(self):
+X if self.child: self.child.timer()
+X #
+X # Upcalls from child to parent
+X #
+X def need_mouse(self, child):
+X self.parent.need_mouse(self)
+X def no_mouse(self, child):
+X self.parent.no_mouse(self)
+X #
+X def need_timer(self, child):
+X self.parent.need_timer(self)
+X def no_timer(self, child):
+X self.parent.no_timer(self)
+X #
+X def begindrawing(self):
+X return self.parent.begindrawing()
+X def beginmeasuring(self):
+X return self.parent.beginmeasuring()
+X #
+X def change(self, area):
+X self.parent.change(area)
+X def scroll(self, args):
+X self.parent.scroll(args)
+X def settimer(self, itimer):
+X self.parent.settimer(itimer)
+EOF
+fi
+if test -s 'lib/auds.py'
+then echo '*** I will not over-write existing file lib/auds.py'
+else
+echo 'x - lib/auds.py'
+sed 's/^X//' > 'lib/auds.py' << 'EOF'
+Ximport audio
+X
+XRATE = 8192
+X
+X# Initialize the audio stuff
+Xaudio.setrate(3)
+Xaudio.setoutgain(100) # for speaker
+X
+Xplay = audio.write
+X
+Xdef samp(n):
+X savegain = audio.getoutgain()
+X try:
+X audio.setoutgain(0)
+X x = raw_input('Hit Enter to sample ' + `n` + ' seconds: ')
+X return audio.read(n*RATE)
+X finally:
+X audio.setoutgain(savegain)
+X
+Xdef echo(s, delay, gain):
+X return s[:delay] + audio.add(s[delay:], audio.amplify(s, gain, gain))
+X
+Xdef save(s, file):
+X f = open(file, 'w')
+X f.write(s)
+X
+Xdef load(file):
+X return loadfp(open(file, 'r'))
+X
+Xdef loadfp(fp):
+X s = ''
+X while 1:
+X buf = fp.read(16*1024)
+X if not buf: break
+X s = s + buf
+X return s
+X
+Xdef unbias(s):
+X if not s: return s
+X a = audio.chr2num(s)
+X sum = 0
+X for i in a: sum = sum + i
+X bias = (sum + len(a)/2) / len(a)
+X print 'Bias value:', bias
+X if bias:
+X for i in range(len(a)):
+X a[i] = a[i] - bias
+X s = audio.num2chr(a)
+X return s
+X
+X# Stretch by a/b.
+X# Think of this as converting the sampling rate from a samples/sec
+X# to b samples/sec. Or, if the input is a bytes long, the output
+X# will be b bytes long.
+X#
+Xdef stretch(s, a, b):
+X y = audio.chr2num(s)
+X m = len(y)
+X out = []
+X n = m * b / a
+X # i, j will walk through y and out (step 1)
+X # ib, ja are i*b, j*a and are kept as close together as possible
+X i, ib = 0, 0
+X j, ja = 0, 0
+X for j in range(n):
+X ja = ja+a
+X while ib < ja:
+X i = i+1
+X ib = ib+b
+X if i >= m:
+X break
+X if ib = ja:
+X out.append(y[i])
+X else:
+X out.append((y[i]*(ja-(ib-b)) + y[i-1]*(ib-ja)) / b)
+X return audio.num2chr(out)
+X
+Xdef sinus(freq): # return a 1-second sine wave
+X from math import sin, pi
+X factor = 2.0*pi*float(freq)/float(RATE)
+X list = range(RATE)
+X for i in list:
+X list[i] = int(sin(float(i) * factor) * 127.0)
+X return audio.num2chr(list)
+X
+Xdef softclip(s):
+X if '\177' not in s and '\200' not in s:
+X return s
+X num = audio.chr2num(s)
+X extremes = (-128, 127)
+X for i in range(1, len(num)-1):
+X if num[i] in extremes:
+X num[i] = (num[i-1] + num[i+1]) / 2
+X return audio.num2chr(num)
+X
+Xdef demo():
+X gday = load('gday')[1000:6000]
+X save(gday, 'gday0')
+X gg = [gday]
+X for i in range(1, 10):
+X for g in gg: play(g)
+X g = stretch(gday, 10, 10-i)
+X save(g, 'gday' + `i`)
+X gg.append(g)
+X while 1:
+X for g in gg: play(g)
+EOF
+fi
+if test -s 'lib/listwin.py'
+then echo '*** I will not over-write existing file lib/listwin.py'
+else
+echo 'x - lib/listwin.py'
+sed 's/^X//' > 'lib/listwin.py' << 'EOF'
+X# Module 'listwin'
+X# List windows, a subclass of gwin
+X
+Ximport gwin
+Ximport stdwin
+X
+Xdef maxlinewidth(a): # Compute maximum textwidth of lines in a sequence
+X max = 0
+X for line in a:
+X width = stdwin.textwidth(line)
+X if width > max: max = width
+X return max
+X
+Xdef action(w, string, i, detail): # Default item selection method
+X pass
+X
+Xdef mup(w, detail): # Mouse up method
+X (h, v), clicks, button, mask = detail
+X i = divmod(v, w.lineheight)[0]
+X if 0 <= i < len(w.data):
+X w.action(w, w.data[i], i, detail)
+X
+Xdef draw(w, ((left, top), (right, bottom))): # Text window draw method
+X data = w.data
+X d = w.begindrawing()
+X lh = w.lineheight
+X itop = top/lh
+X ibot = (bottom-1)/lh + 1
+X if itop < 0: itop = 0
+X if ibot > len(data): ibot = len(data)
+X for i in range(itop, ibot): d.text((0, i*lh), data[i])
+X
+Xdef open(title, data): # Display a list of texts in a window
+X lineheight = stdwin.lineheight()
+X h, v = maxlinewidth(data), len(data)*lineheight
+X h0, v0 = h + stdwin.textwidth(' '), v + lineheight
+X if h0 > stdwin.textwidth(' ')*80: h0 = 0
+X if v0 > stdwin.lineheight()*24: v0 = 0
+X stdwin.setdefwinsize(h0, v0)
+X w = gwin.open(title)
+X w.setdocsize(h, v)
+X w.lineheight = lineheight
+X w.data = data
+X w.draw = draw
+X w.action = action
+X w.mup = mup
+X return w
+EOF
+fi
+if test -s 'lib/macpath.py'
+then echo '*** I will not over-write existing file lib/macpath.py'
+else
+echo 'x - lib/macpath.py'
+sed 's/^X//' > 'lib/macpath.py' << 'EOF'
+X# module 'macpath' -- pathname (or -related) operations for the Macintosh
+X
+Ximport mac
+X
+Xfrom stat import *
+X
+X
+X# Return true if a path is absolute.
+X# On the Mac, relative paths begin with a colon,
+X# but as a special case, paths with no colons at all are also relative.
+X# Anything else is absolute (the string up to the first colon is the
+X# volume name).
+X
+Xdef isabs(s):
+X return ':' in s and s[0] <> ':'
+X
+X
+X# Concatenate two pathnames.
+X# The result is equivalent to what the second pathname would refer to
+X# if the first pathname were the current directory.
+X
+Xdef cat(s, t):
+X if (not s) or isabs(t): return t
+X if t[:1] = ':': t = t[1:]
+X if ':' not in s:
+X s = ':' + s
+X if s[-1:] <> ':':
+X s = s + ':'
+X return s + t
+X
+X
+X# Split a pathname in two parts: the directory leading up to the final bit,
+X# and the basename (the filename, without colons, in that directory).
+X# The result (s, t) is such that cat(s, t) yields the original argument.
+X
+Xdef split(s):
+X if ':' not in s: return '', s
+X colon = 0
+X for i in range(len(s)):
+X if s[i] = ':': colon = i+1
+X return s[:colon], s[colon:]
+X
+X
+X# Normalize a pathname: get rid of '::' sequences by backing up,
+X# e.g., 'foo:bar::bletch' becomes 'foo:bletch'.
+X# Raise the exception norm_error below if backing up is impossible,
+X# e.g., for '::foo'.
+X
+Xnorm_error = 'macpath.norm_error: path cannot be normalized'
+X
+Xdef norm(s):
+X import string
+X if ':' not in s:
+X return ':' + s
+X f = string.splitfields(s, ':')
+X pre = []
+X post = []
+X if not f[0]:
+X pre = f[:1]
+X f = f[1:]
+X if not f[len(f)-1]:
+X post = f[-1:]
+X f = f[:-1]
+X res = []
+X for seg in f:
+X if seg:
+X res.append(seg)
+X else:
+X if not res: raise norm_error, 'path starts with ::'
+X del res[len(res)-1]
+X if not (pre or res):
+X raise norm_error, 'path starts with volume::'
+X if pre: res = pre + res
+X if post: res = res + post
+X s = res[0]
+X for seg in res[1:]:
+X s = s + ':' + seg
+X return s
+X
+X
+X# Return true if the pathname refers to an existing directory.
+X
+Xdef isdir(s):
+X try:
+X st = mac.stat(s)
+X except mac.error:
+X return 0
+X return S_ISDIR(st[ST_MODE])
+X
+X
+X# Return true if the pathname refers to an existing regular file.
+X
+Xdef isfile(s):
+X try:
+X st = mac.stat(s)
+X except mac.error:
+X return 0
+X return S_ISREG(st[ST_MODE])
+X
+X
+X# Return true if the pathname refers to an existing file or directory.
+X
+Xdef exists(s):
+X try:
+X st = mac.stat(s)
+X except mac.error:
+X return 0
+X return 1
+EOF
+fi
+if test -s 'lib/textwin.py'
+then echo '*** I will not over-write existing file lib/textwin.py'
+else
+echo 'x - lib/textwin.py'
+sed 's/^X//' > 'lib/textwin.py' << 'EOF'
+X# Module 'textwin'
+X
+X# Text windows, a subclass of gwin
+X
+Ximport stdwin
+Ximport stdwinsupport
+Ximport gwin
+X
+XS = stdwinsupport # Shorthand
+X
+X
+Xdef fixsize(w):
+X docwidth, docheight = w.text.getrect()[1]
+X winheight = w.getwinsize()[1]
+X if winheight > docheight: docheight = winheight
+X w.setdocsize(0, docheight)
+X fixeditmenu(w)
+X
+Xdef cut(w, m, id):
+X s = w.text.getfocustext()
+X if s:
+X stdwin.setcutbuffer(0, s)
+X w.text.replace('')
+X fixsize(w)
+X
+Xdef copy(w, m, id):
+X s = w.text.getfocustext()
+X if s:
+X stdwin.setcutbuffer(0, s)
+X fixeditmenu(w)
+X
+Xdef paste(w, m, id):
+X w.text.replace(stdwin.getcutbuffer(0))
+X fixsize(w)
+X
+Xdef addeditmenu(w):
+X m = w.editmenu = w.menucreate('Edit')
+X m.action = []
+X m.additem('Cut', 'X')
+X m.action.append(cut)
+X m.additem('Copy', 'C')
+X m.action.append(copy)
+X m.additem('Paste', 'V')
+X m.action.append(paste)
+X
+Xdef fixeditmenu(w):
+X m = w.editmenu
+X f = w.text.getfocus()
+X can_copy = (f[0] < f[1])
+X m.enable(1, can_copy)
+X if not w.readonly:
+X m.enable(0, can_copy)
+X m.enable(2, (stdwin.getcutbuffer(0) <> ''))
+X
+Xdef draw(w, area): # Draw method
+X w.text.draw(area)
+X
+Xdef size(w, newsize): # Size method
+X w.text.move((0, 0), newsize)
+X fixsize(w)
+X
+Xdef close(w): # Close method
+X del w.text # Break circular ref
+X gwin.close(w)
+X
+Xdef char(w, c): # Char method
+X w.text.replace(c)
+X fixsize(w)
+X
+Xdef backspace(w): # Backspace method
+X void = w.text.event(S.we_command, w, S.wc_backspace)
+X fixsize(w)
+X
+Xdef arrow(w, detail): # Arrow method
+X w.text.arrow(detail)
+X fixeditmenu(w)
+X
+Xdef mdown(w, detail): # Mouse down method
+X void = w.text.event(S.we_mouse_down, w, detail)
+X fixeditmenu(w)
+X
+Xdef mmove(w, detail): # Mouse move method
+X void = w.text.event(S.we_mouse_move, w, detail)
+X
+Xdef mup(w, detail): # Mouse up method
+X void = w.text.event(S.we_mouse_up, w, detail)
+X fixeditmenu(w)
+X
+Xdef activate(w): # Activate method
+X fixeditmenu(w)
+X
+Xdef open(title, str): # Display a string in a window
+X w = gwin.open(title)
+X w.readonly = 0
+X w.text = w.textcreate((0, 0), w.getwinsize())
+X w.text.replace(str)
+X w.text.setfocus(0, 0)
+X addeditmenu(w)
+X fixsize(w)
+X w.draw = draw
+X w.size = size
+X w.close = close
+X w.mdown = mdown
+X w.mmove = mmove
+X w.mup = mup
+X w.char = char
+X w.backspace = backspace
+X w.arrow = arrow
+X w.activate = activate
+X return w
+X
+Xdef open_readonly(title, str): # Same with char input disabled
+X w = open(title, str)
+X w.readonly = 1
+X w.char = w.backspace = gwin.nop
+X # Disable Cut and Paste menu item; leave Copy alone
+X w.editmenu.enable(0, 0)
+X w.editmenu.enable(2, 0)
+X return w
+EOF
+fi
+if test -s 'lib/zmod.py'
+then echo '*** I will not over-write existing file lib/zmod.py'
+else
+echo 'x - lib/zmod.py'
+sed 's/^X//' > 'lib/zmod.py' << 'EOF'
+X# module 'zmod'
+X
+X# Compute properties of mathematical "fields" formed by taking
+X# Z/n (the whole numbers modulo some whole number n) and an
+X# irreducible polynomial (i.e., a polynomial with only complex zeros),
+X# e.g., Z/5 and X**2 + 2.
+X#
+X# The field is formed by taking all possible linear combinations of
+X# a set of d base vectors (where d is the degree of the polynomial).
+X#
+X# Note that this procedure doesn't yield a field for all combinations
+X# of n and p: it may well be that some numbers have more than one
+X# inverse and others have none. This is what we check.
+X#
+X# Remember that a field is a ring where each element has an inverse.
+X# A ring has commutative addition and multiplication, a zero and a one:
+X# 0*x = x*0 = 0, 0+x = x+0 = x, 1*x = x*1 = x. Also, the distributive
+X# property holds: a*(b+c) = a*b + b*c.
+X# (XXX I forget if this is an axiom or follows from the rules.)
+X
+Ximport poly
+X
+X
+X# Example N and polynomial
+X
+XN = 5
+XP = poly.plus(poly.one(0, 2), poly.one(2, 1)) # 2 + x**2
+X
+X
+X# Return x modulo y. Returns >= 0 even if x < 0.
+X
+Xdef mod(x, y):
+X return divmod(x, y)[1]
+X
+X
+X# Normalize a polynomial modulo n and modulo p.
+X
+Xdef norm(a, n, p):
+X a = poly.modulo(a, p)
+X a = a[:]
+X for i in range(len(a)): a[i] = mod(a[i], n)
+X a = poly.normalize(a)
+X return a
+X
+X
+X# Make a list of all n^d elements of the proposed field.
+X
+Xdef make_all(mat):
+X all = []
+X for row in mat:
+X for a in row:
+X all.append(a)
+X return all
+X
+Xdef make_elements(n, d):
+X if d = 0: return [poly.one(0, 0)]
+X sub = make_elements(n, d-1)
+X all = []
+X for a in sub:
+X for i in range(n):
+X all.append(poly.plus(a, poly.one(d-1, i)))
+X return all
+X
+Xdef make_inv(all, n, p):
+X x = poly.one(1, 1)
+X inv = []
+X for a in all:
+X inv.append(norm(poly.times(a, x), n, p))
+X return inv
+X
+Xdef checkfield(n, p):
+X all = make_elements(n, len(p)-1)
+X inv = make_inv(all, n, p)
+X all1 = all[:]
+X inv1 = inv[:]
+X all1.sort()
+X inv1.sort()
+X if all1 = inv1: print 'BINGO!'
+X else:
+X print 'Sorry:', n, p
+X print all
+X print inv
+X
+Xdef rj(s, width):
+X if type(s) <> type(''): s = `s`
+X n = len(s)
+X if n >= width: return s
+X return ' '*(width - n) + s
+X
+Xdef lj(s, width):
+X if type(s) <> type(''): s = `s`
+X n = len(s)
+X if n >= width: return s
+X return s + ' '*(width - n)
+EOF
+fi
+if test -s 'src/PROTO.h'
+then echo '*** I will not over-write existing file src/PROTO.h'
+else
+echo 'x - src/PROTO.h'
+sed 's/^X//' > 'src/PROTO.h' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/*
+XThe macro PROTO(x) is used to put function prototypes in the source.
+XThis is defined differently for compilers that support prototypes than
+Xfor compilers that don't. It should be used as follows:
+X int some_function PROTO((int arg1, char *arg2));
+XA variant FPROTO(x) is used for cases where Standard C allows prototypes
+Xbut Think C doesn't (mostly function pointers).
+X
+XThis file also defines the macro HAVE_PROTOTYPES if and only if
+Xthe PROTO() macro expands the prototype. It is also allowed to predefine
+XHAVE_PROTOTYPES to force prototypes on.
+X*/
+X
+X#ifndef PROTO
+X
+X#ifdef __STDC__
+X#define HAVE_PROTOTYPES
+X#endif
+X
+X#ifdef THINK_C
+X#undef HAVE_PROTOTYPES
+X#define HAVE_PROTOTYPES
+X#endif
+X
+X#ifdef sgi
+X#ifdef mips
+X#define HAVE_PROTOTYPES
+X#endif
+X#endif
+X
+X#ifdef HAVE_PROTOTYPES
+X#define PROTO(x) x
+X#else
+X#define PROTO(x) ()
+X#endif
+X
+X#endif /* PROTO */
+X
+X
+X/* FPROTO() is for cases where Think C doesn't like prototypes */
+X
+X#ifdef THINK_C
+X#define FPROTO(arglist) ()
+X#else /* !THINK_C */
+X#define FPROTO(arglist) PROTO(arglist)
+X#endif /* !THINK_C */
+X
+X#ifndef HAVE_PROTOTYPES
+X#define const /*empty*/
+X#else /* HAVE_PROTOTYPES */
+X#ifdef THINK_C
+X#undef const
+X#define const /*empty*/
+X#endif /* THINK_C */
+X#endif /* HAVE_PROTOTYPES */
+EOF
+fi
+if test -s 'src/bitset.c'
+then echo '*** I will not over-write existing file src/bitset.c'
+else
+echo 'x - src/bitset.c'
+sed 's/^X//' > 'src/bitset.c' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/* Bitset primitives used by the parser generator */
+X
+X#include "pgenheaders.h"
+X#include "bitset.h"
+X
+Xbitset
+Xnewbitset(nbits)
+X int nbits;
+X{
+X int nbytes = NBYTES(nbits);
+X bitset ss = NEW(BYTE, nbytes);
+X
+X if (ss == NULL)
+X fatal("no mem for bitset");
+X
+X ss += nbytes;
+X while (--nbytes >= 0)
+X *--ss = 0;
+X return ss;
+X}
+X
+Xvoid
+Xdelbitset(ss)
+X bitset ss;
+X{
+X DEL(ss);
+X}
+X
+Xint
+Xaddbit(ss, ibit)
+X bitset ss;
+X int ibit;
+X{
+X int ibyte = BIT2BYTE(ibit);
+X BYTE mask = BIT2MASK(ibit);
+X
+X if (ss[ibyte] & mask)
+X return 0; /* Bit already set */
+X ss[ibyte] |= mask;
+X return 1;
+X}
+X
+X#if 0 /* Now a macro */
+Xint
+Xtestbit(ss, ibit)
+X bitset ss;
+X int ibit;
+X{
+X return (ss[BIT2BYTE(ibit)] & BIT2MASK(ibit)) != 0;
+X}
+X#endif
+X
+Xint
+Xsamebitset(ss1, ss2, nbits)
+X bitset ss1, ss2;
+X int nbits;
+X{
+X int i;
+X
+X for (i = NBYTES(nbits); --i >= 0; )
+X if (*ss1++ != *ss2++)
+X return 0;
+X return 1;
+X}
+X
+Xvoid
+Xmergebitset(ss1, ss2, nbits)
+X bitset ss1, ss2;
+X int nbits;
+X{
+X int i;
+X
+X for (i = NBYTES(nbits); --i >= 0; )
+X *ss1++ |= *ss2++;
+X}
+EOF
+fi
+if test -s 'src/configmac.c'
+then echo '*** I will not over-write existing file src/configmac.c'
+else
+echo 'x - src/configmac.c'
+sed 's/^X//' > 'src/configmac.c' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/* Configuration using STDWIN on the Mac (THINK_C or MPW) */
+X
+X#ifdef THINK_C
+X#define USE_STDWIN
+X#endif
+X
+X#ifdef USE_STDWIN
+X#include "stdwin.h"
+X#endif
+X
+Xvoid
+Xinitargs(p_argc, p_argv)
+X int *p_argc;
+X char ***p_argv;
+X{
+X#ifdef USE_STDWIN
+X
+X#ifdef THINK_C_3_0
+X wsetstdio(1);
+X#else
+X /* This printf() statement is really needed only
+X to initialize THINK C 4.0's stdio: */
+X printf(
+X"Python 4.0, Copyright 1990 Stichting Mathematisch Centrum, Amsterdam\n");
+X#endif
+X
+X wargs(p_argc, p_argv);
+X#endif
+X}
+X
+Xvoid
+Xinitcalls()
+X{
+X}
+X
+Xvoid
+Xdonecalls()
+X{
+X#ifdef USE_STDWIN
+X wdone();
+X#endif
+X}
+X
+X#ifndef PYTHONPATH
+X/* On the Mac, the search path is a space-separated list of directories */
+X#define PYTHONPATH ": :lib :lib:stdwin :lib:mac :lib:demo"
+X#endif
+X
+Xchar *
+Xgetpythonpath()
+X{
+X return PYTHONPATH;
+X}
+X
+X
+X/* Table of built-in modules.
+X These are initialized when first imported. */
+X
+X/* Standard modules */
+Xextern void inittime();
+Xextern void initmath();
+Xextern void initregexp();
+X
+X/* Mac-specific modules */
+Xextern void initmac();
+X#ifdef USE_STDWIN
+Xextern void initstdwin();
+X#endif
+X
+Xstruct {
+X char *name;
+X void (*initfunc)();
+X} inittab[] = {
+X /* Standard modules */
+X {"time", inittime},
+X {"math", initmath},
+X {"regexp", initregexp},
+X
+X /* Mac-specific modules */
+X {"mac", initmac},
+X#ifdef USE_STDWIN
+X {"stdwin", initstdwin},
+X#endif
+X {0, 0} /* Sentinel */
+X};
+EOF
+fi
+if test -s 'src/fgetsintr.c'
+then echo '*** I will not over-write existing file src/fgetsintr.c'
+else
+echo 'x - src/fgetsintr.c'
+sed 's/^X//' > 'src/fgetsintr.c' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/* Interruptable version of fgets().
+X Return < 0 for interrupted, 1 for EOF, 0 for valid input. */
+X
+X/* XXX This uses longjmp() from a signal out of fgets().
+X Should use read() instead?! */
+X
+X#include "pgenheaders.h"
+X
+X#include <signal.h>
+X#include <setjmp.h>
+X
+X#include "errcode.h"
+X#include "sigtype.h"
+X#include "fgetsintr.h"
+X
+X#ifndef AMOEBA
+X#define sig_block() /*empty*/
+X#define sig_unblock() /*empty*/
+X#endif
+X
+Xstatic jmp_buf jback;
+X
+Xstatic void catcher PROTO((int));
+X
+Xstatic void
+Xcatcher(sig)
+X int sig;
+X{
+X longjmp(jback, 1);
+X}
+X
+Xint
+Xfgets_intr(buf, size, fp)
+X char *buf;
+X int size;
+X FILE *fp;
+X{
+X int ret;
+X SIGTYPE (*sigsave)();
+X
+X if (setjmp(jback)) {
+X clearerr(fp);
+X signal(SIGINT, sigsave);
+X#ifdef THINK_C_3_0
+X Set_Echo(1);
+X#endif
+X return E_INTR;
+X }
+X
+X /* The casts to (SIGTYPE(*)()) are needed by THINK_C only */
+X
+X sigsave = signal(SIGINT, (SIGTYPE(*)()) SIG_IGN);
+X if (sigsave != (SIGTYPE(*)()) SIG_IGN)
+X signal(SIGINT, (SIGTYPE(*)()) catcher);
+X
+X#ifndef THINK_C
+X if (intrcheck())
+X ret = E_INTR;
+X else
+X#endif
+X {
+X sig_block();
+X ret = (fgets(buf, size, fp) == NULL) ? E_EOF : E_OK;
+X sig_unblock();
+X }
+X
+X if (sigsave != (SIGTYPE(*)()) SIG_IGN)
+X signal(SIGINT, (SIGTYPE(*)()) sigsave);
+X return ret;
+X}
+EOF
+fi
+if test -s 'src/getcwd.c'
+then echo '*** I will not over-write existing file src/getcwd.c'
+else
+echo 'x - src/getcwd.c'
+sed 's/^X//' > 'src/getcwd.c' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/* Two PD getcwd() implementations.
+X Author: Guido van Rossum, CWI Amsterdam, Jan 1991, <[email protected]>. */
+X
+X/* #define NO_GETWD /* Turn this on to popen pwd instead of calling getwd() */
+X
+X#include <stdio.h>
+X#include <errno.h>
+X
+Xextern int errno;
+X
+X#ifndef NO_GETWD
+X
+X/* Default: Version for BSD systems -- use getwd() */
+X
+X#include "sys/param.h"
+X
+Xextern char *getwd();
+X
+Xchar *
+Xgetcwd(buf, size)
+X char *buf;
+X int size;
+X{
+X char localbuf[MAXPATHLEN+1];
+X char *ret;
+X
+X if (size <= 0) {
+X errno = EINVAL;
+X return NULL;
+X }
+X ret = getwd(localbuf);
+X if (ret != NULL && strlen(localbuf) >= size) {
+X errno = ERANGE;
+X return NULL;
+X }
+X if (ret == NULL) {
+X errno = EACCES; /* Most likely error */
+X return NULL;
+X }
+X strncpy(buf, localbuf, size);
+X return buf;
+X}
+X
+X#else
+X
+X/* NO_GETWD defined: Version for backward UNIXes -- popen /bin/pwd */
+X
+X#define PWD_CMD "/bin/pwd"
+X
+Xchar *
+Xgetcwd(buf, size)
+X char *buf;
+X int size;
+X{
+X FILE *fp;
+X char *p;
+X int sts;
+X if (size <= 0) {
+X errno = EINVAL;
+X return NULL;
+X }
+X if ((fp = popen(PWD_CMD, "r")) == NULL)
+X return NULL;
+X if (fgets(buf, size, fp) == NULL || (sts = pclose(fp)) != 0) {
+X errno = EACCES; /* Most likely error */
+X return NULL;
+X }
+X for (p = buf; *p != '\n'; p++) {
+X if (*p == '\0') {
+X errno = ERANGE;
+X return NULL;
+X }
+X }
+X *p = '\0';
+X return buf;
+X}
+X
+X#endif
+EOF
+fi
+if test -s 'src/graminit.h'
+then echo '*** I will not over-write existing file src/graminit.h'
+else
+echo 'x - src/graminit.h'
+sed 's/^X//' > 'src/graminit.h' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X#define single_input 256
+X#define file_input 257
+X#define expr_input 258
+X#define eval_input 259
+X#define funcdef 260
+X#define parameters 261
+X#define fplist 262
+X#define fpdef 263
+X#define stmt 264
+X#define simple_stmt 265
+X#define expr_stmt 266
+X#define print_stmt 267
+X#define del_stmt 268
+X#define pass_stmt 269
+X#define flow_stmt 270
+X#define break_stmt 271
+X#define return_stmt 272
+X#define raise_stmt 273
+X#define import_stmt 274
+X#define compound_stmt 275
+X#define if_stmt 276
+X#define while_stmt 277
+X#define for_stmt 278
+X#define try_stmt 279
+X#define except_clause 280
+X#define suite 281
+X#define test 282
+X#define and_test 283
+X#define not_test 284
+X#define comparison 285
+X#define comp_op 286
+X#define expr 287
+X#define term 288
+X#define factor 289
+X#define atom 290
+X#define trailer 291
+X#define subscript 292
+X#define exprlist 293
+X#define testlist 294
+X#define classdef 295
+X#define baselist 296
+X#define arguments 297
+EOF
+fi
+if test -s 'src/listnode.c'
+then echo '*** I will not over-write existing file src/listnode.c'
+else
+echo 'x - src/listnode.c'
+sed 's/^X//' > 'src/listnode.c' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/* List a node on a file */
+X
+X#include "pgenheaders.h"
+X#include "token.h"
+X#include "node.h"
+X
+X/* Forward */
+Xstatic void list1node PROTO((FILE *, node *));
+X
+Xvoid
+Xlisttree(n)
+X node *n;
+X{
+X listnode(stdout, n);
+X}
+X
+Xstatic int level, atbol;
+X
+Xvoid
+Xlistnode(fp, n)
+X FILE *fp;
+X node *n;
+X{
+X level = 0;
+X atbol = 1;
+X list1node(fp, n);
+X}
+X
+Xstatic void
+Xlist1node(fp, n)
+X FILE *fp;
+X node *n;
+X{
+X if (n == 0)
+X return;
+X if (ISNONTERMINAL(TYPE(n))) {
+X int i;
+X for (i = 0; i < NCH(n); i++)
+X list1node(fp, CHILD(n, i));
+X }
+X else if (ISTERMINAL(TYPE(n))) {
+X switch (TYPE(n)) {
+X case INDENT:
+X ++level;
+X break;
+X case DEDENT:
+X --level;
+X break;
+X default:
+X if (atbol) {
+X int i;
+X for (i = 0; i < level; ++i)
+X fprintf(fp, "\t");
+X atbol = 0;
+X }
+X if (TYPE(n) == NEWLINE) {
+X if (STR(n) != NULL)
+X fprintf(fp, "%s", STR(n));
+X fprintf(fp, "\n");
+X atbol = 1;
+X }
+X else
+X fprintf(fp, "%s ", STR(n));
+X break;
+X }
+X }
+X else
+X fprintf(fp, "? ");
+X}
+EOF
+fi
+if test -s 'src/listobject.h'
+then echo '*** I will not over-write existing file src/listobject.h'
+else
+echo 'x - src/listobject.h'
+sed 's/^X//' > 'src/listobject.h' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/* List object interface */
+X
+X/*
+X123456789-123456789-123456789-123456789-123456789-123456789-123456789-12
+X
+XAnother generally useful object type is an list of object pointers.
+XThis is a mutable type: the list items can be changed, and items can be
+Xadded or removed. Out-of-range indices or non-list objects are ignored.
+X
+X*** WARNING *** setlistitem does not increment the new item's reference
+Xcount, but does decrement the reference count of the item it replaces,
+Xif not nil. It does *decrement* the reference count if it is *not*
+Xinserted in the list. Similarly, getlistitem does not increment the
+Xreturned item's reference count.
+X*/
+X
+Xtypedef struct {
+X OB_VARHEAD
+X object **ob_item;
+X} listobject;
+X
+Xextern typeobject Listtype;
+X
+X#define is_listobject(op) ((op)->ob_type == &Listtype)
+X
+Xextern object *newlistobject PROTO((int size));
+Xextern int getlistsize PROTO((object *));
+Xextern object *getlistitem PROTO((object *, int));
+Xextern int setlistitem PROTO((object *, int, object *));
+Xextern int inslistitem PROTO((object *, int, object *));
+Xextern int addlistitem PROTO((object *, object *));
+Xextern int sortlist PROTO((object *));
+X
+X/* Macro, trading safety for speed */
+X#define GETLISTITEM(op, i) ((op)->ob_item[i])
+EOF
+fi
+if test -s 'src/node.c'
+then echo '*** I will not over-write existing file src/node.c'
+else
+echo 'x - src/node.c'
+sed 's/^X//' > 'src/node.c' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/* Parse tree node implementation */
+X
+X#include "pgenheaders.h"
+X#include "node.h"
+X
+Xnode *
+Xnewtree(type)
+X int type;
+X{
+X node *n = NEW(node, 1);
+X if (n == NULL)
+X return NULL;
+X n->n_type = type;
+X n->n_str = NULL;
+X n->n_lineno = 0;
+X n->n_nchildren = 0;
+X n->n_child = NULL;
+X return n;
+X}
+X
+X#define XXX 3 /* Node alignment factor to speed up realloc */
+X#define XXXROUNDUP(n) ((n) == 1 ? 1 : ((n) + XXX - 1) / XXX * XXX)
+X
+Xnode *
+Xaddchild(n1, type, str, lineno)
+X register node *n1;
+X int type;
+X char *str;
+X int lineno;
+X{
+X register int nch = n1->n_nchildren;
+X register int nch1 = nch+1;
+X register node *n;
+X if (XXXROUNDUP(nch) < nch1) {
+X n = n1->n_child;
+X nch1 = XXXROUNDUP(nch1);
+X RESIZE(n, node, nch1);
+X if (n == NULL)
+X return NULL;
+X n1->n_child = n;
+X }
+X n = &n1->n_child[n1->n_nchildren++];
+X n->n_type = type;
+X n->n_str = str;
+X n->n_lineno = lineno;
+X n->n_nchildren = 0;
+X n->n_child = NULL;
+X return n;
+X}
+X
+X/* Forward */
+Xstatic void freechildren PROTO((node *));
+X
+X
+Xvoid
+Xfreetree(n)
+X node *n;
+X{
+X if (n != NULL) {
+X freechildren(n);
+X DEL(n);
+X }
+X}
+X
+Xstatic void
+Xfreechildren(n)
+X node *n;
+X{
+X int i;
+X for (i = NCH(n); --i >= 0; )
+X freechildren(CHILD(n, i));
+X if (n->n_child != NULL)
+X DEL(n->n_child);
+X if (STR(n) != NULL)
+X DEL(STR(n));
+X}
+EOF
+fi
+if test -s 'src/stringobject.h'
+then echo '*** I will not over-write existing file src/stringobject.h'
+else
+echo 'x - src/stringobject.h'
+sed 's/^X//' > 'src/stringobject.h' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/* String object interface */
+X
+X/*
+X123456789-123456789-123456789-123456789-123456789-123456789-123456789-12
+X
+XType stringobject represents a character string. An extra zero byte is
+Xreserved at the end to ensure it is zero-terminated, but a size is
+Xpresent so strings with null bytes in them can be represented. This
+Xis an immutable object type.
+X
+XThere are functions to create new string objects, to test
+Xan object for string-ness, and to get the
+Xstring value. The latter function returns a null pointer
+Xif the object is not of the proper type.
+XThere is a variant that takes an explicit size as well as a
+Xvariant that assumes a zero-terminated string. Note that none of the
+Xfunctions should be applied to nil objects.
+X*/
+X
+X/* NB The type is revealed here only because it is used in dictobject.c */
+X
+Xtypedef struct {
+X OB_VARHEAD
+X char ob_sval[1];
+X} stringobject;
+X
+Xextern typeobject Stringtype;
+X
+X#define is_stringobject(op) ((op)->ob_type == &Stringtype)
+X
+Xextern object *newsizedstringobject PROTO((char *, int));
+Xextern object *newstringobject PROTO((char *));
+Xextern unsigned int getstringsize PROTO((object *));
+Xextern char *getstringvalue PROTO((object *));
+Xextern void joinstring PROTO((object **, object *));
+Xextern int resizestring PROTO((object **, int));
+X
+X/* Macro, trading safety for speed */
+X#define GETSTRINGVALUE(op) ((op)->ob_sval)
+EOF
+fi
+if test -s 'src/structmember.h'
+then echo '*** I will not over-write existing file src/structmember.h'
+else
+echo 'x - src/structmember.h'
+sed 's/^X//' > 'src/structmember.h' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/* Interface to map C struct members to Python object attributes */
+X
+X/* The offsetof() macro calculates the offset of a structure member
+X in its structure. Unfortunately this cannot be written down
+X portably, hence it is provided by a Standard C header file.
+X For pre-Standard C compilers, here is a version that usually works
+X (but watch out!): */
+X
+X#ifndef offsetof
+X#define offsetof(type, member) ( (int) & ((type*)0) -> member )
+X#endif
+X
+X/* An array of memberlist structures defines the name, type and offset
+X of selected members of a C structure. These can be read by
+X getmember() and set by setmember() (except if their READONLY flag
+X is set). The array must be terminated with an entry whose name
+X pointer is NULL. */
+X
+Xstruct memberlist {
+X char *name;
+X int type;
+X int offset;
+X int readonly;
+X};
+X
+X/* Types */
+X#define T_SHORT 0
+X#define T_INT 1
+X#define T_LONG 2
+X#define T_FLOAT 3
+X#define T_DOUBLE 4
+X#define T_STRING 5
+X#define T_OBJECT 6
+X
+X/* Readonly flag */
+X#define READONLY 1
+X#define RO READONLY /* Shorthand */
+X
+Xobject *getmember PROTO((char *, struct memberlist *, char *));
+Xint setmember PROTO((char *, struct memberlist *, char *, object *));
+EOF
+fi
+if test -s 'src/tokenizer.h'
+then echo '*** I will not over-write existing file src/tokenizer.h'
+else
+echo 'x - src/tokenizer.h'
+sed 's/^X//' > 'src/tokenizer.h' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/* Tokenizer interface */
+X
+X#include "token.h" /* For token types */
+X
+X#define MAXINDENT 100 /* Max indentation level */
+X
+X/* Tokenizer state */
+Xstruct tok_state {
+X /* Input state; buf <= cur <= inp <= end */
+X /* NB an entire token must fit in the buffer */
+X char *buf; /* Input buffer */
+X char *cur; /* Next character in buffer */
+X char *inp; /* End of data in buffer */
+X char *end; /* End of input buffer */
+X int done; /* 0 normally, 1 at EOF, -1 after error */
+X FILE *fp; /* Rest of input; NULL if tokenizing a string */
+X int tabsize; /* Tab spacing */
+X int indent; /* Current indentation index */
+X int indstack[MAXINDENT]; /* Stack of indents */
+X int atbol; /* Nonzero if at begin of new line */
+X int pendin; /* Pending indents (if > 0) or dedents (if < 0) */
+X char *prompt, *nextprompt; /* For interactive prompting */
+X int lineno; /* Current line number */
+X};
+X
+Xextern struct tok_state *tok_setups PROTO((char *));
+Xextern struct tok_state *tok_setupf PROTO((FILE *, char *ps1, char *ps2));
+Xextern void tok_free PROTO((struct tok_state *));
+Xextern int tok_get PROTO((struct tok_state *, char **, char **));
+EOF
+fi
+if test -s 'src/tupleobject.h'
+then echo '*** I will not over-write existing file src/tupleobject.h'
+else
+echo 'x - src/tupleobject.h'
+sed 's/^X//' > 'src/tupleobject.h' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/* Tuple object interface */
+X
+X/*
+X123456789-123456789-123456789-123456789-123456789-123456789-123456789-12
+X
+XAnother generally useful object type is an tuple of object pointers.
+XThis is a mutable type: the tuple items can be changed (but not their
+Xnumber). Out-of-range indices or non-tuple objects are ignored.
+X
+X*** WARNING *** settupleitem does not increment the new item's reference
+Xcount, but does decrement the reference count of the item it replaces,
+Xif not nil. It does *decrement* the reference count if it is *not*
+Xinserted in the tuple. Similarly, gettupleitem does not increment the
+Xreturned item's reference count.
+X*/
+X
+Xtypedef struct {
+X OB_VARHEAD
+X object *ob_item[1];
+X} tupleobject;
+X
+Xextern typeobject Tupletype;
+X
+X#define is_tupleobject(op) ((op)->ob_type == &Tupletype)
+X
+Xextern object *newtupleobject PROTO((int size));
+Xextern int gettuplesize PROTO((object *));
+Xextern object *gettupleitem PROTO((object *, int));
+Xextern int settupleitem PROTO((object *, int, object *));
+X
+X/* Macro, trading safety for speed */
+X#define GETTUPLEITEM(op, i) ((op)->ob_item[i])
+EOF
+fi
+echo 'Part 18 out of 21 of pack.out complete.'
+exit 0
diff --git a/shar/python-0.9.1-19-21.shar b/shar/python-0.9.1-19-21.shar
new file mode 100644
index 0000000..c52113b
--- /dev/null
+++ b/shar/python-0.9.1-19-21.shar
@@ -0,0 +1,1997 @@
+: This is a shell archive.
+: Extract with 'sh this_file'.
+:
+: Extract part 01 first since it makes all directories
+echo 'Start of pack.out, part 19 out of 21:'
+if test -s 'demo/scripts/xxci.py'
+then echo '*** I will not over-write existing file demo/scripts/xxci.py'
+else
+echo 'x - demo/scripts/xxci.py'
+sed 's/^X//' > 'demo/scripts/xxci.py' << 'EOF'
+X#! /ufs/guido/bin/sgi/python
+X
+X# xxci
+X#
+X# check in files for which rcsdiff returns nonzero exit status
+X
+Ximport sys
+Ximport posix
+Ximport stat
+Ximport path
+Ximport commands
+X
+XMAXSIZE = 200*1024 # Files this big must be binaries and are skipped.
+X
+Xdef getargs():
+X args = sys.argv[1:]
+X if args:
+X return args
+X print 'No arguments, checking almost *'
+X for file in posix.listdir('.'):
+X if not skipfile(file):
+X args.append(file)
+X if not args:
+X print 'Nothing to do -- exit 1'
+X sys.exit(1)
+X args.sort()
+X return args
+X
+Xbadnames = ['tags', 'xyzzy']
+Xbadprefixes = ['.', ',', '@', '#', 'o.']
+Xbadsuffixes = \
+X ['~', '.a', '.o', '.old', '.bak', '.orig', '.new', '.prev', '.not']
+X# XXX Should generalize even more to use fnmatch!
+X
+Xdef skipfile(file):
+X if file in badnames or \
+X badprefix(file) or badsuffix(file) or \
+X path.islink(file) or path.isdir(file):
+X return 1
+X # Skip huge files -- probably binaries.
+X try:
+X st = posix.stat(file)
+X except posix.error:
+X return 1 # Doesn't exist -- skip it
+X return st[stat.ST_SIZE] >= MAXSIZE
+X
+Xdef badprefix(file):
+X for bad in badprefixes:
+X if file[:len(bad)] = bad: return 1
+X return 0
+X
+Xdef badsuffix(file):
+X for bad in badsuffixes:
+X if file[-len(bad):] = bad: return 1
+X return 0
+X
+Xdef go(args):
+X for file in args:
+X print file + ':'
+X if run('rcsdiff -c', file):
+X if askyesno('Check in ' + file + ' ? '):
+X sts = run('rcs -l', file) # ignored
+X # can't use run() here because it's interactive
+X sts = posix.system('ci -l ' + file)
+X
+Xdef run(cmd, file):
+X sts, output = commands.getstatusoutput(cmd + commands.mkarg(file))
+X if sts:
+X print output
+X print 'Exit status', sts
+X return sts
+X
+Xdef askyesno(prompt):
+X s = raw_input(prompt)
+X return s in ['y', 'yes']
+X
+Xgo(getargs())
+EOF
+chmod +x 'demo/scripts/xxci.py'
+fi
+if test -s 'demo/sgi/gl_panel/apanel/apanel.s'
+then echo '*** I will not over-write existing file demo/sgi/gl_panel/apanel/apanel.s'
+else
+echo 'x - demo/sgi/gl_panel/apanel/apanel.s'
+sed 's/^X//' > 'demo/sgi/gl_panel/apanel/apanel.s' << 'EOF'
+X;;; This file was automatically generated by the panel editor.
+X;;; If you read it into gnu emacs, it will automagically format itself.
+X
+X(panel (prop help creator:user-panel-help)
+X(prop user-panel #t)
+X(label "Audio Control Panel")
+X(x 395)
+X(y 69)
+X(al (pnl_filled_vslider (name "outputgain")
+X(prop help creator:user-act-help)
+X(label "output gain")
+X(x 6.5)
+X(y 0.75)
+X(w 0.4)
+X(h 4.35)
+X(val 0.329)
+X(labeltype 13)
+X(downfunc move-then-resize)
+X)
+X(pnl_frame (prop help creator:user-frame-help)
+X(x 0.25)
+X(y 2.75)
+X(w 5.1)
+X(h 2.3)
+X(downfunc move-then-resize)
+X(al (pnl_filled_hslider (name "recordsize")
+X(prop help creator:user-act-help)
+X(label "recording length")
+X(x -0.75)
+X(w 3.3)
+X(h 0.4)
+X(val 0.1)
+X(labeltype 11)
+X(downfunc move-then-resize)
+X)
+X(pnl_label (prop help creator:user-act-help)
+X(label "(max 10 seconds)")
+X(x -0.75)
+X(y -0.75)
+X(downfunc move-then-resize)
+X)
+X(pnl_wide_button (name "recordbutton")
+X(prop help creator:user-act-help)
+X(label "record from microphone...")
+X(x -0.75)
+X(y 0.75)
+X(w 4.7)
+X(downfunc move-then-resize)
+X)
+X)
+X)
+X(pnl_wide_button (name "playbackbutton")
+X(prop help creator:user-act-help)
+X(label "playback to speaker")
+X(x 0.25)
+X(y 2)
+X(w 5.15)
+X(downfunc move-then-resize)
+X)
+X(pnl_wide_button (name "quitbutton")
+X(prop help creator:user-act-help)
+X(label "quit")
+X(x 0.25)
+X(y 0.25)
+X(w 1.75)
+X(downfunc move-then-resize)
+X)
+X)
+X)
+X;;; Local Variables:
+X;;; mode: scheme
+X;;; eval: (save-excursion (goto-char (point-min)) (kill-line 3))
+X;;; eval: (save-excursion (goto-char (point-min)) (replace-regexp "[ \n]*)" ")"))
+X;;; eval: (indent-region (point-min) (point-max) nil)
+X;;; eval: (progn (kill-line -3) (delete-backward-char 1) (save-buffer))
+X;;; End:
+EOF
+fi
+if test -s 'demo/sgi/gl_panel/flying/light.s'
+then echo '*** I will not over-write existing file demo/sgi/gl_panel/flying/light.s'
+else
+echo 'x - demo/sgi/gl_panel/flying/light.s'
+sed 's/^X//' > 'demo/sgi/gl_panel/flying/light.s' << 'EOF'
+X;;; This file was automatically generated by the panel editor.
+X;;; If you read it into gnu emacs, it will automagically format itself.
+X
+X(panel (prop help creator:user-panel-help)
+X(prop user-panel #t)
+X(label "Light Sources")
+X(al (pnl_hslider (name "X")
+X(prop help creator:user-act-help)
+X(label "x")
+X(y 4)
+X(w 3.3)
+X(h 0.4)
+X(val 0.50)
+X(labeltype 0)
+X(downfunc move-then-resize)
+X)
+X(pnl_hslider (name "Y")
+X(prop help creator:user-act-help)
+X(label "y")
+X(y 3.5)
+X(w 3.3)
+X(h 0.4)
+X(val 0.50)
+X(labeltype 0)
+X(downfunc move-then-resize)
+X)
+X(pnl_hslider (name "Z")
+X(prop help creator:user-act-help)
+X(label "z")
+X(y 3)
+X(w 3.3)
+X(h 0.4)
+X(val 0.50)
+X(labeltype 0)
+X(downfunc move-then-resize)
+X)
+X(pnl_radio_button (name "light2")
+X(prop help creator:user-act-help)
+X(label "light 2")
+X(x 5)
+X(y 4)
+X(h 0.36)
+X(downfunc move-then-resize)
+X)
+X(pnl_radio_button (name "light1")
+X(prop help creator:user-act-help)
+X(label "light 1")
+X(x 5)
+X(y 4.5)
+X(h 0.36)
+X(downfunc move-then-resize)
+X)
+X(pnl_toggle_button (name "local")
+X(prop help creator:user-act-help)
+X(label "local")
+X(x 5)
+X(y 2.75)
+X(downfunc move-then-resize)
+X)
+X(pnl_filled_hslider (name "B")
+X(prop help creator:user-act-help)
+X(label "B")
+X(w 3.3)
+X(h 0.4)
+X(labeltype 0)
+X(downfunc move-then-resize)
+X)
+X(pnl_filled_hslider (name "G")
+X(prop help creator:user-act-help)
+X(label "G")
+X(y 0.5)
+X(w 3.3)
+X(h 0.4)
+X(labeltype 0)
+X(downfunc move-then-resize)
+X)
+X(pnl_filled_hslider (name "R")
+X(prop help creator:user-act-help)
+X(label "R")
+X(y 1)
+X(w 3.3)
+X(h 0.4)
+X(labeltype 0)
+X(downfunc move-then-resize)
+X)
+X)
+X)
+X;;; Local Variables:
+X;;; mode: scheme
+X;;; eval: (save-excursion (goto-char (point-min)) (kill-line 3))
+X;;; eval: (save-excursion (goto-char (point-min)) (replace-regexp "[ \n]*)" ")"))
+X;;; eval: (indent-region (point-min) (point-max) nil)
+X;;; eval: (progn (kill-line -3) (delete-backward-char 1) (save-buffer))
+X;;; End:
+EOF
+fi
+if test -s 'demo/sgi/gl_panel/flying/panel.s'
+then echo '*** I will not over-write existing file demo/sgi/gl_panel/flying/panel.s'
+else
+echo 'x - demo/sgi/gl_panel/flying/panel.s'
+sed 's/^X//' > 'demo/sgi/gl_panel/flying/panel.s' << 'EOF'
+X;;; This file was automatically generated by the panel editor.
+X;;; If you read it into gnu emacs, it will automagically format itself.
+X
+X(panel (prop help creator:user-panel-help)
+X(prop user-panel #t)
+X(label "Panel Control")
+X(x 394)
+X(y 622)
+X(al (pnl_radio_button (name "button4")
+X(prop help creator:user-act-help)
+X(y 2.5)
+X(h 0.36)
+X(downfunc move-then-resize)
+X)
+X(pnl_radio_button (name "button3")
+X(prop help creator:user-act-help)
+X(y 3)
+X(h 0.36)
+X(downfunc move-then-resize)
+X)
+X(pnl_radio_button (name "button2")
+X(prop help creator:user-act-help)
+X(y 3.5)
+X(h 0.36)
+X(downfunc move-then-resize)
+X)
+X(pnl_radio_button (name "button1")
+X(prop help creator:user-act-help)
+X(y 4)
+X(h 0.36)
+X(downfunc move-then-resize)
+X)
+X(pnl_wide_button (name "title1")
+X(prop help creator:user-act-help)
+X(x 0.75)
+X(y 4.75)
+X(w 2.44)
+X(downfunc move-then-resize)
+X)
+X(pnl_wide_button (name "title2")
+X(prop help creator:user-act-help)
+X(x 3.5)
+X(y 4.75)
+X(w 2.44)
+X(downfunc move-then-resize)
+X)
+X(pnl_wide_button (name "title3")
+X(prop help creator:user-act-help)
+X(x 6.25)
+X(y 4.75)
+X(w 2.44)
+X(downfunc move-then-resize)
+X)
+X(pnl_wide_button (name "title4")
+X(prop help creator:user-act-help)
+X(x 9)
+X(y 4.75)
+X(w 2.44)
+X(downfunc move-then-resize)
+X)
+X(pnl_button (name "root")
+X(prop help creator:user-act-help)
+X(label "R")
+X(y 4.75)
+X(labeltype 16)
+X(downfunc move-then-resize)
+X)
+X)
+X)
+X;;; Local Variables:
+X;;; mode: scheme
+X;;; eval: (save-excursion (goto-char (point-min)) (kill-line 3))
+X;;; eval: (save-excursion (goto-char (point-min)) (replace-regexp "[ \n]*)" ")"))
+X;;; eval: (indent-region (point-min) (point-max) nil)
+X;;; eval: (progn (kill-line -3) (delete-backward-char 1) (save-buffer))
+X;;; End:
+EOF
+fi
+if test -s 'lib/Abstract.py'
+then echo '*** I will not over-write existing file lib/Abstract.py'
+else
+echo 'x - lib/Abstract.py'
+sed 's/^X//' > 'lib/Abstract.py' << 'EOF'
+X# Abstract classes for parents and children.
+X#
+X# Do not use as base class -- this is for documentation only.
+X#
+X# Note that the tree must be built top down (create the parent,
+X# then add the children).
+X#
+X# Also note that the creation methods are not standardized --
+X# these have extra parameters dependent on the widget type.
+X# For historical reasons, button creation methods are called
+X# define() while split creation methods are called create().
+X
+Xclass AbstractParent():
+X #
+X # Upcalls from child to parent
+X #
+X def addchild(self, child): unimpl()
+X def delchild(self, child): unimpl()
+X #
+X def need_mouse(self, child): unimpl()
+X def no_mouse(self, child): unimpl()
+X #
+X def need_timer(self, child): unimpl()
+X def no_timer(self, child): unimpl()
+X #
+X # XXX need_kbd, no_kbd; focus???
+X #
+X def begindrawing(self): return unimpl()
+X def beginmeasuring(self): return unimpl()
+X #
+X def change(self, area): unimpl()
+X def scroll(self, (area, (dh, dv))): unimpl()
+X def settimer(self, itimer): unimpl()
+X
+Xclass AbstractChild():
+X #
+X # Downcalls from parent to child
+X #
+X def destroy(self): unimpl()
+X #
+X def minsize(self, m): return unimpl()
+X def getbounds(self): return unimpl()
+X def setbounds(self, bounds): unimpl()
+X def draw(self, (d, area)): unimpl()
+X #
+X # Downcalls only made after certain upcalls
+X #
+X def mouse_down(self, detail): unimpl()
+X def mouse_move(self, detail): unimpl()
+X def mouse_up(self, detail): unimpl()
+X #
+X def timer(self): unimpl()
+X
+X# A "Split" is a child that manages one or more children.
+X# (This terminology is due to DEC SRC, except for CSplits.)
+X# A child of a split may be another split, a button, a slider, etc.
+X# Certain upcalls and downcalls can be handled transparently, but
+X# for others (e.g., all geometry related calls) this is not possible.
+X
+Xclass AbstractSplit() = AbstractChild(), AbstractParent():
+X pass
+EOF
+fi
+if test -s 'lib/StripChart.py'
+then echo '*** I will not over-write existing file lib/StripChart.py'
+else
+echo 'x - lib/StripChart.py'
+sed 's/^X//' > 'lib/StripChart.py' << 'EOF'
+X# Module 'StripChart'
+X
+Ximport rect
+Xfrom Buttons import LabelAppearance, NoReactivity
+X
+X# A StripChart doesn't really look like a label but it needs a base class.
+X# LabelAppearance allows it to be disabled and hilited.
+X
+Xclass StripChart() = LabelAppearance(), NoReactivity():
+X #
+X def define(self, (parent, scale)):
+X self.parent = parent
+X parent.addchild(self)
+X self.init_appearance()
+X self.init_reactivity()
+X self.ydata = []
+X self.scale = scale
+X self.resetbounds()
+X return self
+X #
+X def setbounds(self, bounds):
+X LabelAppearance.setbounds(self, bounds)
+X self.resetbounds()
+X #
+X def resetbounds(self):
+X (left, top), (right, bottom) = self.bounds
+X self.width = right-left
+X self.height = bottom-top
+X excess = len(self.ydata) - self.width
+X if excess > 0:
+X del self.ydata[:excess]
+X elif excess < 0:
+X while len(self.ydata) < self.width:
+X self.ydata.insert(0, 0)
+X #
+X def append(self, y):
+X self.ydata.append(y)
+X excess = len(self.ydata) - self.width
+X if excess > 0:
+X del self.ydata[:excess]
+X if self.bounds <> rect.empty:
+X self.parent.scroll(self.bounds, (-excess, 0))
+X if self.bounds <> rect.empty:
+X (left, top), (right, bottom) = self.bounds
+X i = len(self.ydata)
+X area = (left+i-1, top), (left+i, bottom)
+X self.draw(self.parent.begindrawing(), area)
+X #
+X def draw(self, (d, area)):
+X area = rect.intersect(area, self.bounds)
+X if area = rect.empty:
+X print 'mt'
+X return
+X d.cliprect(area)
+X d.erase(self.bounds)
+X (a_left, a_top), (a_right, a_bottom) = area
+X (left, top), (right, bottom) = self.bounds
+X height = bottom - top
+X i1 = a_left - left
+X i2 = a_right - left
+X for i in range(max(0, i1), min(len(self.ydata), i2)):
+X split = bottom-self.ydata[i]*height/self.scale
+X d.paint((left+i, split), (left+i+1, bottom))
+X if not self.enabled:
+X self.flipenable(d)
+X if self.hilited:
+X self.fliphilite(d)
+X d.noclip()
+EOF
+fi
+if test -s 'lib/cmp.py'
+then echo '*** I will not over-write existing file lib/cmp.py'
+else
+echo 'x - lib/cmp.py'
+sed 's/^X//' > 'lib/cmp.py' << 'EOF'
+X# Module 'cmp'
+X
+X# Efficiently compare files, boolean outcome only (equal / not equal).
+X
+X# Tricks (used in this order):
+X# - Files with identical type, size & mtime are assumed to be clones
+X# - Files with different type or size cannot be identical
+X# - We keep a cache of outcomes of earlier comparisons
+X# - We don't fork a process to run 'cmp' but read the files ourselves
+X
+Ximport posix
+X
+Xcache = {}
+X
+Xdef cmp(f1, f2): # Compare two files, use the cache if possible.
+X # Return 1 for identical files, 0 for different.
+X # Raise exceptions if either file could not be statted, read, etc.
+X s1, s2 = sig(posix.stat(f1)), sig(posix.stat(f2))
+X if s1[0] <> 8 or s2[0] <> 8:
+X # Either is a not a plain file -- always report as different
+X return 0
+X if s1 = s2:
+X # type, size & mtime match -- report same
+X return 1
+X if s1[:2] <> s2[:2]: # Types or sizes differ, don't bother
+X # types or sizes differ -- report different
+X return 0
+X # same type and size -- look in the cache
+X key = f1 + ' ' + f2
+X try:
+X cs1, cs2, outcome = cache[key]
+X # cache hit
+X if s1 = cs1 and s2 = cs2:
+X # cached signatures match
+X return outcome
+X # stale cached signature(s)
+X except RuntimeError:
+X # cache miss
+X pass
+X # really compare
+X outcome = do_cmp(f1, f2)
+X cache[key] = s1, s2, outcome
+X return outcome
+X
+Xdef sig(st): # Return signature (i.e., type, size, mtime) from raw stat data
+X # 0-5: st_mode, st_ino, st_dev, st_nlink, st_uid, st_gid
+X # 6-9: st_size, st_atime, st_mtime, st_ctime
+X type = st[0] / 4096
+X size = st[6]
+X mtime = st[8]
+X return type, size, mtime
+X
+Xdef do_cmp(f1, f2): # Compare two files, really
+X bufsize = 8096 # Could be tuned
+X fp1 = open(f1, 'r')
+X fp2 = open(f2, 'r')
+X while 1:
+X b1 = fp1.read(bufsize)
+X b2 = fp2.read(bufsize)
+X if b1 <> b2: return 0
+X if not b1: return 1
+EOF
+fi
+if test -s 'lib/commands.py'
+then echo '*** I will not over-write existing file lib/commands.py'
+else
+echo 'x - lib/commands.py'
+sed 's/^X//' > 'lib/commands.py' << 'EOF'
+X# Module 'commands'
+X#
+X# Various tools for executing commands and looking at their output and status.
+X
+Ximport rand
+Ximport posix
+Ximport stat
+Ximport path
+X
+X
+X# Get 'ls -l' status for an object into a string
+X#
+Xdef getstatus(file):
+X return getoutput('ls -ld' + mkarg(file))
+X
+X
+X# Get the output from a shell command into a string.
+X# The exit status is ignored; a trailing newline is stripped.
+X# Assume the command will work with ' >tempfile 2>&1' appended.
+X# XXX This should use posix.popen() instead, should it exist.
+X#
+Xdef getoutput(cmd):
+X return getstatusoutput(cmd)[1]
+X
+X
+X# Ditto but preserving the exit status.
+X# Returns a pair (sts, output)
+X#
+Xdef getstatusoutput(cmd):
+X tmp = '/usr/tmp/wdiff' + `rand.rand()`
+X sts = -1
+X try:
+X sts = posix.system(cmd + ' >' + tmp + ' 2>&1')
+X text = readfile(tmp)
+X finally:
+X altsts = posix.system('rm -f ' + tmp)
+X if text[-1:] = '\n': text = text[:-1]
+X return sts, text
+X
+X
+X# Return a string containing a file's contents.
+X#
+Xdef readfile(fn):
+X st = posix.stat(fn)
+X size = st[stat.ST_SIZE]
+X if not size: return ''
+X try:
+X fp = open(fn, 'r')
+X except:
+X raise posix.error, 'readfile(' + fn + '): open failed'
+X try:
+X return fp.read(size)
+X except:
+X raise posix.error, 'readfile(' + fn + '): read failed'
+X
+X
+X# Make command argument from directory and pathname (prefix space, add quotes).
+X#
+Xdef mk2arg(head, x):
+X return mkarg(path.cat(head, x))
+X
+X
+X# Make a shell command argument from a string.
+X# Two strategies: enclose in single quotes if it contains none;
+X# otherwis, enclose in double quotes and prefix quotable characters
+X# with backslash.
+X#
+Xdef mkarg(x):
+X if '\'' not in x:
+X return ' \'' + x + '\''
+X s = ' "'
+X for c in x:
+X if c in '\\$"':
+X s = s + '\\'
+X s = s + c
+X s = s + '"'
+X return s
+EOF
+fi
+if test -s 'lib/getopt.py'
+then echo '*** I will not over-write existing file lib/getopt.py'
+else
+echo 'x - lib/getopt.py'
+sed 's/^X//' > 'lib/getopt.py' << 'EOF'
+X# module getopt -- Standard command line processing.
+X
+X# Function getopt.getopt() has a different interface but provides the
+X# same functionality as the Unix getopt() function.
+X
+X# It has two arguments: the first should be argv[1:] (it doesn't want
+X# the script name), the second the string of option letters as passed
+X# to Unix getopt() (i.e., a string of allowable option letters, with
+X# options requiring an argument followed by a colon).
+X
+X# It raises the exception getopt.error with a string argument if it
+X# detects an error.
+X
+X# It returns two items:
+X# (1) a list of pairs (option, option_argument) giving the options in
+X# the order in which they were specified. (I'd use a dictionary
+X# but applications may depend on option order or multiple
+X# occurrences.) Boolean options have '' as option_argument.
+X# (2) the list of remaining arguments (may be empty).
+X
+Xerror = 'getopt error'
+X
+Xdef getopt(args, options):
+X list = []
+X while args and args[0][0] = '-' and args[0] <> '-':
+X if args[0] = '--':
+X args = args[1:]
+X break
+X optstring, args = args[0][1:], args[1:]
+X while optstring <> '':
+X opt, optstring = optstring[0], optstring[1:]
+X if classify(opt, options): # May raise exception as well
+X if optstring = '':
+X if not args:
+X raise error, 'option -' + opt + ' requires argument'
+X optstring, args = args[0], args[1:]
+X optarg, optstring = optstring, ''
+X else:
+X optarg = ''
+X list.append('-' + opt, optarg)
+X return list, args
+X
+Xdef classify(opt, options): # Helper to check type of option
+X for i in range(len(options)):
+X if opt = options[i] <> ':':
+X return options[i+1:i+2] = ':'
+X raise error, 'option -' + opt + ' not recognized'
+EOF
+fi
+if test -s 'lib/rect.py'
+then echo '*** I will not over-write existing file lib/rect.py'
+else
+echo 'x - lib/rect.py'
+sed 's/^X//' > 'lib/rect.py' << 'EOF'
+X# Module 'rect'.
+X#
+X# Operations on rectangles.
+X# There is some normalization: all results return the object 'empty'
+X# if their result would contain no points.
+X
+X
+X# Exception.
+X#
+Xerror = 'rect.error'
+X
+X
+X# The empty rectangle.
+X#
+Xempty = (0, 0), (0, 0)
+X
+X
+X# Check if a rectangle is empty.
+X#
+Xdef is_empty((left, top), (right, bottom)):
+X return left >= right or top >= bottom
+X
+X
+X# Compute the intersection or two or more rectangles.
+X# This works with a list or tuple argument.
+X#
+Xdef intersect(list):
+X if not list: raise error, 'intersect called with empty list'
+X if is_empty(list[0]): return empty
+X (left, top), (right, bottom) = list[0]
+X for rect in list[1:]:
+X if is_empty(rect):
+X return empty
+X (l, t), (r, b) = rect
+X if left < l: left = l
+X if top < t: top = t
+X if right > r: right = r
+X if bottom > b: bottom = b
+X if is_empty((left, top), (right, bottom)):
+X return empty
+X return (left, top), (right, bottom)
+X
+X
+X# Compute the smallest rectangle containing all given rectangles.
+X# This works with a list or tuple argument.
+X#
+Xdef union(list):
+X (left, top), (right, bottom) = empty
+X for (l, t), (r, b) in list[1:]:
+X if not is_empty((l, t), (r, b)):
+X if l < left: left = l
+X if t < top: top = t
+X if r > right: right = r
+X if b > bottom: bottom = b
+X res = (left, top), (right, bottom)
+X if is_empty(res):
+X return empty
+X return res
+X
+X
+X# Check if a point is in a rectangle.
+X#
+Xdef pointinrect((h, v), ((left, top), (right, bottom))):
+X return left <= h < right and top <= v < bottom
+X
+X
+X# Return a rectangle that is dh, dv inside another
+X#
+Xdef inset(((left, top), (right, bottom)), (dh, dv)):
+X left = left + dh
+X top = top + dv
+X right = right - dh
+X bottom = bottom - dv
+X r = (left, top), (right, bottom)
+X if is_empty(r):
+X return empty
+X else:
+X return r
+X
+X
+X# Conversions between rectangles and 'geometry tuples',
+X# given as origin (h, v) and dimensions (width, height).
+X#
+Xdef rect2geom((left, top), (right, bottom)):
+X return (left, top), (right-left, bottom-top)
+X
+Xdef geom2rect((h, v), (width, height)):
+X return (h, v), (h+width, v+height)
+EOF
+fi
+if test -s 'lib/selection.py'
+then echo '*** I will not over-write existing file lib/selection.py'
+else
+echo 'x - lib/selection.py'
+sed 's/^X//' > 'lib/selection.py' << 'EOF'
+X# DAWKINS' BLIND WATCHMAKER -- "METHINKS IT IS LIKE A WEASEL" EXAMPLE
+X#
+X# Start with a random phrase. Successively:
+X# Breed a next generation by copying with small mutations.
+X# Choose the member of the next generation that most closely resembles
+X# the target phrase to start breeding the next generation.
+X# How many generations will it take before the target is reached?
+X
+Xfrom whrandom import random
+X
+X# Parameters determining the problem space
+XTarget = 'methinks it is like a weasel'
+XAlphabet = ' abcdefghijklmnopqrstuvwxyz'
+X
+X# Parameters to play with
+XGenerationSize = 100
+XMutationChance = 1.0/28.0
+X
+XIndexSet = range(len(Target)) # Used to speed up loops
+X
+Xdef choice(sequence):
+X n = len(sequence)
+X i = int(random() * float(n)) % n
+X return sequence[i]
+X
+Xdef random_phrase():
+X phrase = ''
+X for i in IndexSet:
+X phrase = phrase + choice(Alphabet)
+X return phrase
+X
+Xdef mutate_phrase(phrase):
+X mutant = phrase
+X for i in range(int(0.5 + MutationChance*float(len(phrase)))):
+X i = choice(IndexSet)
+X c = choice(Alphabet)
+X mutant = mutant[:i] + c + mutant[i+1:]
+X #print `mutant`
+X return mutant
+X
+Xdef matching_factor(phrase):
+X factor = 0
+X for i in IndexSet:
+X if phrase[i] = Target[i]: factor = factor + 1
+X return factor
+X
+Xdef breed_generation(phrase):
+X generation = [phrase]
+X while len(generation) < GenerationSize:
+X generation.append(mutate_phrase(phrase))
+X return generation
+X
+Xdef select_best(generation):
+X factor, selected = -1, ''
+X for phrase in generation:
+X f = matching_factor(phrase)
+X if f > factor:
+X factor, selected = f, phrase
+X return selected
+X
+Xdef main():
+X gen = 0
+X phrase = random_phrase()
+X print gen, `phrase`
+X while phrase <> Target:
+X next_generation = breed_generation(phrase)
+X #print next_generation
+X phrase = select_best(next_generation)
+X gen = gen+1
+X print gen, `phrase`
+X
+Xmain()
+EOF
+fi
+if test -s 'lib/statcache.py'
+then echo '*** I will not over-write existing file lib/statcache.py'
+else
+echo 'x - lib/statcache.py'
+sed 's/^X//' > 'lib/statcache.py' << 'EOF'
+X# Module 'statcache'
+X#
+X# Maintain a cache of file stats.
+X# There are functions to reset the cache or to selectively remove items.
+X
+Ximport posix
+Xfrom stat import *
+X
+X# The cache.
+X# Keys are pathnames, values are `posix.stat' outcomes.
+X#
+Xcache = {}
+X
+X
+X# Stat a file, possibly out of the cache.
+X#
+Xdef stat(path):
+X if cache.has_key(path):
+X return cache[path]
+X cache[path] = ret = posix.stat(path)
+X return ret
+X
+X
+X# Reset the cache completely.
+X# Hack: to reset a global variable, we import this module.
+X#
+Xdef reset():
+X import statcache
+X # Check that we really imported the same module
+X if cache is not statcache.cache:
+X raise 'sorry, statcache identity crisis'
+X statcache.cache = {}
+X
+X
+X# Remove a given item from the cache, if it exists.
+X#
+Xdef forget(path):
+X if cache.has_key(path):
+X del cache[path]
+X
+X
+X# Remove all pathnames with a given prefix.
+X#
+Xdef forget_prefix(prefix):
+X n = len(prefix)
+X for path in cache.keys():
+X if path[:n] = prefix:
+X del cache[path]
+X
+X
+X# Forget about a directory and all entries in it, but not about
+X# entries in subdirectories.
+X#
+Xdef forget_dir(prefix):
+X if prefix[-1:] = '/' and prefix <> '/':
+X prefix = prefix[:-1]
+X forget(prefix)
+X if prefix[-1:] <> '/':
+X prefix = prefix + '/'
+X n = len(prefix)
+X for path in cache.keys():
+X if path[:n] = prefix:
+X rest = path[n:]
+X if rest[-1:] = '/': rest = rest[:-1]
+X if '/' not in rest:
+X del cache[path]
+X
+X
+X# Remove all pathnames except with a given prefix.
+X# Normally used with prefix = '/' after a chdir().
+X#
+Xdef forget_except_prefix(prefix):
+X n = len(prefix)
+X for path in cache.keys():
+X if path[:n] <> prefix:
+X del cache[path]
+X
+X
+X# Check for directory.
+X#
+Xdef isdir(path):
+X try:
+X st = stat(path)
+X except posix.error:
+X return 0
+X return S_ISDIR(st[ST_MODE])
+EOF
+fi
+if test -s 'src/allobjects.h'
+then echo '*** I will not over-write existing file src/allobjects.h'
+else
+echo 'x - src/allobjects.h'
+sed 's/^X//' > 'src/allobjects.h' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/* "allobjects.c" -- Source for precompiled header "allobjects.h" */
+X
+X#include <stdio.h>
+X#include <string.h>
+X
+X#include "PROTO.h"
+X
+X#include "object.h"
+X#include "objimpl.h"
+X
+X#include "intobject.h"
+X#include "floatobject.h"
+X#include "stringobject.h"
+X#include "tupleobject.h"
+X#include "listobject.h"
+X#include "dictobject.h"
+X#include "methodobject.h"
+X#include "moduleobject.h"
+X#include "funcobject.h"
+X#include "classobject.h"
+X#include "fileobject.h"
+X
+X#include "errors.h"
+X#include "malloc.h"
+X
+Xextern char *strdup PROTO((const char *));
+EOF
+fi
+if test -s 'src/bitset.h'
+then echo '*** I will not over-write existing file src/bitset.h'
+else
+echo 'x - src/bitset.h'
+sed 's/^X//' > 'src/bitset.h' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/* Bitset interface */
+X
+X#define BYTE char
+X
+Xtypedef BYTE *bitset;
+X
+Xbitset newbitset PROTO((int nbits));
+Xvoid delbitset PROTO((bitset bs));
+X/* int testbit PROTO((bitset bs, int ibit)); /* Now a macro, see below */
+Xint addbit PROTO((bitset bs, int ibit)); /* Returns 0 if already set */
+Xint samebitset PROTO((bitset bs1, bitset bs2, int nbits));
+Xvoid mergebitset PROTO((bitset bs1, bitset bs2, int nbits));
+X
+X#define BITSPERBYTE (8*sizeof(BYTE))
+X#define NBYTES(nbits) (((nbits) + BITSPERBYTE - 1) / BITSPERBYTE)
+X
+X#define BIT2BYTE(ibit) ((ibit) / BITSPERBYTE)
+X#define BIT2SHIFT(ibit) ((ibit) % BITSPERBYTE)
+X#define BIT2MASK(ibit) (1 << BIT2SHIFT(ibit))
+X#define BYTE2BIT(ibyte) ((ibyte) * BITSPERBYTE)
+X
+X#define testbit(ss, ibit) (((ss)[BIT2BYTE(ibit)] & BIT2MASK(ibit)) != 0)
+EOF
+fi
+if test -s 'src/cgensupport.h'
+then echo '*** I will not over-write existing file src/cgensupport.h'
+else
+echo 'x - src/cgensupport.h'
+sed 's/^X//' > 'src/cgensupport.h' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/* Definitions used by cgen output */
+X
+Xtypedef char *string;
+X
+X#define mknewlongobject(x) newintobject(x)
+X#define mknewshortobject(x) newintobject((long)x)
+X#define mknewfloatobject(x) newfloatobject(x)
+X
+Xextern object *mknewcharobject PROTO((int c));
+X
+Xextern int getiobjectarg PROTO((object *args, int nargs, int i, object **p_a));
+Xextern int getilongarg PROTO((object *args, int nargs, int i, long *p_a));
+Xextern int getishortarg PROTO((object *args, int nargs, int i, short *p_a));
+Xextern int getifloatarg PROTO((object *args, int nargs, int i, float *p_a));
+Xextern int getistringarg PROTO((object *args, int nargs, int i, string *p_a));
+EOF
+fi
+if test -s 'src/classobject.h'
+then echo '*** I will not over-write existing file src/classobject.h'
+else
+echo 'x - src/classobject.h'
+sed 's/^X//' > 'src/classobject.h' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/* Class object interface */
+X
+X/*
+XClasses are really hacked in at the last moment.
+XIt should be possible to use other object types as base classes,
+Xbut currently it isn't. We'll see if we can fix that later, sigh...
+X*/
+X
+Xextern typeobject Classtype, Classmembertype, Classmethodtype;
+X
+X#define is_classobject(op) ((op)->ob_type == &Classtype)
+X#define is_classmemberobject(op) ((op)->ob_type == &Classmembertype)
+X#define is_classmethodobject(op) ((op)->ob_type == &Classmethodtype)
+X
+Xextern object *newclassobject PROTO((object *, object *));
+Xextern object *newclassmemberobject PROTO((object *));
+Xextern object *newclassmethodobject PROTO((object *, object *));
+X
+Xextern object *classmethodgetfunc PROTO((object *));
+Xextern object *classmethodgetself PROTO((object *));
+EOF
+fi
+if test -s 'src/compile.h'
+then echo '*** I will not over-write existing file src/compile.h'
+else
+echo 'x - src/compile.h'
+sed 's/^X//' > 'src/compile.h' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/* Definitions for compiled intermediate code */
+X
+X
+X/* An intermediate code fragment contains:
+X - a string that encodes the instructions,
+X - a list of the constants,
+X - and a list of the names used. */
+X
+Xtypedef struct {
+X OB_HEAD
+X stringobject *co_code; /* instruction opcodes */
+X object *co_consts; /* list of immutable constant objects */
+X object *co_names; /* list of stringobjects */
+X object *co_filename; /* string */
+X} codeobject;
+X
+Xextern typeobject Codetype;
+X
+X#define is_codeobject(op) ((op)->ob_type == &Codetype)
+X
+X
+X/* Public interface */
+Xcodeobject *compile PROTO((struct _node *, char *));
+EOF
+fi
+if test -s 'src/dictobject.h'
+then echo '*** I will not over-write existing file src/dictobject.h'
+else
+echo 'x - src/dictobject.h'
+sed 's/^X//' > 'src/dictobject.h' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/*
+XDictionary object type -- mapping from char * to object.
+XNB: the key is given as a char *, not as a stringobject.
+XThese functions set errno for errors. Functions dictremove() and
+Xdictinsert() return nonzero for errors, getdictsize() returns -1,
+Xthe others NULL. A successful call to dictinsert() calls INCREF()
+Xfor the inserted item.
+X*/
+X
+Xextern typeobject Dicttype;
+X
+X#define is_dictobject(op) ((op)->ob_type == &Dicttype)
+X
+Xextern object *newdictobject PROTO((void));
+Xextern object *dictlookup PROTO((object *dp, char *key));
+Xextern int dictinsert PROTO((object *dp, char *key, object *item));
+Xextern int dictremove PROTO((object *dp, char *key));
+Xextern int getdictsize PROTO((object *dp));
+Xextern char *getdictkey PROTO((object *dp, int i));
+Xextern object *getdictkeys PROTO((object *dp));
+EOF
+fi
+if test -s 'src/errors.h'
+then echo '*** I will not over-write existing file src/errors.h'
+else
+echo 'x - src/errors.h'
+sed 's/^X//' > 'src/errors.h' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/* Error handling definitions */
+X
+Xvoid err_set PROTO((object *));
+Xvoid err_setval PROTO((object *, object *));
+Xvoid err_setstr PROTO((object *, char *));
+Xint err_occurred PROTO((void));
+Xvoid err_get PROTO((object **, object **));
+Xvoid err_clear PROTO((void));
+X
+X/* Predefined exceptions */
+X
+Xextern object *RuntimeError;
+Xextern object *EOFError;
+Xextern object *TypeError;
+Xextern object *MemoryError;
+Xextern object *NameError;
+Xextern object *SystemError;
+Xextern object *KeyboardInterrupt;
+X
+X/* Some more planned for the future */
+X
+X#define IndexError RuntimeError
+X#define KeyError RuntimeError
+X#define ZeroDivisionError RuntimeError
+X#define OverflowError RuntimeError
+X
+X/* Convenience functions */
+X
+Xextern int err_badarg PROTO((void));
+Xextern object *err_nomem PROTO((void));
+Xextern object *err_errno PROTO((object *));
+Xextern void err_input PROTO((int));
+X
+Xextern void err_badcall PROTO((void));
+EOF
+fi
+if test -s 'src/grammar1.c'
+then echo '*** I will not over-write existing file src/grammar1.c'
+else
+echo 'x - src/grammar1.c'
+sed 's/^X//' > 'src/grammar1.c' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/* Grammar subroutines needed by parser */
+X
+X#include "pgenheaders.h"
+X#include "assert.h"
+X#include "grammar.h"
+X#include "token.h"
+X
+X/* Return the DFA for the given type */
+X
+Xdfa *
+Xfinddfa(g, type)
+X grammar *g;
+X register int type;
+X{
+X register int i;
+X register dfa *d;
+X
+X for (i = g->g_ndfas, d = g->g_dfa; --i >= 0; d++) {
+X if (d->d_type == type)
+X return d;
+X }
+X assert(0);
+X /* NOTREACHED */
+X}
+X
+Xchar *
+Xlabelrepr(lb)
+X label *lb;
+X{
+X static char buf[100];
+X
+X if (lb->lb_type == ENDMARKER)
+X return "EMPTY";
+X else if (ISNONTERMINAL(lb->lb_type)) {
+X if (lb->lb_str == NULL) {
+X sprintf(buf, "NT%d", lb->lb_type);
+X return buf;
+X }
+X else
+X return lb->lb_str;
+X }
+X else {
+X if (lb->lb_str == NULL)
+X return tok_name[lb->lb_type];
+X else {
+X sprintf(buf, "%.32s(%.32s)",
+X tok_name[lb->lb_type], lb->lb_str);
+X return buf;
+X }
+X }
+X}
+EOF
+fi
+if test -s 'src/malloc.h'
+then echo '*** I will not over-write existing file src/malloc.h'
+else
+echo 'x - src/malloc.h'
+sed 's/^X//' > 'src/malloc.h' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/* Lowest-level memory allocation interface */
+X
+X#ifdef THINK_C
+X#define ANY void
+X#ifndef THINK_C_3_0
+X#define HAVE_STDLIB
+X#endif
+X#endif
+X
+X#ifdef __STD_C__
+X#define ANY void
+X#define HAVE_STDLIB
+X#endif
+X
+X#ifndef ANY
+X#define ANY char
+X#endif
+X
+X#ifndef NULL
+X#define NULL 0
+X#endif
+X
+X#define NEW(type, n) ( (type *) malloc((n) * sizeof(type)) )
+X#define RESIZE(p, type, n) \
+X if ((p) == NULL) \
+X (p) = (type *) malloc((n) * sizeof(type)); \
+X else \
+X (p) = (type *) realloc((char *)(p), (n) * sizeof(type))
+X#define DEL(p) free((char *)p)
+X#define XDEL(p) if ((p) == NULL) ; else DEL(p)
+X
+X#ifdef HAVE_STDLIB
+X#include <stdlib.h>
+X#else
+Xextern ANY *malloc PROTO((unsigned int));
+Xextern ANY *calloc PROTO((unsigned int, unsigned int));
+Xextern ANY *realloc PROTO((ANY *, unsigned int));
+Xextern void free PROTO((ANY *)); /* XXX sometimes int on Unix old systems */
+X#endif
+EOF
+fi
+if test -s 'src/node.h'
+then echo '*** I will not over-write existing file src/node.h'
+else
+echo 'x - src/node.h'
+sed 's/^X//' > 'src/node.h' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/* Parse tree node interface */
+X
+Xtypedef struct _node {
+X int n_type;
+X char *n_str;
+X int n_lineno;
+X int n_nchildren;
+X struct _node *n_child;
+X} node;
+X
+Xextern node *newtree PROTO((int type));
+Xextern node *addchild PROTO((node *n, int type, char *str, int lineno));
+Xextern void freetree PROTO((node *n));
+X
+X/* Node access functions */
+X#define NCH(n) ((n)->n_nchildren)
+X#define CHILD(n, i) (&(n)->n_child[i])
+X#define TYPE(n) ((n)->n_type)
+X#define STR(n) ((n)->n_str)
+X
+X/* Assert that the type of a node is what we expect */
+X#ifndef DEBUG
+X#define REQ(n, type) { /*pass*/ ; }
+X#else
+X#define REQ(n, type) \
+X { if (TYPE(n) != (type)) { \
+X fprintf(stderr, "FATAL: node type %d, required %d\n", \
+X TYPE(n), type); \
+X abort(); \
+X } }
+X#endif
+X
+Xextern void listtree PROTO((node *));
+Xextern void listnode PROTO((FILE *, node *));
+EOF
+fi
+if test -s 'src/parser.h'
+then echo '*** I will not over-write existing file src/parser.h'
+else
+echo 'x - src/parser.h'
+sed 's/^X//' > 'src/parser.h' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/* Parser interface */
+X
+X#define MAXSTACK 100
+X
+Xtypedef struct _stackentry {
+X int s_state; /* State in current DFA */
+X dfa *s_dfa; /* Current DFA */
+X struct _node *s_parent; /* Where to add next node */
+X} stackentry;
+X
+Xtypedef struct _stack {
+X stackentry *s_top; /* Top entry */
+X stackentry s_base[MAXSTACK];/* Array of stack entries */
+X /* NB The stack grows down */
+X} stack;
+X
+Xtypedef struct {
+X struct _stack p_stack; /* Stack of parser states */
+X struct _grammar *p_grammar; /* Grammar to use */
+X struct _node *p_tree; /* Top of parse tree */
+X} parser_state;
+X
+Xparser_state *newparser PROTO((struct _grammar *g, int start));
+Xvoid delparser PROTO((parser_state *ps));
+Xint addtoken PROTO((parser_state *ps, int type, char *str, int lineno));
+Xvoid addaccelerators PROTO((grammar *g));
+EOF
+fi
+if test -s 'src/pgenheaders.h'
+then echo '*** I will not over-write existing file src/pgenheaders.h'
+else
+echo 'x - src/pgenheaders.h'
+sed 's/^X//' > 'src/pgenheaders.h' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/* Include files and extern declarations used by most of the parser.
+X This is a precompiled header for THINK C. */
+X
+X#include <stdio.h>
+X#include <string.h>
+X
+X#ifdef THINK_C
+X/* #define THINK_C_3_0 /*** TURN THIS ON FOR THINK C 3.0 ****/
+X#define label label_
+X#undef label
+X#endif
+X
+X#ifdef THINK_C_3_0
+X#include <proto.h>
+X#endif
+X
+X#ifdef THINK_C
+X#ifndef THINK_C_3_0
+X#include <stdlib.h>
+X#endif
+X#endif
+X
+X#include "PROTO.h"
+X#include "malloc.h"
+X
+Xextern void fatal PROTO((char *));
+EOF
+fi
+if test -s 'src/pythonrun.h'
+then echo '*** I will not over-write existing file src/pythonrun.h'
+else
+echo 'x - src/pythonrun.h'
+sed 's/^X//' > 'src/pythonrun.h' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/* Interfaces to parse and execute pieces of python code */
+X
+Xvoid initall PROTO((void));
+X
+Xint run PROTO((FILE *, char *));
+X
+Xint run_script PROTO((FILE *, char *));
+Xint run_tty_1 PROTO((FILE *, char *));
+Xint run_tty_loop PROTO((FILE *, char *));
+X
+Xint parse_string PROTO((char *, int, struct _node **));
+Xint parse_file PROTO((FILE *, char *, int, struct _node **));
+X
+Xobject *eval_node PROTO((struct _node *, char *, object *, object *));
+X
+Xobject *run_string PROTO((char *, int, object *, object *));
+Xobject *run_file PROTO((FILE *, char *, int, object *, object *));
+Xobject *run_err_node PROTO((int, struct _node *, char *, object *, object *));
+Xobject *run_node PROTO((struct _node *, char *, object *, object *));
+X
+Xvoid print_error PROTO((void));
+X
+Xvoid goaway PROTO((int));
+EOF
+fi
+if test -s 'src/regexp.h'
+then echo '*** I will not over-write existing file src/regexp.h'
+else
+echo 'x - src/regexp.h'
+sed 's/^X//' > 'src/regexp.h' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/*
+X * Definitions etc. for regexp(3) routines.
+X *
+X * Caveat: this is V8 regexp(3) [actually, a reimplementation thereof],
+X * not the System V one.
+X */
+X
+X#define MULTILINE
+X
+X#define NSUBEXP 10
+Xtypedef struct regexp {
+X char *startp[NSUBEXP];
+X char *endp[NSUBEXP];
+X char regstart; /* Internal use only. */
+X char reganch; /* Internal use only. */
+X char *regmust; /* Internal use only. */
+X int regmlen; /* Internal use only. */
+X char program[1]; /* Unwarranted chumminess with compiler. */
+X} regexp;
+X
+Xextern regexp *regcomp();
+Xextern int regexec();
+X#ifdef MULTILINE
+Xextern int reglexec();
+X#endif
+Xextern void regsub();
+Xextern void regerror();
+EOF
+fi
+if test -s 'src/sigtype.h'
+then echo '*** I will not over-write existing file src/sigtype.h'
+else
+echo 'x - src/sigtype.h'
+sed 's/^X//' > 'src/sigtype.h' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/* The type of signal handlers is somewhat problematic.
+X This file encapsulates my knowledge about it:
+X - on the Mac (THINK C), it's int for 3.0, void for 4.0
+X - on other systems, it's usually void, except it's int on vax Ultrix.
+X Pass -DSIGTYPE=... to cc if you know better. */
+X
+X#ifndef SIGTYPE
+X
+X#ifdef THINK_C
+X
+X#ifdef THINK_C_3_0
+X#define SIGTYPE int
+X#else
+X#define SIGTYPE void
+X#endif
+X
+X#else /* !THINK_C */
+X
+X#if defined(vax) && !defined(AMOEBA)
+X#define SIGTYPE int
+X#else
+X#define SIGTYPE void
+X#endif
+X
+X#endif /* !THINK_C */
+X
+X#endif /* !SIGTYPE */
+EOF
+fi
+if test -s 'src/token.h'
+then echo '*** I will not over-write existing file src/token.h'
+else
+echo 'x - src/token.h'
+sed 's/^X//' > 'src/token.h' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/* Token types */
+X
+X#define ENDMARKER 0
+X#define NAME 1
+X#define NUMBER 2
+X#define STRING 3
+X#define NEWLINE 4
+X#define INDENT 5
+X#define DEDENT 6
+X#define LPAR 7
+X#define RPAR 8
+X#define LSQB 9
+X#define RSQB 10
+X#define COLON 11
+X#define COMMA 12
+X#define SEMI 13
+X#define PLUS 14
+X#define MINUS 15
+X#define STAR 16
+X#define SLASH 17
+X#define VBAR 18
+X#define AMPER 19
+X#define LESS 20
+X#define GREATER 21
+X#define EQUAL 22
+X#define DOT 23
+X#define PERCENT 24
+X#define BACKQUOTE 25
+X#define LBRACE 26
+X#define RBRACE 27
+X#define OP 28
+X#define ERRORTOKEN 29
+X#define N_TOKENS 30
+X
+X/* Special definitions for cooperation with parser */
+X
+X#define NT_OFFSET 256
+X
+X#define ISTERMINAL(x) ((x) < NT_OFFSET)
+X#define ISNONTERMINAL(x) ((x) >= NT_OFFSET)
+X#define ISEOF(x) ((x) == ENDMARKER)
+X
+X
+Xextern char *tok_name[]; /* Token names */
+Xextern int tok_1char PROTO((int));
+EOF
+fi
+if test -s 'src/typeobject.c'
+then echo '*** I will not over-write existing file src/typeobject.c'
+else
+echo 'x - src/typeobject.c'
+sed 's/^X//' > 'src/typeobject.c' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/* Type object implementation */
+X
+X#include "allobjects.h"
+X
+X/* Type object implementation */
+X
+Xstatic void
+Xtype_print(v, fp, flags)
+X typeobject *v;
+X FILE *fp;
+X int flags;
+X{
+X fprintf(fp, "<type '%s'>", v->tp_name);
+X}
+X
+Xstatic object *
+Xtype_repr(v)
+X typeobject *v;
+X{
+X char buf[100];
+X sprintf(buf, "<type '%.80s'>", v->tp_name);
+X return newstringobject(buf);
+X}
+X
+Xtypeobject Typetype = {
+X OB_HEAD_INIT(&Typetype)
+X 0, /* Number of items for varobject */
+X "type", /* Name of this type */
+X sizeof(typeobject), /* Basic object size */
+X 0, /* Item size for varobject */
+X 0, /*tp_dealloc*/
+X type_print, /*tp_print*/
+X 0, /*tp_getattr*/
+X 0, /*tp_setattr*/
+X 0, /*tp_compare*/
+X type_repr, /*tp_repr*/
+X};
+EOF
+fi
+echo 'Part 19 out of 21 of pack.out complete.'
+exit 0
diff --git a/shar/python-0.9.1-20-21.shar b/shar/python-0.9.1-20-21.shar
new file mode 100644
index 0000000..59df200
--- /dev/null
+++ b/shar/python-0.9.1-20-21.shar
@@ -0,0 +1,1941 @@
+: This is a shell archive.
+: Extract with 'sh this_file'.
+:
+: Extract part 01 first since it makes all directories
+echo 'Start of pack.out, part 20 out of 21:'
+if test -s 'demo/scripts/mkreal.py'
+then echo '*** I will not over-write existing file demo/scripts/mkreal.py'
+else
+echo 'x - demo/scripts/mkreal.py'
+sed 's/^X//' > 'demo/scripts/mkreal.py' << 'EOF'
+X#! /ufs/guido/bin/sgi/python
+X
+X# mkreal
+X#
+X# turn a symlink to a directory into a real directory
+X
+Ximport sys
+Ximport posix
+Ximport path
+Xfrom stat import *
+X
+Xcat = path.cat
+X
+Xerror = 'mkreal error'
+X
+XBUFSIZE = 32*1024
+X
+Xdef mkrealfile(name):
+X st = posix.stat(name) # Get the mode
+X mode = S_IMODE(st[ST_MODE])
+X linkto = posix.readlink(name) # Make sure again it's a symlink
+X f_in = open(name, 'r') # This ensures it's a file
+X posix.unlink(name)
+X f_out = open(name, 'w')
+X while 1:
+X buf = f_in.read(BUFSIZE)
+X if not buf: break
+X f_out.write(buf)
+X del f_out # Flush data to disk before changing mode
+X posix.chmod(name, mode)
+X
+Xdef mkrealdir(name):
+X st = posix.stat(name) # Get the mode
+X mode = S_IMODE(st[ST_MODE])
+X linkto = posix.readlink(name)
+X files = posix.listdir(name)
+X posix.unlink(name)
+X posix.mkdir(name, mode)
+X posix.chmod(name, mode)
+X linkto = cat('..', linkto)
+X #
+X for file in files:
+X if file not in ('.', '..'):
+X posix.symlink(cat(linkto, file), cat(name, file))
+X
+Xdef main():
+X sys.stdout = sys.stderr
+X progname = path.basename(sys.argv[0])
+X args = sys.argv[1:]
+X if not args:
+X print 'usage:', progname, 'path ...'
+X sys.exit(2)
+X status = 0
+X for name in args:
+X if not path.islink(name):
+X print progname+':', name+':', 'not a symlink'
+X status = 1
+X else:
+X if path.isdir(name):
+X mkrealdir(name)
+X else:
+X mkrealfile(name)
+X sys.exit(status)
+X
+Xmain()
+EOF
+chmod +x 'demo/scripts/mkreal.py'
+fi
+if test -s 'demo/scripts/ptags.py'
+then echo '*** I will not over-write existing file demo/scripts/ptags.py'
+else
+echo 'x - demo/scripts/ptags.py'
+sed 's/^X//' > 'demo/scripts/ptags.py' << 'EOF'
+X#! /ufs/guido/bin/sgi/python
+X
+X# ptags
+X#
+XCreate a tags file for Python programs
+X# Tagged are:
+X# - functions (even inside other defs or classes)
+X# - classes
+X# - filenames
+X# Warns about files it cannot open.
+X# No warnings about duplicate tags.
+X
+Ximport sys
+Ximport posix
+Ximport path
+Ximport string
+X
+Xkeywords = ['def', 'class'] # If you add keywords, update starts!!!
+Xstarts = 'dc' # Starting characters of keywords
+X
+Xwhitespace = string.whitespace
+Xidentchars = string.letters + string.digits + '_'
+X
+Xtags = [] # Modified!
+X
+Xdef main():
+X args = sys.argv[1:]
+X for file in args: treat_file(file)
+X if tags:
+X fp = open('tags', 'w')
+X tags.sort()
+X for s in tags: fp.write(s)
+X
+Xdef treat_file(file):
+X try:
+X fp = open(file, 'r')
+X except:
+X print 'Cannot open', file
+X return
+X base = path.basename(file)
+X if base[-3:] = '.py': base = base[:-3]
+X s = base + '\t' + file + '\t' + '1\n'
+X tags.append(s)
+X while 1:
+X line = fp.readline()
+X if not line: break
+X maketag(line, file)
+X
+Xdef maketag(line, file):
+X i = 0
+X while line[i:i+1] in whitespace: i = i+1
+X if line[i:i+1] not in starts: return
+X n = len(line)
+X j = i
+X while i < n and line[i] not in whitespace: i = i+1
+X if line[j:i] not in keywords: return
+X while i < n and line[i] in whitespace: i = i+1
+X j = i
+X while i < n and line[i] in identchars: i = i+1
+X name = line[j:i]
+X while i < n and line[i] in whitespace: i = i+1
+X if i < n and line[i] = '(': i = i+1
+X s = name + '\t' + file + '\t' + '/^' + line[:i] + '/\n'
+X tags.append(s)
+X
+Xmain()
+EOF
+chmod +x 'demo/scripts/ptags.py'
+fi
+if test -s 'demo/sgi/audio/play.py'
+then echo '*** I will not over-write existing file demo/sgi/audio/play.py'
+else
+echo 'x - demo/sgi/audio/play.py'
+sed 's/^X//' > 'demo/sgi/audio/play.py' << 'EOF'
+X#!/ufs/guido/bin/sgi/python
+X
+Ximport sys
+Ximport audio
+X
+Ximport string
+Ximport getopt
+Ximport auds
+X
+Xdebug = []
+X
+XDEF_RATE = 3
+X
+Xdef main():
+X #
+X gain = 100
+X rate = 0
+X starter = audio.write
+X stopper = 0
+X #
+X optlist, args = getopt.getopt(sys.argv[1:], 'adg:r:')
+X #
+X for optname, optarg in optlist:
+X if 0:
+X pass
+X elif optname = '-d':
+X debug.append(1)
+X elif optname = '-g':
+X gain = string.atoi(optarg)
+X if not (0 < gain < 256):
+X raise optarg.error, '-g gain out of range'
+X elif optname = '-r':
+X rate = string.atoi(optarg)
+X if not (1 <= rate <= 3):
+X raise optarg.error, '-r rate out of range'
+X elif optname = '-a':
+X starter = audio.start_playing
+X stopper = audio.wait_playing
+X #
+X audio.setoutgain(gain)
+X audio.setrate(rate)
+X #
+X if not args:
+X play(starter, rate, auds.loadfp(sys.stdin))
+X else:
+X real_stopper = 0
+X for file in args:
+X if real_stopper:
+X real_stopper()
+X play(starter, rate, auds.load(file))
+X real_stopper = stopper
+X
+Xdef play(starter, rate, data):
+X magic = data[:4]
+X if magic = '0008':
+X mrate = 3
+X elif magic = '0016':
+X mrate = 2
+X elif magic = '0032':
+X mrate = 1
+X else:
+X mrate = 0
+X if mrate:
+X data = data[4:]
+X else:
+X mrate = DEF_RATE
+X if not rate: rate = mrate
+X audio.setrate(rate)
+X starter(data)
+X
+Xtry:
+X main()
+Xfinally:
+X audio.setoutgain(0)
+X audio.done()
+EOF
+chmod +x 'demo/sgi/audio/play.py'
+fi
+if test -s 'demo/sgi/gl_panel/flying/data.py'
+then echo '*** I will not over-write existing file demo/sgi/gl_panel/flying/data.py'
+else
+echo 'x - demo/sgi/gl_panel/flying/data.py'
+sed 's/^X//' > 'demo/sgi/gl_panel/flying/data.py' << 'EOF'
+X
+X# two string constants
+XARROW = '-> '
+XNULL = ''
+XZERO = 0
+XONE = 1
+X
+X#
+X# the color light-blue
+X#
+Xlightblue = (43,169,255)
+X
+X
+X#
+X# a couple of rotation, translation, scaling vectors
+X#
+Xrts1 = [[3.0,3.1,2.0],[2.2, 1.2, 2.0], [0.8,0.8,0.8]]
+Xrts2 = [[3.2,2.6,1.8],[-1.9, 1.2, 1.6], [0.3,0.3,1.0]]
+Xrts3 = [[2.2,3.3,1.4], [-1.0, 1.2,-1.5], [0.6,0.6, 0.6]]
+Xrts4 = [[4.2,2.1,3.2],[1.2, 1.3, 1.0],[0.5,0.5,0.8]]
+Xrts5 = [[1.2,3.3,2.4], [-2.0, 1.4,-2.1], [0.8, 0.8, 0.2]]
+Xrts6 = [[3.2,3.6,2.4], [1.1, 1.6, 2.5], [0.8,0.3,0.1]]
+Xrts7 = [[2.3,2.7,3.3], [1.1, 2.3, 1.7], [0.6,0.6,0.5]]
+Xrts8 = [[4.2,2.1,3.2], [1.2, 1.3, 0.0], [0.5,0.5,0.5]]
+X#
+Xrts90 = [[4.2,2.1,3.2], [2.0, 0.0, 0.9], [0.3,0.3,1.0]]
+Xrts91 = [[4.2,2.1,3.2], [-2.0, 0.0, 0.9], [0.3,0.3,1.0]]
+Xrts92 = [[4.2,2.1,3.2], [0.0, 2.0, 0.9], [0.3,0.3,1.0]]
+Xrts93 = [[4.2,2.1,3.2], [0.0, -2.0, 0.9], [0.3,0.3,1.0]]
+Xrts10 = [[4.2,2.1,3.2], [0.0, 0.0, 0.0], [2.2,2.2,0.2]]
+X
+X#
+X# (composite) object definitions
+X#
+Xo1 = [['sphere',rts1, 1]]
+Xo2 = [['cylinder', rts2, 4]]
+Xo3 = [['cube', rts3, 3]]
+Xo4 = [['cone', rts4, 2], ['sphere', rts8, 9]]
+Xo5 = [['sphere', rts5, 5]]
+Xo6 = [['cube', rts6, 6]]
+Xo7 = [['pyramid', rts7, 8]]
+Xo8 = [['cube', rts10, 9], ['cylinder', rts90, 2], ['cylinder', rts91, 2], ['cylinder', rts92, 2], ['cylinder', rts93, 2]]
+EOF
+fi
+if test -s 'demo/sgi/gl_panel/nurbs/nurbsdata.py'
+then echo '*** I will not over-write existing file demo/sgi/gl_panel/nurbs/nurbsdata.py'
+else
+echo 'x - demo/sgi/gl_panel/nurbs/nurbsdata.py'
+sed 's/^X//' > 'demo/sgi/gl_panel/nurbs/nurbsdata.py' << 'EOF'
+X# Data used by fancy nurbs demo.
+X
+XTRUE = 1
+XFALSE = 0
+X
+XRED = 0xff
+XYELLOW = 0xffff
+X
+X#
+X# nurb order
+X#
+XORDER = 4
+X
+X#
+X# identity matrix
+X#
+Xidmat = [1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1]
+X
+X#
+X# s and t knots
+X#
+Xsurfknots = [-1, -1, -1, -1, 1, 1, 1, 1]
+X
+X#
+X# list of list of control points
+X#
+Xdef make_ctlpoints():
+X c = []
+X #
+X ci = []
+X ci.append(-2.5, -3.7, 1.0)
+X ci.append(-1.5, -3.7, 3.0)
+X ci.append(1.5, -3.7, -2.5)
+X ci.append(2.5, -3.7, -0.75)
+X c.append(ci)
+X #
+X ci = []
+X ci.append(-2.5, -2.0, 3.0)
+X ci.append(-1.5, -2.0, 4.0)
+X ci.append(1.5, -2.0, -3.0)
+X ci.append(2.5, -2.0, 0.0)
+X c.append(ci)
+X #
+X ci = []
+X ci.append(-2.5, 2.0, 1.0)
+X ci.append(-1.5, 2.0, 0.0)
+X ci.append(1.5, 2.0, -1.0)
+X ci.append(2.5, 2.0, 2.0)
+X c.append(ci)
+X #
+X ci = []
+X ci.append(-2.5, 2.7, 1.25)
+X ci.append(-1.5, 2.7, 0.1)
+X ci.append(1.5, 2.7, -0.6)
+X ci.append(2.5, 2.7, 0.2)
+X c.append(ci)
+X #
+X return c
+X
+Xctlpoints = make_ctlpoints ()
+X
+X#
+X# trim knots
+X#
+Xtrimknots = [0., 0., 0., 1., 1., 2., 2., 3., 3., 4., 4., 4.]
+X
+Xdef make_trimpoints():
+X c = []
+X #
+X c.append(1.0, 0.0, 1.0)
+X c.append(1.0, 1.0, 1.0)
+X c.append(0.0, 2.0, 2.0)
+X c.append(-1.0, 1.0, 1.0)
+X c.append(-1.0, 0.0, 1.0)
+X c.append(-1.0, -1.0, 1.0)
+X c.append(0.0, -2.0, 2.0)
+X c.append(1.0, -1.0, 1.0)
+X c.append(1.0, 0.0, 1.0)
+X #
+X return c
+X
+Xtrimpoints = make_trimpoints()
+EOF
+fi
+if test -s 'demo/sgi/gl_panel/twoview/block.py'
+then echo '*** I will not over-write existing file demo/sgi/gl_panel/twoview/block.py'
+else
+echo 'x - demo/sgi/gl_panel/twoview/block.py'
+sed 's/^X//' > 'demo/sgi/gl_panel/twoview/block.py' << 'EOF'
+X# module 'block' imported by twoview demo.
+X
+Xfrom gl import n3f, bgnpolygon, varray, endpolygon, lmbind
+Xfrom GL import MATERIAL
+X
+X# Draw a single 2x2x2 block with its center at (0, 0, 0)
+X# Arguments are the material indices (0 = don't call lmbind)
+X#
+Xdef block(m_front, m_back, m_left, m_right, m_top, m_bottom):
+X #
+X # Distances defining the sides
+X #
+X x_left = -1.0
+X x_right = 1.0
+X y_top = 1.0
+X y_bottom = -1.0
+X z_front = 1.0
+X z_back = -1.0
+X #
+X # Top surface points: A, B, C, D
+X #
+X A = x_right, y_top, z_front
+X B = x_right, y_top, z_back
+X C = x_left, y_top, z_back
+X D = x_left, y_top, z_front
+X #
+X # Bottom surface points: E, F, G, H
+X #
+X E = x_right, y_bottom, z_front
+X F = x_right, y_bottom, z_back
+X G = x_left, y_bottom, z_back
+X H = x_left, y_bottom, z_front
+X #
+X # Draw front face
+X #
+X if m_front: lmbind(MATERIAL, m_front)
+X n3f(0.0, 0.0, 1.0)
+X face(H, E, A, D)
+X #
+X # Draw back face
+X #
+X if m_back: lmbind(MATERIAL, m_back)
+X n3f(0.0, 0.0, -1.0)
+X face(G, F, B, C)
+X #
+X # Draw left face
+X #
+X if m_left: lmbind(MATERIAL, m_left)
+X n3f(-1.0, 0.0, 0.0)
+X face(G, H, D, C)
+X #
+X # Draw right face
+X #
+X if m_right: lmbind(MATERIAL, m_right)
+X n3f(1.0, 0.0, 0.0)
+X face(F, E, A, B)
+X #
+X # Draw top face
+X #
+X if m_top: lmbind(MATERIAL, m_top)
+X n3f(0.0, 1.0, 0.0)
+X face(A, B, C, D)
+X #
+X # Draw bottom face
+X #
+X if m_bottom: lmbind(MATERIAL, m_bottom)
+X n3f(0.0, -1.0, 0.0)
+X face(E, F, G, H)
+X
+Xdef face(points):
+X bgnpolygon()
+X varray(points)
+X endpolygon()
+EOF
+fi
+if test -s 'demo/sgi/gl_panel/twoview/camera.s'
+then echo '*** I will not over-write existing file demo/sgi/gl_panel/twoview/camera.s'
+else
+echo 'x - demo/sgi/gl_panel/twoview/camera.s'
+sed 's/^X//' > 'demo/sgi/gl_panel/twoview/camera.s' << 'EOF'
+X;;; This file was automatically generated by the panel editor.
+X;;; If you read it into gnu emacs, it will automagically format itself.
+X
+X(panel (prop help creator:user-panel-help)
+X(prop user-panel #t)
+X(label "Camera Control")
+X(x 1010)
+X(y 589)
+X(al (pnl_wide_button (name "quitbutton")
+X(prop help creator:user-act-help)
+X(label "quit")
+X(x 3.5)
+X(y 1)
+X(w 0.94)
+X(downfunc move-then-resize)
+X)
+X(pnl_filled_hslider (name "farclip")
+X(prop help creator:user-act-help)
+X(label "far clipping plane")
+X(x 1.25)
+X(y 3.5)
+X(w 3.3)
+X(h 0.4)
+X(val 0.752)
+X(downfunc move-then-resize)
+X)
+X(pnl_filled_hslider (name "nearclip")
+X(prop help creator:user-act-help)
+X(label "near clipping plane")
+X(x 1.25)
+X(y 4.5)
+X(w 3.3)
+X(h 0.4)
+X(val 0.17)
+X(downfunc move-then-resize)
+X)
+X(pnl_filled_vslider (name "zoom")
+X(prop help creator:user-act-help)
+X(label "zoom")
+X(x 0.2)
+X(y 1.25)
+X(w 0.4)
+X(h 3.9)
+X(val 0.344)
+X(downfunc move-then-resize)
+X)
+X)
+X)
+X;;; Local Variables:
+X;;; mode: scheme
+X;;; eval: (save-excursion (goto-char (point-min)) (kill-line 3))
+X;;; eval: (save-excursion (goto-char (point-min)) (replace-regexp "[ \n]*)" ")"))
+X;;; eval: (indent-region (point-min) (point-max) nil)
+X;;; eval: (progn (kill-line -3) (delete-backward-char 1) (save-buffer))
+X;;; End:
+EOF
+fi
+if test -s 'lib/HVSplit.py'
+then echo '*** I will not over-write existing file lib/HVSplit.py'
+else
+echo 'x - lib/HVSplit.py'
+sed 's/^X//' > 'lib/HVSplit.py' << 'EOF'
+X# HVSplit contains generic code for HSplit and VSplit.
+X# HSplit and VSplit are specializations to either dimension.
+X
+X# XXX This does not yet stretch/shrink children if there is too much
+X# XXX or too little space in the split dimension.
+X# XXX (NB There is no interface to ask children for stretch preferences.)
+X
+Xfrom Split import Split
+X
+Xclass HVSplit() = Split():
+X #
+X def create(self, (parent, hv)):
+X # hv is 0 or 1 for HSplit or VSplit
+X self = Split.create(self, parent)
+X self.hv = hv
+X return self
+X #
+X def minsize(self, m):
+X hv, vh = self.hv, 1 - self.hv
+X size = [0, 0]
+X for c in self.children:
+X csize = c.minsize(m)
+X if csize[vh] > size[vh]: size[vh] = csize[vh]
+X size[hv] = size[hv] + csize[hv]
+X return size[0], size[1]
+X #
+X def getbounds(self):
+X return self.bounds
+X #
+X def setbounds(self, bounds):
+X self.bounds = bounds
+X hv, vh = self.hv, 1 - self.hv
+X mf = self.parent.beginmeasuring
+X size = self.minsize(mf())
+X # XXX not yet used! Later for stretching
+X maxsize_hv = bounds[1][hv] - bounds[0][hv]
+X origin = [self.bounds[0][0], self.bounds[0][1]]
+X for c in self.children:
+X size = c.minsize(mf())
+X corner = [0, 0]
+X corner[vh] = bounds[1][vh]
+X corner[hv] = origin[hv] + size[hv]
+X c.setbounds((origin[0], origin[1]), \
+X (corner[0], corner[1]))
+X origin[hv] = corner[hv]
+X # XXX stretch
+X # XXX too-small
+X #
+X
+Xclass HSplit() = HVSplit():
+X def create(self, parent):
+X return HVSplit.create(self, (parent, 0))
+X
+Xclass VSplit() = HVSplit():
+X def create(self, parent):
+X return HVSplit.create(self, (parent, 1))
+EOF
+fi
+if test -s 'lib/dump.py'
+then echo '*** I will not over-write existing file lib/dump.py'
+else
+echo 'x - lib/dump.py'
+sed 's/^X//' > 'lib/dump.py' << 'EOF'
+X# Module 'dump'
+X#
+X# Print python code that reconstructs a variable.
+X# This only works in certain cases.
+X#
+X# It works fine for:
+X# - ints and floats (except NaNs and other weird things)
+X# - strings
+X# - compounds and lists, provided it works for all their elements
+X# - imported modules, provided their name is the module name
+X#
+X# It works for top-level dictionaries but not for dictionaries
+X# contained in other objects (could be made to work with some hassle
+X# though).
+X#
+X# It does not work for functions (all sorts), classes, class objects,
+X# windows, files etc.
+X#
+X# Finally, objects referenced by more than one name or contained in more
+X# than one other object lose their sharing property (this is bad for
+X# strings used as exception identifiers, for instance).
+X
+X# Dump a whole symbol table
+X#
+Xdef dumpsymtab(dict):
+X for key in dict.keys():
+X dumpvar(key, dict[key])
+X
+X# Dump a single variable
+X#
+Xdef dumpvar(name, x):
+X import sys
+X t = type(x)
+X if t = type({}):
+X print name, '= {}'
+X for key in x.keys():
+X item = x[key]
+X if not printable(item):
+X print '#',
+X print name, '[', `key`, '] =', `item`
+X elif t in (type(''), type(0), type(0.0), type([]), type(())):
+X if not printable(x):
+X print '#',
+X print name, '=', `x`
+X elif t = type(sys):
+X print 'import', name, '#', x
+X else:
+X print '#', name, '=', x
+X
+X# check if a value is printable in a way that can be read back with input()
+X#
+Xdef printable(x):
+X t = type(x)
+X if t in (type(''), type(0), type(0.0)):
+X return 1
+X if t in (type([]), type(())):
+X for item in x:
+X if not printable(item):
+X return 0
+X return 1
+X if x = {}:
+X return 1
+X return 0
+EOF
+fi
+if test -s 'lib/localtime.py'
+then echo '*** I will not over-write existing file lib/localtime.py'
+else
+echo 'x - lib/localtime.py'
+sed 's/^X//' > 'lib/localtime.py' << 'EOF'
+X# module localtime -- Time conversions
+X
+Ximport posix
+X
+Xepoch = 1970 # 1 jan 00:00:00, UCT
+Xday0 = 4 # day 0 was a thursday
+X
+Xday_names = ('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat')
+X
+Xmonth_names = ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun')
+Xmonth_names = month_names + ('Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec')
+X
+Xmonth_sizes = (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)
+X
+Xdef isleap(year):
+X return year % 4 = 0 and (year % 100 <> 0 or year % 400 = 0)
+X
+Xdef gmtime(secs): # decode time into UCT
+X mins, secs = divmod(secs, 60)
+X hours, mins = divmod(mins, 60)
+X days, hours = divmod(hours, 24)
+X wday = (day0 + days) % 7
+X year = epoch
+X lp = isleap(year)
+X dpy = 365 + lp
+X while days >= dpy:
+X days = days - dpy
+X year = year + 1
+X lp = isleap(year)
+X dpy = 365 + lp
+X yday = days
+X month = 0
+X dpm = month_sizes[month] + (lp and month = 1)
+X while days >= dpm:
+X days = days - dpm
+X month = month + 1
+X dpm = month_sizes[month] + (lp and month = 1)
+X return (year, month, days+1, hours, mins, secs, yday, wday)
+X
+Xdef dd(x):
+X s = `x`
+X while len(s) < 2: s = '0' + s
+X return s
+X
+Xdef zd(x):
+X s = `x`
+X while len(s) < 2: s = ' ' + s
+X return s
+X
+Xdef format(year, month, days, hours, mins, secs, yday, wday):
+X s = day_names[wday] + ' ' + zd(days) + ' ' + month_names[month] + ' '
+X s = s + dd(hours) + ':' + dd(mins) + ':' + dd(secs)
+X return s
+EOF
+fi
+if test -s 'lib/poly.py'
+then echo '*** I will not over-write existing file lib/poly.py'
+else
+echo 'x - lib/poly.py'
+sed 's/^X//' > 'lib/poly.py' << 'EOF'
+X# module 'poly' -- Polynomials
+X
+X# A polynomial is represented by a list of coefficients, e.g.,
+X# [1, 10, 5] represents 1*x**0 + 10*x**1 + 5*x**2 (or 1 + 10x + 5x**2).
+X# There is no way to suppress internal zeros; trailing zeros are
+X# taken out by normalize().
+X
+Xdef normalize(p): # Strip unnecessary zero coefficients
+X n = len(p)
+X while p:
+X if p[n-1]: return p[:n]
+X n = n-1
+X return []
+X
+Xdef plus(a, b):
+X if len(a) < len(b): a, b = b, a # make sure a is the longest
+X res = a[:] # make a copy
+X for i in range(len(b)):
+X res[i] = res[i] + b[i]
+X return normalize(res)
+X
+Xdef minus(a, b):
+X if len(a) < len(b): a, b = b, a # make sure a is the longest
+X res = a[:] # make a copy
+X for i in range(len(b)):
+X res[i] = res[i] - b[i]
+X return normalize(res)
+X
+Xdef one(power, coeff): # Representation of coeff * x**power
+X res = []
+X for i in range(power): res.append(0)
+X return res + [coeff]
+X
+Xdef times(a, b):
+X res = []
+X for i in range(len(a)):
+X for j in range(len(b)):
+X res = plus(res, one(i+j, a[i]*b[j]))
+X return res
+X
+Xdef power(a, n): # Raise polynomial a to the positive integral power n
+X if n = 0: return [1]
+X if n = 1: return a
+X if n/2*2 = n:
+X b = power(a, n/2)
+X return times(b, b)
+X return times(power(a, n-1), a)
+X
+Xdef der(a): # First derivative
+X res = a[1:]
+X for i in range(len(res)):
+X res[i] = res[i] * (i+1)
+X return res
+X
+X# Computing a primitive function would require rational arithmetic...
+EOF
+fi
+if test -s 'lib/shutil.py'
+then echo '*** I will not over-write existing file lib/shutil.py'
+else
+echo 'x - lib/shutil.py'
+sed 's/^X//' > 'lib/shutil.py' << 'EOF'
+X# Module 'shutil' -- utility functions usable in a shell-like program
+X
+Ximport posix
+Ximport path
+X
+XMODEBITS = 010000 # Lower 12 mode bits
+X# Change this to 01000 (9 mode bits) to avoid copying setuid etc.
+X
+X# Copy data from src to dst
+X#
+Xdef copyfile(src, dst):
+X fsrc = open(src, 'r')
+X fdst = open(dst, 'w')
+X while 1:
+X buf = fsrc.read(16*1024)
+X if not buf: break
+X fdst.write(buf)
+X
+X# Copy mode bits from src to dst
+X#
+Xdef copymode(src, dst):
+X st = posix.stat(src)
+X mode = divmod(st[0], MODEBITS)[1]
+X posix.chmod(dst, mode)
+X
+X# Copy all stat info (mode bits, atime and mtime) from src to dst
+X#
+Xdef copystat(src, dst):
+X st = posix.stat(src)
+X mode = divmod(st[0], MODEBITS)[1]
+X posix.chmod(dst, mode)
+X posix.utimes(dst, st[7:9])
+X
+X# Copy data and mode bits ("cp src dst")
+X#
+Xdef copy(src, dst):
+X copyfile(src, dst)
+X copymode(src, dst)
+X
+X# Copy data and all stat info ("cp -p src dst")
+X#
+Xdef copy2(src, dst):
+X copyfile(src, dst)
+X copystat(src, dst)
+X
+X# Recursively copy a directory tree.
+X# The destination must not already exist.
+X#
+Xdef copytree(src, dst):
+X names = posix.listdir(src)
+X posix.mkdir(dst, 0777)
+X dot_dotdot = '.', '..'
+X for name in names:
+X if name not in dot_dotdot:
+X srcname = path.cat(src, name)
+X dstname = path.cat(dst, name)
+X #print 'Copying', srcname, 'to', dstname
+X try:
+X #if path.islink(srcname):
+X # linkto = posix.readlink(srcname)
+X # posix.symlink(linkto, dstname)
+X #elif path.isdir(srcname):
+X if path.isdir(srcname):
+X copytree(srcname, dstname)
+X else:
+X copy2(srcname, dstname)
+X # XXX What about devices, sockets etc.?
+X except posix.error, why:
+X print 'Could not copy', srcname, 'to', dstname,
+X print '(', why[1], ')'
+EOF
+fi
+if test -s 'lib/stdwinevents.py'
+then echo '*** I will not over-write existing file lib/stdwinevents.py'
+else
+echo 'x - lib/stdwinevents.py'
+sed 's/^X//' > 'lib/stdwinevents.py' << 'EOF'
+X# Module 'stdwinevents' -- Constants for stdwin event types
+X#
+X# Suggested usage:
+X# from stdwinevents import *
+X
+X# The function stdwin.getevent() returns a tuple containing:
+X# (type, window, detail)
+X# where detail may be <no value> or a value depending on type, see below:
+X
+X# Values for type:
+X
+XWE_NULL = 0 # not reported -- means 'no event' internally
+XWE_ACTIVATE = 1 # detail is <no object>
+XWE_CHAR = 2 # detail is the character
+XWE_COMMAND = 3 # detail is one of the WC_* constants below
+XWE_MOUSE_DOWN = 4 # detail is ((h, v), clicks, button, mask)
+XWE_MOUSE_MOVE = 5 # ditto
+XWE_MOUSE_UP = 6 # ditto
+XWE_MENU = 7 # detail is (menu, item)
+XWE_SIZE = 8 # detail is (width, height) [???]
+XWE_MOVE = 9 # not reported -- reserved for future use
+XWE_DRAW = 10 # detail is ((left, top), (right, bottom))
+XWE_TIMER = 11 # detail is <no object>
+XWE_DEACTIVATE = 12 # detail is <no object>
+XWE_EXTERN = 13 # detail is <no object>
+XWE_KEY = 14 # detail is ???
+XWE_LOST_SEL = 15 # detail is selection number
+XWE_CLOSE = 16 # detail is <no object>
+X
+X# Values for detail when type is WE_COMMAND:
+X
+XWC_CLOSE = 1 # user hit close box
+XWC_LEFT = 2 # left arrow key
+XWC_RIGHT = 3 # right arrow key
+XWC_UP = 4 # up arrow key
+XWC_DOWN = 5 # down arrow key
+XWC_CANCEL = 6 # not reported -- turned into KeyboardInterrupt
+XWC_BACKSPACE = 7 # backspace key
+XWC_TAB = 8 # tab key
+XWC_RETURN = 9 # return or enter key
+X
+X# Selection numbers
+X
+XWS_CLIPBOARD = 0
+XWS_PRIMARY = 1
+XWS_SECONDARY = 2
+EOF
+fi
+if test -s 'lib/sunaudio.py'
+then echo '*** I will not over-write existing file lib/sunaudio.py'
+else
+echo 'x - lib/sunaudio.py'
+sed 's/^X//' > 'lib/sunaudio.py' << 'EOF'
+X# Module 'sunaudio' -- interpret sun audio headers
+X
+Ximport audio
+X
+XMAGIC = '.snd'
+X
+Xerror = 'sunaudio sound header conversion error'
+X
+X
+X# convert a 4-char value to integer
+X
+Xdef c2i(data):
+X if type(data) <> type('') or len(data) <> 4:
+X raise error, 'c2i: bad arg (not string[4])'
+X bytes = audio.chr2num(data)
+X for i in (1, 2, 3):
+X if bytes[i] < 0:
+X bytes[i] = bytes[i] + 256
+X return ((bytes[0]*256 + bytes[1])*256 + bytes[2])*256 + bytes[3]
+X
+X
+X# read a sound header from an open file
+X
+Xdef gethdr(fp):
+X if fp.read(4) <> MAGIC:
+X raise error, 'gethdr: bad magic word'
+X hdr_size = c2i(fp.read(4))
+X data_size = c2i(fp.read(4))
+X encoding = c2i(fp.read(4))
+X sample_rate = c2i(fp.read(4))
+X channels = c2i(fp.read(4))
+X excess = hdr_size - 24
+X if excess < 0:
+X raise error, 'gethdr: bad hdr_size'
+X if excess > 0:
+X info = fp.read(excess)
+X else:
+X info = ''
+X return (data_size, encoding, sample_rate, channels, info)
+X
+X
+X# read and print the sound header of a named file
+X
+Xdef printhdr(file):
+X hdr = gethdr(open(file, 'r'))
+X data_size, encoding, sample_rate, channels, info = hdr
+X while info[-1:] = '\0':
+X info = info[:-1]
+X print 'File name: ', file
+X print 'Data size: ', data_size
+X print 'Encoding: ', encoding
+X print 'Sample rate:', sample_rate
+X print 'Channels: ', channels
+X print 'Info: ', `info`
+EOF
+fi
+if test -s 'lib/whrandom.py'
+then echo '*** I will not over-write existing file lib/whrandom.py'
+else
+echo 'x - lib/whrandom.py'
+sed 's/^X//' > 'lib/whrandom.py' << 'EOF'
+X# WICHMANN-HILL RANDOM NUMBER GENERATOR
+X#
+X# Wichmann, B. A. & Hill, I. D. (1982)
+X# Algorithm AS 183:
+X# An efficient and portable pseudo-random number generator
+X# Applied Statistics 31 (1982) 188-190
+X#
+X# see also:
+X# Correction to Algorithm AS 183
+X# Applied Statistics 33 (1984) 123
+X#
+X# McLeod, A. I. (1985)
+X# A remark on Algorithm AS 183
+X# Applied Statistics 34 (1985),198-200
+X#
+X#
+X# USE:
+X# whrandom.random() yields double precision random numbers
+X# uniformly distributed between 0 and 1.
+X#
+X# whrandom.seed() must be called before whrandom.random()
+X# to seed the generator
+X
+X
+X# Translated by Guido van Rossum from C source provided by
+X# Adrian Baddeley.
+X
+X
+X# The seed
+X#
+X_seed = [0, 0, 0]
+X
+X
+X# Set the seed
+X#
+Xdef seed(x, y, z):
+X _seed[:] = [x, y, z]
+X
+X
+X# Return the next random number in the range [0.0 .. 1.0)
+X#
+Xdef random():
+X from math import floor # floor() function
+X #
+X [x, y, z] = _seed
+X x = 171 * (x % 177) - 2 * (x/177)
+X y = 172 * (y % 176) - 35 * (y/176)
+X z = 170 * (z % 178) - 63 * (z/178)
+X #
+X if x < 0: x = x + 30269
+X if y < 0: y = y + 30307
+X if z < 0: z = z + 30323
+X #
+X _seed[:] = [x, y, z]
+X #
+X term = float(x)/30269.0 + float(y)/30307.0 + float(z)/30323.0
+X rand = term - floor(term)
+X #
+X if rand >= 1.0: rand = 0.0 # floor() inaccuracy?
+X #
+X return rand
+X
+X
+X# Initialize from the current time
+X#
+Xdef init():
+X import time
+X t = time.time()
+X seed(t%256, t/256%256, t/65536%256)
+X
+X
+X# Make sure the generator is preset to a nonzero value
+X#
+Xinit()
+EOF
+fi
+if test -s 'src/README'
+then echo '*** I will not over-write existing file src/README'
+else
+echo 'x - src/README'
+sed 's/^X//' > 'src/README' << 'EOF'
+XThis directory contains the source for the Python interpreter.
+X
+XTo build the interpreter, edit the Makefile, follow the instructions
+Xthere, and type "make python".
+X
+XTo use the interpreter, you must set the environment variable PYTHONPATH
+Xto point to the directory containing the standard modules. These are
+Xdistributed as a sister directory called 'lib' of this source directory.
+XTry importing the module 'testall' to see if everything works.
+X
+XGood Luck!
+EOF
+fi
+if test -s 'src/asa.h'
+then echo '*** I will not over-write existing file src/asa.h'
+else
+echo 'x - src/asa.h'
+sed 's/^X//' > 'src/asa.h' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/* Interface for asynchronous audio module */
+X
+Xextern int asa_init(void);
+Xextern void asa_done(void);
+Xextern void asa_start_write(char *, int);
+Xextern void asa_start_read(char *, int);
+Xextern int asa_poll(void);
+Xextern int asa_wait(void);
+Xextern int asa_cancel(void);
+EOF
+fi
+if test -s 'src/ceval.h'
+then echo '*** I will not over-write existing file src/ceval.h'
+else
+echo 'x - src/ceval.h'
+sed 's/^X//' > 'src/ceval.h' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/* Interface to execute compiled code */
+X/* This header depends on "compile.h" */
+X
+Xobject *eval_code PROTO((codeobject *, object *, object *, object *));
+X
+Xobject *getglobals PROTO((void));
+Xobject *getlocals PROTO((void));
+X
+Xvoid printtraceback PROTO((FILE *));
+EOF
+fi
+if test -s 'src/errcode.h'
+then echo '*** I will not over-write existing file src/errcode.h'
+else
+echo 'x - src/errcode.h'
+sed 's/^X//' > 'src/errcode.h' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/* Error codes passed around between file input, tokenizer, parser and
+X interpreter. This was necessary so we can turn them into Python
+X exceptions at a higher level. */
+X
+X#define E_OK 10 /* No error */
+X#define E_EOF 11 /* (Unexpected) EOF read */
+X#define E_INTR 12 /* Interrupted */
+X#define E_TOKEN 13 /* Bad token */
+X#define E_SYNTAX 14 /* Syntax error */
+X#define E_NOMEM 15 /* Ran out of memory */
+X#define E_DONE 16 /* Parsing complete */
+X#define E_ERROR 17 /* Execution error */
+EOF
+fi
+if test -s 'src/fileobject.h'
+then echo '*** I will not over-write existing file src/fileobject.h'
+else
+echo 'x - src/fileobject.h'
+sed 's/^X//' > 'src/fileobject.h' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/* File object interface */
+X
+Xextern typeobject Filetype;
+X
+X#define is_fileobject(op) ((op)->ob_type == &Filetype)
+X
+Xextern object *newfileobject PROTO((char *, char *));
+Xextern object *newopenfileobject PROTO((FILE *, char *, char *));
+Xextern FILE *getfilefile PROTO((object *));
+EOF
+fi
+if test -s 'src/floatobject.h'
+then echo '*** I will not over-write existing file src/floatobject.h'
+else
+echo 'x - src/floatobject.h'
+sed 's/^X//' > 'src/floatobject.h' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/* Float object interface */
+X
+X/*
+Xfloatobject represents a (double precision) floating point number.
+X*/
+X
+Xtypedef struct {
+X OB_HEAD
+X double ob_fval;
+X} floatobject;
+X
+Xextern typeobject Floattype;
+X
+X#define is_floatobject(op) ((op)->ob_type == &Floattype)
+X
+Xextern object *newfloatobject PROTO((double));
+Xextern double getfloatvalue PROTO((object *));
+X
+X/* Macro, trading safety for speed */
+X#define GETFLOATVALUE(op) ((op)->ob_fval)
+EOF
+fi
+if test -s 'src/fmod.c'
+then echo '*** I will not over-write existing file src/fmod.c'
+else
+echo 'x - src/fmod.c'
+sed 's/^X//' > 'src/fmod.c' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/* Portable fmod(x, y) implementation for systems that don't have it */
+X
+X#include <math.h>
+X#include <errno.h>
+X
+Xextern int errno;
+X
+Xdouble
+Xfmod(x, y)
+X double x, y;
+X{
+X double i, f;
+X
+X if (y == 0.0) {
+X errno = EDOM;
+X return 0.0;
+X }
+X
+X /* return f such that x = i*y + f for some integer i
+X such that |f| < |y| and f has the same sign as x */
+X
+X i = floor(x/y);
+X f = x - i*y;
+X if ((x < 0.0) != (y < 0.0))
+X f = f-y;
+X return f;
+X}
+EOF
+fi
+if test -s 'src/funcobject.h'
+then echo '*** I will not over-write existing file src/funcobject.h'
+else
+echo 'x - src/funcobject.h'
+sed 's/^X//' > 'src/funcobject.h' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/* Function object interface */
+X
+Xextern typeobject Functype;
+X
+X#define is_funcobject(op) ((op)->ob_type == &Functype)
+X
+Xextern object *newfuncobject PROTO((object *, object *));
+Xextern object *getfunccode PROTO((object *));
+Xextern object *getfuncglobals PROTO((object *));
+EOF
+fi
+if test -s 'src/import.h'
+then echo '*** I will not over-write existing file src/import.h'
+else
+echo 'x - src/import.h'
+sed 's/^X//' > 'src/import.h' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/* Module definition and import interface */
+X
+Xobject *get_modules PROTO((void));
+Xobject *add_module PROTO((char *name));
+Xobject *import_module PROTO((char *name));
+Xobject *reload_module PROTO((object *m));
+Xvoid doneimport PROTO((void));
+EOF
+fi
+if test -s 'src/metagrammar.h'
+then echo '*** I will not over-write existing file src/metagrammar.h'
+else
+echo 'x - src/metagrammar.h'
+sed 's/^X//' > 'src/metagrammar.h' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X#define MSTART 256
+X#define RULE 257
+X#define RHS 258
+X#define ALT 259
+X#define ITEM 260
+X#define ATOM 261
+EOF
+fi
+if test -s 'src/methodobject.h'
+then echo '*** I will not over-write existing file src/methodobject.h'
+else
+echo 'x - src/methodobject.h'
+sed 's/^X//' > 'src/methodobject.h' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/* Method object interface */
+X
+Xextern typeobject Methodtype;
+X
+X#define is_methodobject(op) ((op)->ob_type == &Methodtype)
+X
+Xtypedef object *(*method) FPROTO((object *, object *));
+X
+Xextern object *newmethodobject PROTO((char *, method, object *));
+Xextern method getmethod PROTO((object *));
+Xextern object *getself PROTO((object *));
+X
+Xstruct methodlist {
+X char *ml_name;
+X method ml_meth;
+X};
+X
+Xextern object *findmethod PROTO((struct methodlist *, object *, char *));
+EOF
+fi
+if test -s 'src/modsupport.h'
+then echo '*** I will not over-write existing file src/modsupport.h'
+else
+echo 'x - src/modsupport.h'
+sed 's/^X//' > 'src/modsupport.h' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/* Module support interface */
+X
+Xextern object *initmodule PROTO((char *, struct methodlist *));
+EOF
+fi
+if test -s 'src/moduleobject.h'
+then echo '*** I will not over-write existing file src/moduleobject.h'
+else
+echo 'x - src/moduleobject.h'
+sed 's/^X//' > 'src/moduleobject.h' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/* Module object interface */
+X
+Xextern typeobject Moduletype;
+X
+X#define is_moduleobject(op) ((op)->ob_type == &Moduletype)
+X
+Xextern object *newmoduleobject PROTO((char *));
+Xextern object *getmoduledict PROTO((object *));
+Xextern char *getmodulename PROTO((object *));
+EOF
+fi
+if test -s 'src/parsetok.h'
+then echo '*** I will not over-write existing file src/parsetok.h'
+else
+echo 'x - src/parsetok.h'
+sed 's/^X//' > 'src/parsetok.h' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/* Parser-tokenizer link interface */
+X
+Xextern int parsestring PROTO((char *, grammar *, int start, node **n_ret));
+Xextern int parsefile PROTO((FILE *, char *, grammar *, int start,
+X char *ps1, char *ps2, node **n_ret));
+EOF
+fi
+if test -s 'src/pgen.h'
+then echo '*** I will not over-write existing file src/pgen.h'
+else
+echo 'x - src/pgen.h'
+sed 's/^X//' > 'src/pgen.h' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/* Parser generator interface */
+X
+Xextern grammar gram;
+X
+Xextern grammar *meta_grammar PROTO((void));
+Xextern grammar *pgen PROTO((struct _node *));
+EOF
+fi
+if test -s 'src/regmagic.h'
+then echo '*** I will not over-write existing file src/regmagic.h'
+else
+echo 'x - src/regmagic.h'
+sed 's/^X//' > 'src/regmagic.h' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/*
+X * The first byte of the regexp internal "program" is actually this magic
+X * number; the start node begins in the second byte.
+X */
+X#define MAGIC 0234
+EOF
+fi
+if test -s 'src/sc_errors.h'
+then echo '*** I will not over-write existing file src/sc_errors.h'
+else
+echo 'x - src/sc_errors.h'
+sed 's/^X//' > 'src/sc_errors.h' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X
+X#define NoBufSize 1
+X#define TwoBufSize 2
+X#define StackOverflow 3
+X#define StackUnderflow 4
+X#define TypeFailure 5
+X#define RangeError 6
+X#define SizeError 7
+X#define BufferOverflow 8
+X#define NoEndLoop 9
+X#define FlagError 10
+X#define ElementIsNull 11
+X#define TransError 12
+X
+Xextern object *err_scerr PROTO((int sc_errno));
+Xextern err_scerrset PROTO((int sc_errno, object *value, char *instr));
+Xextern object *StubcodeError;
+EOF
+fi
+if test -s 'src/stdwinobject.h'
+then echo '*** I will not over-write existing file src/stdwinobject.h'
+else
+echo 'x - src/stdwinobject.h'
+sed 's/^X//' > 'src/stdwinobject.h' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/* Stdwin object interface */
+X
+Xextern typeobject Stdwintype;
+X
+X#define is_stdwinobject(op) ((op)->ob_type == &Stdwintype)
+X
+Xextern object *newstdwinobject PROTO((void));
+EOF
+fi
+if test -s 'src/strdup.c'
+then echo '*** I will not over-write existing file src/strdup.c'
+else
+echo 'x - src/strdup.c'
+sed 's/^X//' > 'src/strdup.c' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X#include "PROTO.h"
+X#include "malloc.h"
+X#include "string.h"
+X
+Xchar *
+Xstrdup(str)
+X const char *str;
+X{
+X if (str != NULL) {
+X register char *copy = NEW(char, strlen(str) + 1);
+X if (copy != NULL)
+X return strcpy(copy, str);
+X }
+X return NULL;
+X}
+EOF
+fi
+if test -s 'src/strerror.c'
+then echo '*** I will not over-write existing file src/strerror.c'
+else
+echo 'x - src/strerror.c'
+sed 's/^X//' > 'src/strerror.c' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/* PD implementation of strerror() for systems that don't have it.
+X Author: Guido van Rossum, CWI Amsterdam, Oct. 1990, <[email protected]>. */
+X
+X#include <stdio.h>
+X
+Xextern int sys_nerr;
+Xextern char *sys_errlist[];
+X
+Xchar *
+Xstrerror(err)
+X int err;
+X{
+X static char buf[20];
+X if (err >= 0 && err < sys_nerr)
+X return sys_errlist[err];
+X sprintf(buf, "Unknown errno %d", err);
+X return buf;
+X}
+X
+X#ifdef THINK_C
+Xint sys_nerr = 0;
+Xchar *sys_errlist[1] = 0;
+X#endif
+EOF
+fi
+if test -s 'src/sysmodule.h'
+then echo '*** I will not over-write existing file src/sysmodule.h'
+else
+echo 'x - src/sysmodule.h'
+sed 's/^X//' > 'src/sysmodule.h' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/* System module interface */
+X
+Xobject *sysget PROTO((char *));
+Xint sysset PROTO((char *, object *));
+XFILE *sysgetfile PROTO((char *, FILE *));
+Xvoid initsys PROTO((void));
+EOF
+fi
+if test -s 'src/traceback.h'
+then echo '*** I will not over-write existing file src/traceback.h'
+else
+echo 'x - src/traceback.h'
+sed 's/^X//' > 'src/traceback.h' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/* Traceback interface */
+X
+Xint tb_here PROTO((struct _frame *, int, int));
+Xobject *tb_fetch PROTO((void));
+Xint tb_store PROTO((object *));
+Xint tb_print PROTO((object *, FILE *));
+EOF
+fi
+echo 'Part 20 out of 21 of pack.out complete.'
+exit 0
diff --git a/shar/python-0.9.1-21-21.shar b/shar/python-0.9.1-21-21.shar
new file mode 100644
index 0000000..5e50481
--- /dev/null
+++ b/shar/python-0.9.1-21-21.shar
@@ -0,0 +1,1675 @@
+: This is a shell archive.
+: Extract with 'sh this_file'.
+:
+: Extract part 01 first since it makes all directories
+echo 'Start of pack.out, part 21 out of 21:'
+if test -s 'demo/README'
+then echo '*** I will not over-write existing file demo/README'
+else
+echo 'x - demo/README'
+sed 's/^X//' > 'demo/README' << 'EOF'
+XThis directory contains various demonstrations of what you can do with
+XPython. The demos are grouped sub(sub*)directories according to
+Xrequired optional built-in modules.
+X
+Xscripts Some useful Python scripts that I put in my bin
+X directory. No optional built-in modules meeded.
+X
+Xsgi Demos that only run on Silicon Graphics machines.
+X Require the built-in modules 'audio' and/or 'gl'.
+X
+Xstdwin Demos that use the STDWIN library. Require the 'stdwin'
+X built-in module.
+X
+XWARNING: some scripts are executable and have a first line saying
+X
+X #! /ufs/guido/bin/sgi/python
+X
+XThis is unlikely to give good results anywhere else except in my
+Xoffice. Edit the first line before installing such scripts; to try
+Xthem out, you can just say "python file.py". (The .py suffix is not
+Xnecessary in this case, but makes it possible to debug the modules
+Xinteractively by importing them.)
+EOF
+fi
+if test -s 'demo/scripts/findlinksto.py'
+then echo '*** I will not over-write existing file demo/scripts/findlinksto.py'
+else
+echo 'x - demo/scripts/findlinksto.py'
+sed 's/^X//' > 'demo/scripts/findlinksto.py' << 'EOF'
+X#! /ufs/guido/bin/sgi/python
+X
+X# findlinksto
+X#
+X# find symbolic links to a given path
+X
+Ximport posix, path, sys
+X
+Xdef visit(pattern, dirname, names):
+X if path.islink(dirname):
+X names[:] = []
+X return
+X if path.ismount(dirname):
+X print 'descend into', dirname
+X n = len(pattern)
+X for name in names:
+X name = path.cat(dirname, name)
+X try:
+X linkto = posix.readlink(name)
+X if linkto[:n] = pattern:
+X print name, '->', linkto
+X except posix.error:
+X pass
+X
+Xdef main(pattern, args):
+X for dirname in args:
+X path.walk(dirname, visit, pattern)
+X
+Xmain(sys.argv[1], sys.argv[2:])
+EOF
+chmod +x 'demo/scripts/findlinksto.py'
+fi
+if test -s 'demo/scripts/suff.py'
+then echo '*** I will not over-write existing file demo/scripts/suff.py'
+else
+echo 'x - demo/scripts/suff.py'
+sed 's/^X//' > 'demo/scripts/suff.py' << 'EOF'
+X#! /ufs/guido/bin/sgi/python
+X
+X# suff
+X#
+X# show different suffixes amongst arguments
+X
+Ximport sys
+X
+Xdef main():
+X files = sys.argv[1:]
+X suffixes = {}
+X for file in files:
+X suff = getsuffix(file)
+X if not suffixes.has_key(suff):
+X suffixes[suff] = []
+X suffixes[suff].append(file)
+X keys = suffixes.keys()
+X keys.sort()
+X for suff in keys:
+X print `suff`, len(suffixes[suff])
+X
+Xdef getsuffix(file):
+X suff = ''
+X for i in range(len(file)):
+X if file[i] = '.':
+X suff = file[i:]
+X return suff
+X
+Xmain()
+EOF
+chmod +x 'demo/scripts/suff.py'
+fi
+if test -s 'demo/sgi/README'
+then echo '*** I will not over-write existing file demo/sgi/README'
+else
+echo 'x - demo/sgi/README'
+sed 's/^X//' > 'demo/sgi/README' << 'EOF'
+XDemonstrations of Python that use various features of the Silicon
+XGraphics IRIS machines.
+X
+Xaudio Demonstrations of the audio capabilities of the 4D/25.
+X Require the built-in module 'audio'.
+X
+Xaudio_stdwin Window-based demonstrations the audio capabilities of
+X the 4D/25. Require the built-in modules 'stdwin' and
+X 'audio'.
+X
+Xgl Demonstrations of the Graphics Library (GL).
+X Require the built-in module 'gl'.
+X
+Xgl_panel Demonstrations of the Panel Library by NASA Ames.
+X Require the built-in modules 'gl' and 'pnl'.
+EOF
+fi
+if test -s 'demo/sgi/audio/README'
+then echo '*** I will not over-write existing file demo/sgi/audio/README'
+else
+echo 'x - demo/sgi/audio/README'
+sed 's/^X//' > 'demo/sgi/audio/README' << 'EOF'
+XPrograms that demonstrate the use of the audio device on the SGI 4D/25.
+XThese require the built-in module 'audio'.
+X
+Xplay Read a sound sample from a file and play it through the
+X speaker. Options to set volume, sampling rate etc.
+EOF
+fi
+if test -s 'demo/sgi/audio_stdwin/vumeter.py'
+then echo '*** I will not over-write existing file demo/sgi/audio_stdwin/vumeter.py'
+else
+echo 'x - demo/sgi/audio_stdwin/vumeter.py'
+sed 's/^X//' > 'demo/sgi/audio_stdwin/vumeter.py' << 'EOF'
+X#! /ufs/guido/bin/sgi/python
+X
+Ximport audio
+Ximport stdwin
+X
+Xfrom VUMeter import VUMeter
+Xfrom WindowParent import WindowParent
+Ximport MainLoop
+X
+XNBUFS=20
+XBUFSIZE = NBUFS*48
+XSCALE=128
+X
+Xclass MyVUMeter() = VUMeter():
+X def init_reactivity(self):
+X self.parent.need_mouse(self)
+X def mouse_down(self, detail):
+X if self.enabled:
+X self.stop()
+X else:
+X self.start()
+X def mouse_move(self, detail): pass
+X def mouse_up(self, detail): pass
+X
+Xdef main():
+X audio.setrate(3)
+X audio.setoutgain(0)
+X w = WindowParent().create('VU Meter', (200, 100))
+X v = MyVUMeter().define(w)
+X v.start()
+X w.realize()
+X while 1:
+X w.dispatch(stdwin.getevent())
+X
+Xmain()
+EOF
+chmod +x 'demo/sgi/audio_stdwin/vumeter.py'
+fi
+if test -s 'demo/sgi/gl/README'
+then echo '*** I will not over-write existing file demo/sgi/gl/README'
+else
+echo 'x - demo/sgi/gl/README'
+sed 's/^X//' > 'demo/sgi/gl/README' << 'EOF'
+XThese demos run only on SGI machines and require the 'gl' built-in module.
+XThe demonstrate the abilities of SGI's GL library as well as the ease of
+XGL programming in Python. Most demos require the Z-buffer (aka
+X24-bitplane) option.
+X
+Xbackface Demonstrates the 'backface' GL function.
+X
+Xkites Show 3 flying kites. Demonstrates the rendering speed
+X obtainable by Python programs.
+X
+Xmclock A colorful clock with more options than you can
+X remember. Works on 8-bit machines (but allows more
+X colors on 24-bit machines).
+X
+Xmixing Demonstrates the effect of color mixing: through
+X frequent color switching it gives the effect of white
+X light.
+X
+Xnurbs A simple demonstration of the 'nurbs' GL functions.
+X
+Xzrgb Displays a 3-D Gouraud-shaded figure which can be moved
+X around with the mouse.
+EOF
+fi
+if test -s 'demo/sgi/gl_panel/README'
+then echo '*** I will not over-write existing file demo/sgi/gl_panel/README'
+else
+echo 'x - demo/sgi/gl_panel/README'
+sed 's/^X//' > 'demo/sgi/gl_panel/README' << 'EOF'
+XThis directory contains demos that use the Panel Library by NASA Ames.
+XThey only run on SGI machines and require the 'pnl' and 'gl' built-in
+Xmodules. Each subdirectory contains one demo.
+X
+Xapanel A trivial user interface to the audio capabilities of
+X the 4D/25 (Personal IRIS). Lets you record a sample and
+X play it back at different volumes. Requires the 'audio'
+X built-in module.
+X
+Xflying A large demonstration that can display several
+X differently shaped objects through space. Control
+X panels let you manipulate light sources, material
+X properties and drawing modes.
+X
+Xnurbs A demo of the capabilities of the GL 'nurbs' functions
+X that can display the control points. (It was intended
+X to let you move these as well, but there was a problem
+X with the mapping of mouse movements in a 3-D world.)
+X
+Xtwoview A demo of GL's transformation primitives. Two views on
+X a scene are given, and the position and orientation of a
+X viewer in one of the views can be changed through
+X various buttons and dials in a control panel.
+EOF
+fi
+if test -s 'demo/sgi/gl_panel/apanel/apanel.py'
+then echo '*** I will not over-write existing file demo/sgi/gl_panel/apanel/apanel.py'
+else
+echo 'x - demo/sgi/gl_panel/apanel/apanel.py'
+sed 's/^X//' > 'demo/sgi/gl_panel/apanel/apanel.py' << 'EOF'
+X#! /ufs/guido/bin/sgi/python
+X
+X# A (too) trivial control panel to record a sound sample and play it back.
+X# Requires the audio built-in module.
+X# Requires the NASA AMES Panel Library.
+X
+Ximport sys
+X
+Ximport gl
+Ximport panel
+X
+Xpanel.block(1)
+X
+Ximport audio
+X
+Xdef main():
+X gl.foreground()
+X gl.noport()
+X #gl.prefposition(700, 850, 950, 970)
+X wid = gl.winopen('audio demo')
+X #
+X panels = panel.defpanellist('apanel.s') # XXX
+X p = panels[0]
+X p.playbackbutton.back = p
+X p.recordbutton.back = p
+X p.sample = ''
+X #
+X def quit(a):
+X sys.exit(0)
+X #
+X p.quitbutton.downfunc = quit
+X #
+X def playback(a):
+X p = a.back
+X gain = int(255.0*p.outputgain.val)
+X a.val = 1.0
+X a.fixact()
+X panel.drawpanel()
+X audio.setoutgain(gain)
+X audio.write(p.sample)
+X audio.setoutgain(0)
+X a.val = 0.0
+X a.fixact()
+X #
+X p.playbackbutton.downfunc = playback
+X #
+X def record(a):
+X p = a.back
+X size = int(10.0 * 8192.0 * p.recordsize.val)
+X a.val = 1.0
+X a.fixact()
+X panel.drawpanel()
+X audio.setoutgain(0)
+X p.sample = audio.read(size)
+X a.val = 0.0
+X a.fixact()
+X #
+X p.recordbutton.downfunc = record
+X #
+X while 1:
+X act = panel.dopanel()
+X
+Xmain()
+EOF
+chmod +x 'demo/sgi/gl_panel/apanel/apanel.py'
+fi
+if test -s 'demo/sgi/gl_panel/flying/material.py'
+then echo '*** I will not over-write existing file demo/sgi/gl_panel/flying/material.py'
+else
+echo 'x - demo/sgi/gl_panel/flying/material.py'
+sed 's/^X//' > 'demo/sgi/gl_panel/flying/material.py' << 'EOF'
+Ximport light
+X
+Xdef mkmatdict () :
+X m = {}
+X m['material 1'] = light.m1
+X m['material 2'] = light.m2
+X m['material 3'] = light.m3
+X m['material 4'] = light.m4
+X m['material 5'] = light.m5
+X m['material 6'] = light.m6
+X m['material 7'] = light.m7
+X m['material 8'] = light.m8
+X m['material 9'] = light.m9
+X #
+X return m
+X
+Xmaterdict = mkmatdict ()
+X
+Xdef mklichtdict () :
+X m = {}
+X m['light 1'] = light.light1
+X m['light 2'] = light.light2
+X #
+X return m
+X
+Xlichtdict = mklichtdict ()
+EOF
+fi
+if test -s 'demo/sgi/gl_panel/flying/objdict.py'
+then echo '*** I will not over-write existing file demo/sgi/gl_panel/flying/objdict.py'
+else
+echo 'x - demo/sgi/gl_panel/flying/objdict.py'
+sed 's/^X//' > 'demo/sgi/gl_panel/flying/objdict.py' << 'EOF'
+X
+Xfrom data import *
+X
+X#
+X#the color light-blue
+X#
+XLightBlue = lightblue
+X
+X# the 'object' dictionary contains the strings of the menu items
+X# that denote the objects
+Xobjects = {}
+X
+X# object dictionary initialization
+Xobjects['sphere'] = [ZERO, o1]
+Xobjects['cylinder'] = [ZERO, o2]
+Xobjects['cube'] = [ONE, o3]
+Xobjects['icecream'] = [ZERO, o4]
+Xobjects['disk'] = [ZERO, o5]
+Xobjects['diamond'] = [ZERO, o6]
+X#objects['glass'] = [ZERO]
+Xobjects['pyramid'] = [ZERO, o7]
+Xobjects['table'] = [ZERO, o8]
+X
+X# 'putDict' sets the value of entry 'key' of dictionary 'dict'
+Xdef putDict(dict, key, val) :
+X dict[key][0] = val
+X
+X#
+X# 'getDict' get the contents of entry i of key 'key'
+X# of dictionary 'dict'
+X#
+Xdef getDict(dict, key, i) :
+X return dict[key][i]
+X
+X# the 'options' dictionary contains the strings of the menu items
+X# that denote the options
+Xoptions = {}
+X
+X# option dictionary initialization
+Xoptions['wire'] = [ZERO]
+Xoptions['filled'] = [ONE]
+EOF
+fi
+if test -s 'demo/sgi/gl_panel/twoview/topview.s'
+then echo '*** I will not over-write existing file demo/sgi/gl_panel/twoview/topview.s'
+else
+echo 'x - demo/sgi/gl_panel/twoview/topview.s'
+sed 's/^X//' > 'demo/sgi/gl_panel/twoview/topview.s' << 'EOF'
+X;;; This file was automatically generated by the panel editor.
+X;;; If you read it into gnu emacs, it will automagically format itself.
+X
+X(panel (prop help creator:user-panel-help)
+X(prop user-panel #t)
+X(label "Top View Control")
+X(x 1020)
+X(y 287)
+X(al (pnl_hslider (name "xpos")
+X(prop help creator:user-act-help)
+X(label "X")
+X(x 2)
+X(y 0.5)
+X(w 3.85)
+X(h 0.4)
+X(val 0.5)
+X(downfunc move-then-resize)
+X)
+X(pnl_vslider (name "zpos")
+X(prop help creator:user-act-help)
+X(label "Z")
+X(x 1.25)
+X(y 1.3)
+X(w 0.4)
+X(h 3.6)
+X(val 0.5)
+X(downfunc move-then-resize)
+X)
+X(pnl_dial (name "direction")
+X(prop help creator:user-act-help)
+X(label "looking direction")
+X(x 2.15)
+X(y 1.4)
+X(w 3.5)
+X(h 3.45)
+X(val 0.5)
+X(downfunc move-then-resize)
+X)
+X)
+X)
+X;;; Local Variables:
+X;;; mode: scheme
+X;;; eval: (save-excursion (goto-char (point-min)) (kill-line 3))
+X;;; eval: (save-excursion (goto-char (point-min)) (replace-regexp "[ \n]*)" ")"))
+X;;; eval: (indent-region (point-min) (point-max) nil)
+X;;; eval: (progn (kill-line -3) (delete-backward-char 1) (save-buffer))
+X;;; End:
+EOF
+fi
+if test -s 'doc/README'
+then echo '*** I will not over-write existing file doc/README'
+else
+echo 'x - doc/README'
+sed 's/^X//' > 'doc/README' << 'EOF'
+XThis directory contains the LaTeX source to the Python documentation.
+XThe documentation is not all finished, but good enough to get you
+Xstarted.
+X
+XThe following are the important latex source files:
+X
+X tut.tex A tutorial
+X mod.tex The library reference
+X
+XThey both read the style option file "myformat.sty".
+X
+XYou can use the Makefile to format, preview and print the documents.
+XType "make tut" or "make mod" to preview either document with xdvi.
+XType "make print" to print them both (this only works if your print
+Xspooler is set up just like mine...), or "make all" to create postscript
+Xfiles that you can you can print using your local printing commands.
+XType "make clean" to get rid of all the intermediate files produced by
+Xthe latex process, and other junk files.
+X
+XYou can just as well ignore the Makefile; all you really need is:
+X latex tut
+X latex tut
+X dvips tut | lpr
+Xand similar for the "mod" document.
+EOF
+fi
+if test -s 'doc/SetClass.py'
+then echo '*** I will not over-write existing file doc/SetClass.py'
+else
+echo 'x - doc/SetClass.py'
+sed 's/^X//' > 'doc/SetClass.py' << 'EOF'
+Xclass Set():
+X def new(self):
+X self.elements = []
+X return self
+X def add(self, e):
+X if e not in self.elements:
+X self.elements.append(e)
+X def remove(self, e):
+X if e in self.elements:
+X for i in range(len(self.elements)):
+X if self.elements[i] = e:
+X del self.elements[i]
+X break
+X def is_element(self, e):
+X return e in self.elements
+X def size(self):
+X return len(self.elements)
+EOF
+fi
+if test -s 'doc/fibo.py'
+then echo '*** I will not over-write existing file doc/fibo.py'
+else
+echo 'x - doc/fibo.py'
+sed 's/^X//' > 'doc/fibo.py' << 'EOF'
+X# Fibonacci numbers demo
+X
+Xdef fib(n): # write Fibonacci series up to n
+X a, b = 0, 1
+X while b <= n:
+X print b,
+X a, b = b, a+b
+X
+Xdef fib2(n): # return Fibonacci series up to n
+X ret = []
+X a, b = 0, 1
+X while b <= n:
+X ret.append(b)
+X a, b = b, a+b
+X return ret
+EOF
+fi
+if test -s 'doc/mod.tex'
+then echo '*** I will not over-write existing file doc/mod.tex'
+else
+echo 'x - doc/mod.tex'
+sed 's/^X//' > 'doc/mod.tex' << 'EOF'
+X% Format this file with latex.
+X
+X%\documentstyle[garamond,11pt,myformat]{article}
+X\documentstyle[11pt,myformat]{article}
+X
+X% A command to force the text after an item to start on a new line
+X\newcommand{\itembreak}{
+X \mbox{}\\*[0mm]
+X}
+X
+X% A command to define a function item
+X\newcommand{\funcitem}[2]{\item[#1(#2)]}
+X
+X% A command to define an exception item
+X\newcommand{\excitem}[2]{
+X\item[#1 = {\tt '#2'}]
+X\itembreak
+X}
+X
+X\title{\bf
+X Python Library Reference \\
+X (DRAFT)
+X}
+X
+X\author{
+X Guido van Rossum \\
+X Dept. CST, CWI, Kruislaan 413 \\
+X 1098 SJ Amsterdam, The Netherlands \\
+X E-mail: {\tt [email protected]}
+X}
+X
+X\begin{document}
+X
+X\pagenumbering{roman}
+X
+X\maketitle
+X
+X\begin{abstract}
+X
+X\noindent
+XThis document describes the built-in types, exceptions and functions and
+Xthe standard modules that come with the {\Python} system.
+XIt assumes basic knowledge about the {\Python} language.
+XFor an informal introduction to the language, see the Tutorial document.
+XThe Language Reference document (XXX not yet existing)
+Xgives a more formal reference to the language.
+X
+X\end{abstract}
+X
+X\pagebreak
+X
+X\tableofcontents
+X
+X\pagebreak
+X
+X\pagenumbering{arabic}
+X
+X\input{mod1.tex}
+X\input{mod2.tex}
+X\input{mod3.tex}
+X
+X\end{document}
+EOF
+fi
+if test -s 'doc/myformat.sty'
+then echo '*** I will not over-write existing file doc/myformat.sty'
+else
+echo 'x - doc/myformat.sty'
+sed 's/^X//' > 'doc/myformat.sty' << 'EOF'
+X% Style parameters and macros used by all documents here
+X
+X% Page lay-out parameters
+X\textwidth = 160mm
+X\textheight = 240mm
+X\topmargin = -11mm
+X\oddsidemargin = 0mm
+X\evensidemargin = 0mm
+X%\parindent = 0mm
+X
+X% Frequently used system names
+X\newcommand{\Python}{Python} % Sometimes I want this italicized
+X\newcommand{\UNIX}{U{\sc nix}}
+X
+X% Variable used by begin code command
+X\newlength{\codewidth}
+X
+X\newcommand{\bcode}{
+X % Calculate the text width for the minipage:
+X \setlength{\codewidth}{\linewidth}
+X \addtolength{\codewidth}{-\parindent}
+X %
+X \vspace{3mm}
+X \par
+X \indent
+X \begin{minipage}[t]{\codewidth}
+X}
+X
+X\newcommand{\ecode}{
+X \end{minipage}
+X \vspace{3mm}
+X \par
+X \noindent
+X}
+EOF
+fi
+if test -s 'doc/pytry'
+then echo '*** I will not over-write existing file doc/pytry'
+else
+echo 'x - doc/pytry'
+sed 's/^X//' > 'doc/pytry' << 'EOF'
+XTMP=/usr/tmp/pytry$$
+Xtrap 'rm -f $TMP; exit 1' 1 2 3 13 14 15
+X
+Xcat $* >$TMP
+X
+X(
+X cat $TMP
+X
+X sed '
+X s/^>>> //
+X s/^>>>$//
+X s/^\.\.\. //
+X s/^\.\.\.$//
+X ' $TMP |
+X python
+X
+X echo '>>> '
+X) 2>&1
+X
+Xrm $TMP
+EOF
+chmod +x 'doc/pytry'
+fi
+if test -s 'lib/Histogram.py'
+then echo '*** I will not over-write existing file lib/Histogram.py'
+else
+echo 'x - lib/Histogram.py'
+sed 's/^X//' > 'lib/Histogram.py' << 'EOF'
+X# Module 'Histogram'
+X
+Xfrom Buttons import *
+X
+X# A Histogram displays a histogram of numeric data.
+X#
+Xclass HistogramAppearance() = LabelAppearance(), Define():
+X #
+X def define(self, parent):
+X Define.define(self, (parent, ''))
+X self.ydata = []
+X self.scale = (0, 100)
+X return self
+X #
+X def setdata(self, (ydata, scale)):
+X self.ydata = ydata
+X self.scale = scale # (min, max)
+X self.parent.change(self.bounds)
+X #
+X def drawpict(self, d):
+X (left, top), (right, bottom) = self.bounds
+X min, max = self.scale
+X size = max-min
+X width, height = right-left, bottom-top
+X ydata = self.ydata
+X npoints = len(ydata)
+X v1 = top + height # constant
+X h1 = left # changed in loop
+X for i in range(npoints):
+X h0 = h1
+X v0 = top + height - (ydata[i]-min)*height/size
+X h1 = left + (i+1) * width/npoints
+X d.paint((h0, v0), (h1, v1))
+X #
+X
+Xclass Histogram() = NoReactivity(), HistogramAppearance(): pass
+EOF
+fi
+if test -s 'lib/Soundogram.py'
+then echo '*** I will not over-write existing file lib/Soundogram.py'
+else
+echo 'x - lib/Soundogram.py'
+sed 's/^X//' > 'lib/Soundogram.py' << 'EOF'
+X# Module 'Soundogram'
+X
+Ximport audio
+Xfrom Histogram import Histogram
+X
+Xclass Soundogram() = Histogram():
+X #
+X def define(self, (win, chunk)):
+X width, height = corner = win.getwinsize()
+X bounds = (0, 0), corner
+X self.chunk = chunk
+X self.step = (len(chunk)-1)/(width/2+1) + 1
+X ydata = _make_ydata(chunk, self.step)
+X return Histogram.define(self, (win, bounds, ydata, (0, 128)))
+X #
+X def setchunk(self, chunk):
+X self.chunk = chunk
+X self.recompute()
+X #
+X def recompute(self):
+X (left, top), (right, bottom) = self.bounds
+X width = right - left
+X self.step = (len(chunk)-1)/width + 1
+X ydata = _make_ydata(chunk, self.step)
+X self.setdata(ydata, (0, 128))
+X #
+X
+X
+Xdef _make_ydata(chunk, step):
+X ydata = []
+X for i in range(0, len(chunk), step):
+X piece = audio.chr2num(chunk[i:i+step])
+X mi, ma = min(piece), max(piece)
+X y = max(abs(mi), abs(ma))
+X ydata.append(y)
+X return ydata
+EOF
+fi
+if test -s 'lib/TestCSplit.py'
+then echo '*** I will not over-write existing file lib/TestCSplit.py'
+else
+echo 'x - lib/TestCSplit.py'
+sed 's/^X//' > 'lib/TestCSplit.py' << 'EOF'
+X# TestCSplit
+X
+Ximport stdwin
+Xfrom stdwinevents import WE_CLOSE
+Xfrom WindowParent import WindowParent
+Xfrom Buttons import PushButton
+X
+Xdef main(n):
+X from CSplit import CSplit
+X
+X the_window = WindowParent().create('TestCSplit', (0, 0))
+X the_csplit = CSplit().create(the_window)
+X
+X for i in range(n):
+X the_child = PushButton().define(the_csplit)
+X the_child.settext(`(i+n-1)%n+1`)
+X
+X the_window.realize()
+X
+X while 1:
+X the_event = stdwin.getevent()
+X if the_event[0] = WE_CLOSE: break
+X the_window.dispatch(the_event)
+X the_window.destroy()
+X
+Xmain(12)
+EOF
+fi
+if test -s 'lib/VUMeter.py'
+then echo '*** I will not over-write existing file lib/VUMeter.py'
+else
+echo 'x - lib/VUMeter.py'
+sed 's/^X//' > 'lib/VUMeter.py' << 'EOF'
+X# Module 'VUMeter'
+X
+Ximport audio
+Xfrom StripChart import StripChart
+X
+XK = 1024
+XRates = [0, 32*K, 16*K, 8*K]
+X
+Xclass VUMeter() = StripChart():
+X #
+X # Override define() and timer() methods
+X #
+X def define(self, parent):
+X self = StripChart.define(self, (parent, 128))
+X self.parent.need_timer(self)
+X self.sampling = 0
+X self.rate = 3
+X self.enable(0)
+X return self
+X #
+X def timer(self):
+X if self.sampling:
+X chunk = audio.wait_recording()
+X self.sampling = 0
+X nums = audio.chr2num(chunk)
+X ampl = max(abs(min(nums)), abs(max(nums)))
+X self.append(ampl)
+X if self.enabled and not self.sampling:
+X audio.setrate(self.rate)
+X size = Rates[self.rate]/10
+X size = size/48*48
+X audio.start_recording(size)
+X self.sampling = 1
+X if self.sampling:
+X self.parent.settimer(1)
+X #
+X # New methods: start() and stop()
+X #
+X def stop(self):
+X if self.sampling:
+X chunk = audio.stop_recording()
+X self.sampling = 0
+X self.enable(0)
+X #
+X def start(self):
+X self.enable(1)
+X self.timer()
+EOF
+fi
+if test -s 'lib/anywin.py'
+then echo '*** I will not over-write existing file lib/anywin.py'
+else
+echo 'x - lib/anywin.py'
+sed 's/^X//' > 'lib/anywin.py' << 'EOF'
+X# Module 'anywin'
+X# Open a file or directory in a window
+X
+Ximport dirwin
+Ximport filewin
+Ximport path
+X
+Xdef open(name):
+X print 'opening', name, '...'
+X if path.isdir(name):
+X w = dirwin.open(name)
+X else:
+X w = filewin.open(name)
+X return w
+EOF
+fi
+if test -s 'lib/dircache.py'
+then echo '*** I will not over-write existing file lib/dircache.py'
+else
+echo 'x - lib/dircache.py'
+sed 's/^X//' > 'lib/dircache.py' << 'EOF'
+X# Module 'dircache'
+X#
+X# Return a sorted list of the files in a POSIX directory, using a cache
+X# to avoid reading the directory more often than necessary.
+X# Also contains a subroutine to append slashes to directories.
+X
+Ximport posix
+Ximport path
+X
+Xcache = {}
+X
+Xdef listdir(path): # List directory contents, using cache
+X try:
+X cached_mtime, list = cache[path]
+X del cache[path]
+X except RuntimeError:
+X cached_mtime, list = -1, []
+X try:
+X mtime = posix.stat(path)[8]
+X except posix.error:
+X return []
+X if mtime <> cached_mtime:
+X try:
+X list = posix.listdir(path)
+X except posix.error:
+X return []
+X list.sort()
+X cache[path] = mtime, list
+X return list
+X
+Xopendir = listdir # XXX backward compatibility
+X
+Xdef annotate(head, list): # Add '/' suffixes to directories
+X for i in range(len(list)):
+X if path.isdir(path.cat(head, list[i])):
+X list[i] = list[i] + '/'
+EOF
+fi
+if test -s 'lib/dirwin.py'
+then echo '*** I will not over-write existing file lib/dirwin.py'
+else
+echo 'x - lib/dirwin.py'
+sed 's/^X//' > 'lib/dirwin.py' << 'EOF'
+X# Module 'dirwin'
+X
+X# Directory windows, a subclass of listwin
+X
+Ximport gwin
+Ximport listwin
+Ximport anywin
+Ximport path
+Ximport dircache
+X
+Xdef action(w, string, i, detail):
+X (h, v), clicks, button, mask = detail
+X if clicks = 2:
+X name = path.cat(w.name, string)
+X try:
+X w2 = anywin.open(name)
+X w2.parent = w
+X except posix.error, why:
+X stdwin.message('Can\'t open ' + name + ': ' + why[1])
+X
+Xdef open(name):
+X name = path.cat(name, '')
+X list = dircache.opendir(name)[:]
+X list.sort()
+X dircache.annotate(name, list)
+X w = listwin.open(name, list)
+X w.name = name
+X w.action = action
+X return w
+EOF
+fi
+if test -s 'lib/fact.py'
+then echo '*** I will not over-write existing file lib/fact.py'
+else
+echo 'x - lib/fact.py'
+sed 's/^X//' > 'lib/fact.py' << 'EOF'
+X# Factorize numbers -- slow, could use a table of all primes <= 2*16
+X
+Ximport sys
+Ximport math
+X
+Xerror = 'fact.error' # exception
+X
+Xdef fact(n):
+X if n < 1: raise error # fact() argument should be >= 1
+X if n = 1: return [] # special case
+X res = []
+X _fact(n, 2, res)
+X return res
+X
+Xdef _fact(n, lowest, res):
+X highest = int(math.sqrt(float(n+1)))
+X for i in range(lowest, highest+1):
+X if n%i = 0:
+X res.append(i)
+X _fact(n/i, i, res)
+X break
+X else:
+X res.append(n)
+X
+Xdef main():
+X if len(sys.argv) > 1:
+X for arg in sys.argv[1:]:
+X n = eval(arg)
+X print n, fact(n)
+X else:
+X try:
+X while 1:
+X print fact(input())
+X except EOFError:
+X pass
+X
+Xmain()
+EOF
+fi
+if test -s 'lib/filewin.py'
+then echo '*** I will not over-write existing file lib/filewin.py'
+else
+echo 'x - lib/filewin.py'
+sed 's/^X//' > 'lib/filewin.py' << 'EOF'
+X# Module 'filewin'
+X# File windows, a subclass of textwin (which is a subclass of gwin)
+X
+Ximport textwin
+Xfrom util import readfile
+X
+X
+X# FILE WINDOW
+X
+Xdef open_readonly(fn): # Open a file window
+X w = textwin.open_readonly(fn, readfile(fn))
+X w.fn = fn
+X return w
+X
+Xdef open(fn): # Open a file window
+X w = textwin.open(fn, readfile(fn))
+X w.fn = fn
+X return w
+EOF
+fi
+if test -s 'lib/fnmatch.py'
+then echo '*** I will not over-write existing file lib/fnmatch.py'
+else
+echo 'x - lib/fnmatch.py'
+sed 's/^X//' > 'lib/fnmatch.py' << 'EOF'
+X# module 'fnmatch' -- filename matching with shell patterns
+X
+X# XXX [] patterns are not supported (but recognized)
+X
+Xdef fnmatch(name, pat):
+X if '*' in pat or '?' in pat or '[' in pat:
+X return fnmatch1(name, pat)
+X return name = pat
+X
+Xdef fnmatch1(name, pat):
+X for i in range(len(pat)):
+X c = pat[i]
+X if c = '*':
+X restpat = pat[i+1:]
+X if '*' in restpat or '?' in restpat or '[' in restpat:
+X for i in range(i, len(name)):
+X if fnmatch1(name[i:], restpat):
+X return 1
+X return 0
+X else:
+X return name[len(name)-len(restpat):] = restpat
+X elif c = '?':
+X if len(name) <= i : return 0
+X elif c = '[':
+X return 0 # XXX
+X else:
+X if name[i:i+1] <> c:
+X return 0
+X return 1
+X
+Xdef fnmatchlist(names, pat):
+X res = []
+X for name in names:
+X if fnmatch(name, pat): res.append(name)
+X return res
+EOF
+fi
+if test -s 'lib/glob.py'
+then echo '*** I will not over-write existing file lib/glob.py'
+else
+echo 'x - lib/glob.py'
+sed 's/^X//' > 'lib/glob.py' << 'EOF'
+X# Module 'glob' -- filename globbing.
+X
+Ximport posix
+Ximport path
+Ximport fnmatch
+X
+Xdef glob(pathname):
+X if not has_magic(pathname): return [pathname]
+X dirname, basename = path.split(pathname)
+X if dirname[-1:] = '/' and dirname <> '/':
+X dirname = dirname[:-1]
+X if has_magic(dirname):
+X list = glob(dirname)
+X else:
+X list = [dirname]
+X if not has_magic(basename):
+X result = []
+X for dirname in list:
+X if basename or path.isdir(dirname):
+X name = path.cat(dirname, basename)
+X if path.exists(name):
+X result.append(name)
+X else:
+X result = []
+X for dirname in list:
+X sublist = glob1(dirname, basename)
+X for name in sublist:
+X result.append(path.cat(dirname, name))
+X return result
+X
+Xdef glob1(dirname, pattern):
+X if not dirname: dirname = '.'
+X try:
+X names = posix.listdir(dirname)
+X except posix.error:
+X return []
+X result = []
+X for name in names:
+X if name[0] <> '.' or pattern[0] = '.':
+X if fnmatch.fnmatch(name, pattern): result.append(name)
+X return result
+X
+Xdef has_magic(s):
+X return '*' in s or '?' in s or '[' in s
+EOF
+fi
+if test -s 'lib/grep.py'
+then echo '*** I will not over-write existing file lib/grep.py'
+else
+echo 'x - lib/grep.py'
+sed 's/^X//' > 'lib/grep.py' << 'EOF'
+X# 'grep'
+X
+Ximport regexp
+Ximport string
+X
+Xdef grep(expr, filename):
+X prog = regexp.compile(expr)
+X fp = open(filename, 'r')
+X lineno = 0
+X while 1:
+X line = fp.readline()
+X if not line: break
+X lineno = lineno + 1
+X res = prog.exec(line)
+X if res:
+X #print res
+X start, end = res[0]
+X if line[-1:] = '\n': line = line[:-1]
+X prefix = string.rjust(`lineno`, 3) + ': '
+X print prefix + line
+X if 0:
+X line = line[:start]
+X if '\t' not in line:
+X prefix = ' ' * (len(prefix) + start)
+X else:
+X prefix = ' ' * len(prefix)
+X for c in line:
+X if c <> '\t': c = ' '
+X prefix = prefix + c
+X if start = end: prefix = prefix + '\\'
+X else: prefix = prefix + '^'*(end-start)
+X print prefix
+EOF
+fi
+if test -s 'lib/maccache.py'
+then echo '*** I will not over-write existing file lib/maccache.py'
+else
+echo 'x - lib/maccache.py'
+sed 's/^X//' > 'lib/maccache.py' << 'EOF'
+X# Module 'maccache'
+X#
+X# Maintain a cache of listdir(), isdir(), isfile() or exists() outcomes.
+X
+Ximport mac
+Ximport macpath
+X
+X
+X# The cache.
+X# Keys are absolute pathnames;
+X# values are 0 (nothing), 1 (file) or [...] (dir).
+X#
+Xcache = {}
+X
+X
+X# Current working directory.
+X#
+Xcwd = mac.getcwd()
+X
+X
+X# Constants.
+X#
+XNONE = 0
+XFILE = 1
+XLISTTYPE = type([])
+X
+Xdef _stat(name):
+X name = macpath.cat(cwd, name)
+X if cache.has_key(name):
+X return cache[name]
+X if macpath.isfile(name):
+X cache[name] = FILE
+X return FILE
+X try:
+X list = mac.listdir(name)
+X except:
+X cache[name] = NONE
+X return NONE
+X cache[name] = list
+X if name[-1:] = ':': cache[name[:-1]] = list
+X else: cache[name+':'] = list
+X return list
+X
+Xdef isdir(name):
+X st = _stat(name)
+X return type(st) = LISTTYPE
+X
+Xdef isfile(name):
+X st = _stat(name)
+X return st = FILE
+X
+Xdef exists(name):
+X st = _stat(name)
+X return st <> NONE
+X
+Xdef listdir(name):
+X st = _stat(name)
+X if type(st) = LISTTYPE:
+X return st
+X else:
+X raise RuntimeError, 'list non-directory'
+EOF
+fi
+if test -s 'lib/macglob.py'
+then echo '*** I will not over-write existing file lib/macglob.py'
+else
+echo 'x - lib/macglob.py'
+sed 's/^X//' > 'lib/macglob.py' << 'EOF'
+X# Module 'macglob' -- version of 'glob' for the Macintosh.
+X
+X# XXX At least one bug is left: a pattern like '*:' is treated
+X# XXX as a relative pathname (and returns as if it was ':*:').
+X
+Ximport mac
+Ximport macpath
+Ximport fnmatch
+X
+Xdef glob(pathname):
+X if not has_magic(pathname): return [pathname]
+X dirname, basename = macpath.split(pathname)
+X if has_magic(dirname):
+X if dirname[-1:] = ':': dirname = dirname[:-1]
+X list = glob(dirname)
+X else:
+X list = [dirname]
+X if not has_magic(basename):
+X result = []
+X for dirname in list:
+X if basename or macpath.isdir(dirname):
+X name = macpath.cat(dirname, basename)
+X if macpath.exists(name):
+X result.append(name)
+X else:
+X result = []
+X for dirname in list:
+X sublist = glob1(dirname, basename)
+X for name in sublist:
+X result.append(macpath.cat(dirname, name))
+X return result
+X
+Xdef glob1(dirname, pattern):
+X if not dirname: dirname = ':'
+X try:
+X names = mac.listdir(dirname)
+X except mac.error:
+X return []
+X result = []
+X for name in names:
+X if name[0] <> '.' or pattern[0] = '.':
+X if fnmatch.fnmatch(name, pattern): result.append(name)
+X return result
+X
+Xdef has_magic(s):
+X return '*' in s or '?' in s or '[' in s
+EOF
+fi
+if test -s 'lib/minmax.py'
+then echo '*** I will not over-write existing file lib/minmax.py'
+else
+echo 'x - lib/minmax.py'
+sed 's/^X//' > 'lib/minmax.py' << 'EOF'
+X# Module 'minmax'
+X# These are now built in functions.
+X# For compatibility, we export the builtins
+X
+Xmin = min
+Xmax = max
+EOF
+fi
+if test -s 'lib/packmail.py'
+then echo '*** I will not over-write existing file lib/packmail.py'
+else
+echo 'x - lib/packmail.py'
+sed 's/^X//' > 'lib/packmail.py' << 'EOF'
+X# Module 'packmail' -- create a shell script out of some files.
+X
+Ximport mac
+Ximport macpath
+Xfrom stat import ST_MTIME
+X
+X# Pack one file
+Xdef pack(outfp, file, name):
+X fp = open(file, 'r')
+X outfp.write('sed "s/^X//" >' + name + ' <<"!"\n')
+X while 1:
+X line = fp.readline()
+X if not line: break
+X if line[-1:] <> '\n':
+X line = line + '\n'
+X outfp.write('X' + line)
+X outfp.write('!\n')
+X
+X# Pack some files from a directory
+Xdef packsome(outfp, dirname, names):
+X for name in names:
+X print name
+X file = macpath.cat(dirname, name)
+X pack(outfp, file, name)
+X
+X# Pack all files from a directory
+Xdef packall(outfp, dirname):
+X names = mac.listdir(dirname)
+X names.sort()
+X packsome(outfp, dirname, names)
+X
+X# Pack all files from a directory that are not older than a give one
+Xdef packnotolder(outfp, dirname, oldest):
+X names = mac.listdir(dirname)
+X oldest = macpath.cat(dirname, oldest)
+X st = mac.stat(oldest)
+X mtime = st[ST_MTIME]
+X todo = []
+X for name in names:
+X print name, '...',
+X st = mac.stat(macpath.cat(dirname, name))
+X if st[ST_MTIME] >= mtime:
+X print 'Yes.'
+X todo.append(name)
+X else:
+X print 'No.'
+X todo.sort()
+X packsome(outfp, dirname, todo)
+EOF
+fi
+if test -s 'lib/rand.py'
+then echo '*** I will not over-write existing file lib/rand.py'
+else
+echo 'x - lib/rand.py'
+sed 's/^X//' > 'lib/rand.py' << 'EOF'
+X# Module 'rand'
+X
+Ximport whrandom
+X
+Xdef srand(seed):
+X whrandom.seed(seed%256, seed/256%256, seed/65536%256)
+X
+Xdef rand():
+X return int(whrandom.random() * 32768.0) % 32768
+X
+Xdef choice(seq):
+X return seq[rand() % len(seq)]
+EOF
+fi
+if test -s 'lib/stat.py'
+then echo '*** I will not over-write existing file lib/stat.py'
+else
+echo 'x - lib/stat.py'
+sed 's/^X//' > 'lib/stat.py' << 'EOF'
+X# Module 'stat'
+X
+X# Defines constants and functions for interpreting stat/lstat struct
+X# as returned by posix.stat() and posix.lstat() (if it exists).
+X
+X# XXX This module may have to be adapted for UNIXoid systems whose
+X# <sys/stat.h> deviates from AT&T or BSD UNIX; their S_IF* constants
+X# may differ.
+X
+X# Suggested usage: from stat import *
+X
+X# Tuple indices for stat struct members
+X
+XST_MODE = 0
+XST_INO = 1
+XST_DEV = 2
+XST_NLINK = 3
+XST_UID = 4
+XST_GID = 5
+XST_SIZE = 6
+XST_ATIME = 7
+XST_MTIME = 8
+XST_CTIME = 9
+X
+Xdef S_IMODE(mode):
+X return mode%4096
+Xdef S_IFMT(mode):
+X return mode - mode%4096
+X
+XS_IFDIR = 0040000
+XS_IFCHR = 0020000
+XS_IFBLK = 0060000
+XS_IFREG = 0100000
+XS_IFIFO = 0010000
+XS_IFLNK = 0120000
+XS_IFSOCK = 0140000
+X
+Xdef S_ISDIR(mode):
+X return S_IFMT(mode) = S_IFDIR
+X
+Xdef S_ISCHR(mode):
+X return S_IFMT(mode) = S_IFCHR
+X
+Xdef S_ISBLK(mode):
+X return S_IFMT(mode) = S_IFBLK
+X
+Xdef S_ISREG(mode):
+X return S_IFMT(mode) = S_IFREG
+X
+Xdef S_ISFIFO(mode):
+X return S_IFMT(mode) = S_IFIFO
+X
+Xdef S_ISLNK(mode):
+X return S_IFMT(mode) = S_IFLNK
+X
+Xdef S_ISSOCK(mode):
+X return S_IFMT(mode) = S_IFSOCK
+EOF
+fi
+if test -s 'lib/stdwinsupport.py'
+then echo '*** I will not over-write existing file lib/stdwinsupport.py'
+else
+echo 'x - lib/stdwinsupport.py'
+sed 's/^X//' > 'lib/stdwinsupport.py' << 'EOF'
+X# Module 'stdwinsupport'
+X
+Ximport stdwin
+X
+Xeventnames = ['null', 'activate', 'char', 'command']
+Xeventnames = eventnames + ['mouse_down', 'mouse_move', 'mouse_up', 'menu']
+Xeventnames = eventnames + ['size', 'move', 'draw', 'timer', 'deactivate']
+X
+Xwe_null = 0
+Xwe_activate = 1
+Xwe_char = 2
+Xwe_command = 3
+Xwe_mouse_down = 4
+Xwe_mouse_move = 5
+Xwe_mouse_up = 6
+Xwe_menu = 7
+Xwe_size = 8
+Xwe_move = 9
+Xwe_draw = 10
+Xwe_timer = 11
+Xwe_deactivate = 12
+X
+Xcommandnames = ['?', 'close', 'left', 'right', 'up', 'down', 'cancel']
+Xcommandnames = commandnames + ['backspace', 'tab', 'return']
+X
+Xwc_close = 1
+Xwc_left = 2
+Xwc_right = 3
+Xwc_up = 4
+Xwc_down = 5
+Xwc_cancel = 6 # not reported -- turned into KeyboardInterrupt
+Xwc_backspace = 7
+Xwc_tab = 8
+Xwc_return = 9
+EOF
+fi
+if test -s 'lib/util.py'
+then echo '*** I will not over-write existing file lib/util.py'
+else
+echo 'x - lib/util.py'
+sed 's/^X//' > 'lib/util.py' << 'EOF'
+X# Module 'util' -- some useful functions that don't fit elsewhere
+X
+X
+X# Remove an item from a list.
+X# No complaints if it isn't in the list at all.
+X# If it occurs more than once, remove the first occurrence.
+X#
+Xdef remove(item, list):
+X for i in range(len(list)):
+X if list[i] = item:
+X del list[i]
+X break
+X
+X
+X# Return a string containing a file's contents.
+X#
+Xdef readfile(fn):
+X return readopenfile(open(fn, 'r'))
+X
+X
+X# Read an open file until EOF.
+X#
+Xdef readopenfile(fp):
+X BUFSIZE = 512*8
+X data = ''
+X while 1:
+X buf = fp.read(BUFSIZE)
+X if not buf: break
+X data = data + buf
+X return data
+EOF
+fi
+if test -s 'src/To.do'
+then echo '*** I will not over-write existing file src/To.do'
+else
+echo 'x - src/To.do'
+sed 's/^X//' > 'src/To.do' << 'EOF'
+X- return better errors for file objects (also check read/write allowed, etc.)
+X
+X- introduce more specific exceptions (e.g., zero divide, index failure, ...)
+X
+X- why do reads from stdin fail when I suspend the process?
+X
+X- introduce macros to set/inspect errno for syscalls, to support things
+X like getoserr()
+X
+X- fix interrupt handling (interruptable system calls should call
+X intrcheck() to clear the interrupt status)
+EOF
+fi
+if test -s 'src/assert.h'
+then echo '*** I will not over-write existing file src/assert.h'
+else
+echo 'x - src/assert.h'
+sed 's/^X//' > 'src/assert.h' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X#define assert(e) { if (!(e)) { printf("Assertion failed\n"); abort(); } }
+EOF
+fi
+if test -s 'src/bltinmodule.h'
+then echo '*** I will not over-write existing file src/bltinmodule.h'
+else
+echo 'x - src/bltinmodule.h'
+sed 's/^X//' > 'src/bltinmodule.h' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X/* Built-in module interface */
+X
+Xextern object *getbuiltin PROTO((char *));
+EOF
+fi
+if test -s 'src/fgetsintr.h'
+then echo '*** I will not over-write existing file src/fgetsintr.h'
+else
+echo 'x - src/fgetsintr.h'
+sed 's/^X//' > 'src/fgetsintr.h' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+Xextern int fgets_intr PROTO((char *, int, FILE *));
+EOF
+fi
+if test -s 'src/rltokenizer.c'
+then echo '*** I will not over-write existing file src/rltokenizer.c'
+else
+echo 'x - src/rltokenizer.c'
+sed 's/^X//' > 'src/rltokenizer.c' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X#define USE_READLINE
+X#include "tokenizer.c"
+EOF
+fi
+if test -s 'src/stubcode.h'
+then echo '*** I will not over-write existing file src/stubcode.h'
+else
+echo 'x - src/stubcode.h'
+sed 's/^X//' > 'src/stubcode.h' << 'EOF'
+X/***********************************************************
+XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+XNetherlands.
+X
+X All Rights Reserved
+X
+XPermission to use, copy, modify, and distribute this software and its
+Xdocumentation for any purpose and without fee is hereby granted,
+Xprovided that the above copyright notice appear in all copies and that
+Xboth that copyright notice and this permission notice appear in
+Xsupporting documentation, and that the names of Stichting Mathematisch
+XCentrum or CWI not be used in advertising or publicity pertaining to
+Xdistribution of the software without specific, written prior permission.
+X
+XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+X
+X******************************************************************/
+X
+X
+X#define CAP 0
+X#define STUBC 1
+X#define NAME 2
+EOF
+fi
+echo 'Part 21 out of 21 of pack.out complete.'
+exit 0
diff --git a/src/Grammar b/src/Grammar
new file mode 100644
index 0000000..574acd6
--- /dev/null
+++ b/src/Grammar
@@ -0,0 +1,72 @@
+# Grammar for Python, version 4
+
+# Changes compared to version 3:
+# Removed 'dir' statement.
+# Function call argument is a testlist instead of exprlist.
+
+# Changes compared to version 2:
+# The syntax of Boolean operations is changed to use more
+# conventional priorities: or < and < not.
+
+# Changes compared to version 1:
+# modules and scripts are unified;
+# 'quit' is gone (use ^D);
+# empty_stmt is gone, replaced by explicit NEWLINE where appropriate;
+# 'import' and 'def' aren't special any more;
+# added 'from' NAME option on import clause, and '*' to import all;
+# added class definition.
+
+# Start symbols for the grammar:
+# single_input is a single interactive statement;
+# file_input is a module or sequence of commands read from an input file;
+# expr_input is the input for the input() function;
+# eval_input is the input for the eval() function.
+
+# NB: compound_stmt in single_input is followed by extra NEWLINE!
+single_input: NEWLINE | simple_stmt | compound_stmt NEWLINE
+file_input: (NEWLINE | stmt)* ENDMARKER
+expr_input: testlist NEWLINE
+eval_input: testlist ENDMARKER
+
+funcdef: 'def' NAME parameters ':' suite
+parameters: '(' [fplist] ')'
+fplist: fpdef (',' fpdef)*
+fpdef: NAME | '(' fplist ')'
+
+stmt: simple_stmt | compound_stmt
+simple_stmt: expr_stmt | print_stmt | pass_stmt | del_stmt | flow_stmt | import_stmt
+expr_stmt: (exprlist '=')* exprlist NEWLINE
+# For assignments, additional restrictions enforced by the interpreter
+print_stmt: 'print' (test ',')* [test] NEWLINE
+del_stmt: 'del' exprlist NEWLINE
+pass_stmt: 'pass' NEWLINE
+flow_stmt: break_stmt | return_stmt | raise_stmt
+break_stmt: 'break' NEWLINE
+return_stmt: 'return' [testlist] NEWLINE
+raise_stmt: 'raise' expr [',' expr] NEWLINE
+import_stmt: 'import' NAME (',' NAME)* NEWLINE | 'from' NAME 'import' ('*' | NAME (',' NAME)*) NEWLINE
+compound_stmt: if_stmt | while_stmt | for_stmt | try_stmt | funcdef | classdef
+if_stmt: 'if' test ':' suite ('elif' test ':' suite)* ['else' ':' suite]
+while_stmt: 'while' test ':' suite ['else' ':' suite]
+for_stmt: 'for' exprlist 'in' exprlist ':' suite ['else' ':' suite]
+try_stmt: 'try' ':' suite (except_clause ':' suite)* ['finally' ':' suite]
+except_clause: 'except' [expr [',' expr]]
+suite: simple_stmt | NEWLINE INDENT NEWLINE* (stmt NEWLINE*)+ DEDENT
+
+test: and_test ('or' and_test)*
+and_test: not_test ('and' not_test)*
+not_test: 'not' not_test | comparison
+comparison: expr (comp_op expr)*
+comp_op: '<'|'>'|'='|'>' '='|'<' '='|'<' '>'|'in'|'not' 'in'|'is'|'is' 'not'
+expr: term (('+'|'-') term)*
+term: factor (('*'|'/'|'%') factor)*
+factor: ('+'|'-') factor | atom trailer*
+atom: '(' [testlist] ')' | '[' [testlist] ']' | '{' '}' | '`' testlist '`' | NAME | NUMBER | STRING
+trailer: '(' [testlist] ')' | '[' subscript ']' | '.' NAME
+subscript: expr | [expr] ':' [expr]
+exprlist: expr (',' expr)* [',']
+testlist: test (',' test)* [',']
+
+classdef: 'class' NAME parameters ['=' baselist] ':' suite
+baselist: atom arguments (',' atom arguments)*
+arguments: '(' [testlist] ')'
diff --git a/src/Makefile b/src/Makefile
new file mode 100644
index 0000000..d47eceb
--- /dev/null
+++ b/src/Makefile
@@ -0,0 +1,508 @@
+# /***********************************************************
+# Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+# Netherlands.
+#
+# All Rights Reserved
+#
+# Permission to use, copy, modify, and distribute this software and its
+# documentation for any purpose and without fee is hereby granted,
+# provided that the above copyright notice appear in all copies and that
+# both that copyright notice and this permission notice appear in
+# supporting documentation, and that the names of Stichting Mathematisch
+# Centrum or CWI not be used in advertising or publicity pertaining to
+# distribution of the software without specific, written prior permission.
+#
+# STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+# THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+# FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+# FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+#
+# ******************************************************************/
+
+# Makefile for Python
+# ===================
+#
+# If you are in a hurry, you can just edit this Makefile to choose the
+# correct settings for SYSV and RANLIB below, and type "make" in this
+# directory. If you are using a recent version of SunOS (or Ultrix?)
+# you don't even have to edit: the Makefile comes pre-configured for
+# such systems with all configurable options turned off, building the
+# minimal portable version of the Python interpreter.
+#
+# If have more time, read the section on configurable options below.
+# It may still be wise to begin building the minimal portable Python,
+# to see if it works at all, and select options later. You don't have
+# to rebuild all objects when you turn on options; all dependencies
+# are concentrated in the file "config.c" which is rebuilt whenever
+# the Makefile changes. (Except if you turn on the GNU Readline option
+# you may have to toss out the tokenizer.o object.)
+
+
+# Operating System Defines (ALWAYS READ THIS)
+# ===========================================
+
+# Uncomment the following line if you are using a System V derivative.
+# This must be used, for instance, on an SGI IRIS. Don't use it for
+# SunOS. (This is only needed by posixmodule.c...)
+
+#SYSVDEF= -DSYSV
+
+# Choose one of the following two lines depending on whether your system
+# requires the use of 'ranlib' after creating a library, or not.
+
+#RANLIB = true # For System V
+RANLIB = ranlib # For BSD
+
+# If your system doesn't have symbolic links, uncomment the following
+# line.
+
+#NOSYMLINKDEF= -DNO_LSTAT
+
+
+# Installation Options
+# ====================
+
+# You may want to change DEFPYTHONPATH to reflect where you install the
+# Python module library. The default contains "../lib" so running
+# the interpreter from the source/build directory as distributed will
+# find the library (admittedly a hack).
+
+DEFPYTHONPATH= .:/usr/local/lib/python:/ufs/guido/lib/python:../lib
+
+
+# For "Pure" BSD Systems
+# ======================
+#
+# "Pure" BSD systems (as opposed to enhanced BSD derivatives like SunOS)
+# often miss certain standard library functions. Source for
+# these is provided, you just have to turn it on. This may work for
+# other systems as well, where these things are needed.
+
+# If your system does not have a strerror() function in the library,
+# uncomment the following two lines to use one I wrote. (Actually, this
+# is missing in most systems I have encountered, so it is turned on
+# in the Makefile. Turn it off if your system doesn't have sys_errlist.)
+
+STRERROR_SRC= strerror.c
+STRERROR_OBJ= strerror.o
+
+# If your BSD system does not have a fmod() function in the library,
+# uncomment the following two lines to use one I wrote.
+
+#FMOD_SRC= fmod.c
+#FMOD_OBJ= fmod.o
+
+# If your BSD system does not have a strtol() function in the library,
+# uncomment the following two lines to use one I wrote.
+
+#STRTOL_SRC= strtol.c
+#STRTOL_OBJ= strtol.o
+
+# If your BSD system does not have a getcwd() function in the library,
+# but it does have a getwd() function, uncomment the following two lines
+# to use one I wrote. (If you don't have getwd() either, turn on the
+# NO_GETWD #define in getcwd.c.)
+
+#GETCWD_SRC= getcwd.c
+#GETCWD_OBJ= getcwd.o
+
+# If your signal() function believes signal handlers return int,
+# uncomment the following line.
+
+#SIGTYPEDEF= -DSIGTYPE=int
+
+
+# Further porting hints
+# =====================
+#
+# If you don't have the header file <string.h>, but you do have
+# <strings.h>, create a file "string.h" in this directory which contains
+# the single line "#include <strings.h>", and add "-I." to CFLAGS.
+# If you don't have the functions strchr and strrchr, add definitions
+# "-Dstrchr=index -Dstrrchr=rindex" to CFLAGS. (NB: CFLAGS is not
+# defined in this Makefile.)
+
+
+# Configurable Options
+# ====================
+#
+# Python can be configured to interface to various system libraries that
+# are not available on all systems. It is also possible to configure
+# the input module to use the GNU Readline library for interactive
+# input. For each configuration choice you must uncomment the relevant
+# section of the Makefile below. Note: you may also have to change a
+# pathname and/or an architecture identifier that is hardcoded in the
+# Makefile.
+#
+# Read the comments to determine if you can use the option. (You can
+# always leave all options off and build a minimal portable version of
+# Python.)
+
+
+# BSD Time Option
+# ===============
+#
+# This option does not add a new module but adds two functions to
+# an existing module.
+#
+# It implements time.millisleep() and time.millitimer()
+# using the BSD system calls select() and gettimeofday().
+#
+# Uncomment the following line to select this option.
+
+#BSDTIMEDEF= -DBSD_TIME
+
+
+# GNU Readline Option
+# ===================
+#
+# If you have the sources of the GNU Readline library you can have
+# full interactive command line editing and history in Python.
+# The GNU Readline library is distributed with the BASH shell
+# (I only know of version 1.05). You must build the GNU Readline
+# library and the alloca routine it needs in their own source
+# directories (which are subdirectories of the basg source directory),
+# and plant a pointer to the BASH source directory in this Makefile.
+#
+# Uncomment and edit the following block to use the GNU Readline option.
+# - Edit the definition of BASHDIR to point to the bash source tree.
+# You may have to fix the definition of LIBTERMCAP; leave the LIBALLOCA
+# definition commented if alloca() is in your C library.
+
+#BASHDIR= ../../bash-1.05
+#LIBREADLINE= $(BASHDIR)/readline/libreadline.a
+#LIBALLOCA= $(BASHDIR)/alloc-files/alloca.o
+#LIBTERMCAP= -ltermcap
+#RL_USE = -DUSE_READLINE
+#RL_LIBS= $(LIBREADLINE) $(LIBALLOCA) $(LIBTERMCAP)
+#RL_LIBDEPS= $(LIBREADLINE) $(LIBALLOCA)
+
+
+# STDWIN Option
+# =============
+#
+# If you have the sources of STDWIN (by the same author) you can
+# configure Python to incorporate the built-in module 'stdwin'.
+# This requires a fairly recent version of STDWIN (dated late 1990).
+#
+# Uncomment and edit the following block to use the STDWIN option.
+# - Edit the STDWINDIR defition to reflect the top of the STDWIN source
+# tree.
+# - Edit the ARCH definition to reflect your system's architecture
+# (usually the program 'arch' or 'machine' returns this).
+# You may have to edit the LIBX11 defition to reflect the location of
+# the X11 runtime library if it is non-standard.
+
+#STDWINDIR= ../../stdwin
+#ARCH= sgi
+#LIBSTDWIN= $(STDWINDIR)/Build/$(ARCH)/x11/lib/lib.a
+#LIBX11 = -lX11
+#STDW_INCL= -I$(STDWINDIR)/H
+#STDW_USE= -DUSE_STDWIN
+#STDW_LIBS= $(LIBSTDWIN) $(LIBX11)
+#STDW_LIBDEPS= $(LIBSTDWIN)
+#STDW_SRC= stdwinmodule.c
+#STDW_OBJ= stdwinmodule.o
+
+
+# Amoeba Option
+# =============
+#
+# If you have the Amoeba 4.0 distribution (Beta or otherwise) you can
+# configure Python to incorporate the built-in module 'amoeba'.
+# (Python can also be built for native Amoeba, but it requires more
+# work and thought. Contact the author.)
+#
+# Uncomment and edit the following block to use the Amoeba option.
+# - Edit the AMOEBADIR defition to reflect the top of the Amoeba source
+# tree.
+# - Edit the AM_CONF definition to reflect the machine/operating system
+# configuration needed by Amoeba (this is the name of a subdirectory
+# of $(AMOEBADIR)/conf/unix, e.g., vax.ultrix).
+
+#AMOEBADIR= /usr/amoeba
+#AM_CONF= mipseb.irix
+#LIBAMUNIX= $(AMOEBADIR)/conf/unix/$(AM_CONF)/lib/amunix/libamunix.a
+#AM_INCL= -I$(AMOEBADIR)/src/h
+#AM_USE = -DUSE_AMOEBA
+#AM_LIBDEPS= $(LIBAMUNIX)
+#AM_LIBS= $(LIBAMUNIX)
+#AM_SRC = amoebamodule.c sc_interpr.c sc_errors.c
+#AM_OBJ = amoebamodule.o sc_interpr.o sc_errors.o
+
+
+# Silicon Graphics IRIS Options
+# =============================
+#
+# The following three options are only relevant if you are using a
+# Silicon Graphics IRIS machine. These have been tested with IRIX 3.3.1
+# on a 4D/25.
+
+
+# GL Option
+# =========
+#
+# This option incorporates the built-in module 'gl', which provides a
+# complete interface to the Silicon Graphics GL library. It adds
+# about 70K to the Python text size and about 260K to the unstripped
+# binary size.
+#
+# NOTE WHEN BUILDING FOR THE FIRST TIME:
+# There is a circular dependency in the build process: you need to have
+# a working Python interpreter before you can build a Python interpreter
+# that incorporates the 'gl' module -- the source file 'glmodule.c' is
+# not distributed (it's about 140K!) and a Python script is used to
+# create it. Thus, you first have to build python without the the GL
+# and Panel options, then edit the Makefile to turn them (or at least GL)
+# on and rebuild. You may also have to set PYTHONPATH to point to
+# the place where the module library is for the generation script to
+# work.
+#
+# Uncomment the following block to use the GL option.
+
+#GL_USE = -DUSE_GL
+#GL_LIBDEPS=
+#GL_LIBS= -lgl_s
+#GL_SRC = glmodule.c cgensupport.c
+#GL_OBJ = glmodule.o cgensupport.o
+
+
+# Panel Option
+# ============
+#
+# If you have source to the NASA Ames Panel Library, you can configure
+# Python to incorporate the built-in module 'pnl', which is used byu
+# the standard module 'panel' to provide an interface to most features
+# of the Panel Library. This option requires that you also turn on the
+# GL option. It adds about 100K to the Python text size and about 160K
+# to the unstripped binary size. This requires Panel Library version 9.7
+# (for lower versions you may have to remove some functionality -- send
+# me the patches if you bothered to do this).
+#
+# Uncomment and edit the following block to use the Panel option.
+# - Edit the PANELDIR definition to point to the top-level directory
+# of the Panel distribution tree.
+
+#PANELDIR= /usr/people/guido/src/pl
+#PANELLIBDIR= $(PANELDIR)/library
+#LIBPANEL= $(PANELLIBDIR)/lib/libpanel.a
+#PANEL_USE= -DUSE_PANEL
+#PANEL_INCL= -I$(PANELLIBDIR)/include
+#PANEL_LIBDEPS= $(LIBPANEL)
+#PANEL_LIBS= $(LIBPANEL)
+#PANEL_SRC= panelmodule.c
+#PANEL_OBJ= panelmodule.o
+
+
+# Audio Option
+# ============
+#
+# This option lets you play with /dev/audio on the IRIS 4D/25.
+# It incorporates the built-in module 'audio'.
+# Warning: using the asynchronous I/O facilities of this module can
+# create a second 'thread', which looks in the listings of 'ps' like a
+# forked child. However, it shares its address space with the parent.
+#
+# Uncomment the following block to use the Audio option.
+
+#AUDIO_USE= -DUSE_AUDIO
+#AUDIO_SRC= audiomodule.c asa.c
+#AUDIO_OBJ= audiomodule.o asa.o
+
+
+# Major Definitions
+# =================
+
+STANDARD_OBJ= acceler.o bltinmodule.o ceval.o classobject.o \
+ compile.o dictobject.o errors.o fgetsintr.o \
+ fileobject.o floatobject.o $(FMOD_OBJ) frameobject.o \
+ funcobject.o $(GETCWD_OBJ) \
+ graminit.o grammar1.o import.o \
+ intobject.o intrcheck.o listnode.o listobject.o \
+ mathmodule.o methodobject.o modsupport.o \
+ moduleobject.o node.o object.o parser.o \
+ parsetok.o posixmodule.o regexp.o regexpmodule.o \
+ strdup.o $(STRERROR_OBJ) \
+ stringobject.o $(STRTOL_OBJ) structmember.o \
+ sysmodule.o timemodule.o tokenizer.o traceback.o \
+ tupleobject.o typeobject.o
+
+STANDARD_SRC= acceler.c bltinmodule.c ceval.c classobject.c \
+ compile.c dictobject.c errors.c fgetsintr.c \
+ fileobject.c floatobject.c $(FMOD_SRC) frameobject.c \
+ funcobject.c $(GETCWD_SRC) \
+ graminit.c grammar1.c import.c \
+ intobject.c intrcheck.c listnode.c listobject.c \
+ mathmodule.c methodobject.c modsupport.c \
+ moduleobject.c node.c object.c parser.c \
+ parsetok.c posixmodule.c regexp.c regexpmodule.c \
+ strdup.c $(STRERROR_SRC) \
+ stringobject.c $(STRTOL_SRC) structmember.c \
+ sysmodule.c timemodule.c tokenizer.c traceback.c \
+ tupleobject.c typeobject.c
+
+CONFIGDEFS= $(STDW_USE) $(AM_USE) $(AUDIO_USE) $(GL_USE) $(PANEL_USE) \
+ '-DPYTHONPATH="$(DEFPYTHONPATH)"'
+
+CONFIGINCLS= $(STDW_INCL)
+
+LIBDEPS= libpython.a $(STDW_LIBDEPS) $(AM_LIBDEPS) \
+ $(GL_LIBDEPS) $(PANEL_LIBSDEP) $(RL_LIBDEPS)
+
+# NB: the ordering of items in LIBS is significant!
+LIBS= libpython.a $(STDW_LIBS) $(AM_LIBS) \
+ $(PANEL_LIBS) $(GL_LIBS) $(RL_LIBS) -lm
+
+LIBOBJECTS= $(STANDARD_OBJ) $(STDW_OBJ) $(AM_OBJ) $(AUDIO_OBJ) \
+ $(GL_OBJ) $(PANEL_OBJ)
+
+LIBSOURCES= $(STANDARD_SRC) $(STDW_SRC) $(AM_SRC) $(AUDIO_SRC) \
+ $(GL_SRC) $(PANEL_SRC)
+
+OBJECTS= pythonmain.o config.o
+
+SOURCES= $(LIBSOURCES) pythonmain.c config.c
+
+GENOBJECTS= acceler.o fgetsintr.o grammar1.o \
+ intrcheck.o listnode.o node.o parser.o \
+ parsetok.o strdup.o tokenizer.o bitset.o \
+ firstsets.o grammar.o metagrammar.o pgen.o \
+ pgenmain.o printgrammar.o
+
+GENSOURCES= acceler.c fgetsintr.c grammar1.c \
+ intrcheck.c listnode.c node.c parser.c \
+ parsetok.c strdup.c tokenizer.c bitset.c \
+ firstsets.c grammar.c metagrammar.c pgen.c \
+ pgenmain.c printgrammar.c
+
+
+# Main Targets
+# ============
+
+python: libpython.a $(OBJECTS) $(LIBDEPS) Makefile
+ $(CC) $(CFLAGS) $(OBJECTS) $(LIBS) -o @python
+ mv @python python
+
+libpython.a: $(LIBOBJECTS)
+ -rm -f @lib
+ ar cr @lib $(LIBOBJECTS)
+ $(RANLIB) @lib
+ mv @lib libpython.a
+
+python_gen: $(GENOBJECTS) $(RL_LIBDEPS)
+ $(CC) $(CFLAGS) $(GENOBJECTS) $(RL_LIBS) -o python_gen
+
+
+# Utility Targets
+# ===============
+
+# Don't take the output from lint too seriously. I have not attempted
+# to make Python lint-free. But I use function prototypes.
+
+LINTFLAGS= -h
+
+LINTCPPFLAGS= $(CONFIGDEFS) $(CONFIGINCLS) $(SYSVDEF) \
+ $(AM_INCL) $(PANEL_INCL)
+
+LINT= lint
+
+lint:: $(SOURCES)
+ $(LINT) $(LINTFLAGS) $(LINTCPPFLAGS) $(SOURCES)
+
+lint:: $(GENSOURCES)
+ $(LINT) $(LINTFLAGS) $(GENSOURCES)
+
+# Generating dependencies is only necessary if you intend to hack Python.
+# You may change $(MKDEP) to your favorite dependency generator (it should
+# edit the Makefile in place).
+
+MKDEP= mkdep
+
+depend::
+ $(MKDEP) $(LINTCPPFLAGS) $(SOURCES) $(GENSOURCES)
+
+# You may change $(CTAGS) to suit your taste...
+
+CTAGS= ctags -t -w
+
+HEADERS= *.h
+
+tags: $(SOURCES) $(GENSOURCES) $(HEADERS)
+ $(CTAGS) $(SOURCES) $(GENSOURCES) $(HEADERS)
+
+clean::
+ -rm -f *.o core [,#@]*
+
+clobber:: clean
+ -rm -f python python_gen libpython.a tags
+
+
+# Build Special Objects
+# =====================
+
+# You may change $(COMPILE) to reflect the default .c.o rule...
+
+COMPILE= $(CC) -c $(CFLAGS)
+
+amoebamodule.o: amoebamodule.c
+ $(COMPILE) $(AM_INCL) $*.c
+
+config.o: config.c Makefile
+ $(COMPILE) $(CONFIGDEFS) $(CONFIGINCLS) $*.c
+
+fgetsintr.o: fgetsintr.c
+ $(COMPILE) $(SIGTYPEDEF) $*.c
+
+intrcheck.o: intrcheck.c
+ $(COMPILE) $(SIGTYPEDEF) $*.c
+
+panelmodule.o: panelmodule.c
+ $(COMPILE) $(PANEL_INCL) $*.c
+
+posixmodule.o: posixmodule.c
+ $(COMPILE) $(SYSVDEF) $(NOSYMLINKDEF) $*.c
+
+sc_interpr.o: sc_interpr.c
+ $(COMPILE) $(AM_INCL) $*.c
+
+sc_error.o: sc_error.c
+ $(COMPILE) $(AM_INCL) $*.c
+
+stdwinmodule.o: stdwinmodule.c
+ $(COMPILE) $(STDW_INCL) $*.c
+
+timemodule.o: timemodule.c
+ $(COMPILE) $(SIGTYPEDEF) $(BSDTIMEDEF) $*.c
+
+tokenizer.o: tokenizer.c
+ $(COMPILE) $(RL_USE) $*.c
+
+.PRECIOUS: python libpython.a glmodule.c graminit.c graminit.h
+
+
+# Generated Sources
+# =================
+#
+# Some source files are (or may be) generated.
+# The rules for doing so are given here.
+
+# Build "glmodule.c", the GL interface.
+# See important note at "GL Option" above.
+# You may have to set and export PYTHONPATH for this to work.
+# Ignore the messages emitted by the cgen script as long as its exit
+# status is zero.
+# Also ignore the warnings emitted while compiling glmodule.c; it works.
+
+glmodule.c: cstubs cgen
+ python cgen <cstubs >@glmodule.c
+ mv @glmodule.c glmodule.c
+
+# The dependencies for graminit.[ch] are not turned on in the
+# distributed Makefile because the files themselves are distributed.
+# Turn them on if you want to hack the grammar.
+
+#graminit.c graminit.h: Grammar python_gen
+# python_gen Grammar
diff --git a/src/PROTO.h b/src/PROTO.h
new file mode 100644
index 0000000..88b94fe
--- /dev/null
+++ b/src/PROTO.h
@@ -0,0 +1,79 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/*
+The macro PROTO(x) is used to put function prototypes in the source.
+This is defined differently for compilers that support prototypes than
+for compilers that don't. It should be used as follows:
+ int some_function PROTO((int arg1, char *arg2));
+A variant FPROTO(x) is used for cases where Standard C allows prototypes
+but Think C doesn't (mostly function pointers).
+
+This file also defines the macro HAVE_PROTOTYPES if and only if
+the PROTO() macro expands the prototype. It is also allowed to predefine
+HAVE_PROTOTYPES to force prototypes on.
+*/
+
+#ifndef PROTO
+
+#ifdef __STDC__
+#define HAVE_PROTOTYPES
+#endif
+
+#ifdef THINK_C
+#undef HAVE_PROTOTYPES
+#define HAVE_PROTOTYPES
+#endif
+
+#ifdef sgi
+#ifdef mips
+#define HAVE_PROTOTYPES
+#endif
+#endif
+
+#ifdef HAVE_PROTOTYPES
+#define PROTO(x) x
+#else
+#define PROTO(x) ()
+#endif
+
+#endif /* PROTO */
+
+
+/* FPROTO() is for cases where Think C doesn't like prototypes */
+
+#ifdef THINK_C
+#define FPROTO(arglist) ()
+#else /* !THINK_C */
+#define FPROTO(arglist) PROTO(arglist)
+#endif /* !THINK_C */
+
+#ifndef HAVE_PROTOTYPES
+#define const /*empty*/
+#else /* HAVE_PROTOTYPES */
+#ifdef THINK_C
+#undef const
+#define const /*empty*/
+#endif /* THINK_C */
+#endif /* HAVE_PROTOTYPES */
diff --git a/src/README b/src/README
new file mode 100644
index 0000000..714cd5b
--- /dev/null
+++ b/src/README
@@ -0,0 +1,11 @@
+This directory contains the source for the Python interpreter.
+
+To build the interpreter, edit the Makefile, follow the instructions
+there, and type "make python".
+
+To use the interpreter, you must set the environment variable PYTHONPATH
+to point to the directory containing the standard modules. These are
+distributed as a sister directory called 'lib' of this source directory.
+Try importing the module 'testall' to see if everything works.
+
+Good Luck!
diff --git a/src/To.do b/src/To.do
new file mode 100644
index 0000000..893e96d
--- /dev/null
+++ b/src/To.do
@@ -0,0 +1,11 @@
+- return better errors for file objects (also check read/write allowed, etc.)
+
+- introduce more specific exceptions (e.g., zero divide, index failure, ...)
+
+- why do reads from stdin fail when I suspend the process?
+
+- introduce macros to set/inspect errno for syscalls, to support things
+ like getoserr()
+
+- fix interrupt handling (interruptable system calls should call
+ intrcheck() to clear the interrupt status)
diff --git a/src/acceler.c b/src/acceler.c
new file mode 100644
index 0000000..5ed37d3
--- /dev/null
+++ b/src/acceler.c
@@ -0,0 +1,136 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* Parser accelerator module */
+
+/* The parser as originally conceived had disappointing performance.
+ This module does some precomputation that speeds up the selection
+ of a DFA based upon a token, turning a search through an array
+ into a simple indexing operation. The parser now cannot work
+ without the accelerators installed. Note that the accelerators
+ are installed dynamically when the parser is initialized, they
+ are not part of the static data structure written on graminit.[ch]
+ by the parser generator. */
+
+#include "pgenheaders.h"
+#include "grammar.h"
+#include "token.h"
+#include "parser.h"
+
+/* Forward references */
+static void fixdfa PROTO((grammar *, dfa *));
+static void fixstate PROTO((grammar *, dfa *, state *));
+
+void
+addaccelerators(g)
+ grammar *g;
+{
+ dfa *d;
+ int i;
+#ifdef DEBUG
+ printf("Adding parser accellerators ...\n");
+#endif
+ d = g->g_dfa;
+ for (i = g->g_ndfas; --i >= 0; d++)
+ fixdfa(g, d);
+ g->g_accel = 1;
+#ifdef DEBUG
+ printf("Done.\n");
+#endif
+}
+
+static void
+fixdfa(g, d)
+ grammar *g;
+ dfa *d;
+{
+ state *s;
+ int j;
+ s = d->d_state;
+ for (j = 0; j < d->d_nstates; j++, s++)
+ fixstate(g, d, s);
+}
+
+static void
+fixstate(g, d, s)
+ grammar *g;
+ dfa *d;
+ state *s;
+{
+ arc *a;
+ int k;
+ int *accel;
+ int nl = g->g_ll.ll_nlabels;
+ s->s_accept = 0;
+ accel = NEW(int, nl);
+ for (k = 0; k < nl; k++)
+ accel[k] = -1;
+ a = s->s_arc;
+ for (k = s->s_narcs; --k >= 0; a++) {
+ int lbl = a->a_lbl;
+ label *l = &g->g_ll.ll_label[lbl];
+ int type = l->lb_type;
+ if (a->a_arrow >= (1 << 7)) {
+ printf("XXX too many states!\n");
+ continue;
+ }
+ if (ISNONTERMINAL(type)) {
+ dfa *d1 = finddfa(g, type);
+ int ibit;
+ if (type - NT_OFFSET >= (1 << 7)) {
+ printf("XXX too high nonterminal number!\n");
+ continue;
+ }
+ for (ibit = 0; ibit < g->g_ll.ll_nlabels; ibit++) {
+ if (testbit(d1->d_first, ibit)) {
+ if (accel[ibit] != -1)
+ printf("XXX ambiguity!\n");
+ accel[ibit] = a->a_arrow | (1 << 7) |
+ ((type - NT_OFFSET) << 8);
+ }
+ }
+ }
+ else if (lbl == EMPTY)
+ s->s_accept = 1;
+ else if (lbl >= 0 && lbl < nl)
+ accel[lbl] = a->a_arrow;
+ }
+ while (nl > 0 && accel[nl-1] == -1)
+ nl--;
+ for (k = 0; k < nl && accel[k] == -1;)
+ k++;
+ if (k < nl) {
+ int i;
+ s->s_accel = NEW(int, nl-k);
+ if (s->s_accel == NULL) {
+ fprintf(stderr, "no mem to add parser accelerators\n");
+ exit(1);
+ }
+ s->s_lower = k;
+ s->s_upper = nl;
+ for (i = 0; k < nl; i++, k++)
+ s->s_accel[i] = accel[k];
+ }
+ DEL(accel);
+}
diff --git a/src/allobjects.h b/src/allobjects.h
new file mode 100644
index 0000000..b6b487b
--- /dev/null
+++ b/src/allobjects.h
@@ -0,0 +1,50 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* "allobjects.c" -- Source for precompiled header "allobjects.h" */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "PROTO.h"
+
+#include "object.h"
+#include "objimpl.h"
+
+#include "intobject.h"
+#include "floatobject.h"
+#include "stringobject.h"
+#include "tupleobject.h"
+#include "listobject.h"
+#include "dictobject.h"
+#include "methodobject.h"
+#include "moduleobject.h"
+#include "funcobject.h"
+#include "classobject.h"
+#include "fileobject.h"
+
+#include "errors.h"
+#include "malloc.h"
+
+extern char *strdup PROTO((const char *));
diff --git a/src/amoebamodule.c b/src/amoebamodule.c
new file mode 100644
index 0000000..c9131b7
--- /dev/null
+++ b/src/amoebamodule.c
@@ -0,0 +1,774 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* Amoeba module implementation */
+
+/* Amoeba includes */
+#include <amoeba.h>
+#include <cmdreg.h>
+#include <stdcom.h>
+#include <stderr.h>
+#include <caplist.h>
+#include <server/bullet/bullet.h>
+#include <server/tod/tod.h>
+#include <module/name.h>
+#include <module/direct.h>
+#include <module/mutex.h>
+#include <module/prv.h>
+#include <module/stdcmd.h>
+
+/* C includes */
+#include <stdlib.h>
+#include <ctype.h>
+
+/* POSIX includes */
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+/* Python includes */
+#include "allobjects.h"
+#include "modsupport.h"
+#include "sc_global.h"
+#include "stubcode.h"
+
+extern char *err_why();
+extern char *ar_cap();
+
+#define STUBCODE "+stubcode"
+
+static object *AmoebaError;
+object *StubcodeError;
+
+static object *sc_dict;
+
+/* Module initialization */
+
+extern struct methodlist amoeba_methods[]; /* Forward */
+extern object *convertcapv(); /* Forward */
+
+static void
+ins(d, name, v)
+ object *d;
+ char *name;
+ object *v;
+{
+ if (v == NULL || dictinsert(d, name, v) != 0)
+ fatal("can't initialize amoeba module");
+}
+
+void
+initamoeba()
+{
+ object *m, *d, *v;
+
+ m = initmodule("amoeba", amoeba_methods);
+ d = getmoduledict(m);
+
+ /* Define capv */
+ v = convertcapv();
+ ins(d, "capv", v);
+ DECREF(v);
+
+ /* Set timeout */
+ timeout((interval)2000);
+
+ /* Initialize amoeba.error exception */
+ AmoebaError = newstringobject("amoeba.error");
+ ins(d, "error", AmoebaError);
+ StubcodeError = newstringobject("amoeba.stubcode_error");
+ ins(d, "stubcode_error", StubcodeError);
+ sc_dict = newdictobject();
+}
+
+
+/* Set an Amoeba-specific error, and return NULL */
+
+object *
+amoeba_error(err)
+ errstat err;
+{
+ object *v = newtupleobject(2);
+ if (v != NULL) {
+ settupleitem(v, 0, newintobject((long)err));
+ settupleitem(v, 1, newstringobject(err_why(err)));
+ }
+ err_setval(AmoebaError, v);
+ if (v != NULL)
+ DECREF(v);
+ return NULL;
+}
+
+
+/* Capability object implementation */
+
+extern typeobject Captype; /* Forward */
+
+#define is_capobject(v) ((v)->ob_type == &Captype)
+
+typedef struct {
+ OB_HEAD
+ capability ob_cap;
+} capobject;
+
+object *
+newcapobject(cap)
+ capability *cap;
+{
+ capobject *v = NEWOBJ(capobject, &Captype);
+ if (v == NULL)
+ return NULL;
+ v->ob_cap = *cap;
+ return (object *)v;
+}
+
+getcapability(v, cap)
+ object *v;
+ capability *cap;
+{
+
+ if (!is_capobject(v))
+ return err_badarg();
+ *cap = ((capobject *)v)->ob_cap;
+ return 0;
+}
+
+/*
+ * is_capobj exports the is_capobject macro to the stubcode modules
+ */
+
+int
+is_capobj(v)
+ object *v;
+{
+
+ return is_capobject(v);
+}
+
+/* Methods */
+
+static void
+capprint(v, fp, flags)
+ capobject *v;
+ FILE *fp;
+ int flags;
+{
+ /* XXX needs lock when multi-threading */
+ fputs(ar_cap(&v->ob_cap), fp);
+}
+
+static object *
+caprepr(v)
+ capobject *v;
+{
+ /* XXX needs lock when multi-threading */
+ return newstringobject(ar_cap(&v->ob_cap));
+}
+
+extern object *sc_interpreter();
+
+extern struct methodlist cap_methods[]; /* Forward */
+
+object *
+sc_makeself(cap, stubcode, name)
+ object *cap, *stubcode;
+ char *name;
+{
+ object *sc_name, *sc_self;
+
+ sc_name = newstringobject(name);
+ if (sc_name == NULL)
+ return NULL;
+ sc_self = newtupleobject(3);
+ if (sc_self == NULL) {
+ DECREF(sc_name);
+ return NULL;
+ }
+ if (settupleitem(sc_self, NAME, sc_name) != 0) {
+ DECREF(sc_self);
+ return NULL;
+ }
+ INCREF(cap);
+ if (settupleitem(sc_self, CAP, cap) != 0) {
+ DECREF(sc_self);
+ return NULL;
+ }
+ INCREF(stubcode);
+ if (settupleitem(sc_self, STUBC, stubcode) != 0) {
+ DECREF(sc_self);
+ return NULL;
+ }
+ return sc_self;
+}
+
+
+static void
+swapcode(code, len)
+ char *code;
+ int len;
+{
+ int i = sizeof(TscOperand);
+ TscOpcode opcode;
+ TscOperand operand;
+
+ while (i < len) {
+ memcpy(&opcode, &code[i], sizeof(TscOpcode));
+ SwapOpcode(opcode);
+ memcpy(&code[i], &opcode, sizeof(TscOpcode));
+ i += sizeof(TscOpcode);
+ if (opcode & OPERAND) {
+ memcpy(&operand, &code[i], sizeof(TscOperand));
+ SwapOperand(operand);
+ memcpy(&code[i], &operand, sizeof(TscOperand));
+ i += sizeof(TscOperand);
+ }
+ }
+}
+
+object *
+sc_findstubcode(v, name)
+ object *v;
+ char *name;
+{
+ int fd, fsize;
+ char *fname, *buffer;
+ struct stat statbuf;
+ object *sc_stubcode, *ret;
+ TscOperand sc_magic;
+
+ /*
+ * Only look in the current directory for now.
+ */
+ fname = malloc(strlen(name) + 4);
+ if (fname == NULL) {
+ return err_nomem();
+ }
+ sprintf(fname, "%s.sc", name);
+ if ((fd = open(fname, O_RDONLY)) == -1) {
+ extern int errno;
+
+ if (errno == 2) {
+ /*
+ ** errno == 2 is file not found.
+ */
+ err_setstr(NameError, fname);
+ return NULL;
+ }
+ free(fname);
+ return err_errno(newstringobject(name));
+ }
+ fstat(fd, &statbuf);
+ fsize = (int)statbuf.st_size;
+ buffer = malloc(fsize);
+ if (buffer == NULL) {
+ free(fname);
+ close(fd);
+ return err_nomem();
+ }
+ if (read(fd, buffer, fsize) != fsize) {
+ close(fd);
+ free(fname);
+ return err_errno(newstringobject(name));
+ }
+ close(fd);
+ free(fname);
+ memcpy(&sc_magic, buffer, sizeof(TscOperand));
+ if (sc_magic != SC_MAGIC) {
+ SwapOperand(sc_magic);
+ if (sc_magic != SC_MAGIC) {
+ free(buffer);
+ return NULL;
+ } else {
+ swapcode(buffer, fsize);
+ }
+ }
+ sc_stubcode = newsizedstringobject( &buffer[sizeof(TscOperand)],
+ fsize - sizeof(TscOperand));
+ free(buffer);
+ if (sc_stubcode == NULL) {
+ return NULL;
+ }
+ if (dictinsert(sc_dict, name, sc_stubcode) != 0) {
+ DECREF(sc_stubcode);
+ return NULL;
+ }
+ DECREF(sc_stubcode); /* XXXX */
+ sc_stubcode = sc_makeself(v, sc_stubcode, name);
+ if (sc_stubcode == NULL) {
+ return NULL;
+ }
+ return sc_stubcode;
+}
+
+object *
+capgetattr(v, name)
+ capobject *v;
+ char *name;
+{
+ object *sc_method, *sc_stubcodemethod;
+
+ if (sc_dict == NULL) {
+ /*
+ ** For some reason the dictionary has not been
+ ** initialized. Try to find one of the built in
+ ** methods.
+ */
+ return findmethod(cap_methods, (object *)v, name);
+ }
+ sc_stubcodemethod = dictlookup(sc_dict, name);
+ if (sc_stubcodemethod != NULL) {
+ /*
+ ** There is a stubcode method in the dictionary.
+ ** Execute the stubcode interpreter with the right
+ ** arguments.
+ */
+ object *self, *ret;
+
+ self = sc_makeself((object *)v, sc_stubcodemethod, name);
+ if (self == NULL) {
+ return NULL;
+ }
+ ret = findmethod(cap_methods, self, STUBCODE);
+ DECREF(self);
+ return ret;
+ }
+ err_clear();
+ sc_method = findmethod(cap_methods, (object *)v, name);
+ if (sc_method == NULL) {
+ /*
+ ** The method is not built in and not in the
+ ** dictionary. Try to find it as a stubcode file.
+ */
+ object *self, *ret;
+
+ err_clear();
+ self = sc_findstubcode((object *)v, name);
+ if (self == NULL) {
+ return NULL;
+ }
+ ret = findmethod(cap_methods, self, STUBCODE);
+ DECREF(self);
+ return ret;
+ }
+ return sc_method;
+}
+
+int
+capcompare(v, w)
+ capobject *v, *w;
+{
+ int cmp = bcmp((char *)&v->ob_cap.cap_port,
+ (char *)&w->ob_cap, PORTSIZE);
+ if (cmp != 0)
+ return cmp;
+ return prv_number(&v->ob_cap.cap_priv) -
+ prv_number(&w->ob_cap.cap_priv);
+}
+
+static typeobject Captype = {
+ OB_HEAD_INIT(&Typetype)
+ 0,
+ "capability",
+ sizeof(capobject),
+ 0,
+ free, /*tp_dealloc*/
+ capprint, /*tp_print*/
+ capgetattr, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ capcompare, /*tp_comp
+are*/
+ caprepr, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+};
+
+
+/* Return a dictionary corresponding to capv */
+
+extern struct caplist *capv;
+
+static object *
+convertcapv()
+{
+ object *d;
+ struct caplist *c;
+ d = newdictobject();
+ if (d == NULL)
+ return NULL;
+ if (capv == NULL)
+ return d;
+ for (c = capv; c->cl_name != NULL; c++) {
+ object *v = newcapobject(c->cl_cap);
+ if (v == NULL || dictinsert(d, c->cl_name, v) != 0) {
+ DECREF(d);
+ return NULL;
+ }
+ DECREF(v);
+ }
+ return d;
+}
+
+
+/* Strongly Amoeba-specific argument handlers */
+
+static int
+getcaparg(v, a)
+ object *v;
+ capability *a;
+{
+ if (v == NULL || !is_capobject(v))
+ return err_badarg();
+ *a = ((capobject *)v) -> ob_cap;
+ return 1;
+}
+
+static int
+getstrcapargs(v, a, b)
+ object *v;
+ object **a;
+ capability *b;
+{
+ if (v == NULL || !is_tupleobject(v) || gettuplesize(v) != 2)
+ return err_badarg();
+ return getstrarg(gettupleitem(v, 0), a) &&
+ getcaparg(gettupleitem(v, 1), b);
+}
+
+
+/* Amoeba methods */
+
+static object *
+amoeba_name_lookup(self, args)
+ object *self;
+ object *args;
+{
+ object *name;
+ capability cap;
+ errstat err;
+ if (!getstrarg(args, &name))
+ return NULL;
+ err = name_lookup(getstringvalue(name), &cap);
+ if (err != STD_OK)
+ return amoeba_error(err);
+ return newcapobject(&cap);
+}
+
+static object *
+amoeba_name_append(self, args)
+ object *self;
+ object *args;
+{
+ object *name;
+ capability cap;
+ errstat err;
+ if (!getstrcapargs(args, &name, &cap))
+ return NULL;
+ err = name_append(getstringvalue(name), &cap);
+ if (err != STD_OK)
+ return amoeba_error(err);
+ INCREF(None);
+ return None;
+}
+
+static object *
+amoeba_name_replace(self, args)
+ object *self;
+ object *args;
+{
+ object *name;
+ capability cap;
+ errstat err;
+ if (!getstrcapargs(args, &name, &cap))
+ return NULL;
+ err = name_replace(getstringvalue(name), &cap);
+ if (err != STD_OK)
+ return amoeba_error(err);
+ INCREF(None);
+ return None;
+}
+
+static object *
+amoeba_name_delete(self, args)
+ object *self;
+ object *args;
+{
+ object *name;
+ errstat err;
+ if (!getstrarg(args, &name))
+ return NULL;
+ err = name_delete(getstringvalue(name));
+ if (err != STD_OK)
+ return amoeba_error(err);
+ INCREF(None);
+ return None;
+}
+
+static object *
+amoeba_timeout(self, args)
+ object *self;
+ object *args;
+{
+ int i;
+ object *v;
+ interval tout;
+ if (!getintarg(args, &i))
+ return NULL;
+ tout = timeout((interval)i);
+ v = newintobject((long)tout);
+ if (v == NULL)
+ timeout(tout);
+ return v;
+}
+
+static struct methodlist amoeba_methods[] = {
+ {"name_append", amoeba_name_append},
+ {"name_delete", amoeba_name_delete},
+ {"name_lookup", amoeba_name_lookup},
+ {"name_replace", amoeba_name_replace},
+ {"timeout", amoeba_timeout},
+ {NULL, NULL} /* Sentinel */
+};
+
+/* Capability methods */
+
+static object *
+cap_b_size(self, args)
+ capobject *self;
+ object *args;
+{
+ errstat err;
+ b_fsize size;
+ if (!getnoarg(args))
+ return NULL;
+ err = b_size(&self->ob_cap, &size);
+ if (err != STD_OK)
+ return amoeba_error(err);
+ return newintobject((long)size);
+}
+
+static object *
+cap_b_read(self, args)
+ capobject *self;
+ object *args;
+{
+ errstat err;
+ char *buf;
+ object *v;
+ long offset, size;
+ b_fsize nread;
+ if (!getlonglongargs(args, &offset, &size))
+ return NULL;
+ buf = malloc((unsigned int)size);
+ if (buf == NULL) {
+ return err_nomem();
+ }
+ err = b_read(&self->ob_cap, (b_fsize)offset, buf, (b_fsize)size,
+ &nread);
+ if (err != STD_OK) {
+ free(buf);
+ return amoeba_error(err);
+ }
+ v = newsizedstringobject(buf, (int)nread);
+ free(buf);
+ return v;
+}
+
+static object *
+cap_dir_lookup(self, args)
+ capobject *self;
+ object *args;
+{
+ object *name;
+ capability cap;
+ errstat err;
+ if (!getstrarg(args, &name))
+ return NULL;
+ err = dir_lookup(&self->ob_cap, getstringvalue(name), &cap);
+ if (err != STD_OK)
+ return amoeba_error(err);
+ return newcapobject(&cap);
+}
+
+static object *
+cap_dir_append(self, args)
+ capobject *self;
+ object *args;
+{
+ object *name;
+ capability cap;
+ errstat err;
+ if (!getstrcapargs(args, &name, &cap))
+ return NULL;
+ err = dir_append(&self->ob_cap, getstringvalue(name), &cap);
+ if (err != STD_OK)
+ return amoeba_error(err);
+ INCREF(None);
+ return None;
+}
+
+static object *
+cap_dir_delete(self, args)
+ capobject *self;
+ object *args;
+{
+ object *name;
+ errstat err;
+ if (!getstrarg(args, &name))
+ return NULL;
+ err = dir_delete(&self->ob_cap, getstringvalue(name));
+ if (err != STD_OK)
+ return amoeba_error(err);
+ INCREF(None);
+ return None;
+}
+
+static object *
+cap_dir_replace(self, args)
+ capobject *self;
+ object *args;
+{
+ object *name;
+ capability cap;
+ errstat err;
+ if (!getstrcapargs(args, &name, &cap))
+ return NULL;
+ err = dir_replace(&self->ob_cap, getstringvalue(name), &cap);
+ if (err != STD_OK)
+ return amoeba_error(err);
+ INCREF(None);
+ return None;
+}
+
+static object *
+cap_dir_list(self, args)
+ capobject *self;
+ object *args;
+{
+ errstat err;
+ struct dir_open *dd;
+ object *d;
+ char *name;
+ if (!getnoarg(args))
+ return NULL;
+ if ((dd = dir_open(&self->ob_cap)) == NULL)
+ return amoeba_error(STD_COMBAD);
+ if ((d = newlistobject(0)) == NULL) {
+ dir_close(dd);
+ return NULL;
+ }
+ while ((name = dir_next(dd)) != NULL) {
+ object *v;
+ v = newstringobject(name);
+ if (v == NULL) {
+ DECREF(d);
+ d = NULL;
+ break;
+ }
+ if (addlistitem(d, v) != 0) {
+ DECREF(v);
+ DECREF(d);
+ d = NULL;
+ break;
+ }
+ DECREF(v);
+ }
+ dir_close(dd);
+ return d;
+}
+
+object *
+cap_std_info(self, args)
+ capobject *self;
+ object *args;
+{
+ char buf[256];
+ errstat err;
+ int n;
+ if (!getnoarg(args))
+ return NULL;
+ err = std_info(&self->ob_cap, buf, sizeof buf, &n);
+ if (err != STD_OK)
+ return amoeba_error(err);
+ return newsizedstringobject(buf, n);
+}
+
+object *
+cap_tod_gettime(self, args)
+ capobject *self;
+ object *args;
+{
+ header h;
+ errstat err;
+ bufsize n;
+ long sec;
+ int msec, tz, dst;
+ if (!getnoarg(args))
+ return NULL;
+ h.h_port = self->ob_cap.cap_port;
+ h.h_priv = self->ob_cap.cap_priv;
+ h.h_command = TOD_GETTIME;
+ n = trans(&h, NILBUF, 0, &h, NILBUF, 0);
+ if (ERR_STATUS(n))
+ return amoeba_error(ERR_CONVERT(n));
+ tod_decode(&h, &sec, &msec, &tz, &dst);
+ return newintobject(sec);
+}
+
+object *
+cap_tod_settime(self, args)
+ capobject *self;
+ object *args;
+{
+ header h;
+ errstat err;
+ bufsize n;
+ long sec;
+ if (!getlongarg(args, &sec))
+ return NULL;
+ h.h_port = self->ob_cap.cap_port;
+ h.h_priv = self->ob_cap.cap_priv;
+ h.h_command = TOD_SETTIME;
+ tod_encode(&h, sec, 0, 0, 0);
+ n = trans(&h, NILBUF, 0, &h, NILBUF, 0);
+ if (ERR_STATUS(n))
+ return amoeba_error(ERR_CONVERT(n));
+ INCREF(None);
+ return None;
+}
+
+static struct methodlist cap_methods[] = {
+ { STUBCODE, sc_interpreter},
+ {"b_read", cap_b_read},
+ {"b_size", cap_b_size},
+ {"dir_append", cap_dir_append},
+ {"dir_delete", cap_dir_delete},
+ {"dir_list", cap_dir_list},
+ {"dir_lookup", cap_dir_lookup},
+ {"dir_replace", cap_dir_replace},
+ {"std_info", cap_std_info},
+ {"tod_gettime", cap_tod_gettime},
+ {"tod_settime", cap_tod_settime},
+ {NULL, NULL} /* Sentinel */
+};
diff --git a/src/asa.c b/src/asa.c
new file mode 100644
index 0000000..f7f7378
--- /dev/null
+++ b/src/asa.c
@@ -0,0 +1,494 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* Asynchronous audio module for Silicon Graphics 4D/20 under IRIX 3.3
+ Copyright 1990 Stichting Mathematisch Centrum, Amsterdam
+ Author: Guido van Rossum, <[email protected]>
+ Last modified: [email protected], Oct 14, 1990
+
+ Callers should #include "asa.h".
+
+ This code is strongly IRIX 3.3 dependent. (Or are sproc() and
+ friends standard SYSV now?)
+
+ Caution: if you put printf's in the slave for debugging, use "-lmpc"
+ to get the semaphore version of stdio!
+
+
+ This file contains two library layers and a test program:
+
+
+ The lower layer implements a simple asynchronous execution facility,
+ built directly on the system calls sproc() and [un]blockproc().
+
+ A slave thread sits in an infinite loop waiting for work assigned to
+ it by the master thread. Work is represented by a function pointer
+ and an argument of type void*. The function returns a void* pointer
+ which is transferred back to the master when it submits the next bit
+ of work. Submitting a NULL function pointer can be used by the
+ master to wait for completion of the previous work. This lower
+ layer could be generally useful, but is currently implemented by
+ static functions, for exclusive by the asynchronous audio layer.
+
+
+ The higher layer implements an asynchronous interface to the
+ /dev/audio device on the Silicon Graphics 4D/20. It defines the
+ following functions:
+
+ int asa_init()
+ Required initialization function. The other functions will call
+ abort() when they are called before asa_init(). It creates the
+ slave process and returns a file descriptor for the audio
+ device which can be used to set the sampling rate and output
+ gain, etc. It prints a message to stderr and returns -1 if the
+ initialization failed. Calling this function more than onece is
+ harmless.
+
+ void asa_start_read(char *buf, int len)
+ Starts an asynchronous read call on the audio device. This
+ waits for completion of the previous request, if any.
+
+ void asa_start_write(char *buf, int len)
+ Starts an asynchronous write call on the audio device. This
+ waits for completion of the previous request, if any.
+
+ int asa_poll()
+ Polls whether the last asynchronous read or write request is
+ finished. Returns -1 if no request was queued, 0 if the request
+ is not yet finished, and 1 if it is finished.
+
+ int asa_wait()
+ Waits for completion if the last asynchronous read or write
+ request. It returns the result of the read or write request,
+ and sets the error code to the error code set by the request if
+ the result is -1. If no request was queued, this also returns
+ -1 but leaves the error code unchanged. Note: to get the error
+ code, don't inspect the global variable errno but call the
+ function oserror().
+
+ int asa_cancel()
+ Cancels the last asynchronous read or write request (by sending
+ the slave thread a signal for which it has a handler) then
+ returns its result and error code as asa_wait().
+
+ void asa_done()
+ Kills the slave process and closes the audio device. After
+ this, if further use of the module is required, asa_init()
+ should be called again. Calling this function when asa_init()
+ has not been called is harmless.
+
+
+ Finally, this file contains a simple test program that is compiled if
+ MAIN is defined (e.g., compile with cc -DMAIN). It makes a recording
+ and plays it back. The user must indicate begin and end of recording
+ and play-back by pressing the Return key.
+*/
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/prctl.h>
+
+#include "asa.h"
+
+
+/* Asynchronous execution facility (lower layer) */
+
+
+/* Signal used to cancel requests in progress */
+#define MYSIG SIGUSR1
+
+/* Respective process IDs */
+static pid_t master_pid = -1;
+static pid_t slave_pid = -1;
+
+/* Work and result "queue" (1 element) */
+static void * (*work_func)();
+static void *work_arg;
+static void *work_result;
+
+/* Signal handler for MYSIG -- interrupts read or write system call */
+
+/*ARGSUSED*/
+static void
+handler(sig)
+ int sig;
+{
+ /* Reinstate the handler (non-BSD signal semantics) */
+ signal(sig, handler);
+}
+
+/* Subroutine to fiddle signals */
+
+static void
+dosig(sig)
+ int sig;
+{
+ if (signal(sig, SIG_IGN) != SIG_IGN)
+ signal(sig, SIG_DFL);
+}
+
+/* Slave control flow */
+
+/*ARGSUSED*/
+static void
+slave(arg)
+ void *arg;
+{
+ void * (*func)();
+ void *arg;
+ void *result;
+
+ /* Reset signal handlers that interactive programs often catch.
+ The assumption is that if the master has a handler for these
+ signals, it will be a cleanup function. The slave must die
+ from these. */
+ dosig(SIGHUP);
+ dosig(SIGQUIT);
+ dosig(SIGTERM);
+ dosig(SIGPIPE);
+
+ /* Ignore SIGINT if caught or ignored */
+ if (signal(SIGINT, SIG_IGN) == SIG_DFL)
+ signal(SIGINT, SIG_DFL);
+
+ /* Let the handler install itself */
+ handler(MYSIG);
+
+ /* Set slave_pid. This is also done in the master thread, but
+ there is a race condition whereby the slave begins execution
+ before the master has assigned the result of sproc() to
+ slave_pid. So we set it here as well -- since this sets the
+ same value it should be OK. */
+ slave_pid = getpid();
+
+ /* Set the dummy result returned by the first rendezvous */
+ result = NULL;
+
+ /* Loop forever, waiting for and executing work */
+ for (;;) {
+ /* First rendezvous: store previous result */
+ if (blockproc(slave_pid) < 0)
+ perror("slave: [result] blockproc(slave_pid)");
+ work_result = result;
+ if (unblockproc(master_pid) < 0)
+ perror("slave: [result] unblockproc(master_pid)");
+
+ /* Second rendezvous: fetch work */
+ if (blockproc(slave_pid) < 0)
+ perror("slave: [func,arg] blockproc(slave_pid)");
+ func = work_func;
+ arg = work_arg;
+ if (unblockproc(master_pid) < 0)
+ perror("slave: [func,arg] unblockproc(master_pid)");
+
+ /* Execute work, computing new result */
+ if (func == NULL) {
+ result = arg;
+ }
+ else {
+ result = (*func)(arg);
+ }
+ }
+}
+
+static int
+slave_init()
+{
+ if (slave_pid > 0)
+ return slave_pid;
+ master_pid = getpid();
+
+ /* Reset the queue, in case this is a re-init after asa_done() */
+ work_result = NULL;
+ work_func = NULL;
+ work_arg = NULL;
+
+ /* Create the slave process, sharing all segments and properties */
+ slave_pid = sproc(slave, PR_SALL, (char *)NULL);
+ if (slave_pid < 0)
+ perror("slave_init: sproc(slave, PR_SALL, NULL)");
+
+ /* Set up initial conditions---tricky!
+ Both the master and the slave start with one credit, since
+ both the result slot and the work/func slots are initially
+ free.
+ Note that we use setblockproccnt() for the master so a
+ possible indeterminate semaphore value caused by a previous
+ asa_done() at an unfortunate moment doesn't harm us.
+ */
+ setblockproccnt(master_pid, 1);
+ unblockproc(slave_pid);
+
+ return slave_pid;
+}
+
+static void
+slave_done()
+{
+ if (slave_pid > 0) {
+ if (kill(slave_pid, SIGKILL) < 0)
+ perror("slave_done: kill(slave_pid, SIGKILL)");
+ }
+ slave_pid = -1;
+}
+
+/* Queue new work and return result of previous work */
+
+static void *
+rendezvous(func, arg)
+ void * (*func)();
+ void *arg;
+{
+ void *result;
+
+ if (slave_pid <= 0)
+ abort(); /* Illegal call: not initialized properly */
+
+ /* First rendezvous: store new work */
+ if (blockproc(master_pid) < 0)
+ perror("rendezvous: [func,arg] blockproc(master_pid)");
+ work_func = func;
+ work_arg = arg;
+ if (unblockproc(slave_pid) < 0)
+ perror("rendezvous: [func,arg] unblockproc(slave_pid)");
+
+ /* Second rendezvous: fetch previous result */
+ if (blockproc(master_pid) < 0)
+ perror("rendezvous: [result] blockproc(master_pid)");
+ result = work_result;
+ if (unblockproc(slave_pid) < 0)
+ perror("rendezvous: [result] unblockproc(slave_pid)");
+
+ return result;
+}
+
+
+/* Asynchronous audio interface (higher layer) */
+
+
+int audio_fd = -1; /* File descriptor -- not initialized yet */
+
+static struct queue {
+ int func; /* 0 = read, 1 = write */
+ char *buf;
+ int len;
+ int result;
+ int error;
+} queue[2];
+
+static int qindex = 0;
+
+int
+asa_init()
+{
+ int fd;
+ char *p;
+
+ if (audio_fd >= 0)
+ return audio_fd;
+ fd = open("/dev/audio", 2);
+ if (fd < 0) {
+ perror("asa_init: Can't open /dev/audio");
+ return -1;
+ }
+ if (slave_init() < 0) {
+ perror("asa_init: Can't create slave process");
+ close(fd);
+ return -1;
+ }
+ audio_fd = fd;
+ return fd;
+}
+
+void
+asa_done()
+{
+ slave_done();
+ if (audio_fd >= 0) {
+ if (close(audio_fd) < 0)
+ perror("asa_done: close(audio_fd)");
+ }
+ audio_fd = -1;
+}
+
+static void *
+runjob(arg)
+ void *arg;
+{
+ extern int errno;
+ struct queue *q = (struct queue *)arg;
+ char *buf = q->buf;
+ int len = q->len;
+ int n = 0;
+
+ if (q->func == 0)
+ n = read(audio_fd, buf, len);
+ else
+ n = write(audio_fd, buf, len);
+ if (q->func == 0 && n >= 0) {
+ while (--len >= n && buf[len] == '\0')
+ ;
+ n = len+1;
+ }
+ q->result = n;
+ q->error = oserror();
+ return arg;
+}
+
+static void
+startjob(func, buf, len)
+ int func;
+ char *buf;
+ int len;
+{
+ struct queue *q;
+
+ q = &queue[qindex];
+ qindex = (qindex+1) & 1;
+ q->func = func;
+ q->buf = buf;
+ q->len = len;
+ (void) rendezvous(runjob, (void *)q);
+}
+
+void
+asa_start_read(buf, len)
+ char *buf;
+ int len;
+{
+ memset(buf, '\0', len);
+ startjob(0, buf, len);
+}
+
+void
+asa_start_write(buf, len)
+ char *buf;
+ int len;
+{
+ startjob(1, buf, len);
+}
+
+int
+asa_wait()
+{
+ struct queue *q;
+
+ q = (struct queue *) rendezvous((void*(*)())NULL, (void *)NULL);
+ if (q == NULL) {
+ setoserror(0);
+ return -1; /* No work was queued */
+ }
+ setoserror(q->error);
+ return q->result;
+}
+
+int
+asa_poll()
+{
+ int err;
+
+ err = prctl(PR_ISBLOCKED, slave_pid);
+ if (err < 0) {
+ perror("prctl(PR_ISBLOCKED, slave_pid)");
+ return -1;
+ }
+ else if (err == 0)
+ return 0;
+ else if (work_result == NULL) {
+ setoserror(0);
+ return -1;
+ }
+ else
+ return 1;
+}
+
+int
+asa_cancel()
+{
+ int result;
+
+ kill(slave_pid, MYSIG);
+ result = asa_wait();
+ return result;
+}
+
+
+#ifdef MAIN
+
+/* Test program */
+
+#include <sys/audio.h>
+
+main()
+{
+ static char buf[10*16*1024]; /* 10 seconds of sound at 16K/sec */
+ int n;
+ int afd;
+
+ if ((afd = asa_init()) < 0)
+ exit(1);
+ ioctl(afd, AUDIOCSETRATE, 3);
+ ioctl(afd, AUDIOCSETOUTGAIN, 0);
+ printf("Poll returns %d\n", asa_poll());
+ go("Hit enter to start recording:\n");
+ asa_start_read(buf, sizeof buf);
+ go("Hit enter to stop recording:\n");
+ /*printf("Poll returns %d\n", asa_poll());*/
+ n = asa_cancel();
+ if (n < 0)
+ perror("Read failed");
+ else {
+ printf("Got %d bytes\n", n);
+ printf("Poll returns %d\n", asa_poll());
+ go("Hit enter to start playing:\n");
+ ioctl(afd, AUDIOCSETOUTGAIN, 50);
+ asa_start_write(buf, n);
+ go("Hit enter to stop playing:\n");
+ printf("Poll returns %d\n", asa_poll());
+ n = asa_cancel();
+ if (n < 0)
+ perror("Write failed");
+ else
+ printf("Stopped at %d bytes\n", n);
+ }
+ ioctl(afd, AUDIOCSETOUTGAIN, 0);
+ asa_done();
+ exit(n < 0 ? 1 : 0);
+}
+
+go(str)
+ char *str;
+{
+ char line[100];
+
+ sleep(1);
+ fputs(str, stdout);
+ fflush(stdout);
+ fgets(line, sizeof line, stdin);
+}
+
+#endif /* MAIN */
diff --git a/src/asa.h b/src/asa.h
new file mode 100644
index 0000000..d9a7d10
--- /dev/null
+++ b/src/asa.h
@@ -0,0 +1,33 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* Interface for asynchronous audio module */
+
+extern int asa_init(void);
+extern void asa_done(void);
+extern void asa_start_write(char *, int);
+extern void asa_start_read(char *, int);
+extern int asa_poll(void);
+extern int asa_wait(void);
+extern int asa_cancel(void);
diff --git a/src/assert.h b/src/assert.h
new file mode 100644
index 0000000..f21225e
--- /dev/null
+++ b/src/assert.h
@@ -0,0 +1,25 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+#define assert(e) { if (!(e)) { printf("Assertion failed\n"); abort(); } }
diff --git a/src/audiomodule.c b/src/audiomodule.c
new file mode 100644
index 0000000..cca0102
--- /dev/null
+++ b/src/audiomodule.c
@@ -0,0 +1,615 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* Silicon Graphics audio module implementation */
+/* For SGI Personal IRIS 4D/20 under IRIX 3.3; <sys/audio.h> mentions "IP6" */
+/* Note: The set-in-gain ioctl exists but is non-functional */
+
+#include <errno.h>
+#include <sys/audio.h>
+#include "asa.h"
+
+#include "allobjects.h"
+#include "modsupport.h"
+
+static int audio_fd = -1;
+
+static int
+init()
+{
+ if (audio_fd >= 0)
+ return 1;
+ if ((audio_fd = asa_init()) >= 0)
+ return 1;
+ err_setstr(RuntimeError, "can't initialize async audio");
+ return 0;
+}
+
+
+/* POSIX methods */
+
+static object *
+audio_get_ioctl(self, args, code)
+ object *self;
+ object *args;
+ long code;
+{
+ long x;
+ if (!getnoarg(args))
+ return NULL;
+ if (!init())
+ return NULL;
+ if ((x = ioctl(audio_fd, code, (char *) NULL)) < 0) {
+ return NULL;
+ }
+ return newintobject(x);
+}
+
+static object *
+audio_set_ioctl(self, args, code)
+ object *self;
+ object *args;
+ long code;
+{
+ long x;
+ if (!getlongarg(args, &x))
+ return NULL;
+ if (!init())
+ return NULL;
+ if (ioctl(audio_fd, code, (char *) x) != 0)
+ return NULL;
+ INCREF(None);
+ return None;
+}
+
+static object *
+audio_getingain(self, args)
+ object *self;
+ object *args;
+{
+ return audio_get_ioctl(self, args, AUDIOCGETINGAIN);
+}
+
+static object *
+audio_getoutgain(self, args)
+ object *self;
+ object *args;
+{
+ return audio_get_ioctl(self, args, AUDIOCGETOUTGAIN);
+}
+
+static object *
+audio_setingain(self, args)
+ object *self;
+ object *args;
+{
+ return audio_set_ioctl(self, args, AUDIOCSETINGAIN);
+}
+
+static object *
+audio_setoutgain(self, args)
+ object *self;
+ object *args;
+{
+ return audio_set_ioctl(self, args, AUDIOCSETOUTGAIN);
+}
+
+static object *
+audio_setrate(self, args)
+ object *self;
+ object *args;
+{
+ return audio_set_ioctl(self, args, AUDIOCSETRATE);
+}
+
+static object *
+audio_setduration(self, args)
+ object *self;
+ object *args;
+{
+ return audio_set_ioctl(self, args, AUDIOCDURATION);
+}
+
+/* Compute average bias, and remove it */
+
+static void
+unbias(buf, len)
+ char *buf;
+ int len;
+{
+ register int i;
+ register int c;
+ register long bias;
+ if (len == 0)
+ return;
+ bias = 0;
+ for (i = 0; i < len; i++) {
+ c = buf[i];
+ if (c > 127)
+ c -= 256;
+ bias += c;
+ }
+ bias = (bias + len/2) / len; /* Rounded average */
+ if (bias != 0) {
+ for (i = 0; i < len; i++) {
+ buf[i] -= bias;
+ }
+ }
+}
+
+static object *
+audio_read(self, args)
+ object *self;
+ object *args;
+{
+ int c, i, n;
+ object *v;
+ char *s;
+ if (!getintarg(args, &n))
+ return NULL;
+ if (n <= 0) {
+ err_setstr(RuntimeError, "audio.read: arg <= 0");
+ return NULL;
+ }
+ if (!init())
+ return NULL;
+ v = newsizedstringobject((char *)NULL, n);
+ if (v == NULL)
+ return err_nomem();
+ s = getstringvalue(v);
+ n = read(audio_fd, s, n);
+ if (intrcheck()) {
+ DECREF(v);
+ err_set(KeyboardInterrupt);
+ return NULL;
+ }
+ /* Check for errors */
+ if (n < 0) {
+ DECREF(v);
+ return NULL;
+ }
+ /* But EOF is reported as an empty string */
+
+ unbias(s, n);
+ resizestring(&v, n);
+ return v;
+}
+
+static object *
+audio_write(self, args)
+ object *self;
+ object *args;
+{
+ int n, n2;
+ object *v;
+ if (!getstrarg(args, &v))
+ return NULL;
+ if (!init())
+ return NULL;
+ errno = 0;
+ n2 = write(audio_fd, getstringvalue(v), n = getstringsize(v));
+ if (intrcheck()) {
+ err_set(KeyboardInterrupt);
+ return NULL;
+ }
+ /* Check for other errors */
+ if (n2 != n) {
+ if (errno == 0)
+ errno = EIO;
+ return NULL;
+ }
+ INCREF(None);
+ return None;
+}
+
+/* audio.amplify(sample, f1, f2).
+ Amplify a sample by a factor changing from f1/256 to (almost) f2/256.
+ Negative factors are allowed. Sound values that are to large
+ to fit in a byte are clipped. */
+
+static object *
+audio_amplify(self, args)
+ object *self;
+ object *args;
+{
+ object *v;
+ char *s, *t;
+ int f1, f2;
+ int i, n;
+ int c;
+ if (!getstrintintarg(args, &v, &f1, &f2))
+ return NULL;
+ n = getstringsize(v);
+ s = getstringvalue(v);
+ v = newsizedstringobject((char *)NULL, n);
+ if (v == NULL)
+ return err_nomem();
+ t = getstringvalue(v);
+ for (i = 0; i < n; i++) {
+ c = s[i];
+ if (c > 127) c -= 256; /* If chars are unsigned */
+ c = c * ( f1*(n-i) + f2*i ) / ( n*256 );
+ if (c > 127) c = 127;
+ else if (c < -128) c = -128;
+ t[i] = c;
+ }
+ return v;
+}
+
+/* audio.reverse(s): return a sample backwards */
+
+static object *
+audio_reverse(self, args)
+ object *self;
+ object *args;
+{
+ object *v;
+ char *s, *t;
+ int i, n;
+ if (!getstrarg(args, &v))
+ return NULL;
+ n = getstringsize(v);
+ s = getstringvalue(v);
+ v = newsizedstringobject((char *)NULL, n);
+ if (v == NULL)
+ return err_nomem();
+ t = getstringvalue(v);
+ for (i = 0; i < n; i++) {
+ t[n-1-i] = s[i];
+ }
+ return v;
+}
+
+/* audio.add(a, b): add two samples.
+ Bytes that exceed the range are clipped.
+ If one is shorter, the rest of the longer sample is returned unchanged. */
+
+static object *
+audio_add(self, args)
+ object *self;
+ object *args;
+{
+ object *a, *b, *v;
+ char *sa, *sb, *t;
+ int i, n, na, nb, c, ca, cb;
+ if (!getstrstrarg(args, &a, &b))
+ return NULL;
+ na = getstringsize(a);
+ sa = getstringvalue(a);
+ nb = getstringsize(b);
+ sb = getstringvalue(b);
+ n = (na > nb) ? na : nb;
+ v = newsizedstringobject((char *)NULL, n);
+ if (v == NULL)
+ return err_nomem();
+ t = getstringvalue(v);
+ for (i = 0; i < n; i++) {
+ c = 0;
+ if (i < na) {
+ ca = sa[i];
+ if (ca > 127) ca = ca - 256;
+ c = c + ca;
+ }
+ if (i < nb) {
+ cb = sb[i];
+ if (cb > 127) cb = cb - 256;
+ c = c + cb;
+ }
+ if (c > 127) c = 127;
+ else if (c < -128) c = -128;
+ t[i] = c;
+ }
+ return v;
+}
+
+/* audio.chr2num(s) returns a list containing the numeric values
+ of the samples. */
+
+static object *
+audio_chr2num(self, args)
+ object *self;
+ object *args;
+{
+ object *v, *w;
+ char *s;
+ int c, i, n;
+ static object *ints[256];
+
+ /* To avoid filling memory with all those int objects, we create
+ integer objects for all the desired values and reference these. */
+ if (ints[255] == NULL) {
+ for (i = 0; i < 256; i++) {
+ if (ints[i] != NULL)
+ continue;
+ c = i;
+ if (c > 127) c -= 256;
+ ints[i] = newintobject((long)c);
+ if (ints[i] == NULL)
+ return NULL;
+ }
+ }
+
+ if (!getstrarg(args, &v))
+ return NULL;
+ n = getstringsize(v);
+ s = getstringvalue(v);
+ v = newlistobject(n);
+ if (v == NULL)
+ return err_nomem();
+ for (i = 0; i < n; i++) {
+ c = s[i] & 0xff;
+ w = ints[c];
+ INCREF(w);
+ if (setlistitem(v, i, w) != 0) {
+ DECREF(v);
+ return NULL;
+ }
+ }
+ return v;
+}
+
+/* audio.num2chr is the inverse of audio.chr2num.
+ Excess values are clipped. */
+
+static object *
+audio_num2chr(self, args)
+ object *self;
+ object *args;
+{
+ object *v, *w;
+ char *s;
+ int c, i, n;
+ if (!is_listobject(args)) {
+ err_badarg();
+ return NULL;
+ }
+ n = getlistsize(args);
+ v = newsizedstringobject((char *)NULL, n);
+ if (v == NULL)
+ return NULL;
+ s = getstringvalue(v);
+ for (i = 0; i < n; i++) {
+ w = getlistitem(args, i);
+ if (!is_intobject(w)) {
+ DECREF(v);
+ err_badarg();
+ return NULL;
+ }
+ s[i] = getintvalue(w);
+ }
+ return v;
+}
+
+static object *stdaudio_buffer = NULL;
+
+static object *
+audio_start_recording(self, args)
+ object *self;
+ object *args;
+{
+ int n;
+ object *v;
+ char *s;
+ if (!getintarg(args, &n))
+ return NULL;
+ if (stdaudio_buffer != NULL) {
+ err_setstr(RuntimeError, "audio.start_recording: device busy");
+ return NULL;
+ }
+ if (n <= 0) {
+ err_setstr(TypeError, "audio.start_recording: arg <= 0");
+ return NULL;
+ }
+ if (!init())
+ return NULL;
+ v = newsizedstringobject((char *)NULL, n);
+ if (v == NULL)
+ return err_nomem();
+ s = getstringvalue(v);
+ asa_start_read(s, n);
+ stdaudio_buffer = v;
+ INCREF(None);
+ return None;
+}
+
+static object *
+audio_poll(self, args)
+ object *self;
+ object *args;
+{
+ int n;
+ if (!getnoarg(args))
+ return NULL;
+ if (stdaudio_buffer == NULL) {
+ err_setstr(RuntimeError, "audio.poll: not busy");
+ return NULL;
+ }
+ if (!init())
+ return NULL;
+ if ((n = asa_poll()) < 0)
+ return NULL;
+ return newintobject(n);
+}
+
+static object *
+audio_wait_recording(self, args)
+ object *self;
+ object *args;
+{
+ object *v;
+ int n;
+ if (!getnoarg(args))
+ return NULL;
+ if (stdaudio_buffer == NULL) {
+ err_setstr(RuntimeError, "audio.wait_recording: not busy");
+ return NULL;
+ }
+ if (!init())
+ return NULL;
+ if ((n = asa_wait()) < 0)
+ return NULL;
+ v = stdaudio_buffer;
+ stdaudio_buffer = NULL;
+ unbias(getstringvalue(v), n);
+ resizestring(&v, n);
+ return v;
+}
+
+static object *
+audio_stop_recording(self, args)
+ object *self;
+ object *args;
+{
+ int n;
+ object *v;
+ char *s;
+ if (!getnoarg(args))
+ return NULL;
+ if (stdaudio_buffer == NULL) {
+ err_setstr(RuntimeError, "audio.stop_recording: not busy");
+ return NULL;
+ }
+ if ((n = asa_cancel()) < 0)
+ return NULL;
+ v = stdaudio_buffer;
+ stdaudio_buffer = NULL;
+ s = getstringvalue(v);
+ unbias(s, n);
+ resizestring(&v, n);
+ return v;
+}
+
+static object *
+audio_start_playing(self, args)
+ object *self;
+ object *args;
+{
+ object *v;
+ if (!getstrarg(args, &v))
+ return NULL;
+ if (stdaudio_buffer != NULL) {
+ err_setstr(RuntimeError, "audio.start_recording: device rbusy");
+ return NULL;
+ }
+ asa_start_write(getstringvalue(v), (int)getstringsize(v));
+ INCREF(v);
+ stdaudio_buffer = v;
+ INCREF(None);
+ return None;
+}
+
+static object *
+audio_wait_playing(self, args)
+ object *self;
+ object *args;
+{
+ int n;
+ if (!getnoarg(args))
+ return NULL;
+ if (stdaudio_buffer == NULL) {
+ err_setstr(RuntimeError, "audio.wait_playing: not busy");
+ return NULL;
+ }
+ if ((n = asa_wait()) < 0)
+ return NULL;
+ DECREF(stdaudio_buffer);
+ stdaudio_buffer = NULL;
+ /* XXX return newintobject((long)n); ??? */
+ INCREF(None);
+ return None;
+}
+
+static object *
+audio_stop_playing(self, args)
+ object *self;
+ object *args;
+{
+ int n;
+ if (!getnoarg(args))
+ return NULL;
+ if (stdaudio_buffer == NULL) {
+ err_setstr(RuntimeError, "audio.stop_playing: not busy");
+ return NULL;
+ }
+ if ((n = asa_cancel()) < 0)
+ return NULL;
+ DECREF(stdaudio_buffer);
+ stdaudio_buffer = NULL;
+ return newintobject((long)n);
+}
+
+static object *
+audio_audio_done(self, args)
+ object *self;
+ object *args;
+{
+ if (!getnoarg(args))
+ return NULL;
+ asa_done();
+ if (stdaudio_buffer != NULL)
+ DECREF(stdaudio_buffer);
+ stdaudio_buffer = NULL;
+ audio_fd = -1;
+ INCREF(None);
+ return None;
+}
+
+
+static struct methodlist audio_methods[] = {
+ {"getingain", audio_getingain},
+ {"getoutgain", audio_getoutgain},
+ {"setingain", audio_setingain},
+ {"setoutgain", audio_setoutgain},
+ {"setrate", audio_setrate},
+ {"setduration", audio_setduration},
+ {"read", audio_read},
+ {"write", audio_write},
+ {"amplify", audio_amplify},
+ {"reverse", audio_reverse},
+ {"add", audio_add},
+ {"chr2num", audio_chr2num},
+ {"num2chr", audio_num2chr},
+
+ /* "asa" interface: */
+
+ {"start_recording", audio_start_recording},
+ {"poll_recording", audio_poll},
+ {"wait_recording", audio_wait_recording},
+ {"stop_recording", audio_stop_recording},
+
+ {"start_playing", audio_start_playing},
+ {"poll_playing", audio_poll},
+ {"wait_playing", audio_wait_playing},
+ {"stop_playing", audio_stop_playing},
+
+ {"done", audio_audio_done},
+
+ {NULL, NULL} /* Sentinel */
+};
+
+void
+initaudio()
+{
+ initmodule("audio", audio_methods);
+}
diff --git a/src/bitset.c b/src/bitset.c
new file mode 100644
index 0000000..c08dcc7
--- /dev/null
+++ b/src/bitset.c
@@ -0,0 +1,99 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* Bitset primitives used by the parser generator */
+
+#include "pgenheaders.h"
+#include "bitset.h"
+
+bitset
+newbitset(nbits)
+ int nbits;
+{
+ int nbytes = NBYTES(nbits);
+ bitset ss = NEW(BYTE, nbytes);
+
+ if (ss == NULL)
+ fatal("no mem for bitset");
+
+ ss += nbytes;
+ while (--nbytes >= 0)
+ *--ss = 0;
+ return ss;
+}
+
+void
+delbitset(ss)
+ bitset ss;
+{
+ DEL(ss);
+}
+
+int
+addbit(ss, ibit)
+ bitset ss;
+ int ibit;
+{
+ int ibyte = BIT2BYTE(ibit);
+ BYTE mask = BIT2MASK(ibit);
+
+ if (ss[ibyte] & mask)
+ return 0; /* Bit already set */
+ ss[ibyte] |= mask;
+ return 1;
+}
+
+#if 0 /* Now a macro */
+int
+testbit(ss, ibit)
+ bitset ss;
+ int ibit;
+{
+ return (ss[BIT2BYTE(ibit)] & BIT2MASK(ibit)) != 0;
+}
+#endif
+
+int
+samebitset(ss1, ss2, nbits)
+ bitset ss1, ss2;
+ int nbits;
+{
+ int i;
+
+ for (i = NBYTES(nbits); --i >= 0; )
+ if (*ss1++ != *ss2++)
+ return 0;
+ return 1;
+}
+
+void
+mergebitset(ss1, ss2, nbits)
+ bitset ss1, ss2;
+ int nbits;
+{
+ int i;
+
+ for (i = NBYTES(nbits); --i >= 0; )
+ *ss1++ |= *ss2++;
+}
diff --git a/src/bitset.h b/src/bitset.h
new file mode 100644
index 0000000..5ec6882
--- /dev/null
+++ b/src/bitset.h
@@ -0,0 +1,46 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* Bitset interface */
+
+#define BYTE char
+
+typedef BYTE *bitset;
+
+bitset newbitset PROTO((int nbits));
+void delbitset PROTO((bitset bs));
+/* int testbit PROTO((bitset bs, int ibit)); /* Now a macro, see below */
+int addbit PROTO((bitset bs, int ibit)); /* Returns 0 if already set */
+int samebitset PROTO((bitset bs1, bitset bs2, int nbits));
+void mergebitset PROTO((bitset bs1, bitset bs2, int nbits));
+
+#define BITSPERBYTE (8*sizeof(BYTE))
+#define NBYTES(nbits) (((nbits) + BITSPERBYTE - 1) / BITSPERBYTE)
+
+#define BIT2BYTE(ibit) ((ibit) / BITSPERBYTE)
+#define BIT2SHIFT(ibit) ((ibit) % BITSPERBYTE)
+#define BIT2MASK(ibit) (1 << BIT2SHIFT(ibit))
+#define BYTE2BIT(ibyte) ((ibyte) * BITSPERBYTE)
+
+#define testbit(ss, ibit) (((ss)[BIT2BYTE(ibit)] & BIT2MASK(ibit)) != 0)
diff --git a/src/bltinmodule.c b/src/bltinmodule.c
new file mode 100644
index 0000000..151ba86
--- /dev/null
+++ b/src/bltinmodule.c
@@ -0,0 +1,559 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* Built-in functions */
+
+#include "allobjects.h"
+
+#include "node.h"
+#include "graminit.h"
+#include "errcode.h"
+#include "sysmodule.h"
+#include "bltinmodule.h"
+#include "import.h"
+#include "pythonrun.h"
+#include "compile.h" /* For ceval.h */
+#include "ceval.h"
+#include "modsupport.h"
+
+static object *
+builtin_abs(self, v)
+ object *self;
+ object *v;
+{
+ /* XXX This should be a method in the as_number struct in the type */
+ if (v == NULL) {
+ /* */
+ }
+ else if (is_intobject(v)) {
+ long x = getintvalue(v);
+ if (x < 0)
+ x = -x;
+ return newintobject(x);
+ }
+ else if (is_floatobject(v)) {
+ double x = getfloatvalue(v);
+ if (x < 0)
+ x = -x;
+ return newfloatobject(x);
+ }
+ err_setstr(TypeError, "abs() argument must be float or int");
+ return NULL;
+}
+
+static object *
+builtin_chr(self, v)
+ object *self;
+ object *v;
+{
+ long x;
+ char s[1];
+ if (v == NULL || !is_intobject(v)) {
+ err_setstr(TypeError, "chr() must have int argument");
+ return NULL;
+ }
+ x = getintvalue(v);
+ if (x < 0 || x >= 256) {
+ err_setstr(RuntimeError, "chr() arg not in range(256)");
+ return NULL;
+ }
+ s[0] = x;
+ return newsizedstringobject(s, 1);
+}
+
+static object *
+builtin_dir(self, v)
+ object *self;
+ object *v;
+{
+ object *d;
+ if (v == NULL) {
+ d = getlocals();
+ }
+ else {
+ if (!is_moduleobject(v)) {
+ err_setstr(TypeError,
+ "dir() argument, must be module or absent");
+ return NULL;
+ }
+ d = getmoduledict(v);
+ }
+ v = getdictkeys(d);
+ if (sortlist(v) != 0) {
+ DECREF(v);
+ v = NULL;
+ }
+ return v;
+}
+
+static object *
+builtin_divmod(self, v)
+ object *self;
+ object *v;
+{
+ object *x, *y;
+ long xi, yi, xdivy, xmody;
+ if (v == NULL || !is_tupleobject(v) || gettuplesize(v) != 2) {
+ err_setstr(TypeError, "divmod() requires 2 int arguments");
+ return NULL;
+ }
+ x = gettupleitem(v, 0);
+ y = gettupleitem(v, 1);
+ if (!is_intobject(x) || !is_intobject(y)) {
+ err_setstr(TypeError, "divmod() requires 2 int arguments");
+ return NULL;
+ }
+ xi = getintvalue(x);
+ yi = getintvalue(y);
+ if (yi == 0) {
+ err_setstr(TypeError, "divmod() division by zero");
+ return NULL;
+ }
+ if (yi < 0) {
+ xdivy = -xi / -yi;
+ }
+ else {
+ xdivy = xi / yi;
+ }
+ xmody = xi - xdivy*yi;
+ if (xmody < 0 && yi > 0 || xmody > 0 && yi < 0) {
+ xmody += yi;
+ xdivy -= 1;
+ }
+ v = newtupleobject(2);
+ x = newintobject(xdivy);
+ y = newintobject(xmody);
+ if (v == NULL || x == NULL || y == NULL ||
+ settupleitem(v, 0, x) != 0 ||
+ settupleitem(v, 1, y) != 0) {
+ XDECREF(v);
+ XDECREF(x);
+ XDECREF(y);
+ return NULL;
+ }
+ return v;
+}
+
+static object *
+exec_eval(v, start)
+ object *v;
+ int start;
+{
+ object *str = NULL, *globals = NULL, *locals = NULL;
+ int n;
+ if (v != NULL) {
+ if (is_stringobject(v))
+ str = v;
+ else if (is_tupleobject(v) &&
+ ((n = gettuplesize(v)) == 2 || n == 3)) {
+ str = gettupleitem(v, 0);
+ globals = gettupleitem(v, 1);
+ if (n == 3)
+ locals = gettupleitem(v, 2);
+ }
+ }
+ if (str == NULL || !is_stringobject(str) ||
+ globals != NULL && !is_dictobject(globals) ||
+ locals != NULL && !is_dictobject(locals)) {
+ err_setstr(TypeError,
+ "exec/eval arguments must be string[,dict[,dict]]");
+ return NULL;
+ }
+ return run_string(getstringvalue(str), start, globals, locals);
+}
+
+static object *
+builtin_eval(self, v)
+ object *self;
+ object *v;
+{
+ return exec_eval(v, eval_input);
+}
+
+static object *
+builtin_exec(self, v)
+ object *self;
+ object *v;
+{
+ return exec_eval(v, file_input);
+}
+
+static object *
+builtin_float(self, v)
+ object *self;
+ object *v;
+{
+ if (v == NULL) {
+ /* */
+ }
+ else if (is_floatobject(v)) {
+ INCREF(v);
+ return v;
+ }
+ else if (is_intobject(v)) {
+ long x = getintvalue(v);
+ return newfloatobject((double)x);
+ }
+ err_setstr(TypeError, "float() argument must be float or int");
+ return NULL;
+}
+
+static object *
+builtin_input(self, v)
+ object *self;
+ object *v;
+{
+ FILE *in = sysgetfile("stdin", stdin);
+ FILE *out = sysgetfile("stdout", stdout);
+ node *n;
+ int err;
+ object *m, *d;
+ flushline();
+ if (v != NULL)
+ printobject(v, out, PRINT_RAW);
+ m = add_module("__main__");
+ d = getmoduledict(m);
+ return run_file(in, "<stdin>", expr_input, d, d);
+}
+
+static object *
+builtin_int(self, v)
+ object *self;
+ object *v;
+{
+ if (v == NULL) {
+ /* */
+ }
+ else if (is_intobject(v)) {
+ INCREF(v);
+ return v;
+ }
+ else if (is_floatobject(v)) {
+ double x = getfloatvalue(v);
+ return newintobject((long)x);
+ }
+ err_setstr(TypeError, "int() argument must be float or int");
+ return NULL;
+}
+
+static object *
+builtin_len(self, v)
+ object *self;
+ object *v;
+{
+ long len;
+ typeobject *tp;
+ if (v == NULL) {
+ err_setstr(TypeError, "len() without argument");
+ return NULL;
+ }
+ tp = v->ob_type;
+ if (tp->tp_as_sequence != NULL) {
+ len = (*tp->tp_as_sequence->sq_length)(v);
+ }
+ else if (tp->tp_as_mapping != NULL) {
+ len = (*tp->tp_as_mapping->mp_length)(v);
+ }
+ else {
+ err_setstr(TypeError, "len() of unsized object");
+ return NULL;
+ }
+ return newintobject(len);
+}
+
+static object *
+min_max(v, sign)
+ object *v;
+ int sign;
+{
+ int i, n, cmp;
+ object *w, *x;
+ sequence_methods *sq;
+ if (v == NULL) {
+ err_setstr(TypeError, "min() or max() without argument");
+ return NULL;
+ }
+ sq = v->ob_type->tp_as_sequence;
+ if (sq == NULL) {
+ err_setstr(TypeError, "min() or max() of non-sequence");
+ return NULL;
+ }
+ n = (*sq->sq_length)(v);
+ if (n == 0) {
+ err_setstr(RuntimeError, "min() or max() of empty sequence");
+ return NULL;
+ }
+ w = (*sq->sq_item)(v, 0); /* Implies INCREF */
+ for (i = 1; i < n; i++) {
+ x = (*sq->sq_item)(v, i); /* Implies INCREF */
+ cmp = cmpobject(x, w);
+ if (cmp * sign > 0) {
+ DECREF(w);
+ w = x;
+ }
+ else
+ DECREF(x);
+ }
+ return w;
+}
+
+static object *
+builtin_min(self, v)
+ object *self;
+ object *v;
+{
+ return min_max(v, -1);
+}
+
+static object *
+builtin_max(self, v)
+ object *self;
+ object *v;
+{
+ return min_max(v, 1);
+}
+
+static object *
+builtin_open(self, v)
+ object *self;
+ object *v;
+{
+ object *name, *mode;
+ if (v == NULL || !is_tupleobject(v) || gettuplesize(v) != 2 ||
+ !is_stringobject(name = gettupleitem(v, 0)) ||
+ !is_stringobject(mode = gettupleitem(v, 1))) {
+ err_setstr(TypeError, "open() requires 2 string arguments");
+ return NULL;
+ }
+ v = newfileobject(getstringvalue(name), getstringvalue(mode));
+ return v;
+}
+
+static object *
+builtin_ord(self, v)
+ object *self;
+ object *v;
+{
+ if (v == NULL || !is_stringobject(v)) {
+ err_setstr(TypeError, "ord() must have string argument");
+ return NULL;
+ }
+ if (getstringsize(v) != 1) {
+ err_setstr(RuntimeError, "ord() arg must have length 1");
+ return NULL;
+ }
+ return newintobject((long)(getstringvalue(v)[0] & 0xff));
+}
+
+static object *
+builtin_range(self, v)
+ object *self;
+ object *v;
+{
+ static char *errmsg = "range() requires 1-3 int arguments";
+ int i, n;
+ long ilow, ihigh, istep;
+ if (v != NULL && is_intobject(v)) {
+ ilow = 0; ihigh = getintvalue(v); istep = 1;
+ }
+ else if (v == NULL || !is_tupleobject(v)) {
+ err_setstr(TypeError, errmsg);
+ return NULL;
+ }
+ else {
+ n = gettuplesize(v);
+ if (n < 1 || n > 3) {
+ err_setstr(TypeError, errmsg);
+ return NULL;
+ }
+ for (i = 0; i < n; i++) {
+ if (!is_intobject(gettupleitem(v, i))) {
+ err_setstr(TypeError, errmsg);
+ return NULL;
+ }
+ }
+ if (n == 3) {
+ istep = getintvalue(gettupleitem(v, 2));
+ --n;
+ }
+ else
+ istep = 1;
+ ihigh = getintvalue(gettupleitem(v, --n));
+ if (n > 0)
+ ilow = getintvalue(gettupleitem(v, 0));
+ else
+ ilow = 0;
+ }
+ if (istep == 0) {
+ err_setstr(RuntimeError, "zero step for range()");
+ return NULL;
+ }
+ /* XXX ought to check overflow of subtraction */
+ if (istep > 0)
+ n = (ihigh - ilow + istep - 1) / istep;
+ else
+ n = (ihigh - ilow + istep + 1) / istep;
+ if (n < 0)
+ n = 0;
+ v = newlistobject(n);
+ if (v == NULL)
+ return NULL;
+ for (i = 0; i < n; i++) {
+ object *w = newintobject(ilow);
+ if (w == NULL) {
+ DECREF(v);
+ return NULL;
+ }
+ setlistitem(v, i, w);
+ ilow += istep;
+ }
+ return v;
+}
+
+static object *
+builtin_raw_input(self, v)
+ object *self;
+ object *v;
+{
+ FILE *in = sysgetfile("stdin", stdin);
+ FILE *out = sysgetfile("stdout", stdout);
+ char *p;
+ int err;
+ int n = 1000;
+ flushline();
+ if (v != NULL)
+ printobject(v, out, PRINT_RAW);
+ v = newsizedstringobject((char *)NULL, n);
+ if (v != NULL) {
+ if ((err = fgets_intr(getstringvalue(v), n+1, in)) != E_OK) {
+ err_input(err);
+ DECREF(v);
+ return NULL;
+ }
+ else {
+ n = strlen(getstringvalue(v));
+ if (n > 0 && getstringvalue(v)[n-1] == '\n')
+ n--;
+ resizestring(&v, n);
+ }
+ }
+ return v;
+}
+
+static object *
+builtin_reload(self, v)
+ object *self;
+ object *v;
+{
+ return reload_module(v);
+}
+
+static object *
+builtin_type(self, v)
+ object *self;
+ object *v;
+{
+ if (v == NULL) {
+ err_setstr(TypeError, "type() requres an argument");
+ return NULL;
+ }
+ v = (object *)v->ob_type;
+ INCREF(v);
+ return v;
+}
+
+static struct methodlist builtin_methods[] = {
+ {"abs", builtin_abs},
+ {"chr", builtin_chr},
+ {"dir", builtin_dir},
+ {"divmod", builtin_divmod},
+ {"eval", builtin_eval},
+ {"exec", builtin_exec},
+ {"float", builtin_float},
+ {"input", builtin_input},
+ {"int", builtin_int},
+ {"len", builtin_len},
+ {"max", builtin_max},
+ {"min", builtin_min},
+ {"open", builtin_open}, /* XXX move to OS module */
+ {"ord", builtin_ord},
+ {"range", builtin_range},
+ {"raw_input", builtin_raw_input},
+ {"reload", builtin_reload},
+ {"type", builtin_type},
+ {NULL, NULL},
+};
+
+static object *builtin_dict;
+
+object *
+getbuiltin(name)
+ char *name;
+{
+ return dictlookup(builtin_dict, name);
+}
+
+/* Predefined exceptions */
+
+object *RuntimeError;
+object *EOFError;
+object *TypeError;
+object *MemoryError;
+object *NameError;
+object *SystemError;
+object *KeyboardInterrupt;
+
+static object *
+newstdexception(name, message)
+ char *name, *message;
+{
+ object *v = newstringobject(message);
+ if (v == NULL || dictinsert(builtin_dict, name, v) != 0)
+ fatal("no mem for new standard exception");
+ return v;
+}
+
+static void
+initerrors()
+{
+ RuntimeError = newstdexception("RuntimeError", "run-time error");
+ EOFError = newstdexception("EOFError", "end-of-file read");
+ TypeError = newstdexception("TypeError", "type error");
+ MemoryError = newstdexception("MemoryError", "out of memory");
+ NameError = newstdexception("NameError", "undefined name");
+ SystemError = newstdexception("SystemError", "system error");
+ KeyboardInterrupt =
+ newstdexception("KeyboardInterrupt", "keyboard interrupt");
+}
+
+void
+initbuiltin()
+{
+ object *m;
+ m = initmodule("builtin", builtin_methods);
+ builtin_dict = getmoduledict(m);
+ INCREF(builtin_dict);
+ initerrors();
+ (void) dictinsert(builtin_dict, "None", None);
+}
diff --git a/src/bltinmodule.h b/src/bltinmodule.h
new file mode 100644
index 0000000..fe16907
--- /dev/null
+++ b/src/bltinmodule.h
@@ -0,0 +1,27 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* Built-in module interface */
+
+extern object *getbuiltin PROTO((char *));
diff --git a/src/ceval.c b/src/ceval.c
new file mode 100644
index 0000000..6876208
--- /dev/null
+++ b/src/ceval.c
@@ -0,0 +1,1436 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* Execute compiled code */
+
+#include "allobjects.h"
+
+#include "import.h"
+#include "sysmodule.h"
+#include "compile.h"
+#include "frameobject.h"
+#include "ceval.h"
+#include "opcode.h"
+#include "bltinmodule.h"
+#include "traceback.h"
+
+#ifndef NDEBUG
+#define TRACE
+#endif
+
+#ifdef TRACE
+static int
+prtrace(v, str)
+ object *v;
+ char *str;
+{
+ printf("%s ", str);
+ printobject(v, stdout, 0);
+ printf("\n");
+}
+#endif
+
+static frameobject *current_frame;
+
+object *
+getlocals()
+{
+ if (current_frame == NULL)
+ return NULL;
+ else
+ return current_frame->f_locals;
+}
+
+object *
+getglobals()
+{
+ if (current_frame == NULL)
+ return NULL;
+ else
+ return current_frame->f_globals;
+}
+
+void
+printtraceback(fp)
+ FILE *fp;
+{
+ object *v = tb_fetch();
+ if (v != NULL) {
+ fprintf(fp, "Stack backtrace (innermost last):\n");
+ tb_print(v, fp);
+ DECREF(v);
+ }
+}
+
+
+/* XXX Mixing "print ...," and direct file I/O on stdin/stdout
+ XXX has some bad consequences. The needspace flag should
+ XXX really be part of the file object. */
+
+static int needspace;
+
+void
+flushline()
+{
+ FILE *fp = sysgetfile("stdout", stdout);
+ if (needspace) {
+ fprintf(fp, "\n");
+ needspace = 0;
+ }
+}
+
+
+/* Test a value used as condition, e.g., in a for or if statement */
+
+static int
+testbool(v)
+ object *v;
+{
+ if (is_intobject(v))
+ return getintvalue(v) != 0;
+ if (is_floatobject(v))
+ return getfloatvalue(v) != 0.0;
+ if (v->ob_type->tp_as_sequence != NULL)
+ return (*v->ob_type->tp_as_sequence->sq_length)(v) != 0;
+ if (v->ob_type->tp_as_mapping != NULL)
+ return (*v->ob_type->tp_as_mapping->mp_length)(v) != 0;
+ if (v == None)
+ return 0;
+ /* All other objects are 'true' */
+ return 1;
+}
+
+static object *
+add(v, w)
+ object *v, *w;
+{
+ if (v->ob_type->tp_as_number != NULL)
+ v = (*v->ob_type->tp_as_number->nb_add)(v, w);
+ else if (v->ob_type->tp_as_sequence != NULL)
+ v = (*v->ob_type->tp_as_sequence->sq_concat)(v, w);
+ else {
+ err_setstr(TypeError, "+ not supported by operands");
+ return NULL;
+ }
+ return v;
+}
+
+static object *
+sub(v, w)
+ object *v, *w;
+{
+ if (v->ob_type->tp_as_number != NULL)
+ return (*v->ob_type->tp_as_number->nb_subtract)(v, w);
+ err_setstr(TypeError, "bad operand type(s) for -");
+ return NULL;
+}
+
+static object *
+mul(v, w)
+ object *v, *w;
+{
+ typeobject *tp;
+ if (is_intobject(v) && w->ob_type->tp_as_sequence != NULL) {
+ /* int*sequence -- swap v and w */
+ object *tmp = v;
+ v = w;
+ w = tmp;
+ }
+ tp = v->ob_type;
+ if (tp->tp_as_number != NULL)
+ return (*tp->tp_as_number->nb_multiply)(v, w);
+ if (tp->tp_as_sequence != NULL) {
+ if (!is_intobject(w)) {
+ err_setstr(TypeError,
+ "can't multiply sequence with non-int");
+ return NULL;
+ }
+ if (tp->tp_as_sequence->sq_repeat == NULL) {
+ err_setstr(TypeError, "sequence does not support *");
+ return NULL;
+ }
+ return (*tp->tp_as_sequence->sq_repeat)
+ (v, (int)getintvalue(w));
+ }
+ err_setstr(TypeError, "bad operand type(s) for *");
+ return NULL;
+}
+
+static object *
+divide(v, w)
+ object *v, *w;
+{
+ if (v->ob_type->tp_as_number != NULL)
+ return (*v->ob_type->tp_as_number->nb_divide)(v, w);
+ err_setstr(TypeError, "bad operand type(s) for /");
+ return NULL;
+}
+
+static object *
+rem(v, w)
+ object *v, *w;
+{
+ if (v->ob_type->tp_as_number != NULL)
+ return (*v->ob_type->tp_as_number->nb_remainder)(v, w);
+ err_setstr(TypeError, "bad operand type(s) for %");
+ return NULL;
+}
+
+static object *
+neg(v)
+ object *v;
+{
+ if (v->ob_type->tp_as_number != NULL)
+ return (*v->ob_type->tp_as_number->nb_negative)(v);
+ err_setstr(TypeError, "bad operand type(s) for unary -");
+ return NULL;
+}
+
+static object *
+pos(v)
+ object *v;
+{
+ if (v->ob_type->tp_as_number != NULL)
+ return (*v->ob_type->tp_as_number->nb_positive)(v);
+ err_setstr(TypeError, "bad operand type(s) for unary +");
+ return NULL;
+}
+
+static object *
+not(v)
+ object *v;
+{
+ int outcome = testbool(v);
+ object *w = outcome == 0 ? True : False;
+ INCREF(w);
+ return w;
+}
+
+static object *
+call_builtin(func, arg)
+ object *func;
+ object *arg;
+{
+ if (is_methodobject(func)) {
+ method meth = getmethod(func);
+ object *self = getself(func);
+ return (*meth)(self, arg);
+ }
+ if (is_classobject(func)) {
+ if (arg != NULL) {
+ err_setstr(TypeError,
+ "classobject() allows no arguments");
+ return NULL;
+ }
+ return newclassmemberobject(func);
+ }
+ err_setstr(TypeError, "call of non-function");
+ return NULL;
+}
+
+static object *
+call_function(func, arg)
+ object *func;
+ object *arg;
+{
+ object *newarg = NULL;
+ object *newlocals, *newglobals;
+ object *co, *v;
+
+ if (is_classmethodobject(func)) {
+ object *self = classmethodgetself(func);
+ func = classmethodgetfunc(func);
+ if (arg == NULL) {
+ arg = self;
+ }
+ else {
+ newarg = newtupleobject(2);
+ if (newarg == NULL)
+ return NULL;
+ INCREF(self);
+ INCREF(arg);
+ settupleitem(newarg, 0, self);
+ settupleitem(newarg, 1, arg);
+ arg = newarg;
+ }
+ }
+ else {
+ if (!is_funcobject(func)) {
+ err_setstr(TypeError, "call of non-function");
+ return NULL;
+ }
+ }
+
+ co = getfunccode(func);
+ if (co == NULL) {
+ XDECREF(newarg);
+ return NULL;
+ }
+ if (!is_codeobject(co)) {
+ fprintf(stderr, "XXX Bad code\n");
+ abort();
+ }
+ newlocals = newdictobject();
+ if (newlocals == NULL) {
+ XDECREF(newarg);
+ return NULL;
+ }
+
+ newglobals = getfuncglobals(func);
+ INCREF(newglobals);
+
+ v = eval_code((codeobject *)co, newglobals, newlocals, arg);
+
+ DECREF(newlocals);
+ DECREF(newglobals);
+
+ XDECREF(newarg);
+
+ return v;
+}
+
+static object *
+apply_subscript(v, w)
+ object *v, *w;
+{
+ typeobject *tp = v->ob_type;
+ if (tp->tp_as_sequence == NULL && tp->tp_as_mapping == NULL) {
+ err_setstr(TypeError, "unsubscriptable object");
+ return NULL;
+ }
+ if (tp->tp_as_sequence != NULL) {
+ int i;
+ if (!is_intobject(w)) {
+ err_setstr(TypeError, "sequence subscript not int");
+ return NULL;
+ }
+ i = getintvalue(w);
+ return (*tp->tp_as_sequence->sq_item)(v, i);
+ }
+ return (*tp->tp_as_mapping->mp_subscript)(v, w);
+}
+
+static object *
+loop_subscript(v, w)
+ object *v, *w;
+{
+ sequence_methods *sq = v->ob_type->tp_as_sequence;
+ int i, n;
+ if (sq == NULL) {
+ err_setstr(TypeError, "loop over non-sequence");
+ return NULL;
+ }
+ i = getintvalue(w);
+ n = (*sq->sq_length)(v);
+ if (i >= n)
+ return NULL; /* End of loop */
+ return (*sq->sq_item)(v, i);
+}
+
+static int
+slice_index(v, isize, pi)
+ object *v;
+ int isize;
+ int *pi;
+{
+ if (v != NULL) {
+ if (!is_intobject(v)) {
+ err_setstr(TypeError, "slice index must be int");
+ return -1;
+ }
+ *pi = getintvalue(v);
+ if (*pi < 0)
+ *pi += isize;
+ }
+ return 0;
+}
+
+static object *
+apply_slice(u, v, w) /* return u[v:w] */
+ object *u, *v, *w;
+{
+ typeobject *tp = u->ob_type;
+ int ilow, ihigh, isize;
+ if (tp->tp_as_sequence == NULL) {
+ err_setstr(TypeError, "only sequences can be sliced");
+ return NULL;
+ }
+ ilow = 0;
+ isize = ihigh = (*tp->tp_as_sequence->sq_length)(u);
+ if (slice_index(v, isize, &ilow) != 0)
+ return NULL;
+ if (slice_index(w, isize, &ihigh) != 0)
+ return NULL;
+ return (*tp->tp_as_sequence->sq_slice)(u, ilow, ihigh);
+}
+
+static int
+assign_subscript(w, key, v) /* w[key] = v */
+ object *w;
+ object *key;
+ object *v;
+{
+ typeobject *tp = w->ob_type;
+ sequence_methods *sq;
+ mapping_methods *mp;
+ int (*func)();
+ if ((sq = tp->tp_as_sequence) != NULL &&
+ (func = sq->sq_ass_item) != NULL) {
+ if (!is_intobject(key)) {
+ err_setstr(TypeError,
+ "sequence subscript must be integer");
+ return -1;
+ }
+ else
+ return (*func)(w, (int)getintvalue(key), v);
+ }
+ else if ((mp = tp->tp_as_mapping) != NULL &&
+ (func = mp->mp_ass_subscript) != NULL) {
+ return (*func)(w, key, v);
+ }
+ else {
+ err_setstr(TypeError,
+ "can't assign to this subscripted object");
+ return -1;
+ }
+}
+
+static int
+assign_slice(u, v, w, x) /* u[v:w] = x */
+ object *u, *v, *w, *x;
+{
+ sequence_methods *sq = u->ob_type->tp_as_sequence;
+ int ilow, ihigh, isize;
+ if (sq == NULL) {
+ err_setstr(TypeError, "assign to slice of non-sequence");
+ return -1;
+ }
+ if (sq == NULL || sq->sq_ass_slice == NULL) {
+ err_setstr(TypeError, "unassignable slice");
+ return -1;
+ }
+ ilow = 0;
+ isize = ihigh = (*sq->sq_length)(u);
+ if (slice_index(v, isize, &ilow) != 0)
+ return -1;
+ if (slice_index(w, isize, &ihigh) != 0)
+ return -1;
+ return (*sq->sq_ass_slice)(u, ilow, ihigh, x);
+}
+
+static int
+cmp_exception(err, v)
+ object *err, *v;
+{
+ if (is_tupleobject(v)) {
+ int i, n;
+ n = gettuplesize(v);
+ for (i = 0; i < n; i++) {
+ if (err == gettupleitem(v, i))
+ return 1;
+ }
+ return 0;
+ }
+ return err == v;
+}
+
+static int
+cmp_member(v, w)
+ object *v, *w;
+{
+ int i, n, cmp;
+ object *x;
+ sequence_methods *sq;
+ /* Special case for char in string */
+ if (is_stringobject(w)) {
+ register char *s, *end;
+ register char c;
+ if (!is_stringobject(v) || getstringsize(v) != 1) {
+ err_setstr(TypeError,
+ "string member test needs char left operand");
+ return -1;
+ }
+ c = getstringvalue(v)[0];
+ s = getstringvalue(w);
+ end = s + getstringsize(w);
+ while (s < end) {
+ if (c == *s++)
+ return 1;
+ }
+ return 0;
+ }
+ sq = w->ob_type->tp_as_sequence;
+ if (sq == NULL) {
+ err_setstr(TypeError,
+ "'in' or 'not in' needs sequence right argument");
+ return -1;
+ }
+ n = (*sq->sq_length)(w);
+ for (i = 0; i < n; i++) {
+ x = (*sq->sq_item)(w, i);
+ cmp = cmpobject(v, x);
+ XDECREF(x);
+ if (cmp == 0)
+ return 1;
+ }
+ return 0;
+}
+
+static object *
+cmp_outcome(op, v, w)
+ enum cmp_op op;
+ register object *v;
+ register object *w;
+{
+ register int cmp;
+ register int res = 0;
+ switch (op) {
+ case IS:
+ case IS_NOT:
+ res = (v == w);
+ if (op == IS_NOT)
+ res = !res;
+ break;
+ case IN:
+ case NOT_IN:
+ res = cmp_member(v, w);
+ if (res < 0)
+ return NULL;
+ if (op == NOT_IN)
+ res = !res;
+ break;
+ case EXC_MATCH:
+ res = cmp_exception(v, w);
+ break;
+ default:
+ cmp = cmpobject(v, w);
+ switch (op) {
+ case LT: res = cmp < 0; break;
+ case LE: res = cmp <= 0; break;
+ case EQ: res = cmp == 0; break;
+ case NE: res = cmp != 0; break;
+ case GT: res = cmp > 0; break;
+ case GE: res = cmp >= 0; break;
+ /* XXX no default? (res is initialized to 0 though) */
+ }
+ }
+ v = res ? True : False;
+ INCREF(v);
+ return v;
+}
+
+static int
+import_from(locals, v, name)
+ object *locals;
+ object *v;
+ char *name;
+{
+ object *w, *x;
+ w = getmoduledict(v);
+ if (name[0] == '*') {
+ int i;
+ int n = getdictsize(w);
+ for (i = 0; i < n; i++) {
+ name = getdictkey(w, i);
+ if (name == NULL || name[0] == '_')
+ continue;
+ x = dictlookup(w, name);
+ if (x == NULL) {
+ /* XXX can't happen? */
+ err_setstr(NameError, name);
+ return -1;
+ }
+ if (dictinsert(locals, name, x) != 0)
+ return -1;
+ }
+ return 0;
+ }
+ else {
+ x = dictlookup(w, name);
+ if (x == NULL) {
+ err_setstr(NameError, name);
+ return -1;
+ }
+ else
+ return dictinsert(locals, name, x);
+ }
+}
+
+static object *
+build_class(v, w)
+ object *v; /* None or tuple containing base classes */
+ object *w; /* dictionary */
+{
+ if (is_tupleobject(v)) {
+ int i;
+ for (i = gettuplesize(v); --i >= 0; ) {
+ object *x = gettupleitem(v, i);
+ if (!is_classobject(x)) {
+ err_setstr(TypeError,
+ "base is not a class object");
+ return NULL;
+ }
+ }
+ }
+ else {
+ v = NULL;
+ }
+ if (!is_dictobject(w)) {
+ err_setstr(SystemError, "build_class with non-dictionary");
+ return NULL;
+ }
+ return newclassobject(v, w);
+}
+
+
+/* Status code for main loop (reason for stack unwind) */
+
+enum why_code {
+ WHY_NOT, /* No error */
+ WHY_EXCEPTION, /* Exception occurred */
+ WHY_RERAISE, /* Exception re-raised by 'finally' */
+ WHY_RETURN, /* 'return' statement */
+ WHY_BREAK /* 'break' statement */
+};
+
+/* Interpreter main loop */
+
+object *
+eval_code(co, globals, locals, arg)
+ codeobject *co;
+ object *globals;
+ object *locals;
+ object *arg;
+{
+ register unsigned char *next_instr;
+ register int opcode; /* Current opcode */
+ register int oparg; /* Current opcode argument, if any */
+ register object **stack_pointer;
+ register enum why_code why; /* Reason for block stack unwind */
+ register int err; /* Error status -- nonzero if error */
+ register object *x; /* Result object -- NULL if error */
+ register object *v; /* Temporary objects popped off stack */
+ register object *w;
+ register object *u;
+ register object *t;
+ register frameobject *f; /* Current frame */
+ int lineno; /* Current line number */
+ object *retval; /* Return value iff why == WHY_RETURN */
+ char *name; /* Name used by some instructions */
+ FILE *fp; /* Used by print operations */
+#ifdef TRACE
+ int trace = dictlookup(globals, "__trace__") != NULL;
+#endif
+
+/* Code access macros */
+
+#define GETCONST(i) Getconst(f, i)
+#define GETNAME(i) Getname(f, i)
+#define FIRST_INSTR() (GETUSTRINGVALUE(f->f_code->co_code))
+#define INSTR_OFFSET() (next_instr - FIRST_INSTR())
+#define NEXTOP() (*next_instr++)
+#define NEXTARG() (next_instr += 2, (next_instr[-1]<<8) + next_instr[-2])
+#define JUMPTO(x) (next_instr = FIRST_INSTR() + (x))
+#define JUMPBY(x) (next_instr += (x))
+
+/* Stack manipulation macros */
+
+#define STACK_LEVEL() (stack_pointer - f->f_valuestack)
+#define EMPTY() (STACK_LEVEL() == 0)
+#define TOP() (stack_pointer[-1])
+#define BASIC_PUSH(v) (*stack_pointer++ = (v))
+#define BASIC_POP() (*--stack_pointer)
+
+#ifdef TRACE
+#define PUSH(v) (BASIC_PUSH(v), trace && prtrace(TOP(), "push"))
+#define POP() (trace && prtrace(TOP(), "pop"), BASIC_POP())
+#else
+#define PUSH(v) BASIC_PUSH(v)
+#define POP() BASIC_POP()
+#endif
+
+ f = newframeobject(
+ current_frame, /*back*/
+ co, /*code*/
+ globals, /*globals*/
+ locals, /*locals*/
+ 50, /*nvalues*/
+ 20); /*nblocks*/
+ if (f == NULL)
+ return NULL;
+
+ current_frame = f;
+
+ next_instr = GETUSTRINGVALUE(f->f_code->co_code);
+
+ stack_pointer = f->f_valuestack;
+
+ if (arg != NULL) {
+ INCREF(arg);
+ PUSH(arg);
+ }
+
+ why = WHY_NOT;
+ err = 0;
+ x = None; /* Not a reference, just anything non-NULL */
+ lineno = -1;
+
+ for (;;) {
+ static ticker;
+
+ /* Do periodic things */
+
+ if (--ticker < 0) {
+ ticker = 100;
+ if (intrcheck()) {
+ err_set(KeyboardInterrupt);
+ why = WHY_EXCEPTION;
+ tb_here(f, INSTR_OFFSET(), lineno);
+ break;
+ }
+ }
+
+ /* Extract opcode and argument */
+
+ opcode = NEXTOP();
+ if (HAS_ARG(opcode))
+ oparg = NEXTARG();
+
+#ifdef TRACE
+ /* Instruction tracing */
+
+ if (trace) {
+ if (HAS_ARG(opcode)) {
+ printf("%d: %d, %d\n",
+ (int) (INSTR_OFFSET() - 3),
+ opcode, oparg);
+ }
+ else {
+ printf("%d: %d\n",
+ (int) (INSTR_OFFSET() - 1), opcode);
+ }
+ }
+#endif
+
+ /* Main switch on opcode */
+
+ switch (opcode) {
+
+ /* BEWARE!
+ It is essential that any operation that fails sets either
+ x to NULL, err to nonzero, or why to anything but WHY_NOT,
+ and that no operation that succeeds does this! */
+
+ /* case STOP_CODE: this is an error! */
+
+ case POP_TOP:
+ v = POP();
+ DECREF(v);
+ break;
+
+ case ROT_TWO:
+ v = POP();
+ w = POP();
+ PUSH(v);
+ PUSH(w);
+ break;
+
+ case ROT_THREE:
+ v = POP();
+ w = POP();
+ x = POP();
+ PUSH(v);
+ PUSH(x);
+ PUSH(w);
+ break;
+
+ case DUP_TOP:
+ v = TOP();
+ INCREF(v);
+ PUSH(v);
+ break;
+
+ case UNARY_POSITIVE:
+ v = POP();
+ x = pos(v);
+ DECREF(v);
+ PUSH(x);
+ break;
+
+ case UNARY_NEGATIVE:
+ v = POP();
+ x = neg(v);
+ DECREF(v);
+ PUSH(x);
+ break;
+
+ case UNARY_NOT:
+ v = POP();
+ x = not(v);
+ DECREF(v);
+ PUSH(x);
+ break;
+
+ case UNARY_CONVERT:
+ v = POP();
+ x = reprobject(v);
+ DECREF(v);
+ PUSH(x);
+ break;
+
+ case UNARY_CALL:
+ v = POP();
+ if (is_classmethodobject(v) || is_funcobject(v))
+ x = call_function(v, (object *)NULL);
+ else
+ x = call_builtin(v, (object *)NULL);
+ DECREF(v);
+ PUSH(x);
+ break;
+
+ case BINARY_MULTIPLY:
+ w = POP();
+ v = POP();
+ x = mul(v, w);
+ DECREF(v);
+ DECREF(w);
+ PUSH(x);
+ break;
+
+ case BINARY_DIVIDE:
+ w = POP();
+ v = POP();
+ x = divide(v, w);
+ DECREF(v);
+ DECREF(w);
+ PUSH(x);
+ break;
+
+ case BINARY_MODULO:
+ w = POP();
+ v = POP();
+ x = rem(v, w);
+ DECREF(v);
+ DECREF(w);
+ PUSH(x);
+ break;
+
+ case BINARY_ADD:
+ w = POP();
+ v = POP();
+ x = add(v, w);
+ DECREF(v);
+ DECREF(w);
+ PUSH(x);
+ break;
+
+ case BINARY_SUBTRACT:
+ w = POP();
+ v = POP();
+ x = sub(v, w);
+ DECREF(v);
+ DECREF(w);
+ PUSH(x);
+ break;
+
+ case BINARY_SUBSCR:
+ w = POP();
+ v = POP();
+ x = apply_subscript(v, w);
+ DECREF(v);
+ DECREF(w);
+ PUSH(x);
+ break;
+
+ case BINARY_CALL:
+ w = POP();
+ v = POP();
+ if (is_classmethodobject(v) || is_funcobject(v))
+ x = call_function(v, w);
+ else
+ x = call_builtin(v, w);
+ DECREF(v);
+ DECREF(w);
+ PUSH(x);
+ break;
+
+ case SLICE+0:
+ case SLICE+1:
+ case SLICE+2:
+ case SLICE+3:
+ if ((opcode-SLICE) & 2)
+ w = POP();
+ else
+ w = NULL;
+ if ((opcode-SLICE) & 1)
+ v = POP();
+ else
+ v = NULL;
+ u = POP();
+ x = apply_slice(u, v, w);
+ DECREF(u);
+ XDECREF(v);
+ XDECREF(w);
+ PUSH(x);
+ break;
+
+ case STORE_SLICE+0:
+ case STORE_SLICE+1:
+ case STORE_SLICE+2:
+ case STORE_SLICE+3:
+ if ((opcode-STORE_SLICE) & 2)
+ w = POP();
+ else
+ w = NULL;
+ if ((opcode-STORE_SLICE) & 1)
+ v = POP();
+ else
+ v = NULL;
+ u = POP();
+ t = POP();
+ err = assign_slice(u, v, w, t); /* u[v:w] = t */
+ DECREF(t);
+ DECREF(u);
+ XDECREF(v);
+ XDECREF(w);
+ break;
+
+ case DELETE_SLICE+0:
+ case DELETE_SLICE+1:
+ case DELETE_SLICE+2:
+ case DELETE_SLICE+3:
+ if ((opcode-DELETE_SLICE) & 2)
+ w = POP();
+ else
+ w = NULL;
+ if ((opcode-DELETE_SLICE) & 1)
+ v = POP();
+ else
+ v = NULL;
+ u = POP();
+ err = assign_slice(u, v, w, (object *)NULL);
+ /* del u[v:w] */
+ DECREF(u);
+ XDECREF(v);
+ XDECREF(w);
+ break;
+
+ case STORE_SUBSCR:
+ w = POP();
+ v = POP();
+ u = POP();
+ /* v[w] = u */
+ err = assign_subscript(v, w, u);
+ DECREF(u);
+ DECREF(v);
+ DECREF(w);
+ break;
+
+ case DELETE_SUBSCR:
+ w = POP();
+ v = POP();
+ /* del v[w] */
+ err = assign_subscript(v, w, (object *)NULL);
+ DECREF(v);
+ DECREF(w);
+ break;
+
+ case PRINT_EXPR:
+ v = POP();
+ fp = sysgetfile("stdout", stdout);
+ /* Print value except if procedure result */
+ if (v != None) {
+ flushline();
+ printobject(v, fp, 0);
+ fprintf(fp, "\n");
+ }
+ DECREF(v);
+ break;
+
+ case PRINT_ITEM:
+ v = POP();
+ fp = sysgetfile("stdout", stdout);
+ if (needspace)
+ fprintf(fp, " ");
+ if (is_stringobject(v)) {
+ char *s = getstringvalue(v);
+ int len = getstringsize(v);
+ fwrite(s, 1, len, fp);
+ if (len > 0 && s[len-1] == '\n')
+ needspace = 0;
+ else
+ needspace = 1;
+ }
+ else {
+ printobject(v, fp, 0);
+ needspace = 1;
+ }
+ DECREF(v);
+ break;
+
+ case PRINT_NEWLINE:
+ fp = sysgetfile("stdout", stdout);
+ fprintf(fp, "\n");
+ needspace = 0;
+ break;
+
+ case BREAK_LOOP:
+ why = WHY_BREAK;
+ break;
+
+ case RAISE_EXCEPTION:
+ v = POP();
+ w = POP();
+ if (!is_stringobject(w))
+ err_setstr(TypeError,
+ "exceptions must be strings");
+ else
+ err_setval(w, v);
+ DECREF(v);
+ DECREF(w);
+ why = WHY_EXCEPTION;
+ break;
+
+ case LOAD_LOCALS:
+ v = f->f_locals;
+ INCREF(v);
+ PUSH(v);
+ break;
+
+ case RETURN_VALUE:
+ retval = POP();
+ why = WHY_RETURN;
+ break;
+
+ case REQUIRE_ARGS:
+ if (EMPTY()) {
+ err_setstr(TypeError,
+ "function expects argument(s)");
+ why = WHY_EXCEPTION;
+ }
+ break;
+
+ case REFUSE_ARGS:
+ if (!EMPTY()) {
+ err_setstr(TypeError,
+ "function expects no argument(s)");
+ why = WHY_EXCEPTION;
+ }
+ break;
+
+ case BUILD_FUNCTION:
+ v = POP();
+ x = newfuncobject(v, f->f_globals);
+ DECREF(v);
+ PUSH(x);
+ break;
+
+ case POP_BLOCK:
+ {
+ block *b = pop_block(f);
+ while (STACK_LEVEL() > b->b_level) {
+ v = POP();
+ DECREF(v);
+ }
+ }
+ break;
+
+ case END_FINALLY:
+ v = POP();
+ if (is_intobject(v)) {
+ why = (enum why_code) getintvalue(v);
+ if (why == WHY_RETURN)
+ retval = POP();
+ }
+ else if (is_stringobject(v)) {
+ w = POP();
+ err_setval(v, w);
+ DECREF(w);
+ w = POP();
+ tb_store(w);
+ DECREF(w);
+ why = WHY_RERAISE;
+ }
+ else if (v != None) {
+ err_setstr(SystemError,
+ "'finally' pops bad exception");
+ why = WHY_EXCEPTION;
+ }
+ DECREF(v);
+ break;
+
+ case BUILD_CLASS:
+ w = POP();
+ v = POP();
+ x = build_class(v, w);
+ PUSH(x);
+ DECREF(v);
+ DECREF(w);
+ break;
+
+ case STORE_NAME:
+ name = GETNAME(oparg);
+ v = POP();
+ err = dictinsert(f->f_locals, name, v);
+ DECREF(v);
+ break;
+
+ case DELETE_NAME:
+ name = GETNAME(oparg);
+ if ((err = dictremove(f->f_locals, name)) != 0)
+ err_setstr(NameError, name);
+ break;
+
+ case UNPACK_TUPLE:
+ v = POP();
+ if (!is_tupleobject(v)) {
+ err_setstr(TypeError, "unpack non-tuple");
+ why = WHY_EXCEPTION;
+ }
+ else if (gettuplesize(v) != oparg) {
+ err_setstr(RuntimeError,
+ "unpack tuple of wrong size");
+ why = WHY_EXCEPTION;
+ }
+ else {
+ for (; --oparg >= 0; ) {
+ w = gettupleitem(v, oparg);
+ INCREF(w);
+ PUSH(w);
+ }
+ }
+ DECREF(v);
+ break;
+
+ case UNPACK_LIST:
+ v = POP();
+ if (!is_listobject(v)) {
+ err_setstr(TypeError, "unpack non-list");
+ why = WHY_EXCEPTION;
+ }
+ else if (getlistsize(v) != oparg) {
+ err_setstr(RuntimeError,
+ "unpack list of wrong size");
+ why = WHY_EXCEPTION;
+ }
+ else {
+ for (; --oparg >= 0; ) {
+ w = getlistitem(v, oparg);
+ INCREF(w);
+ PUSH(w);
+ }
+ }
+ DECREF(v);
+ break;
+
+ case STORE_ATTR:
+ name = GETNAME(oparg);
+ v = POP();
+ u = POP();
+ err = setattr(v, name, u); /* v.name = u */
+ DECREF(v);
+ DECREF(u);
+ break;
+
+ case DELETE_ATTR:
+ name = GETNAME(oparg);
+ v = POP();
+ err = setattr(v, name, (object *)NULL);
+ /* del v.name */
+ DECREF(v);
+ break;
+
+ case LOAD_CONST:
+ x = GETCONST(oparg);
+ INCREF(x);
+ PUSH(x);
+ break;
+
+ case LOAD_NAME:
+ name = GETNAME(oparg);
+ x = dictlookup(f->f_locals, name);
+ if (x == NULL) {
+ x = dictlookup(f->f_globals, name);
+ if (x == NULL)
+ x = getbuiltin(name);
+ }
+ if (x == NULL)
+ err_setstr(NameError, name);
+ else
+ INCREF(x);
+ PUSH(x);
+ break;
+
+ case BUILD_TUPLE:
+ x = newtupleobject(oparg);
+ if (x != NULL) {
+ for (; --oparg >= 0;) {
+ w = POP();
+ err = settupleitem(x, oparg, w);
+ if (err != 0)
+ break;
+ }
+ PUSH(x);
+ }
+ break;
+
+ case BUILD_LIST:
+ x = newlistobject(oparg);
+ if (x != NULL) {
+ for (; --oparg >= 0;) {
+ w = POP();
+ err = setlistitem(x, oparg, w);
+ if (err != 0)
+ break;
+ }
+ PUSH(x);
+ }
+ break;
+
+ case BUILD_MAP:
+ x = newdictobject();
+ PUSH(x);
+ break;
+
+ case LOAD_ATTR:
+ name = GETNAME(oparg);
+ v = POP();
+ x = getattr(v, name);
+ DECREF(v);
+ PUSH(x);
+ break;
+
+ case COMPARE_OP:
+ w = POP();
+ v = POP();
+ x = cmp_outcome((enum cmp_op)oparg, v, w);
+ DECREF(v);
+ DECREF(w);
+ PUSH(x);
+ break;
+
+ case IMPORT_NAME:
+ name = GETNAME(oparg);
+ x = import_module(name);
+ XINCREF(x);
+ PUSH(x);
+ break;
+
+ case IMPORT_FROM:
+ name = GETNAME(oparg);
+ v = TOP();
+ err = import_from(f->f_locals, v, name);
+ break;
+
+ case JUMP_FORWARD:
+ JUMPBY(oparg);
+ break;
+
+ case JUMP_IF_FALSE:
+ if (!testbool(TOP()))
+ JUMPBY(oparg);
+ break;
+
+ case JUMP_IF_TRUE:
+ if (testbool(TOP()))
+ JUMPBY(oparg);
+ break;
+
+ case JUMP_ABSOLUTE:
+ JUMPTO(oparg);
+ break;
+
+ case FOR_LOOP:
+ /* for v in s: ...
+ On entry: stack contains s, i.
+ On exit: stack contains s, i+1, s[i];
+ but if loop exhausted:
+ s, i are popped, and we jump */
+ w = POP(); /* Loop index */
+ v = POP(); /* Sequence object */
+ u = loop_subscript(v, w);
+ if (u != NULL) {
+ PUSH(v);
+ x = newintobject(getintvalue(w)+1);
+ PUSH(x);
+ DECREF(w);
+ PUSH(u);
+ }
+ else {
+ DECREF(v);
+ DECREF(w);
+ /* A NULL can mean "s exhausted"
+ but also an error: */
+ if (err_occurred())
+ why = WHY_EXCEPTION;
+ else
+ JUMPBY(oparg);
+ }
+ break;
+
+ case SETUP_LOOP:
+ case SETUP_EXCEPT:
+ case SETUP_FINALLY:
+ setup_block(f, opcode, INSTR_OFFSET() + oparg,
+ STACK_LEVEL());
+ break;
+
+ case SET_LINENO:
+#ifdef TRACE
+ if (trace)
+ printf("--- Line %d ---\n", oparg);
+#endif
+ lineno = oparg;
+ break;
+
+ default:
+ fprintf(stderr,
+ "XXX lineno: %d, opcode: %d\n",
+ lineno, opcode);
+ err_setstr(SystemError, "eval_code: unknown opcode");
+ why = WHY_EXCEPTION;
+ break;
+
+ } /* switch */
+
+
+ /* Quickly continue if no error occurred */
+
+ if (why == WHY_NOT) {
+ if (err == 0 && x != NULL)
+ continue; /* Normal, fast path */
+ why = WHY_EXCEPTION;
+ x = None;
+ err = 0;
+ }
+
+#ifndef NDEBUG
+ /* Double-check exception status */
+
+ if (why == WHY_EXCEPTION || why == WHY_RERAISE) {
+ if (!err_occurred()) {
+ fprintf(stderr, "XXX ghost error\n");
+ err_setstr(SystemError, "ghost error");
+ why = WHY_EXCEPTION;
+ }
+ }
+ else {
+ if (err_occurred()) {
+ fprintf(stderr, "XXX undetected error\n");
+ why = WHY_EXCEPTION;
+ }
+ }
+#endif
+
+ /* Log traceback info if this is a real exception */
+
+ if (why == WHY_EXCEPTION) {
+ int lasti = INSTR_OFFSET() - 1;
+ if (HAS_ARG(opcode))
+ lasti -= 2;
+ tb_here(f, lasti, lineno);
+ }
+
+ /* For the rest, treat WHY_RERAISE as WHY_EXCEPTION */
+
+ if (why == WHY_RERAISE)
+ why = WHY_EXCEPTION;
+
+ /* Unwind stacks if a (pseudo) exception occurred */
+
+ while (why != WHY_NOT && f->f_iblock > 0) {
+ block *b = pop_block(f);
+ while (STACK_LEVEL() > b->b_level) {
+ v = POP();
+ XDECREF(v);
+ }
+ if (b->b_type == SETUP_LOOP && why == WHY_BREAK) {
+ why = WHY_NOT;
+ JUMPTO(b->b_handler);
+ break;
+ }
+ if (b->b_type == SETUP_FINALLY ||
+ b->b_type == SETUP_EXCEPT &&
+ why == WHY_EXCEPTION) {
+ if (why == WHY_EXCEPTION) {
+ object *exc, *val;
+ err_get(&exc, &val);
+ if (val == NULL) {
+ val = None;
+ INCREF(val);
+ }
+ v = tb_fetch();
+ /* Make the raw exception data
+ available to the handler,
+ so a program can emulate the
+ Python main loop. Don't do
+ this for 'finally'. */
+ if (b->b_type == SETUP_EXCEPT) {
+#if 0 /* Oops, this breaks too many things */
+ sysset("exc_traceback", v);
+#endif
+ sysset("exc_value", val);
+ sysset("exc_type", exc);
+ err_clear();
+ }
+ PUSH(v);
+ PUSH(val);
+ PUSH(exc);
+ }
+ else {
+ if (why == WHY_RETURN)
+ PUSH(retval);
+ v = newintobject((long)why);
+ PUSH(v);
+ }
+ why = WHY_NOT;
+ JUMPTO(b->b_handler);
+ break;
+ }
+ } /* unwind stack */
+
+ /* End the loop if we still have an error (or return) */
+
+ if (why != WHY_NOT)
+ break;
+
+ } /* main loop */
+
+ /* Pop remaining stack entries */
+
+ while (!EMPTY()) {
+ v = POP();
+ XDECREF(v);
+ }
+
+ /* Restore previous frame and release the current one */
+
+ current_frame = f->f_back;
+ DECREF(f);
+
+ if (why == WHY_RETURN)
+ return retval;
+ else
+ return NULL;
+}
diff --git a/src/ceval.h b/src/ceval.h
new file mode 100644
index 0000000..7f57738
--- /dev/null
+++ b/src/ceval.h
@@ -0,0 +1,33 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* Interface to execute compiled code */
+/* This header depends on "compile.h" */
+
+object *eval_code PROTO((codeobject *, object *, object *, object *));
+
+object *getglobals PROTO((void));
+object *getlocals PROTO((void));
+
+void printtraceback PROTO((FILE *));
diff --git a/src/cgen b/src/cgen
new file mode 100644
index 0000000..c2f0d0c
--- /dev/null
+++ b/src/cgen
@@ -0,0 +1,458 @@
+# Python script to parse cstubs file for gl and generate C stubs.
+# usage: python cgen <cstubs >glmodule.c
+#
+# XXX BUG return arrays generate wrong code
+# XXX need to change error returns into gotos to free mallocked arrays
+
+
+import string
+import sys
+
+
+# Function to print to stderr
+#
+def err(args):
+ savestdout = sys.stdout
+ try:
+ sys.stdout = sys.stderr
+ for i in args:
+ print i,
+ print
+ finally:
+ sys.stdout = savestdout
+
+
+# The set of digits that form a number
+#
+digits = '0123456789'
+
+
+# Function to extract a string of digits from the front of the string.
+# Returns the leading string of digits and the remaining string.
+# If no number is found, returns '' and the original string.
+#
+def getnum(s):
+ n = ''
+ while s and s[0] in digits:
+ n = n + s[0]
+ s = s[1:]
+ return n, s
+
+
+# Function to check if a string is a number
+#
+def isnum(s):
+ if not s: return 0
+ for c in s:
+ if not c in digits: return 0
+ return 1
+
+
+# Allowed function return types
+#
+return_types = ['void', 'short', 'long']
+
+
+# Allowed function argument types
+#
+arg_types = ['char', 'string', 'short', 'float', 'long', 'double']
+
+
+# Need to classify arguments as follows
+# simple input variable
+# simple output variable
+# input array
+# output array
+# input giving size of some array
+#
+# Array dimensions can be specified as follows
+# constant
+# argN
+# constant * argN
+# retval
+# constant * retval
+#
+# The dimensions given as constants * something are really
+# arrays of points where points are 2- 3- or 4-tuples
+#
+# We have to consider three lists:
+# python input arguments
+# C stub arguments (in & out)
+# python output arguments (really return values)
+#
+# There is a mapping from python input arguments to the input arguments
+# of the C stub, and a further mapping from C stub arguments to the
+# python return values
+
+
+# Exception raised by checkarg() and generate()
+#
+arg_error = 'bad arg'
+
+
+# Function to check one argument.
+# Arguments: the type and the arg "name" (really mode plus subscript).
+# Raises arg_error if something's wrong.
+# Return type, mode, factor, rest of subscript; factor and rest may be empty.
+#
+def checkarg(type, arg):
+ #
+ # Turn "char *x" into "string x".
+ #
+ if type = 'char' and arg[0] = '*':
+ type = 'string'
+ arg = arg[1:]
+ #
+ # Check that the type is supported.
+ #
+ if type not in arg_types:
+ raise arg_error, ('bad type', type)
+ #
+ # Split it in the mode (first character) and the rest.
+ #
+ mode, rest = arg[:1], arg[1:]
+ #
+ # The mode must be 's' for send (= input) or 'r' for return argument.
+ #
+ if mode not in ('r', 's'):
+ raise arg_error, ('bad arg mode', mode)
+ #
+ # Is it a simple argument: if so, we are done.
+ #
+ if not rest:
+ return type, mode, '', ''
+ #
+ # Not a simple argument; must be an array.
+ # The 'rest' must be a subscript enclosed in [ and ].
+ # The subscript must be one of the following forms,
+ # otherwise we don't handle it (where N is a number):
+ # N
+ # argN
+ # retval
+ # N*argN
+ # N*retval
+ #
+ if rest[:1] <> '[' or rest[-1:] <> ']':
+ raise arg_error, ('subscript expected', rest)
+ sub = rest[1:-1]
+ #
+ # Is there a leading number?
+ #
+ num, sub = getnum(sub)
+ if num:
+ # There is a leading number
+ if not sub:
+ # The subscript is just a number
+ return type, mode, num, ''
+ if sub[:1] = '*':
+ # There is a factor prefix
+ sub = sub[1:]
+ else:
+ raise arg_error, ('\'*\' expected', sub)
+ if sub = 'retval':
+ # size is retval -- must be a reply argument
+ if mode <> 'r':
+ raise arg_error, ('non-r mode with [retval]', mode)
+ elif sub[:3] <> 'arg' or not isnum(sub[3:]):
+ raise arg_error, ('bad subscript', sub)
+ #
+ return type, mode, num, sub
+
+
+# List of functions for which we have generated stubs
+#
+functions = []
+
+
+# Generate the stub for the given function, using the database of argument
+# information build by successive calls to checkarg()
+#
+def generate(type, func, database):
+ #
+ # Check that we can handle this case:
+ # no variable size reply arrays yet
+ #
+ n_in_args = 0
+ n_out_args = 0
+ #
+ for a_type, a_mode, a_factor, a_sub in database:
+ if a_mode = 's':
+ n_in_args = n_in_args + 1
+ elif a_mode = 'r':
+ n_out_args = n_out_args + 1
+ else:
+ # Can't happen
+ raise arg_error, ('bad a_mode', a_mode)
+ if (a_mode = 'r' and a_sub) or a_sub = 'retval':
+ e = 'Function', func, 'too complicated:'
+ err(e + (a_type, a_mode, a_factor, a_sub))
+ print '/* XXX Too complicated to generate code for */'
+ return
+ #
+ functions.append(func)
+ #
+ # Stub header
+ #
+ print
+ print 'static object *'
+ print 'gl_' + func + '(self, args)'
+ print '\tobject *self;'
+ print '\tobject *args;'
+ print '{'
+ #
+ # Declare return value if any
+ #
+ if type <> 'void':
+ print '\t' + type, 'retval;'
+ #
+ # Declare arguments
+ #
+ for i in range(len(database)):
+ a_type, a_mode, a_factor, a_sub = database[i]
+ print '\t' + a_type,
+ if a_sub:
+ print '*',
+ print 'arg' + `i+1`,
+ if a_factor and not a_sub:
+ print '[', a_factor, ']',
+ print ';'
+ #
+ # Find input arguments derived from array sizes
+ #
+ for i in range(len(database)):
+ a_type, a_mode, a_factor, a_sub = database[i]
+ if a_mode = 's' and a_sub[:3] = 'arg' and isnum(a_sub[3:]):
+ # Sending a variable-length array
+ n = eval(a_sub[3:])
+ if 1 <= n <= len(database):
+ b_type, b_mode, b_factor, b_sub = database[n-1]
+ if b_mode = 's':
+ database[n-1] = b_type, 'i', a_factor, `i`
+ n_in_args = n_in_args - 1
+ #
+ # Assign argument positions in the Python argument list
+ #
+ in_pos = []
+ i_in = 0
+ for i in range(len(database)):
+ a_type, a_mode, a_factor, a_sub = database[i]
+ if a_mode = 's':
+ in_pos.append(i_in)
+ i_in = i_in + 1
+ else:
+ in_pos.append(-1)
+ #
+ # Get input arguments
+ #
+ for i in range(len(database)):
+ a_type, a_mode, a_factor, a_sub = database[i]
+ if a_mode = 'i':
+ #
+ # Implicit argument;
+ # a_factor is divisor if present,
+ # a_sub indicates which arg (`database index`)
+ #
+ j = eval(a_sub)
+ print '\tif',
+ print '(!geti' + a_type + 'arraysize(args,',
+ print `n_in_args` + ',',
+ print `in_pos[j]` + ',',
+ print '&arg' + `i+1` + '))'
+ print '\t\treturn NULL;'
+ if a_factor:
+ print '\targ' + `i+1`,
+ print '= arg' + `i+1`,
+ print '/', a_factor + ';'
+ elif a_mode = 's':
+ if a_sub: # Allocate memory for varsize array
+ print '\tif ((arg' + `i+1`, '=',
+ print 'NEW(' + a_type + ',',
+ if a_factor: print a_factor, '*',
+ print a_sub, ')) == NULL)'
+ print '\t\treturn err_nomem();'
+ print '\tif',
+ if a_factor or a_sub: # Get a fixed-size array array
+ print '(!geti' + a_type + 'array(args,',
+ print `n_in_args` + ',',
+ print `in_pos[i]` + ',',
+ if a_factor: print a_factor,
+ if a_factor and a_sub: print '*',
+ if a_sub: print a_sub,
+ print ', arg' + `i+1` + '))'
+ else: # Get a simple variable
+ print '(!geti' + a_type + 'arg(args,',
+ print `n_in_args` + ',',
+ print `in_pos[i]` + ',',
+ print '&arg' + `i+1` + '))'
+ print '\t\treturn NULL;'
+ #
+ # Begin of function call
+ #
+ if type <> 'void':
+ print '\tretval =', func + '(',
+ else:
+ print '\t' + func + '(',
+ #
+ # Argument list
+ #
+ for i in range(len(database)):
+ if i > 0: print ',',
+ a_type, a_mode, a_factor, a_sub = database[i]
+ if a_mode = 'r' and not a_factor:
+ print '&',
+ print 'arg' + `i+1`,
+ #
+ # End of function call
+ #
+ print ');'
+ #
+ # Free varsize arrays
+ #
+ for i in range(len(database)):
+ a_type, a_mode, a_factor, a_sub = database[i]
+ if a_mode = 's' and a_sub:
+ print '\tDEL(arg' + `i+1` + ');'
+ #
+ # Return
+ #
+ if n_out_args:
+ #
+ # Multiple return values -- construct a tuple
+ #
+ if type <> 'void':
+ n_out_args = n_out_args + 1
+ if n_out_args = 1:
+ for i in range(len(database)):
+ a_type, a_mode, a_factor, a_sub = database[i]
+ if a_mode = 'r':
+ break
+ else:
+ raise arg_error, 'expected r arg not found'
+ print '\treturn',
+ print mkobject(a_type, 'arg' + `i+1`) + ';'
+ else:
+ print '\t{ object *v = newtupleobject(',
+ print n_out_args, ');'
+ print '\t if (v == NULL) return NULL;'
+ i_out = 0
+ if type <> 'void':
+ print '\t settupleitem(v,',
+ print `i_out` + ',',
+ print mkobject(type, 'retval') + ');'
+ i_out = i_out + 1
+ for i in range(len(database)):
+ a_type, a_mode, a_factor, a_sub = database[i]
+ if a_mode = 'r':
+ print '\t settupleitem(v,',
+ print `i_out` + ',',
+ s = mkobject(a_type, 'arg' + `i+1`)
+ print s + ');'
+ i_out = i_out + 1
+ print '\t return v;'
+ print '\t}'
+ else:
+ #
+ # Simple function return
+ # Return None or return value
+ #
+ if type = 'void':
+ print '\tINCREF(None);'
+ print '\treturn None;'
+ else:
+ print '\treturn', mkobject(type, 'retval') + ';'
+ #
+ # Stub body closing brace
+ #
+ print '}'
+
+
+# Subroutine to return a function call to mknew<type>object(<arg>)
+#
+def mkobject(type, arg):
+ return 'mknew' + type + 'object(' + arg + ')'
+
+
+# Input line number
+lno = 0
+
+
+# Input is divided in two parts, separated by a line containing '%%'.
+# <part1> -- literally copied to stdout
+# <part2> -- stub definitions
+
+# Variable indicating the current input part.
+#
+part = 1
+
+# Main loop over the input
+#
+while 1:
+ try:
+ line = raw_input()
+ except EOFError:
+ break
+ #
+ lno = lno+1
+ words = string.split(line)
+ #
+ if part = 1:
+ #
+ # In part 1, copy everything literally
+ # except look for a line of just '%%'
+ #
+ if words = ['%%']:
+ part = part + 1
+ else:
+ #
+ # Look for names of manually written
+ # stubs: a single percent followed by the name
+ # of the function in Python.
+ # The stub name is derived by prefixing 'gl_'.
+ #
+ if words and words[0][0] = '%':
+ func = words[0][1:]
+ if (not func) and words[1:]:
+ func = words[1]
+ if func:
+ functions.append(func)
+ else:
+ print line
+ elif not words:
+ pass # skip empty line
+ elif words[0] = '#include':
+ print line
+ elif words[0][:1] = '#':
+ pass # ignore comment
+ elif words[0] not in return_types:
+ err('Line', lno, ': bad return type :', words[0])
+ elif len(words) < 2:
+ err('Line', lno, ': no funcname :', line)
+ else:
+ if len(words) % 2 <> 0:
+ err('Line', lno, ': odd argument list :', words[2:])
+ else:
+ database = []
+ try:
+ for i in range(2, len(words), 2):
+ x = checkarg(words[i], words[i+1])
+ database.append(x)
+ print
+ print '/*',
+ for w in words: print w,
+ print '*/'
+ generate(words[0], words[1], database)
+ except arg_error, msg:
+ err('Line', lno, ':', msg)
+
+
+print
+print 'static struct methodlist gl_methods[] = {'
+for func in functions:
+ print '\t{"' + func + '", gl_' + func + '},'
+print '\t{NULL, NULL} /* Sentinel */'
+print '};'
+print
+print 'initgl()'
+print '{'
+print '\tinitmodule("gl", gl_methods);'
+print '}'
diff --git a/src/cgensupport.c b/src/cgensupport.c
new file mode 100644
index 0000000..91adb2a
--- /dev/null
+++ b/src/cgensupport.c
@@ -0,0 +1,393 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* Functions used by cgen output */
+
+#include <stdio.h>
+
+#include "PROTO.h"
+#include "object.h"
+#include "intobject.h"
+#include "floatobject.h"
+#include "stringobject.h"
+#include "tupleobject.h"
+#include "listobject.h"
+#include "methodobject.h"
+#include "moduleobject.h"
+#include "modsupport.h"
+#include "import.h"
+#include "cgensupport.h"
+#include "errors.h"
+
+
+/* Functions to construct return values */
+
+object *
+mknewcharobject(c)
+ int c;
+{
+ char ch[1];
+ ch[0] = c;
+ return newsizedstringobject(ch, 1);
+}
+
+/* Functions to extract arguments.
+ These needs to know the total number of arguments supplied,
+ since the argument list is a tuple only of there is more than
+ one argument. */
+
+int
+getiobjectarg(args, nargs, i, p_arg)
+ register object *args;
+ int nargs, i;
+ object **p_arg;
+{
+ if (nargs != 1) {
+ if (args == NULL || !is_tupleobject(args) ||
+ nargs != gettuplesize(args) ||
+ i < 0 || i >= nargs) {
+ return err_badarg();
+ }
+ else {
+ args = gettupleitem(args, i);
+ }
+ }
+ if (args == NULL) {
+ return err_badarg();
+ }
+ *p_arg = args;
+ return 1;
+}
+
+int
+getilongarg(args, nargs, i, p_arg)
+ register object *args;
+ int nargs, i;
+ long *p_arg;
+{
+ if (nargs != 1) {
+ if (args == NULL || !is_tupleobject(args) ||
+ nargs != gettuplesize(args) ||
+ i < 0 || i >= nargs) {
+ return err_badarg();
+ }
+ args = gettupleitem(args, i);
+ }
+ if (args == NULL || !is_intobject(args)) {
+ return err_badarg();
+ }
+ *p_arg = getintvalue(args);
+ return 1;
+}
+
+int
+getishortarg(args, nargs, i, p_arg)
+ register object *args;
+ int nargs, i;
+ short *p_arg;
+{
+ long x;
+ if (!getilongarg(args, nargs, i, &x))
+ return 0;
+ *p_arg = x;
+ return 1;
+}
+
+static int
+extractdouble(v, p_arg)
+ register object *v;
+ double *p_arg;
+{
+ if (v == NULL) {
+ /* Fall through to error return at end of function */
+ }
+ else if (is_floatobject(v)) {
+ *p_arg = GETFLOATVALUE((floatobject *)v);
+ return 1;
+ }
+ else if (is_intobject(v)) {
+ *p_arg = GETINTVALUE((intobject *)v);
+ return 1;
+ }
+ return err_badarg();
+}
+
+static int
+extractfloat(v, p_arg)
+ register object *v;
+ float *p_arg;
+{
+ if (v == NULL) {
+ /* Fall through to error return at end of function */
+ }
+ else if (is_floatobject(v)) {
+ *p_arg = GETFLOATVALUE((floatobject *)v);
+ return 1;
+ }
+ else if (is_intobject(v)) {
+ *p_arg = GETINTVALUE((intobject *)v);
+ return 1;
+ }
+ return err_badarg();
+}
+
+int
+getifloatarg(args, nargs, i, p_arg)
+ register object *args;
+ int nargs, i;
+ float *p_arg;
+{
+ object *v;
+ float x;
+ if (!getiobjectarg(args, nargs, i, &v))
+ return 0;
+ if (!extractfloat(v, &x))
+ return 0;
+ *p_arg = x;
+ return 1;
+}
+
+int
+getistringarg(args, nargs, i, p_arg)
+ object *args;
+ int nargs, i;
+ string *p_arg;
+{
+ object *v;
+ if (!getiobjectarg(args, nargs, i, &v))
+ return NULL;
+ if (!is_stringobject(v)) {
+ return err_badarg();
+ }
+ *p_arg = getstringvalue(v);
+ return 1;
+}
+
+int
+getichararg(args, nargs, i, p_arg)
+ object *args;
+ int nargs, i;
+ char *p_arg;
+{
+ string x;
+ if (!getistringarg(args, nargs, i, &x))
+ return 0;
+ if (x[0] == '\0' || x[1] != '\0') {
+ /* Not exactly one char */
+ return err_badarg();
+ }
+ *p_arg = x[0];
+ return 1;
+}
+
+int
+getilongarraysize(args, nargs, i, p_arg)
+ object *args;
+ int nargs, i;
+ long *p_arg;
+{
+ object *v;
+ if (!getiobjectarg(args, nargs, i, &v))
+ return 0;
+ if (is_tupleobject(v)) {
+ *p_arg = gettuplesize(v);
+ return 1;
+ }
+ if (is_listobject(v)) {
+ *p_arg = getlistsize(v);
+ return 1;
+ }
+ return err_badarg();
+}
+
+int
+getishortarraysize(args, nargs, i, p_arg)
+ object *args;
+ int nargs, i;
+ short *p_arg;
+{
+ long x;
+ if (!getilongarraysize(args, nargs, i, &x))
+ return 0;
+ *p_arg = x;
+ return 1;
+}
+
+/* XXX The following four are too similar. Should share more code. */
+
+int
+getilongarray(args, nargs, i, n, p_arg)
+ object *args;
+ int nargs, i;
+ int n;
+ long *p_arg; /* [n] */
+{
+ object *v, *w;
+ if (!getiobjectarg(args, nargs, i, &v))
+ return 0;
+ if (is_tupleobject(v)) {
+ if (gettuplesize(v) != n) {
+ return err_badarg();
+ }
+ for (i = 0; i < n; i++) {
+ w = gettupleitem(v, i);
+ if (!is_intobject(w)) {
+ return err_badarg();
+ }
+ p_arg[i] = getintvalue(w);
+ }
+ return 1;
+ }
+ else if (is_listobject(v)) {
+ if (getlistsize(v) != n) {
+ return err_badarg();
+ }
+ for (i = 0; i < n; i++) {
+ w = getlistitem(v, i);
+ if (!is_intobject(w)) {
+ return err_badarg();
+ }
+ p_arg[i] = getintvalue(w);
+ }
+ return 1;
+ }
+ else {
+ return err_badarg();
+ }
+}
+
+int
+getishortarray(args, nargs, i, n, p_arg)
+ object *args;
+ int nargs, i;
+ int n;
+ short *p_arg; /* [n] */
+{
+ object *v, *w;
+ if (!getiobjectarg(args, nargs, i, &v))
+ return 0;
+ if (is_tupleobject(v)) {
+ if (gettuplesize(v) != n) {
+ return err_badarg();
+ }
+ for (i = 0; i < n; i++) {
+ w = gettupleitem(v, i);
+ if (!is_intobject(w)) {
+ return err_badarg();
+ }
+ p_arg[i] = getintvalue(w);
+ }
+ return 1;
+ }
+ else if (is_listobject(v)) {
+ if (getlistsize(v) != n) {
+ return err_badarg();
+ }
+ for (i = 0; i < n; i++) {
+ w = getlistitem(v, i);
+ if (!is_intobject(w)) {
+ return err_badarg();
+ }
+ p_arg[i] = getintvalue(w);
+ }
+ return 1;
+ }
+ else {
+ return err_badarg();
+ }
+}
+
+int
+getidoublearray(args, nargs, i, n, p_arg)
+ object *args;
+ int nargs, i;
+ int n;
+ double *p_arg; /* [n] */
+{
+ object *v, *w;
+ if (!getiobjectarg(args, nargs, i, &v))
+ return 0;
+ if (is_tupleobject(v)) {
+ if (gettuplesize(v) != n) {
+ return err_badarg();
+ }
+ for (i = 0; i < n; i++) {
+ w = gettupleitem(v, i);
+ if (!extractdouble(w, &p_arg[i]))
+ return 0;
+ }
+ return 1;
+ }
+ else if (is_listobject(v)) {
+ if (getlistsize(v) != n) {
+ return err_badarg();
+ }
+ for (i = 0; i < n; i++) {
+ w = getlistitem(v, i);
+ if (!extractdouble(w, &p_arg[i]))
+ return 0;
+ }
+ return 1;
+ }
+ else {
+ return err_badarg();
+ }
+}
+
+int
+getifloatarray(args, nargs, i, n, p_arg)
+ object *args;
+ int nargs, i;
+ int n;
+ float *p_arg; /* [n] */
+{
+ object *v, *w;
+ if (!getiobjectarg(args, nargs, i, &v))
+ return 0;
+ if (is_tupleobject(v)) {
+ if (gettuplesize(v) != n) {
+ return err_badarg();
+ }
+ for (i = 0; i < n; i++) {
+ w = gettupleitem(v, i);
+ if (!extractfloat(w, &p_arg[i]))
+ return 0;
+ }
+ return 1;
+ }
+ else if (is_listobject(v)) {
+ if (getlistsize(v) != n) {
+ return err_badarg();
+ }
+ for (i = 0; i < n; i++) {
+ w = getlistitem(v, i);
+ if (!extractfloat(w, &p_arg[i]))
+ return 0;
+ }
+ return 1;
+ }
+ else {
+ return err_badarg();
+ }
+}
diff --git a/src/cgensupport.h b/src/cgensupport.h
new file mode 100644
index 0000000..a056f5d
--- /dev/null
+++ b/src/cgensupport.h
@@ -0,0 +1,39 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* Definitions used by cgen output */
+
+typedef char *string;
+
+#define mknewlongobject(x) newintobject(x)
+#define mknewshortobject(x) newintobject((long)x)
+#define mknewfloatobject(x) newfloatobject(x)
+
+extern object *mknewcharobject PROTO((int c));
+
+extern int getiobjectarg PROTO((object *args, int nargs, int i, object **p_a));
+extern int getilongarg PROTO((object *args, int nargs, int i, long *p_a));
+extern int getishortarg PROTO((object *args, int nargs, int i, short *p_a));
+extern int getifloatarg PROTO((object *args, int nargs, int i, float *p_a));
+extern int getistringarg PROTO((object *args, int nargs, int i, string *p_a));
diff --git a/src/classobject.c b/src/classobject.c
new file mode 100644
index 0000000..fc32889
--- /dev/null
+++ b/src/classobject.c
@@ -0,0 +1,298 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* Class object implementation */
+
+#include "allobjects.h"
+
+#include "structmember.h"
+
+typedef struct {
+ OB_HEAD
+ object *cl_bases; /* A tuple */
+ object *cl_methods; /* A dictionary */
+} classobject;
+
+object *
+newclassobject(bases, methods)
+ object *bases; /* NULL or tuple of classobjects! */
+ object *methods;
+{
+ classobject *op;
+ op = NEWOBJ(classobject, &Classtype);
+ if (op == NULL)
+ return NULL;
+ if (bases != NULL)
+ INCREF(bases);
+ op->cl_bases = bases;
+ INCREF(methods);
+ op->cl_methods = methods;
+ return (object *) op;
+}
+
+/* Class methods */
+
+static void
+class_dealloc(op)
+ classobject *op;
+{
+ int i;
+ if (op->cl_bases != NULL)
+ DECREF(op->cl_bases);
+ DECREF(op->cl_methods);
+ free((ANY *)op);
+}
+
+static object *
+class_getattr(op, name)
+ register classobject *op;
+ register char *name;
+{
+ register object *v;
+ v = dictlookup(op->cl_methods, name);
+ if (v != NULL) {
+ INCREF(v);
+ return v;
+ }
+ if (op->cl_bases != NULL) {
+ int n = gettuplesize(op->cl_bases);
+ int i;
+ for (i = 0; i < n; i++) {
+ v = class_getattr(gettupleitem(op->cl_bases, i), name);
+ if (v != NULL)
+ return v;
+ err_clear();
+ }
+ }
+ err_setstr(NameError, name);
+ return NULL;
+}
+
+typeobject Classtype = {
+ OB_HEAD_INIT(&Typetype)
+ 0,
+ "class",
+ sizeof(classobject),
+ 0,
+ class_dealloc, /*tp_dealloc*/
+ 0, /*tp_print*/
+ class_getattr, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+};
+
+
+/* We're not done yet: next, we define class member objects... */
+
+typedef struct {
+ OB_HEAD
+ classobject *cm_class; /* The class object */
+ object *cm_attr; /* A dictionary */
+} classmemberobject;
+
+object *
+newclassmemberobject(class)
+ register object *class;
+{
+ register classmemberobject *cm;
+ if (!is_classobject(class)) {
+ err_badcall();
+ return NULL;
+ }
+ cm = NEWOBJ(classmemberobject, &Classmembertype);
+ if (cm == NULL)
+ return NULL;
+ INCREF(class);
+ cm->cm_class = (classobject *)class;
+ cm->cm_attr = newdictobject();
+ if (cm->cm_attr == NULL) {
+ DECREF(cm);
+ return NULL;
+ }
+ return (object *)cm;
+}
+
+/* Class member methods */
+
+static void
+classmember_dealloc(cm)
+ register classmemberobject *cm;
+{
+ DECREF(cm->cm_class);
+ if (cm->cm_attr != NULL)
+ DECREF(cm->cm_attr);
+ free((ANY *)cm);
+}
+
+static object *
+classmember_getattr(cm, name)
+ register classmemberobject *cm;
+ register char *name;
+{
+ register object *v = dictlookup(cm->cm_attr, name);
+ if (v != NULL) {
+ INCREF(v);
+ return v;
+ }
+ v = class_getattr(cm->cm_class, name);
+ if (v == NULL)
+ return v; /* class_getattr() has set the error */
+ if (is_funcobject(v)) {
+ object *w = newclassmethodobject(v, (object *)cm);
+ DECREF(v);
+ return w;
+ }
+ DECREF(v);
+ err_setstr(NameError, name);
+ return NULL;
+}
+
+static int
+classmember_setattr(cm, name, v)
+ classmemberobject *cm;
+ char *name;
+ object *v;
+{
+ if (v == NULL)
+ return dictremove(cm->cm_attr, name);
+ else
+ return dictinsert(cm->cm_attr, name, v);
+}
+
+typeobject Classmembertype = {
+ OB_HEAD_INIT(&Typetype)
+ 0,
+ "class member",
+ sizeof(classmemberobject),
+ 0,
+ classmember_dealloc, /*tp_dealloc*/
+ 0, /*tp_print*/
+ classmember_getattr, /*tp_getattr*/
+ classmember_setattr, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+};
+
+
+/* And finally, here are class method objects */
+/* (Really methods of class members) */
+
+typedef struct {
+ OB_HEAD
+ object *cm_func; /* The method function */
+ object *cm_self; /* The object to which this applies */
+} classmethodobject;
+
+object *
+newclassmethodobject(func, self)
+ object *func;
+ object *self;
+{
+ register classmethodobject *cm;
+ if (!is_funcobject(func)) {
+ err_badcall();
+ return NULL;
+ }
+ cm = NEWOBJ(classmethodobject, &Classmethodtype);
+ if (cm == NULL)
+ return NULL;
+ INCREF(func);
+ cm->cm_func = func;
+ INCREF(self);
+ cm->cm_self = self;
+ return (object *)cm;
+}
+
+object *
+classmethodgetfunc(cm)
+ register object *cm;
+{
+ if (!is_classmethodobject(cm)) {
+ err_badcall();
+ return NULL;
+ }
+ return ((classmethodobject *)cm)->cm_func;
+}
+
+object *
+classmethodgetself(cm)
+ register object *cm;
+{
+ if (!is_classmethodobject(cm)) {
+ err_badcall();
+ return NULL;
+ }
+ return ((classmethodobject *)cm)->cm_self;
+}
+
+/* Class method methods */
+
+#define OFF(x) offsetof(classmethodobject, x)
+
+static struct memberlist classmethod_memberlist[] = {
+ {"cm_func", T_OBJECT, OFF(cm_func)},
+ {"cm_self", T_OBJECT, OFF(cm_self)},
+ {NULL} /* Sentinel */
+};
+
+static object *
+classmethod_getattr(cm, name)
+ register classmethodobject *cm;
+ char *name;
+{
+ return getmember((char *)cm, classmethod_memberlist, name);
+}
+
+static void
+classmethod_dealloc(cm)
+ register classmethodobject *cm;
+{
+ DECREF(cm->cm_func);
+ DECREF(cm->cm_self);
+ free((ANY *)cm);
+}
+
+typeobject Classmethodtype = {
+ OB_HEAD_INIT(&Typetype)
+ 0,
+ "class method",
+ sizeof(classmethodobject),
+ 0,
+ classmethod_dealloc, /*tp_dealloc*/
+ 0, /*tp_print*/
+ classmethod_getattr, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+};
diff --git a/src/classobject.h b/src/classobject.h
new file mode 100644
index 0000000..49db837
--- /dev/null
+++ b/src/classobject.h
@@ -0,0 +1,44 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* Class object interface */
+
+/*
+Classes are really hacked in at the last moment.
+It should be possible to use other object types as base classes,
+but currently it isn't. We'll see if we can fix that later, sigh...
+*/
+
+extern typeobject Classtype, Classmembertype, Classmethodtype;
+
+#define is_classobject(op) ((op)->ob_type == &Classtype)
+#define is_classmemberobject(op) ((op)->ob_type == &Classmembertype)
+#define is_classmethodobject(op) ((op)->ob_type == &Classmethodtype)
+
+extern object *newclassobject PROTO((object *, object *));
+extern object *newclassmemberobject PROTO((object *));
+extern object *newclassmethodobject PROTO((object *, object *));
+
+extern object *classmethodgetfunc PROTO((object *));
+extern object *classmethodgetself PROTO((object *));
diff --git a/src/compile.c b/src/compile.c
new file mode 100644
index 0000000..7904dba
--- /dev/null
+++ b/src/compile.c
@@ -0,0 +1,1772 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* Compile an expression node to intermediate code */
+
+/* XXX TO DO:
+ XXX Compute maximum needed stack sizes while compiling
+ XXX Generate simple jump for break/return outside 'try...finally'
+ XXX Include function name in code (and module names?)
+*/
+
+#include "allobjects.h"
+
+#include "node.h"
+#include "token.h"
+#include "graminit.h"
+#include "compile.h"
+#include "opcode.h"
+#include "structmember.h"
+
+#include <ctype.h>
+
+#define OFF(x) offsetof(codeobject, x)
+
+static struct memberlist code_memberlist[] = {
+ {"co_code", T_OBJECT, OFF(co_code)},
+ {"co_consts", T_OBJECT, OFF(co_consts)},
+ {"co_names", T_OBJECT, OFF(co_names)},
+ {"co_filename", T_OBJECT, OFF(co_filename)},
+ {NULL} /* Sentinel */
+};
+
+static object *
+code_getattr(co, name)
+ codeobject *co;
+ char *name;
+{
+ return getmember((char *)co, code_memberlist, name);
+}
+
+static void
+code_dealloc(co)
+ codeobject *co;
+{
+ XDECREF(co->co_code);
+ XDECREF(co->co_consts);
+ XDECREF(co->co_names);
+ XDECREF(co->co_filename);
+ DEL(co);
+}
+
+typeobject Codetype = {
+ OB_HEAD_INIT(&Typetype)
+ 0,
+ "code",
+ sizeof(codeobject),
+ 0,
+ code_dealloc, /*tp_dealloc*/
+ 0, /*tp_print*/
+ code_getattr, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+};
+
+static codeobject *newcodeobject PROTO((object *, object *, object *, char *));
+
+static codeobject *
+newcodeobject(code, consts, names, filename)
+ object *code;
+ object *consts;
+ object *names;
+ char *filename;
+{
+ codeobject *co;
+ int i;
+ /* Check argument types */
+ if (code == NULL || !is_stringobject(code) ||
+ consts == NULL || !is_listobject(consts) ||
+ names == NULL || !is_listobject(names)) {
+ err_badcall();
+ return NULL;
+ }
+ /* Make sure the list of names contains only strings */
+ for (i = getlistsize(names); --i >= 0; ) {
+ object *v = getlistitem(names, i);
+ if (v == NULL || !is_stringobject(v)) {
+ err_badcall();
+ return NULL;
+ }
+ }
+ co = NEWOBJ(codeobject, &Codetype);
+ if (co != NULL) {
+ INCREF(code);
+ co->co_code = (stringobject *)code;
+ INCREF(consts);
+ co->co_consts = consts;
+ INCREF(names);
+ co->co_names = names;
+ if ((co->co_filename = newstringobject(filename)) == NULL) {
+ DECREF(co);
+ co = NULL;
+ }
+ }
+ return co;
+}
+
+
+/* Data structure used internally */
+struct compiling {
+ object *c_code; /* string */
+ object *c_consts; /* list of objects */
+ object *c_names; /* list of strings (names) */
+ int c_nexti; /* index into c_code */
+ int c_errors; /* counts errors occurred */
+ int c_infunction; /* set when compiling a function */
+ int c_loops; /* counts nested loops */
+ char *c_filename; /* filename of current node */
+};
+
+/* Prototypes */
+static int com_init PROTO((struct compiling *, char *));
+static void com_free PROTO((struct compiling *));
+static void com_done PROTO((struct compiling *));
+static void com_node PROTO((struct compiling *, struct _node *));
+static void com_addbyte PROTO((struct compiling *, int));
+static void com_addint PROTO((struct compiling *, int));
+static void com_addoparg PROTO((struct compiling *, int, int));
+static void com_addfwref PROTO((struct compiling *, int, int *));
+static void com_backpatch PROTO((struct compiling *, int));
+static int com_add PROTO((struct compiling *, object *, object *));
+static int com_addconst PROTO((struct compiling *, object *));
+static int com_addname PROTO((struct compiling *, object *));
+static void com_addopname PROTO((struct compiling *, int, node *));
+
+static int
+com_init(c, filename)
+ struct compiling *c;
+ char *filename;
+{
+ if ((c->c_code = newsizedstringobject((char *)NULL, 0)) == NULL)
+ goto fail_3;
+ if ((c->c_consts = newlistobject(0)) == NULL)
+ goto fail_2;
+ if ((c->c_names = newlistobject(0)) == NULL)
+ goto fail_1;
+ c->c_nexti = 0;
+ c->c_errors = 0;
+ c->c_infunction = 0;
+ c->c_loops = 0;
+ c->c_filename = filename;
+ return 1;
+
+ fail_1:
+ DECREF(c->c_consts);
+ fail_2:
+ DECREF(c->c_code);
+ fail_3:
+ return 0;
+}
+
+static void
+com_free(c)
+ struct compiling *c;
+{
+ XDECREF(c->c_code);
+ XDECREF(c->c_consts);
+ XDECREF(c->c_names);
+}
+
+static void
+com_done(c)
+ struct compiling *c;
+{
+ if (c->c_code != NULL)
+ resizestring(&c->c_code, c->c_nexti);
+}
+
+static void
+com_addbyte(c, byte)
+ struct compiling *c;
+ int byte;
+{
+ int len;
+ if (byte < 0 || byte > 255) {
+ fprintf(stderr, "XXX compiling bad byte: %d\n", byte);
+ abort();
+ err_setstr(SystemError, "com_addbyte: byte out of range");
+ c->c_errors++;
+ }
+ if (c->c_code == NULL)
+ return;
+ len = getstringsize(c->c_code);
+ if (c->c_nexti >= len) {
+ if (resizestring(&c->c_code, len+1000) != 0) {
+ c->c_errors++;
+ return;
+ }
+ }
+ getstringvalue(c->c_code)[c->c_nexti++] = byte;
+}
+
+static void
+com_addint(c, x)
+ struct compiling *c;
+ int x;
+{
+ com_addbyte(c, x & 0xff);
+ com_addbyte(c, x >> 8); /* XXX x should be positive */
+}
+
+static void
+com_addoparg(c, op, arg)
+ struct compiling *c;
+ int op;
+ int arg;
+{
+ com_addbyte(c, op);
+ com_addint(c, arg);
+}
+
+static void
+com_addfwref(c, op, p_anchor)
+ struct compiling *c;
+ int op;
+ int *p_anchor;
+{
+ /* Compile a forward reference for backpatching */
+ int here;
+ int anchor;
+ com_addbyte(c, op);
+ here = c->c_nexti;
+ anchor = *p_anchor;
+ *p_anchor = here;
+ com_addint(c, anchor == 0 ? 0 : here - anchor);
+}
+
+static void
+com_backpatch(c, anchor)
+ struct compiling *c;
+ int anchor; /* Must be nonzero */
+{
+ unsigned char *code = (unsigned char *) getstringvalue(c->c_code);
+ int target = c->c_nexti;
+ int lastanchor = 0;
+ int dist;
+ int prev;
+ for (;;) {
+ /* Make the JUMP instruction at anchor point to target */
+ prev = code[anchor] + (code[anchor+1] << 8);
+ dist = target - (anchor+2);
+ code[anchor] = dist & 0xff;
+ code[anchor+1] = dist >> 8;
+ if (!prev)
+ break;
+ lastanchor = anchor;
+ anchor -= prev;
+ }
+}
+
+/* Handle constants and names uniformly */
+
+static int
+com_add(c, list, v)
+ struct compiling *c;
+ object *list;
+ object *v;
+{
+ int n = getlistsize(list);
+ int i;
+ for (i = n; --i >= 0; ) {
+ object *w = getlistitem(list, i);
+ if (cmpobject(v, w) == 0)
+ return i;
+ }
+ if (addlistitem(list, v) != 0)
+ c->c_errors++;
+ return n;
+}
+
+static int
+com_addconst(c, v)
+ struct compiling *c;
+ object *v;
+{
+ return com_add(c, c->c_consts, v);
+}
+
+static int
+com_addname(c, v)
+ struct compiling *c;
+ object *v;
+{
+ return com_add(c, c->c_names, v);
+}
+
+static void
+com_addopname(c, op, n)
+ struct compiling *c;
+ int op;
+ node *n;
+{
+ object *v;
+ int i;
+ char *name;
+ if (TYPE(n) == STAR)
+ name = "*";
+ else {
+ REQ(n, NAME);
+ name = STR(n);
+ }
+ if ((v = newstringobject(name)) == NULL) {
+ c->c_errors++;
+ i = 255;
+ }
+ else {
+ i = com_addname(c, v);
+ DECREF(v);
+ }
+ com_addoparg(c, op, i);
+}
+
+static object *
+parsenumber(s)
+ char *s;
+{
+ extern long strtol();
+ extern double atof();
+ char *end = s;
+ long x;
+ x = strtol(s, &end, 0);
+ if (*end == '\0')
+ return newintobject(x);
+ if (*end == '.' || *end == 'e' || *end == 'E')
+ return newfloatobject(atof(s));
+ err_setstr(RuntimeError, "bad number syntax");
+ return NULL;
+}
+
+static object *
+parsestr(s)
+ char *s;
+{
+ object *v;
+ int len;
+ char *buf;
+ char *p;
+ int c;
+ if (*s != '\'') {
+ err_badcall();
+ return NULL;
+ }
+ s++;
+ len = strlen(s);
+ if (s[--len] != '\'') {
+ err_badcall();
+ return NULL;
+ }
+ if (strchr(s, '\\') == NULL)
+ return newsizedstringobject(s, len);
+ v = newsizedstringobject((char *)NULL, len);
+ p = buf = getstringvalue(v);
+ while (*s != '\0' && *s != '\'') {
+ if (*s != '\\') {
+ *p++ = *s++;
+ continue;
+ }
+ s++;
+ switch (*s++) {
+ /* XXX This assumes ASCII! */
+ case '\\': *p++ = '\\'; break;
+ case '\'': *p++ = '\''; break;
+ case 'b': *p++ = '\b'; break;
+ case 'f': *p++ = '\014'; break; /* FF */
+ case 't': *p++ = '\t'; break;
+ case 'n': *p++ = '\n'; break;
+ case 'r': *p++ = '\r'; break;
+ case 'v': *p++ = '\013'; break; /* VT */
+ case 'E': *p++ = '\033'; break; /* ESC, not C */
+ case 'a': *p++ = '\007'; break; /* BEL, not classic C */
+ case '0': case '1': case '2': case '3':
+ case '4': case '5': case '6': case '7':
+ c = s[-1] - '0';
+ if ('0' <= *s && *s <= '7') {
+ c = (c<<3) + *s++ - '0';
+ if ('0' <= *s && *s <= '7')
+ c = (c<<3) + *s++ - '0';
+ }
+ *p++ = c;
+ break;
+ case 'x':
+ if (isxdigit(*s)) {
+ sscanf(s, "%x", &c);
+ *p++ = c;
+ do {
+ s++;
+ } while (isxdigit(*s));
+ break;
+ }
+ /* FALLTHROUGH */
+ default: *p++ = '\\'; *p++ = s[-1]; break;
+ }
+ }
+ resizestring(&v, (int)(p - buf));
+ return v;
+}
+
+static void
+com_list_constructor(c, n)
+ struct compiling *c;
+ node *n;
+{
+ int len;
+ int i;
+ object *v, *w;
+ if (TYPE(n) != testlist)
+ REQ(n, exprlist);
+ /* exprlist: expr (',' expr)* [',']; likewise for testlist */
+ len = (NCH(n) + 1) / 2;
+ for (i = 0; i < NCH(n); i += 2)
+ com_node(c, CHILD(n, i));
+ com_addoparg(c, BUILD_LIST, len);
+}
+
+static void
+com_atom(c, n)
+ struct compiling *c;
+ node *n;
+{
+ node *ch;
+ object *v;
+ int i;
+ REQ(n, atom);
+ ch = CHILD(n, 0);
+ switch (TYPE(ch)) {
+ case LPAR:
+ if (TYPE(CHILD(n, 1)) == RPAR)
+ com_addoparg(c, BUILD_TUPLE, 0);
+ else
+ com_node(c, CHILD(n, 1));
+ break;
+ case LSQB:
+ if (TYPE(CHILD(n, 1)) == RSQB)
+ com_addoparg(c, BUILD_LIST, 0);
+ else
+ com_list_constructor(c, CHILD(n, 1));
+ break;
+ case LBRACE:
+ com_addoparg(c, BUILD_MAP, 0);
+ break;
+ case BACKQUOTE:
+ com_node(c, CHILD(n, 1));
+ com_addbyte(c, UNARY_CONVERT);
+ break;
+ case NUMBER:
+ if ((v = parsenumber(STR(ch))) == NULL) {
+ c->c_errors++;
+ i = 255;
+ }
+ else {
+ i = com_addconst(c, v);
+ DECREF(v);
+ }
+ com_addoparg(c, LOAD_CONST, i);
+ break;
+ case STRING:
+ if ((v = parsestr(STR(ch))) == NULL) {
+ c->c_errors++;
+ i = 255;
+ }
+ else {
+ i = com_addconst(c, v);
+ DECREF(v);
+ }
+ com_addoparg(c, LOAD_CONST, i);
+ break;
+ case NAME:
+ com_addopname(c, LOAD_NAME, ch);
+ break;
+ default:
+ fprintf(stderr, "node type %d\n", TYPE(ch));
+ err_setstr(SystemError, "com_atom: unexpected node type");
+ c->c_errors++;
+ }
+}
+
+static void
+com_slice(c, n, op)
+ struct compiling *c;
+ node *n;
+ int op;
+{
+ if (NCH(n) == 1) {
+ com_addbyte(c, op);
+ }
+ else if (NCH(n) == 2) {
+ if (TYPE(CHILD(n, 0)) != COLON) {
+ com_node(c, CHILD(n, 0));
+ com_addbyte(c, op+1);
+ }
+ else {
+ com_node(c, CHILD(n, 1));
+ com_addbyte(c, op+2);
+ }
+ }
+ else {
+ com_node(c, CHILD(n, 0));
+ com_node(c, CHILD(n, 2));
+ com_addbyte(c, op+3);
+ }
+}
+
+static void
+com_apply_subscript(c, n)
+ struct compiling *c;
+ node *n;
+{
+ REQ(n, subscript);
+ if (NCH(n) == 1 && TYPE(CHILD(n, 0)) != COLON) {
+ /* It's a single subscript */
+ com_node(c, CHILD(n, 0));
+ com_addbyte(c, BINARY_SUBSCR);
+ }
+ else {
+ /* It's a slice: [expr] ':' [expr] */
+ com_slice(c, n, SLICE);
+ }
+}
+
+static void
+com_call_function(c, n)
+ struct compiling *c;
+ node *n; /* EITHER testlist OR ')' */
+{
+ if (TYPE(n) == RPAR) {
+ com_addbyte(c, UNARY_CALL);
+ }
+ else {
+ com_node(c, n);
+ com_addbyte(c, BINARY_CALL);
+ }
+}
+
+static void
+com_select_member(c, n)
+ struct compiling *c;
+ node *n;
+{
+ com_addopname(c, LOAD_ATTR, n);
+}
+
+static void
+com_apply_trailer(c, n)
+ struct compiling *c;
+ node *n;
+{
+ REQ(n, trailer);
+ switch (TYPE(CHILD(n, 0))) {
+ case LPAR:
+ com_call_function(c, CHILD(n, 1));
+ break;
+ case DOT:
+ com_select_member(c, CHILD(n, 1));
+ break;
+ case LSQB:
+ com_apply_subscript(c, CHILD(n, 1));
+ break;
+ default:
+ err_setstr(SystemError,
+ "com_apply_trailer: unknown trailer type");
+ c->c_errors++;
+ }
+}
+
+static void
+com_factor(c, n)
+ struct compiling *c;
+ node *n;
+{
+ int i;
+ REQ(n, factor);
+ if (TYPE(CHILD(n, 0)) == PLUS) {
+ com_factor(c, CHILD(n, 1));
+ com_addbyte(c, UNARY_POSITIVE);
+ }
+ else if (TYPE(CHILD(n, 0)) == MINUS) {
+ com_factor(c, CHILD(n, 1));
+ com_addbyte(c, UNARY_NEGATIVE);
+ }
+ else {
+ com_atom(c, CHILD(n, 0));
+ for (i = 1; i < NCH(n); i++)
+ com_apply_trailer(c, CHILD(n, i));
+ }
+}
+
+static void
+com_term(c, n)
+ struct compiling *c;
+ node *n;
+{
+ int i;
+ int op;
+ REQ(n, term);
+ com_factor(c, CHILD(n, 0));
+ for (i = 2; i < NCH(n); i += 2) {
+ com_factor(c, CHILD(n, i));
+ switch (TYPE(CHILD(n, i-1))) {
+ case STAR:
+ op = BINARY_MULTIPLY;
+ break;
+ case SLASH:
+ op = BINARY_DIVIDE;
+ break;
+ case PERCENT:
+ op = BINARY_MODULO;
+ break;
+ default:
+ err_setstr(SystemError,
+ "com_term: term operator not *, / or %");
+ c->c_errors++;
+ op = 255;
+ }
+ com_addbyte(c, op);
+ }
+}
+
+static void
+com_expr(c, n)
+ struct compiling *c;
+ node *n;
+{
+ int i;
+ int op;
+ REQ(n, expr);
+ com_term(c, CHILD(n, 0));
+ for (i = 2; i < NCH(n); i += 2) {
+ com_term(c, CHILD(n, i));
+ switch (TYPE(CHILD(n, i-1))) {
+ case PLUS:
+ op = BINARY_ADD;
+ break;
+ case MINUS:
+ op = BINARY_SUBTRACT;
+ break;
+ default:
+ err_setstr(SystemError,
+ "com_expr: expr operator not + or -");
+ c->c_errors++;
+ op = 255;
+ }
+ com_addbyte(c, op);
+ }
+}
+
+static enum cmp_op
+cmp_type(n)
+ node *n;
+{
+ REQ(n, comp_op);
+ /* comp_op: '<' | '>' | '=' | '>' '=' | '<' '=' | '<' '>'
+ | 'in' | 'not' 'in' | 'is' | 'is' not' */
+ if (NCH(n) == 1) {
+ n = CHILD(n, 0);
+ switch (TYPE(n)) {
+ case LESS: return LT;
+ case GREATER: return GT;
+ case EQUAL: return EQ;
+ case NAME: if (strcmp(STR(n), "in") == 0) return IN;
+ if (strcmp(STR(n), "is") == 0) return IS;
+ }
+ }
+ else if (NCH(n) == 2) {
+ int t2 = TYPE(CHILD(n, 1));
+ switch (TYPE(CHILD(n, 0))) {
+ case LESS: if (t2 == EQUAL) return LE;
+ if (t2 == GREATER) return NE;
+ break;
+ case GREATER: if (t2 == EQUAL) return GE;
+ break;
+ case NAME: if (strcmp(STR(CHILD(n, 1)), "in") == 0)
+ return NOT_IN;
+ if (strcmp(STR(CHILD(n, 0)), "is") == 0)
+ return IS_NOT;
+ }
+ }
+ return BAD;
+}
+
+static void
+com_comparison(c, n)
+ struct compiling *c;
+ node *n;
+{
+ int i;
+ enum cmp_op op;
+ int anchor;
+ REQ(n, comparison); /* comparison: expr (comp_op expr)* */
+ com_expr(c, CHILD(n, 0));
+ if (NCH(n) == 1)
+ return;
+
+ /****************************************************************
+ The following code is generated for all but the last
+ comparison in a chain:
+
+ label: on stack: opcode: jump to:
+
+ a <code to load b>
+ a, b DUP_TOP
+ a, b, b ROT_THREE
+ b, a, b COMPARE_OP
+ b, 0-or-1 JUMP_IF_FALSE L1
+ b, 1 POP_TOP
+ b
+
+ We are now ready to repeat this sequence for the next
+ comparison in the chain.
+
+ For the last we generate:
+
+ b <code to load c>
+ b, c COMPARE_OP
+ 0-or-1
+
+ If there were any jumps to L1 (i.e., there was more than one
+ comparison), we generate:
+
+ 0-or-1 JUMP_FORWARD L2
+ L1: b, 0 ROT_TWO
+ 0, b POP_TOP
+ 0
+ L2:
+ ****************************************************************/
+
+ anchor = 0;
+
+ for (i = 2; i < NCH(n); i += 2) {
+ com_expr(c, CHILD(n, i));
+ if (i+2 < NCH(n)) {
+ com_addbyte(c, DUP_TOP);
+ com_addbyte(c, ROT_THREE);
+ }
+ op = cmp_type(CHILD(n, i-1));
+ if (op == BAD) {
+ err_setstr(SystemError,
+ "com_comparison: unknown comparison op");
+ c->c_errors++;
+ }
+ com_addoparg(c, COMPARE_OP, op);
+ if (i+2 < NCH(n)) {
+ com_addfwref(c, JUMP_IF_FALSE, &anchor);
+ com_addbyte(c, POP_TOP);
+ }
+ }
+
+ if (anchor) {
+ int anchor2 = 0;
+ com_addfwref(c, JUMP_FORWARD, &anchor2);
+ com_backpatch(c, anchor);
+ com_addbyte(c, ROT_TWO);
+ com_addbyte(c, POP_TOP);
+ com_backpatch(c, anchor2);
+ }
+}
+
+static void
+com_not_test(c, n)
+ struct compiling *c;
+ node *n;
+{
+ REQ(n, not_test); /* 'not' not_test | comparison */
+ if (NCH(n) == 1) {
+ com_comparison(c, CHILD(n, 0));
+ }
+ else {
+ com_not_test(c, CHILD(n, 1));
+ com_addbyte(c, UNARY_NOT);
+ }
+}
+
+static void
+com_and_test(c, n)
+ struct compiling *c;
+ node *n;
+{
+ int i;
+ int anchor;
+ REQ(n, and_test); /* not_test ('and' not_test)* */
+ anchor = 0;
+ i = 0;
+ for (;;) {
+ com_not_test(c, CHILD(n, i));
+ if ((i += 2) >= NCH(n))
+ break;
+ com_addfwref(c, JUMP_IF_FALSE, &anchor);
+ com_addbyte(c, POP_TOP);
+ }
+ if (anchor)
+ com_backpatch(c, anchor);
+}
+
+static void
+com_test(c, n)
+ struct compiling *c;
+ node *n;
+{
+ int i;
+ int anchor;
+ REQ(n, test); /* and_test ('and' and_test)* */
+ anchor = 0;
+ i = 0;
+ for (;;) {
+ com_and_test(c, CHILD(n, i));
+ if ((i += 2) >= NCH(n))
+ break;
+ com_addfwref(c, JUMP_IF_TRUE, &anchor);
+ com_addbyte(c, POP_TOP);
+ }
+ if (anchor)
+ com_backpatch(c, anchor);
+}
+
+static void
+com_list(c, n)
+ struct compiling *c;
+ node *n;
+{
+ /* exprlist: expr (',' expr)* [',']; likewise for testlist */
+ if (NCH(n) == 1) {
+ com_node(c, CHILD(n, 0));
+ }
+ else {
+ int i;
+ int len;
+ len = (NCH(n) + 1) / 2;
+ for (i = 0; i < NCH(n); i += 2)
+ com_node(c, CHILD(n, i));
+ com_addoparg(c, BUILD_TUPLE, len);
+ }
+}
+
+
+/* Begin of assignment compilation */
+
+static void com_assign_name PROTO((struct compiling *, node *, int));
+static void com_assign PROTO((struct compiling *, node *, int));
+
+static void
+com_assign_attr(c, n, assigning)
+ struct compiling *c;
+ node *n;
+ int assigning;
+{
+ com_addopname(c, assigning ? STORE_ATTR : DELETE_ATTR, n);
+}
+
+static void
+com_assign_slice(c, n, assigning)
+ struct compiling *c;
+ node *n;
+ int assigning;
+{
+ com_slice(c, n, assigning ? STORE_SLICE : DELETE_SLICE);
+}
+
+static void
+com_assign_subscript(c, n, assigning)
+ struct compiling *c;
+ node *n;
+ int assigning;
+{
+ com_node(c, n);
+ com_addbyte(c, assigning ? STORE_SUBSCR : DELETE_SUBSCR);
+}
+
+static void
+com_assign_trailer(c, n, assigning)
+ struct compiling *c;
+ node *n;
+ int assigning;
+{
+ char *name;
+ REQ(n, trailer);
+ switch (TYPE(CHILD(n, 0))) {
+ case LPAR: /* '(' [exprlist] ')' */
+ err_setstr(TypeError, "can't assign to function call");
+ c->c_errors++;
+ break;
+ case DOT: /* '.' NAME */
+ com_assign_attr(c, CHILD(n, 1), assigning);
+ break;
+ case LSQB: /* '[' subscript ']' */
+ n = CHILD(n, 1);
+ REQ(n, subscript); /* subscript: expr | [expr] ':' [expr] */
+ if (NCH(n) > 1 || TYPE(CHILD(n, 0)) == COLON)
+ com_assign_slice(c, n, assigning);
+ else
+ com_assign_subscript(c, CHILD(n, 0), assigning);
+ break;
+ default:
+ err_setstr(TypeError, "unknown trailer type");
+ c->c_errors++;
+ }
+}
+
+static void
+com_assign_tuple(c, n, assigning)
+ struct compiling *c;
+ node *n;
+ int assigning;
+{
+ int i;
+ if (TYPE(n) != testlist)
+ REQ(n, exprlist);
+ if (assigning)
+ com_addoparg(c, UNPACK_TUPLE, (NCH(n)+1)/2);
+ for (i = 0; i < NCH(n); i += 2)
+ com_assign(c, CHILD(n, i), assigning);
+}
+
+static void
+com_assign_list(c, n, assigning)
+ struct compiling *c;
+ node *n;
+ int assigning;
+{
+ int i;
+ if (assigning)
+ com_addoparg(c, UNPACK_LIST, (NCH(n)+1)/2);
+ for (i = 0; i < NCH(n); i += 2)
+ com_assign(c, CHILD(n, i), assigning);
+}
+
+static void
+com_assign_name(c, n, assigning)
+ struct compiling *c;
+ node *n;
+ int assigning;
+{
+ REQ(n, NAME);
+ com_addopname(c, assigning ? STORE_NAME : DELETE_NAME, n);
+}
+
+static void
+com_assign(c, n, assigning)
+ struct compiling *c;
+ node *n;
+ int assigning;
+{
+ /* Loop to avoid trivial recursion */
+ for (;;) {
+ switch (TYPE(n)) {
+
+ case exprlist:
+ case testlist:
+ if (NCH(n) > 1) {
+ com_assign_tuple(c, n, assigning);
+ return;
+ }
+ n = CHILD(n, 0);
+ break;
+
+ case test:
+ case and_test:
+ case not_test:
+ if (NCH(n) > 1) {
+ err_setstr(TypeError,
+ "can't assign to operator");
+ c->c_errors++;
+ return;
+ }
+ n = CHILD(n, 0);
+ break;
+
+ case comparison:
+ if (NCH(n) > 1) {
+ err_setstr(TypeError,
+ "can't assign to operator");
+ c->c_errors++;
+ return;
+ }
+ n = CHILD(n, 0);
+ break;
+
+ case expr:
+ if (NCH(n) > 1) {
+ err_setstr(TypeError,
+ "can't assign to operator");
+ c->c_errors++;
+ return;
+ }
+ n = CHILD(n, 0);
+ break;
+
+ case term:
+ if (NCH(n) > 1) {
+ err_setstr(TypeError,
+ "can't assign to operator");
+ c->c_errors++;
+ return;
+ }
+ n = CHILD(n, 0);
+ break;
+
+ case factor: /* ('+'|'-') factor | atom trailer* */
+ if (TYPE(CHILD(n, 0)) != atom) { /* '+' | '-' */
+ err_setstr(TypeError,
+ "can't assign to operator");
+ c->c_errors++;
+ return;
+ }
+ if (NCH(n) > 1) { /* trailer present */
+ int i;
+ com_node(c, CHILD(n, 0));
+ for (i = 1; i+1 < NCH(n); i++) {
+ com_apply_trailer(c, CHILD(n, i));
+ } /* NB i is still alive */
+ com_assign_trailer(c,
+ CHILD(n, i), assigning);
+ return;
+ }
+ n = CHILD(n, 0);
+ break;
+
+ case atom:
+ switch (TYPE(CHILD(n, 0))) {
+ case LPAR:
+ n = CHILD(n, 1);
+ if (TYPE(n) == RPAR) {
+ /* XXX Should allow () = () ??? */
+ err_setstr(TypeError,
+ "can't assign to ()");
+ c->c_errors++;
+ return;
+ }
+ break;
+ case LSQB:
+ n = CHILD(n, 1);
+ if (TYPE(n) == RSQB) {
+ err_setstr(TypeError,
+ "can't assign to []");
+ c->c_errors++;
+ return;
+ }
+ com_assign_list(c, n, assigning);
+ return;
+ case NAME:
+ com_assign_name(c, CHILD(n, 0), assigning);
+ return;
+ default:
+ err_setstr(TypeError,
+ "can't assign to constant");
+ c->c_errors++;
+ return;
+ }
+ break;
+
+ default:
+ fprintf(stderr, "node type %d\n", TYPE(n));
+ err_setstr(SystemError, "com_assign: bad node");
+ c->c_errors++;
+ return;
+
+ }
+ }
+}
+
+static void
+com_expr_stmt(c, n)
+ struct compiling *c;
+ node *n;
+{
+ REQ(n, expr_stmt); /* exprlist ('=' exprlist)* NEWLINE */
+ com_node(c, CHILD(n, NCH(n)-2));
+ if (NCH(n) == 2) {
+ com_addbyte(c, PRINT_EXPR);
+ }
+ else {
+ int i;
+ for (i = 0; i < NCH(n)-3; i+=2) {
+ if (i+2 < NCH(n)-3)
+ com_addbyte(c, DUP_TOP);
+ com_assign(c, CHILD(n, i), 1/*assign*/);
+ }
+ }
+}
+
+static void
+com_print_stmt(c, n)
+ struct compiling *c;
+ node *n;
+{
+ int i;
+ REQ(n, print_stmt); /* 'print' (test ',')* [test] NEWLINE */
+ for (i = 1; i+1 < NCH(n); i += 2) {
+ com_node(c, CHILD(n, i));
+ com_addbyte(c, PRINT_ITEM);
+ }
+ if (TYPE(CHILD(n, NCH(n)-2)) != COMMA)
+ com_addbyte(c, PRINT_NEWLINE);
+ /* XXX Alternatively, LOAD_CONST '\n' and then PRINT_ITEM */
+}
+
+static void
+com_return_stmt(c, n)
+ struct compiling *c;
+ node *n;
+{
+ REQ(n, return_stmt); /* 'return' [testlist] NEWLINE */
+ if (!c->c_infunction) {
+ err_setstr(TypeError, "'return' outside function");
+ c->c_errors++;
+ }
+ if (NCH(n) == 2)
+ com_addoparg(c, LOAD_CONST, com_addconst(c, None));
+ else
+ com_node(c, CHILD(n, 1));
+ com_addbyte(c, RETURN_VALUE);
+}
+
+static void
+com_raise_stmt(c, n)
+ struct compiling *c;
+ node *n;
+{
+ REQ(n, raise_stmt); /* 'raise' expr [',' expr] NEWLINE */
+ com_node(c, CHILD(n, 1));
+ if (NCH(n) > 3)
+ com_node(c, CHILD(n, 3));
+ else
+ com_addoparg(c, LOAD_CONST, com_addconst(c, None));
+ com_addbyte(c, RAISE_EXCEPTION);
+}
+
+static void
+com_import_stmt(c, n)
+ struct compiling *c;
+ node *n;
+{
+ int i;
+ REQ(n, import_stmt);
+ /* 'import' NAME (',' NAME)* NEWLINE |
+ 'from' NAME 'import' ('*' | NAME (',' NAME)*) NEWLINE */
+ if (STR(CHILD(n, 0))[0] == 'f') {
+ /* 'from' NAME 'import' ... */
+ REQ(CHILD(n, 1), NAME);
+ com_addopname(c, IMPORT_NAME, CHILD(n, 1));
+ for (i = 3; i < NCH(n); i += 2)
+ com_addopname(c, IMPORT_FROM, CHILD(n, i));
+ com_addbyte(c, POP_TOP);
+ }
+ else {
+ /* 'import' ... */
+ for (i = 1; i < NCH(n); i += 2) {
+ com_addopname(c, IMPORT_NAME, CHILD(n, i));
+ com_addopname(c, STORE_NAME, CHILD(n, i));
+ }
+ }
+}
+
+static void
+com_if_stmt(c, n)
+ struct compiling *c;
+ node *n;
+{
+ int i;
+ int anchor = 0;
+ REQ(n, if_stmt);
+ /*'if' test ':' suite ('elif' test ':' suite)* ['else' ':' suite] */
+ for (i = 0; i+3 < NCH(n); i+=4) {
+ int a = 0;
+ node *ch = CHILD(n, i+1);
+ if (i > 0)
+ com_addoparg(c, SET_LINENO, ch->n_lineno);
+ com_node(c, CHILD(n, i+1));
+ com_addfwref(c, JUMP_IF_FALSE, &a);
+ com_addbyte(c, POP_TOP);
+ com_node(c, CHILD(n, i+3));
+ com_addfwref(c, JUMP_FORWARD, &anchor);
+ com_backpatch(c, a);
+ com_addbyte(c, POP_TOP);
+ }
+ if (i+2 < NCH(n))
+ com_node(c, CHILD(n, i+2));
+ com_backpatch(c, anchor);
+}
+
+static void
+com_while_stmt(c, n)
+ struct compiling *c;
+ node *n;
+{
+ int break_anchor = 0;
+ int anchor = 0;
+ int begin;
+ REQ(n, while_stmt); /* 'while' test ':' suite ['else' ':' suite] */
+ com_addfwref(c, SETUP_LOOP, &break_anchor);
+ begin = c->c_nexti;
+ com_addoparg(c, SET_LINENO, n->n_lineno);
+ com_node(c, CHILD(n, 1));
+ com_addfwref(c, JUMP_IF_FALSE, &anchor);
+ com_addbyte(c, POP_TOP);
+ c->c_loops++;
+ com_node(c, CHILD(n, 3));
+ c->c_loops--;
+ com_addoparg(c, JUMP_ABSOLUTE, begin);
+ com_backpatch(c, anchor);
+ com_addbyte(c, POP_TOP);
+ com_addbyte(c, POP_BLOCK);
+ if (NCH(n) > 4)
+ com_node(c, CHILD(n, 6));
+ com_backpatch(c, break_anchor);
+}
+
+static void
+com_for_stmt(c, n)
+ struct compiling *c;
+ node *n;
+{
+ object *v;
+ int break_anchor = 0;
+ int anchor = 0;
+ int begin;
+ REQ(n, for_stmt);
+ /* 'for' exprlist 'in' exprlist ':' suite ['else' ':' suite] */
+ com_addfwref(c, SETUP_LOOP, &break_anchor);
+ com_node(c, CHILD(n, 3));
+ v = newintobject(0L);
+ if (v == NULL)
+ c->c_errors++;
+ com_addoparg(c, LOAD_CONST, com_addconst(c, v));
+ XDECREF(v);
+ begin = c->c_nexti;
+ com_addoparg(c, SET_LINENO, n->n_lineno);
+ com_addfwref(c, FOR_LOOP, &anchor);
+ com_assign(c, CHILD(n, 1), 1/*assigning*/);
+ c->c_loops++;
+ com_node(c, CHILD(n, 5));
+ c->c_loops--;
+ com_addoparg(c, JUMP_ABSOLUTE, begin);
+ com_backpatch(c, anchor);
+ com_addbyte(c, POP_BLOCK);
+ if (NCH(n) > 8)
+ com_node(c, CHILD(n, 8));
+ com_backpatch(c, break_anchor);
+}
+
+/* Although 'execpt' and 'finally' clauses can be combined
+ syntactically, they are compiled separately. In fact,
+ try: S
+ except E1: S1
+ except E2: S2
+ ...
+ finally: Sf
+ is equivalent to
+ try:
+ try: S
+ except E1: S1
+ except E2: S2
+ ...
+ finally: Sf
+ meaning that the 'finally' clause is entered even if things
+ go wrong again in an exception handler. Note that this is
+ not the case for exception handlers: at most one is entered.
+
+ Code generated for "try: S finally: Sf" is as follows:
+
+ SETUP_FINALLY L
+ <code for S>
+ POP_BLOCK
+ LOAD_CONST <nil>
+ L: <code for Sf>
+ END_FINALLY
+
+ The special instructions use the block stack. Each block
+ stack entry contains the instruction that created it (here
+ SETUP_FINALLY), the level of the value stack at the time the
+ block stack entry was created, and a label (here L).
+
+ SETUP_FINALLY:
+ Pushes the current value stack level and the label
+ onto the block stack.
+ POP_BLOCK:
+ Pops en entry from the block stack, and pops the value
+ stack until its level is the same as indicated on the
+ block stack. (The label is ignored.)
+ END_FINALLY:
+ Pops a variable number of entries from the *value* stack
+ and re-raises the exception they specify. The number of
+ entries popped depends on the (pseudo) exception type.
+
+ The block stack is unwound when an exception is raised:
+ when a SETUP_FINALLY entry is found, the exception is pushed
+ onto the value stack (and the exception condition is cleared),
+ and the interpreter jumps to the label gotten from the block
+ stack.
+
+ Code generated for "try: S except E1, V1: S1 except E2, V2: S2 ...":
+ (The contents of the value stack is shown in [], with the top
+ at the right; 'tb' is trace-back info, 'val' the exception's
+ associated value, and 'exc' the exception.)
+
+ Value stack Label Instruction Argument
+ [] SETUP_EXCEPT L1
+ [] <code for S>
+ [] POP_BLOCK
+ [] JUMP_FORWARD L0
+
+ [tb, val, exc] L1: DUP )
+ [tb, val, exc, exc] <evaluate E1> )
+ [tb, val, exc, exc, E1] COMPARE_OP EXC_MATCH ) only if E1
+ [tb, val, exc, 1-or-0] JUMP_IF_FALSE L2 )
+ [tb, val, exc, 1] POP )
+ [tb, val, exc] POP
+ [tb, val] <assign to V1> (or POP if no V1)
+ [tb] POP
+ [] <code for S1>
+ JUMP_FORWARD L0
+
+ [tb, val, exc, 0] L2: POP
+ [tb, val, exc] DUP
+ .............................etc.......................
+
+ [tb, val, exc, 0] Ln+1: POP
+ [tb, val, exc] END_FINALLY # re-raise exception
+
+ [] L0: <next statement>
+
+ Of course, parts are not generated if Vi or Ei is not present.
+*/
+
+static void
+com_try_stmt(c, n)
+ struct compiling *c;
+ node *n;
+{
+ int finally_anchor = 0;
+ int except_anchor = 0;
+ REQ(n, try_stmt);
+ /* 'try' ':' suite (except_clause ':' suite)* ['finally' ':' suite] */
+
+ if (NCH(n) > 3 && TYPE(CHILD(n, NCH(n)-3)) != except_clause) {
+ /* Have a 'finally' clause */
+ com_addfwref(c, SETUP_FINALLY, &finally_anchor);
+ }
+ if (NCH(n) > 3 && TYPE(CHILD(n, 3)) == except_clause) {
+ /* Have an 'except' clause */
+ com_addfwref(c, SETUP_EXCEPT, &except_anchor);
+ }
+ com_node(c, CHILD(n, 2));
+ if (except_anchor) {
+ int end_anchor = 0;
+ int i;
+ node *ch;
+ com_addbyte(c, POP_BLOCK);
+ com_addfwref(c, JUMP_FORWARD, &end_anchor);
+ com_backpatch(c, except_anchor);
+ for (i = 3;
+ i < NCH(n) && TYPE(ch = CHILD(n, i)) == except_clause;
+ i += 3) {
+ /* except_clause: 'except' [expr [',' expr]] */
+ if (except_anchor == 0) {
+ err_setstr(TypeError,
+ "default 'except:' must be last");
+ c->c_errors++;
+ break;
+ }
+ except_anchor = 0;
+ com_addoparg(c, SET_LINENO, ch->n_lineno);
+ if (NCH(ch) > 1) {
+ com_addbyte(c, DUP_TOP);
+ com_node(c, CHILD(ch, 1));
+ com_addoparg(c, COMPARE_OP, EXC_MATCH);
+ com_addfwref(c, JUMP_IF_FALSE, &except_anchor);
+ com_addbyte(c, POP_TOP);
+ }
+ com_addbyte(c, POP_TOP);
+ if (NCH(ch) > 3)
+ com_assign(c, CHILD(ch, 3), 1/*assigning*/);
+ else
+ com_addbyte(c, POP_TOP);
+ com_addbyte(c, POP_TOP);
+ com_node(c, CHILD(n, i+2));
+ com_addfwref(c, JUMP_FORWARD, &end_anchor);
+ if (except_anchor) {
+ com_backpatch(c, except_anchor);
+ com_addbyte(c, POP_TOP);
+ }
+ }
+ com_addbyte(c, END_FINALLY);
+ com_backpatch(c, end_anchor);
+ }
+ if (finally_anchor) {
+ node *ch;
+ com_addbyte(c, POP_BLOCK);
+ com_addoparg(c, LOAD_CONST, com_addconst(c, None));
+ com_backpatch(c, finally_anchor);
+ ch = CHILD(n, NCH(n)-1);
+ com_addoparg(c, SET_LINENO, ch->n_lineno);
+ com_node(c, ch);
+ com_addbyte(c, END_FINALLY);
+ }
+}
+
+static void
+com_suite(c, n)
+ struct compiling *c;
+ node *n;
+{
+ REQ(n, suite);
+ /* simple_stmt | NEWLINE INDENT NEWLINE* (stmt NEWLINE*)+ DEDENT */
+ if (NCH(n) == 1) {
+ com_node(c, CHILD(n, 0));
+ }
+ else {
+ int i;
+ for (i = 0; i < NCH(n); i++) {
+ node *ch = CHILD(n, i);
+ if (TYPE(ch) == stmt)
+ com_node(c, ch);
+ }
+ }
+}
+
+static void
+com_funcdef(c, n)
+ struct compiling *c;
+ node *n;
+{
+ object *v;
+ REQ(n, funcdef); /* funcdef: 'def' NAME parameters ':' suite */
+ v = (object *)compile(n, c->c_filename);
+ if (v == NULL)
+ c->c_errors++;
+ else {
+ int i = com_addconst(c, v);
+ com_addoparg(c, LOAD_CONST, i);
+ com_addbyte(c, BUILD_FUNCTION);
+ com_addopname(c, STORE_NAME, CHILD(n, 1));
+ DECREF(v);
+ }
+}
+
+static void
+com_bases(c, n)
+ struct compiling *c;
+ node *n;
+{
+ int i, nbases;
+ REQ(n, baselist);
+ /*
+ baselist: atom arguments (',' atom arguments)*
+ arguments: '(' [testlist] ')'
+ */
+ for (i = 0; i < NCH(n); i += 3)
+ com_node(c, CHILD(n, i));
+ com_addoparg(c, BUILD_TUPLE, (NCH(n)+1) / 3);
+}
+
+static void
+com_classdef(c, n)
+ struct compiling *c;
+ node *n;
+{
+ object *v;
+ REQ(n, classdef);
+ /*
+ classdef: 'class' NAME parameters ['=' baselist] ':' suite
+ baselist: atom arguments (',' atom arguments)*
+ arguments: '(' [testlist] ')'
+ */
+ if (NCH(n) == 7)
+ com_bases(c, CHILD(n, 4));
+ else
+ com_addoparg(c, LOAD_CONST, com_addconst(c, None));
+ v = (object *)compile(n, c->c_filename);
+ if (v == NULL)
+ c->c_errors++;
+ else {
+ int i = com_addconst(c, v);
+ com_addoparg(c, LOAD_CONST, i);
+ com_addbyte(c, BUILD_FUNCTION);
+ com_addbyte(c, UNARY_CALL);
+ com_addbyte(c, BUILD_CLASS);
+ com_addopname(c, STORE_NAME, CHILD(n, 1));
+ DECREF(v);
+ }
+}
+
+static void
+com_node(c, n)
+ struct compiling *c;
+ node *n;
+{
+ switch (TYPE(n)) {
+
+ /* Definition nodes */
+
+ case funcdef:
+ com_funcdef(c, n);
+ break;
+ case classdef:
+ com_classdef(c, n);
+ break;
+
+ /* Trivial parse tree nodes */
+
+ case stmt:
+ case flow_stmt:
+ com_node(c, CHILD(n, 0));
+ break;
+
+ case simple_stmt:
+ case compound_stmt:
+ com_addoparg(c, SET_LINENO, n->n_lineno);
+ com_node(c, CHILD(n, 0));
+ break;
+
+ /* Statement nodes */
+
+ case expr_stmt:
+ com_expr_stmt(c, n);
+ break;
+ case print_stmt:
+ com_print_stmt(c, n);
+ break;
+ case del_stmt: /* 'del' exprlist NEWLINE */
+ com_assign(c, CHILD(n, 1), 0/*delete*/);
+ break;
+ case pass_stmt:
+ break;
+ case break_stmt:
+ if (c->c_loops == 0) {
+ err_setstr(TypeError, "'break' outside loop");
+ c->c_errors++;
+ }
+ com_addbyte(c, BREAK_LOOP);
+ break;
+ case return_stmt:
+ com_return_stmt(c, n);
+ break;
+ case raise_stmt:
+ com_raise_stmt(c, n);
+ break;
+ case import_stmt:
+ com_import_stmt(c, n);
+ break;
+ case if_stmt:
+ com_if_stmt(c, n);
+ break;
+ case while_stmt:
+ com_while_stmt(c, n);
+ break;
+ case for_stmt:
+ com_for_stmt(c, n);
+ break;
+ case try_stmt:
+ com_try_stmt(c, n);
+ break;
+ case suite:
+ com_suite(c, n);
+ break;
+
+ /* Expression nodes */
+
+ case testlist:
+ com_list(c, n);
+ break;
+ case test:
+ com_test(c, n);
+ break;
+ case and_test:
+ com_and_test(c, n);
+ break;
+ case not_test:
+ com_not_test(c, n);
+ break;
+ case comparison:
+ com_comparison(c, n);
+ break;
+ case exprlist:
+ com_list(c, n);
+ break;
+ case expr:
+ com_expr(c, n);
+ break;
+ case term:
+ com_term(c, n);
+ break;
+ case factor:
+ com_factor(c, n);
+ break;
+ case atom:
+ com_atom(c, n);
+ break;
+
+ default:
+ fprintf(stderr, "node type %d\n", TYPE(n));
+ err_setstr(SystemError, "com_node: unexpected node type");
+ c->c_errors++;
+ }
+}
+
+static void com_fplist PROTO((struct compiling *, node *));
+
+static void
+com_fpdef(c, n)
+ struct compiling *c;
+ node *n;
+{
+ REQ(n, fpdef); /* fpdef: NAME | '(' fplist ')' */
+ if (TYPE(CHILD(n, 0)) == LPAR)
+ com_fplist(c, CHILD(n, 1));
+ else
+ com_addopname(c, STORE_NAME, CHILD(n, 0));
+}
+
+static void
+com_fplist(c, n)
+ struct compiling *c;
+ node *n;
+{
+ REQ(n, fplist); /* fplist: fpdef (',' fpdef)* */
+ if (NCH(n) == 1) {
+ com_fpdef(c, CHILD(n, 0));
+ }
+ else {
+ int i;
+ com_addoparg(c, UNPACK_TUPLE, (NCH(n)+1)/2);
+ for (i = 0; i < NCH(n); i += 2)
+ com_fpdef(c, CHILD(n, i));
+ }
+}
+
+static void
+com_file_input(c, n)
+ struct compiling *c;
+ node *n;
+{
+ int i;
+ REQ(n, file_input); /* (NEWLINE | stmt)* ENDMARKER */
+ for (i = 0; i < NCH(n); i++) {
+ node *ch = CHILD(n, i);
+ if (TYPE(ch) != ENDMARKER && TYPE(ch) != NEWLINE)
+ com_node(c, ch);
+ }
+}
+
+/* Top-level compile-node interface */
+
+static void
+compile_funcdef(c, n)
+ struct compiling *c;
+ node *n;
+{
+ node *ch;
+ REQ(n, funcdef); /* funcdef: 'def' NAME parameters ':' suite */
+ ch = CHILD(n, 2); /* parameters: '(' [fplist] ')' */
+ ch = CHILD(ch, 1); /* ')' | fplist */
+ if (TYPE(ch) == RPAR)
+ com_addbyte(c, REFUSE_ARGS);
+ else {
+ com_addbyte(c, REQUIRE_ARGS);
+ com_fplist(c, ch);
+ }
+ c->c_infunction = 1;
+ com_node(c, CHILD(n, 4));
+ c->c_infunction = 0;
+ com_addoparg(c, LOAD_CONST, com_addconst(c, None));
+ com_addbyte(c, RETURN_VALUE);
+}
+
+static void
+compile_node(c, n)
+ struct compiling *c;
+ node *n;
+{
+ com_addoparg(c, SET_LINENO, n->n_lineno);
+
+ switch (TYPE(n)) {
+
+ case single_input: /* One interactive command */
+ /* NEWLINE | simple_stmt | compound_stmt NEWLINE */
+ com_addbyte(c, REFUSE_ARGS);
+ n = CHILD(n, 0);
+ if (TYPE(n) != NEWLINE)
+ com_node(c, n);
+ com_addoparg(c, LOAD_CONST, com_addconst(c, None));
+ com_addbyte(c, RETURN_VALUE);
+ break;
+
+ case file_input: /* A whole file, or built-in function exec() */
+ com_addbyte(c, REFUSE_ARGS);
+ com_file_input(c, n);
+ com_addoparg(c, LOAD_CONST, com_addconst(c, None));
+ com_addbyte(c, RETURN_VALUE);
+ break;
+
+ case expr_input: /* Built-in function eval() */
+ com_addbyte(c, REFUSE_ARGS);
+ com_node(c, CHILD(n, 0));
+ com_addbyte(c, RETURN_VALUE);
+ break;
+
+ case eval_input: /* Built-in function input() */
+ com_addbyte(c, REFUSE_ARGS);
+ com_node(c, CHILD(n, 0));
+ com_addbyte(c, RETURN_VALUE);
+ break;
+
+ case funcdef: /* A function definition */
+ compile_funcdef(c, n);
+ break;
+
+ case classdef: /* A class definition */
+ /* 'class' NAME parameters ['=' baselist] ':' suite */
+ com_addbyte(c, REFUSE_ARGS);
+ com_node(c, CHILD(n, NCH(n)-1));
+ com_addbyte(c, LOAD_LOCALS);
+ com_addbyte(c, RETURN_VALUE);
+ break;
+
+ default:
+ fprintf(stderr, "node type %d\n", TYPE(n));
+ err_setstr(SystemError, "compile_node: unexpected node type");
+ c->c_errors++;
+ }
+}
+
+codeobject *
+compile(n, filename)
+ node *n;
+ char *filename;
+{
+ struct compiling sc;
+ codeobject *co;
+ if (!com_init(&sc, filename))
+ return NULL;
+ compile_node(&sc, n);
+ com_done(&sc);
+ if (sc.c_errors == 0)
+ co = newcodeobject(sc.c_code, sc.c_consts, sc.c_names, filename);
+ else
+ co = NULL;
+ com_free(&sc);
+ return co;
+}
diff --git a/src/compile.h b/src/compile.h
new file mode 100644
index 0000000..fb66ea7
--- /dev/null
+++ b/src/compile.h
@@ -0,0 +1,47 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* Definitions for compiled intermediate code */
+
+
+/* An intermediate code fragment contains:
+ - a string that encodes the instructions,
+ - a list of the constants,
+ - and a list of the names used. */
+
+typedef struct {
+ OB_HEAD
+ stringobject *co_code; /* instruction opcodes */
+ object *co_consts; /* list of immutable constant objects */
+ object *co_names; /* list of stringobjects */
+ object *co_filename; /* string */
+} codeobject;
+
+extern typeobject Codetype;
+
+#define is_codeobject(op) ((op)->ob_type == &Codetype)
+
+
+/* Public interface */
+codeobject *compile PROTO((struct _node *, char *));
diff --git a/src/config.c b/src/config.c
new file mode 100644
index 0000000..9d153c1
--- /dev/null
+++ b/src/config.c
@@ -0,0 +1,180 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* Configurable Python configuration file */
+
+#include <stdio.h>
+
+#ifdef USE_STDWIN
+#include <stdwin.h>
+
+static int use_stdwin;
+#endif
+
+/*ARGSUSED*/
+void
+initargs(p_argc, p_argv)
+ int *p_argc;
+ char ***p_argv;
+{
+#ifdef USE_STDWIN
+ extern char *getenv();
+ char *display;
+
+ /* Ignore an initial argument of '-s', for backward compatibility */
+ if (*p_argc > 1 && strcmp((*p_argv)[1], "-s") == 0) {
+ (*p_argv)[1] = (*p_argv)[0];
+ (*p_argc)--, (*p_argv)++;
+ }
+
+ /* Assume we have to initialize stdwin if either of the following
+ conditions holds:
+ - the environment variable $DISPLAY is set
+ - there is an argument "-display" somewhere
+ */
+
+ display = getenv("DISPLAY");
+ if (display != 0)
+ use_stdwin = 1;
+ else {
+ int i;
+ /* Scan through the arguments looking for "-display" */
+ for (i = 1; i < *p_argc; i++) {
+ if (strcmp((*p_argv)[i], "-display") == 0) {
+ use_stdwin = 1;
+ break;
+ }
+ }
+ }
+
+ if (use_stdwin)
+ wargs(p_argc, p_argv);
+#endif
+}
+
+void
+initcalls()
+{
+}
+
+void
+donecalls()
+{
+#ifdef USE_STDWIN
+ if (use_stdwin)
+ wdone();
+#endif
+#ifdef USE_AUDIO
+ asa_done();
+#endif
+}
+
+#ifdef USE_STDWIN
+static void
+maybeinitstdwin()
+{
+ if (use_stdwin)
+ initstdwin();
+ else
+ fprintf(stderr,
+ "No $DISPLAY nor -display arg -- stdwin not available\n");
+}
+#endif
+
+#ifndef PYTHONPATH
+#define PYTHONPATH ".:/usr/local/lib/python"
+#endif
+
+extern char *getenv();
+
+char *
+getpythonpath()
+{
+ char *path = getenv("PYTHONPATH");
+ if (path == 0)
+ path = PYTHONPATH;
+ return path;
+}
+
+
+/* Table of built-in modules.
+ These are initialized when first imported. */
+
+/* Standard modules */
+extern void inittime();
+extern void initmath();
+extern void initregexp();
+extern void initposix();
+#ifdef USE_AUDIO
+extern void initaudio();
+#endif
+#ifdef USE_AMOEBA
+extern void initamoeba();
+#endif
+#ifdef USE_GL
+extern void initgl();
+#ifdef USE_PANEL
+extern void initpanel();
+#endif
+#endif
+#ifdef USE_STDWIN
+extern void maybeinitstdwin();
+#endif
+
+struct {
+ char *name;
+ void (*initfunc)();
+} inittab[] = {
+
+ /* Standard modules */
+
+ {"time", inittime},
+ {"math", initmath},
+ {"regexp", initregexp},
+ {"posix", initposix},
+
+
+ /* Optional modules */
+
+#ifdef USE_AUDIO
+ {"audio", initaudio},
+#endif
+
+#ifdef USE_AMOEBA
+ {"amoeba", initamoeba},
+#endif
+
+#ifdef USE_GL
+ {"gl", initgl},
+#ifdef USE_PANEL
+ {"pnl", initpanel},
+#endif
+#endif
+
+#ifdef USE_STDWIN
+ {"stdwin", maybeinitstdwin},
+#endif
+
+ {0, 0} /* Sentinel */
+};
diff --git a/src/configmac.c b/src/configmac.c
new file mode 100644
index 0000000..c73130a
--- /dev/null
+++ b/src/configmac.c
@@ -0,0 +1,109 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* Configuration using STDWIN on the Mac (THINK_C or MPW) */
+
+#ifdef THINK_C
+#define USE_STDWIN
+#endif
+
+#ifdef USE_STDWIN
+#include "stdwin.h"
+#endif
+
+void
+initargs(p_argc, p_argv)
+ int *p_argc;
+ char ***p_argv;
+{
+#ifdef USE_STDWIN
+
+#ifdef THINK_C_3_0
+ wsetstdio(1);
+#else
+ /* This printf() statement is really needed only
+ to initialize THINK C 4.0's stdio: */
+ printf(
+"Python 4.0, Copyright 1990 Stichting Mathematisch Centrum, Amsterdam\n");
+#endif
+
+ wargs(p_argc, p_argv);
+#endif
+}
+
+void
+initcalls()
+{
+}
+
+void
+donecalls()
+{
+#ifdef USE_STDWIN
+ wdone();
+#endif
+}
+
+#ifndef PYTHONPATH
+/* On the Mac, the search path is a space-separated list of directories */
+#define PYTHONPATH ": :lib :lib:stdwin :lib:mac :lib:demo"
+#endif
+
+char *
+getpythonpath()
+{
+ return PYTHONPATH;
+}
+
+
+/* Table of built-in modules.
+ These are initialized when first imported. */
+
+/* Standard modules */
+extern void inittime();
+extern void initmath();
+extern void initregexp();
+
+/* Mac-specific modules */
+extern void initmac();
+#ifdef USE_STDWIN
+extern void initstdwin();
+#endif
+
+struct {
+ char *name;
+ void (*initfunc)();
+} inittab[] = {
+ /* Standard modules */
+ {"time", inittime},
+ {"math", initmath},
+ {"regexp", initregexp},
+
+ /* Mac-specific modules */
+ {"mac", initmac},
+#ifdef USE_STDWIN
+ {"stdwin", initstdwin},
+#endif
+ {0, 0} /* Sentinel */
+};
diff --git a/src/cstubs b/src/cstubs
new file mode 100644
index 0000000..3996572
--- /dev/null
+++ b/src/cstubs
@@ -0,0 +1,999 @@
+/*
+Input used to generate the Python module "glmodule.c".
+The stub generator is a Python script called "cgen".
+
+Each definition must be contained on one line:
+
+<returntype> <name> <type> <arg> <type> <arg>
+
+<returntype> can be: void, short, long (XXX maybe others?)
+
+<type> can be: char, string, short, float, long, or double
+ string indicates a null terminated string;
+ if <type> is char and <arg> begins with a *, the * is stripped
+ and <type> is changed into string
+
+<arg> has the form <mode> or <mode>[<subscript>]
+ where <mode> can be
+ s: arg is sent
+ r: arg is received (arg is a pointer)
+ and <subscript> can be (N and I are numbers):
+ N
+ argI
+ retval
+ N*argI
+ N*retval
+*/
+
+#include <gl.h>
+#include <device.h>
+
+#include "allobjects.h"
+#include "import.h"
+#include "modsupport.h"
+#include "cgensupport.h"
+
+/*
+Some stubs are too complicated for the stub generator.
+We can include manually written versions of them here.
+A line starting with '%' gives the name of the function so the stub
+generator can include it in the table of functions.
+*/
+
+/*
+varray -- an array of v.. calls.
+The argument is an array (maybe list or tuple) of points.
+Each point must be a tuple or list of coordinates (x, y, z).
+The points may be 2- or 3-dimensional but must all have the
+same dimension. Float and int values may be mixed however.
+The points are always converted to 3D double precision points
+by assuming z=0.0 if necessary (as indicated in the man page),
+and for each point v3d() is called.
+*/
+
+% varray
+
+static object *
+gl_varray(self, args)
+ object *self;
+ object *args;
+{
+ object *v, *w;
+ int i, n, width;
+ double vec[3];
+ object * (*getitem) FPROTO((object *, int));
+
+ if (!getiobjectarg(args, 1, 0, &v))
+ return NULL;
+
+ if (is_listobject(v)) {
+ n = getlistsize(v);
+ getitem = getlistitem;
+ }
+ else if (is_tupleobject(v)) {
+ n = gettuplesize(v);
+ getitem = gettupleitem;
+ }
+ else {
+ err_badarg();
+ return NULL;
+ }
+
+ if (n == 0) {
+ INCREF(None);
+ return None;
+ }
+ if (n > 0)
+ w = (*getitem)(v, 0);
+
+ width = 0;
+ if (w == NULL) {
+ }
+ else if (is_listobject(w)) {
+ width = getlistsize(w);
+ }
+ else if (is_tupleobject(w)) {
+ width = gettuplesize(w);
+ }
+
+ switch (width) {
+ case 2:
+ vec[2] = 0.0;
+ /* Fall through */
+ case 3:
+ break;
+ default:
+ err_badarg();
+ return NULL;
+ }
+
+ for (i = 0; i < n; i++) {
+ w = (*getitem)(v, i);
+ if (!getidoublearray(w, 1, 0, width, vec))
+ return NULL;
+ v3d(vec);
+ }
+
+ INCREF(None);
+ return None;
+}
+
+/*
+vnarray, nvarray -- an array of n3f and v3f calls.
+The argument is an array (list or tuple) of pairs of points and normals.
+Each pair is a tuple (NOT a list) of a point and a normal for that point.
+Each point or normal must be a tuple (NOT a list) of coordinates (x, y, z).
+Three coordinates must be given. Float and int values may be mixed.
+For each pair, n3f() is called for the normal, and then v3f() is called
+for the vector.
+
+vnarray and nvarray differ only in the order of the vector and normal in
+the pair: vnarray expects (v, n) while nvarray expects (n, v).
+*/
+
+static object *gen_nvarray(); /* Forward */
+
+% nvarray
+
+static object *
+gl_nvarray(self, args)
+ object *self;
+ object *args;
+{
+ return gen_nvarray(args, 0);
+}
+
+% vnarray
+
+static object *
+gl_vnarray(self, args)
+ object *self;
+ object *args;
+{
+ return gen_nvarray(args, 1);
+}
+
+/* Generic, internal version of {nv,nv}array: inorm indicates the
+ argument order, 0: normal first, 1: vector first. */
+
+static object *
+gen_nvarray(args, inorm)
+ object *args;
+ int inorm;
+{
+ object *v, *w, *wnorm, *wvec;
+ int i, n;
+ float norm[3], vec[3];
+ object * (*getitem) FPROTO((object *, int));
+
+ if (!getiobjectarg(args, 1, 0, &v))
+ return NULL;
+
+ if (is_listobject(v)) {
+ n = getlistsize(v);
+ getitem = getlistitem;
+ }
+ else if (is_tupleobject(v)) {
+ n = gettuplesize(v);
+ getitem = gettupleitem;
+ }
+ else {
+ err_badarg();
+ return NULL;
+ }
+
+ for (i = 0; i < n; i++) {
+ w = (*getitem)(v, i);
+ if (!is_tupleobject(w) || gettuplesize(w) != 2) {
+ err_badarg();
+ return NULL;
+ }
+ wnorm = gettupleitem(w, inorm);
+ wvec = gettupleitem(w, 1 - inorm);
+ if (!getifloatarray(wnorm, 1, 0, 3, norm) ||
+ !getifloatarray(wvec, 1, 0, 3, vec))
+ return NULL;
+ n3f(norm);
+ v3f(vec);
+ }
+
+ INCREF(None);
+ return None;
+}
+
+/* nurbssurface(s_knots[], t_knots[], ctl[][], s_order, t_order, type).
+ The dimensions of ctl[] are computed as follows:
+ [len(s_knots) - s_order], [len(t_knots) - t_order]
+*/
+
+% nurbssurface
+
+static object *
+gl_nurbssurface(self, args)
+ object *self;
+ object *args;
+{
+ long arg1 ;
+ double * arg2 ;
+ long arg3 ;
+ double * arg4 ;
+ double *arg5 ;
+ long arg6 ;
+ long arg7 ;
+ long arg8 ;
+ long ncoords;
+ long s_byte_stride, t_byte_stride;
+ long s_nctl, t_nctl;
+ long s, t;
+ object *v, *w, *pt;
+ double *pnext;
+ if (!getilongarraysize(args, 6, 0, &arg1))
+ return NULL;
+ if ((arg2 = NEW(double, arg1 )) == NULL) {
+ return err_nomem();
+ }
+ if (!getidoublearray(args, 6, 0, arg1 , arg2))
+ return NULL;
+ if (!getilongarraysize(args, 6, 1, &arg3))
+ return NULL;
+ if ((arg4 = NEW(double, arg3 )) == NULL) {
+ return err_nomem();
+ }
+ if (!getidoublearray(args, 6, 1, arg3 , arg4))
+ return NULL;
+ if (!getilongarg(args, 6, 3, &arg6))
+ return NULL;
+ if (!getilongarg(args, 6, 4, &arg7))
+ return NULL;
+ if (!getilongarg(args, 6, 5, &arg8))
+ return NULL;
+ if (arg8 == N_XYZ)
+ ncoords = 3;
+ else if (arg8 == N_XYZW)
+ ncoords = 4;
+ else {
+ err_badarg();
+ return NULL;
+ }
+ s_nctl = arg1 - arg6;
+ t_nctl = arg3 - arg7;
+ if (!getiobjectarg(args, 6, 2, &v))
+ return NULL;
+ if (!is_listobject(v) || getlistsize(v) != s_nctl) {
+ err_badarg();
+ return NULL;
+ }
+ if ((arg5 = NEW(double, s_nctl*t_nctl*ncoords )) == NULL) {
+ return err_nomem();
+ }
+ pnext = arg5;
+ for (s = 0; s < s_nctl; s++) {
+ w = getlistitem(v, s);
+ if (w == NULL || !is_listobject(w) ||
+ getlistsize(w) != t_nctl) {
+ err_badarg();
+ return NULL;
+ }
+ for (t = 0; t < t_nctl; t++) {
+ pt = getlistitem(w, t);
+ if (!getidoublearray(pt, 1, 0, ncoords, pnext))
+ return NULL;
+ pnext += ncoords;
+ }
+ }
+ s_byte_stride = sizeof(double) * ncoords;
+ t_byte_stride = s_byte_stride * s_nctl;
+ nurbssurface( arg1 , arg2 , arg3 , arg4 ,
+ s_byte_stride , t_byte_stride , arg5 , arg6 , arg7 , arg8 );
+ DEL(arg2);
+ DEL(arg4);
+ DEL(arg5);
+ INCREF(None);
+ return None;
+}
+
+/* nurbscurve(knots, ctlpoints, order, type).
+ The length of ctlpoints is len(knots)-order. */
+
+%nurbscurve
+
+static object *
+gl_nurbscurve(self, args)
+ object *self;
+ object *args;
+{
+ long arg1 ;
+ double * arg2 ;
+ long arg3 ;
+ double * arg4 ;
+ long arg5 ;
+ long arg6 ;
+ int ncoords, npoints;
+ int i;
+ object *v;
+ double *pnext;
+ if (!getilongarraysize(args, 4, 0, &arg1))
+ return NULL;
+ if ((arg2 = NEW(double, arg1 )) == NULL) {
+ return err_nomem();
+ }
+ if (!getidoublearray(args, 4, 0, arg1 , arg2))
+ return NULL;
+ if (!getilongarg(args, 4, 2, &arg5))
+ return NULL;
+ if (!getilongarg(args, 4, 3, &arg6))
+ return NULL;
+ if (arg6 == N_ST)
+ ncoords = 2;
+ else if (arg6 == N_STW)
+ ncoords = 3;
+ else {
+ err_badarg();
+ return NULL;
+ }
+ npoints = arg1 - arg5;
+ if (!getiobjectarg(args, 4, 1, &v))
+ return NULL;
+ if (!is_listobject(v) || getlistsize(v) != npoints) {
+ err_badarg();
+ return NULL;
+ }
+ if ((arg4 = NEW(double, npoints*ncoords )) == NULL) {
+ return err_nomem();
+ }
+ pnext = arg4;
+ for (i = 0; i < npoints; i++) {
+ if (!getidoublearray(getlistitem(v, i), 1, 0, ncoords, pnext))
+ return NULL;
+ pnext += ncoords;
+ }
+ arg3 = (sizeof(double)) * ncoords;
+ nurbscurve( arg1 , arg2 , arg3 , arg4 , arg5 , arg6 );
+ DEL(arg2);
+ DEL(arg4);
+ INCREF(None);
+ return None;
+}
+
+/* pwlcurve(points, type).
+ Points is a list of points. Type must be N_ST. */
+
+%pwlcurve
+
+static object *
+gl_pwlcurve(self, args)
+ object *self;
+ object *args;
+{
+ object *v;
+ long type;
+ double *data, *pnext;
+ long npoints, ncoords;
+ int i;
+ if (!getiobjectarg(args, 2, 0, &v))
+ return NULL;
+ if (!getilongarg(args, 2, 1, &type))
+ return NULL;
+ if (!is_listobject(v)) {
+ err_badarg();
+ return NULL;
+ }
+ npoints = getlistsize(v);
+ if (type == N_ST)
+ ncoords = 2;
+ else {
+ err_badarg();
+ return NULL;
+ }
+ if ((data = NEW(double, npoints*ncoords)) == NULL) {
+ return err_nomem();
+ }
+ pnext = data;
+ for (i = 0; i < npoints; i++) {
+ if (!getidoublearray(getlistitem(v, i), 1, 0, ncoords, pnext))
+ return NULL;
+ pnext += ncoords;
+ }
+ pwlcurve(npoints, data, sizeof(double)*ncoords, type);
+ DEL(data);
+ INCREF(None);
+ return None;
+}
+
+
+/* Picking and Selecting */
+
+static short *pickbuffer = NULL;
+static long pickbuffersize;
+
+static object *
+pick_select(args, func)
+ object *args;
+ void (*func)();
+{
+ if (!getilongarg(args, 1, 0, &pickbuffersize))
+ return NULL;
+ if (pickbuffer != NULL) {
+ err_setstr(RuntimeError,
+ "pick/gselect: already picking/selecting");
+ return NULL;
+ }
+ if ((pickbuffer = NEW(short, pickbuffersize)) == NULL) {
+ return err_nomem();
+ }
+ (*func)(pickbuffer, pickbuffersize);
+ INCREF(None);
+ return None;
+}
+
+static object *
+endpick_select(args, func)
+ object *args;
+ long (*func)();
+{
+ object *v, *w;
+ int i, nhits, n;
+ if (!getnoarg(args))
+ return NULL;
+ if (pickbuffer == NULL) {
+ err_setstr(RuntimeError,
+ "endpick/endselect: not in pick/select mode");
+ return NULL;
+ }
+ nhits = (*func)(pickbuffer);
+ if (nhits < 0) {
+ nhits = -nhits; /* How to report buffer overflow otherwise? */
+ }
+ /* Scan the buffer to see how many integers */
+ n = 0;
+ for (; nhits > 0; nhits--) {
+ n += 1 + pickbuffer[n];
+ }
+ v = newlistobject(n);
+ if (v == NULL)
+ return NULL;
+ /* XXX Could do it nicer and interpret the data structure here,
+ returning a list of lists. But this can be done in Python... */
+ for (i = 0; i < n; i++) {
+ w = newintobject((long)pickbuffer[i]);
+ if (w == NULL) {
+ DECREF(v);
+ return NULL;
+ }
+ setlistitem(v, i, w);
+ }
+ DEL(pickbuffer);
+ pickbuffer = NULL;
+ return v;
+}
+
+extern void pick(), gselect();
+extern long endpick(), endselect();
+
+%pick
+static object *gl_pick(self, args) object *self, *args; {
+ return pick_select(args, pick);
+}
+
+%endpick
+static object *gl_endpick(self, args) object *self, *args; {
+ return endpick_select(args, endpick);
+}
+
+%gselect
+static object *gl_gselect(self, args) object *self, *args; {
+ return pick_select(args, gselect);
+}
+
+%endselect
+static object *gl_endselect(self, args) object *self, *args; {
+ return endpick_select(args, endselect);
+}
+
+
+/* XXX The generator botches this one. Here's a quick hack to fix it. */
+
+% getmatrix float r[16]
+
+static object *
+gl_getmatrix(self, args)
+ object *self;
+ object *args;
+{
+ float arg1 [ 16 ] ;
+ object *v, *w;
+ int i;
+ getmatrix( arg1 );
+ v = newlistobject(16);
+ if (v == NULL) {
+ return err_nomem();
+ }
+ for (i = 0; i < 16; i++) {
+ w = mknewfloatobject(arg1[i]);
+ if (w == NULL) {
+ DECREF(v);
+ return NULL;
+ }
+ setlistitem(v, i, w);
+ }
+ return v;
+}
+
+/* End of manually written stubs */
+
+%%
+
+long getshade
+void devport short s long s
+void rdr2i long s long s
+void rectfs short s short s short s short s
+void rects short s short s short s short s
+void rmv2i long s long s
+void noport
+void popviewport
+void clear
+void clearhitcode
+void closeobj
+void cursoff
+void curson
+void doublebuffer
+void finish
+void gconfig
+void ginit
+void greset
+void multimap
+void onemap
+void popattributes
+void popmatrix
+void pushattributes
+void pushmatrix
+void pushviewport
+void qreset
+void RGBmode
+void singlebuffer
+void swapbuffers
+void gsync
+void tpon
+void tpoff
+void clkon
+void clkoff
+void ringbell
+#void callfunc
+void gbegin
+void textinit
+void initnames
+void pclos
+void popname
+void spclos
+void zclear
+void screenspace
+void reshapeviewport
+void winpush
+void winpop
+void foreground
+void endfullscrn
+void endpupmode
+void fullscrn
+void pupmode
+void winconstraints
+void pagecolor short s
+void textcolor short s
+void color short s
+void curveit short s
+void font short s
+void linewidth short s
+void setlinestyle short s
+void setmap short s
+void swapinterval short s
+void writemask short s
+void textwritemask short s
+void qdevice short s
+void unqdevice short s
+void curvebasis short s
+void curveprecision short s
+void loadname short s
+void passthrough short s
+void pushname short s
+void setmonitor short s
+void setshade short s
+void setpattern short s
+void pagewritemask short s
+#
+void callobj long s
+void delobj long s
+void editobj long s
+void makeobj long s
+void maketag long s
+void chunksize long s
+void compactify long s
+void deltag long s
+void lsrepeat long s
+void objinsert long s
+void objreplace long s
+void winclose long s
+void blanktime long s
+void freepup long s
+# This is not in the library!?
+###void pupcolor long s
+#
+void backbuffer long s
+void frontbuffer long s
+void lsbackup long s
+void resetls long s
+void lampon long s
+void lampoff long s
+void setbell long s
+void blankscreen long s
+void depthcue long s
+void zbuffer long s
+void backface long s
+#
+void cmov2i long s long s
+void draw2i long s long s
+void move2i long s long s
+void pnt2i long s long s
+void patchbasis long s long s
+void patchprecision long s long s
+void pdr2i long s long s
+void pmv2i long s long s
+void rpdr2i long s long s
+void rpmv2i long s long s
+void xfpt2i long s long s
+void objdelete long s long s
+void patchcurves long s long s
+void minsize long s long s
+void maxsize long s long s
+void keepaspect long s long s
+void prefsize long s long s
+void stepunit long s long s
+void fudge long s long s
+void winmove long s long s
+#
+void attachcursor short s short s
+void deflinestyle short s short s
+void noise short s short s
+void picksize short s short s
+void qenter short s short s
+void setdepth short s short s
+void cmov2s short s short s
+void draw2s short s short s
+void move2s short s short s
+void pdr2s short s short s
+void pmv2s short s short s
+void pnt2s short s short s
+void rdr2s short s short s
+void rmv2s short s short s
+void rpdr2s short s short s
+void rpmv2s short s short s
+void xfpt2s short s short s
+#
+void cmov2 float s float s
+void draw2 float s float s
+void move2 float s float s
+void pnt2 float s float s
+void pdr2 float s float s
+void pmv2 float s float s
+void rdr2 float s float s
+void rmv2 float s float s
+void rpdr2 float s float s
+void rpmv2 float s float s
+void xfpt2 float s float s
+#
+void loadmatrix float s[16]
+void multmatrix float s[16]
+void crv float s[16]
+void rcrv float s[16]
+#
+# Methods that have strings.
+#
+void addtopup long s char *s long s
+void charstr char *s
+void getport char *s
+long strwidth char *s
+long winopen char *s
+void wintitle char *s
+#
+# Methods that have 1 long (# of elements) and an array
+#
+void polf long s float s[3*arg1]
+void polf2 long s float s[2*arg1]
+void poly long s float s[3*arg1]
+void poly2 long s float s[2*arg1]
+void crvn long s float s[3*arg1]
+void rcrvn long s float s[4*arg1]
+#
+void polf2i long s long s[2*arg1]
+void polfi long s long s[3*arg1]
+void poly2i long s long s[2*arg1]
+void polyi long s long s[3*arg1]
+#
+void polf2s long s short s[2*arg1]
+void polfs long s short s[3*arg1]
+void polys long s short s[3*arg1]
+void poly2s long s short s[2*arg1]
+#
+void defcursor short s short s[16]
+void writepixels short s short s[arg1]
+void defbasis long s float s[16]
+void gewrite short s short s[arg1]
+#
+void rotate short s char s
+# This is not in the library!?
+###void setbutton short s char s
+void rot float s char s
+#
+void circfi long s long s long s
+void circi long s long s long s
+void cmovi long s long s long s
+void drawi long s long s long s
+void movei long s long s long s
+void pnti long s long s long s
+void newtag long s long s long s
+void pdri long s long s long s
+void pmvi long s long s long s
+void rdri long s long s long s
+void rmvi long s long s long s
+void rpdri long s long s long s
+void rpmvi long s long s long s
+void xfpti long s long s long s
+#
+void circ float s float s float s
+void circf float s float s float s
+void cmov float s float s float s
+void draw float s float s float s
+void move float s float s float s
+void pnt float s float s float s
+void scale float s float s float s
+void translate float s float s float s
+void pdr float s float s float s
+void pmv float s float s float s
+void rdr float s float s float s
+void rmv float s float s float s
+void rpdr float s float s float s
+void rpmv float s float s float s
+void xfpt float s float s float s
+#
+void RGBcolor short s short s short s
+void RGBwritemask short s short s short s
+void setcursor short s short s short s
+void tie short s short s short s
+void circfs short s short s short s
+void circs short s short s short s
+void cmovs short s short s short s
+void draws short s short s short s
+void moves short s short s short s
+void pdrs short s short s short s
+void pmvs short s short s short s
+void pnts short s short s short s
+void rdrs short s short s short s
+void rmvs short s short s short s
+void rpdrs short s short s short s
+void rpmvs short s short s short s
+void xfpts short s short s short s
+void curorigin short s short s short s
+void cyclemap short s short s short s
+#
+void patch float s[16] float s[16] float s[16]
+void splf long s float s[3*arg1] short s[arg1]
+void splf2 long s float s[2*arg1] short s[arg1]
+void splfi long s long s[3*arg1] short s[arg1]
+void splf2i long s long s[2*arg1] short s[arg1]
+void splfs long s short s[3*arg1] short s[arg1]
+void splf2s long s short s[2*arg1] short s[arg1]
+void defpattern short s short s short s[arg2*arg2/16]
+#
+void rpatch float s[16] float s[16] float s[16] float s[16]
+#
+# routines that send 4 floats
+#
+void ortho2 float s float s float s float s
+void rect float s float s float s float s
+void rectf float s float s float s float s
+void xfpt4 float s float s float s float s
+#
+void textport short s short s short s short s
+void mapcolor short s short s short s short s
+void scrmask short s short s short s short s
+void setvaluator short s short s short s short s
+void viewport short s short s short s short s
+void shaderange short s short s short s short s
+void xfpt4s short s short s short s short s
+void rectfi long s long s long s long s
+void recti long s long s long s long s
+void xfpt4i long s long s long s long s
+void prefposition long s long s long s long s
+#
+void arc float s float s float s short s short s
+void arcf float s float s float s short s short s
+void arcfi long s long s long s short s short s
+void arci long s long s long s short s short s
+#
+void bbox2 short s short s float s float s float s float s
+void bbox2i short s short s long s long s long s long s
+void bbox2s short s short s short s short s short s short s
+void blink short s short s short s short s short s
+void ortho float s float s float s float s float s float s
+void window float s float s float s float s float s float s
+void lookat float s float s float s float s float s float s short s
+#
+void perspective short s float s float s float s
+void polarview float s short s short s short s
+# XXX getichararray not supported
+#void writeRGB short s char s[arg1] char s[arg1] char s[arg1]
+#
+void arcfs short s short s short s short s short s
+void arcs short s short s short s short s short s
+void rectcopy short s short s short s short s short s short s
+void RGBcursor short s short s short s short s short s short s short s
+#
+long getbutton short s
+long getcmmode
+long getlsbackup
+long getresetls
+long getdcm
+long getzbuffer
+long ismex
+long isobj long s
+long isqueued short s
+long istag long s
+#
+long genobj
+long gentag
+long getbuffer
+long getcolor
+long getdisplaymode
+long getfont
+long getheight
+long gethitcode
+long getlstyle
+long getlwidth
+long getmap
+long getplanes
+long getwritemask
+long qtest
+long getlsrepeat
+long getmonitor
+long getopenobj
+long getpattern
+long winget
+long winattach
+long getothermonitor
+long newpup
+#
+long getvaluator short s
+void winset long s
+long dopup long s
+void getdepth short r short r
+void getcpos short r short r
+void getsize long r long r
+void getorigin long r long r
+void getviewport short r short r short r short r
+void gettp short r short r short r short r
+void getgpos float r float r float r float r
+void winposition long s long s long s long s
+void gRGBcolor short r short r short r
+void gRGBmask short r short r short r
+void getscrmask short r short r short r short r
+void gRGBcursor short r short r short r short r short r short r short r short r long *
+void getmcolor short s short r short r short r
+void mapw long s short s short s float r float r float r float r float r float r
+void mapw2 long s short s short s float r float r
+void defrasterfont short s short s short s Fontchar s[arg3] short s short s[4*arg5]
+long qread short r
+void getcursor short r short r short r long r
+#
+# For these we receive arrays of stuff
+#
+void getdev long s short s[arg1] short r[arg1]
+#XXX not generated correctly yet
+#void getmatrix float r[16]
+long readpixels short s short r[retval]
+long readRGB short s char r[retval] char r[retval] char r[retval]
+long blkqread short s short r[arg1]
+#
+# New 4D routines
+#
+void cmode
+void concave long s
+void curstype long s
+void drawmode long s
+void gammaramp short s[256] short s[256] short s[256]
+long getbackface
+long getdescender
+long getdrawmode
+long getmmode
+long getsm
+long getvideo long s
+void imakebackground
+void lmbind short s short s
+void lmdef long s long s long s float s[arg3]
+void mmode long s
+void normal float s[3]
+void overlay long s
+void RGBrange short s short s short s short s short s short s short s short s
+void setvideo long s long s
+void shademodel long s
+void underlay long s
+#
+# New Personal Iris/GT Routines
+#
+void bgnclosedline
+void bgnline
+void bgnpoint
+void bgnpolygon
+void bgnsurface
+void bgntmesh
+void bgntrim
+void endclosedline
+void endline
+void endpoint
+void endpolygon
+void endsurface
+void endtmesh
+void endtrim
+void blendfunction long s long s
+void c3f float s[3]
+void c3i long s[3]
+void c3s short s[3]
+void c4f float s[4]
+void c4i long s[4]
+void c4s short s[4]
+void colorf float s
+void cpack long s
+void czclear long s long s
+void dglclose long s
+long dglopen char *s long s
+long getgdesc long s
+void getnurbsproperty long s float r
+void glcompat long s long s
+void iconsize long s long s
+void icontitle char *s
+void lRGBrange short s short s short s short s short s short s long s long s
+void linesmooth long s
+void lmcolor long s
+void logicop long s
+long lrectread short s short s short s short s long r[retval]
+void lrectwrite short s short s short s short s long s[(arg2-arg1+1)*(arg4-arg3+1)]
+long rectread short s short s short s short s short r[retval]
+void rectwrite short s short s short s short s short s[(arg2-arg1+1)*(arg4-arg3+1)]
+void lsetdepth long s long s
+void lshaderange short s short s long s long s
+void n3f float s[3]
+void noborder
+void pntsmooth long s
+void readsource long s
+void rectzoom float s float s
+void sbox float s float s float s float s
+void sboxi long s long s long s long s
+void sboxs short s short s short s short s
+void sboxf float s float s float s float s
+void sboxfi long s long s long s long s
+void sboxfs short s short s short s short s
+void setnurbsproperty long s float s
+void setpup long s long s long s
+void smoothline long s
+void subpixel long s
+void swaptmesh
+long swinopen long s
+void v2f float s[2]
+void v2i long s[2]
+void v2s short s[2]
+void v3f float s[3]
+void v3i long s[3]
+void v3s short s[3]
+void v4f float s[4]
+void v4i long s[4]
+void v4s short s[4]
+void videocmd long s
+long windepth long s
+void wmpack long s
+void zdraw long s
+void zfunction long s
+void zsource long s
+void zwritemask long s
+#
+# uses doubles
+#
+void v2d double s[2]
+void v3d double s[3]
+void v4d double s[4]
diff --git a/src/dictobject.c b/src/dictobject.c
new file mode 100644
index 0000000..3bbd1d5
--- /dev/null
+++ b/src/dictobject.c
@@ -0,0 +1,605 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* Dictionary object implementation; using a hash table */
+
+/*
+XXX Note -- although this may look professional, I didn't think very hard
+about the problem and it is possible that obvious improvements exist.
+A similar module that I saw by Chris Torek:
+- uses chaining instead of hashed linear probing
+- remembers the hash value with the entry to speed up table resizing
+- sets the table size to a power of 2
+- uses a different hash function:
+ h = 0; p = str; while (*p) h = (h<<5) - h + *p++;
+*/
+
+#include "allobjects.h"
+
+
+/*
+Table of primes suitable as keys, in ascending order.
+The first line are the largest primes less than some powers of two,
+the second line is the largest prime less than 6000,
+and the third line is a selection from Knuth, Vol. 3, Sec. 6.1, Table 1.
+The final value is a sentinel and should cause the memory allocation
+of that many entries to fail (if none of the earlier values cause such
+failure already).
+*/
+static unsigned int primes[] = {
+ 3, 7, 13, 31, 61, 127, 251, 509, 1021, 2017, 4093,
+ 5987,
+ 9551, 15683, 19609, 31397,
+ 0xffffffff /* All bits set -- truncation OK */
+};
+
+/* String used as dummy key to fill deleted entries */
+static stringobject *dummy; /* Initialized by first call to newdictobject() */
+
+/*
+Invariant for entries: when in use, de_value is not NULL and de_key is
+not NULL and not dummy; when not in use, de_value is NULL and de_key
+is either NULL or dummy. A dummy key value cannot be replaced by NULL,
+since otherwise other keys may be lost.
+*/
+typedef struct {
+ stringobject *de_key;
+ object *de_value;
+} dictentry;
+
+/*
+To ensure the lookup algorithm terminates, the table size must be a
+prime number and there must be at least one NULL key in the table.
+The value di_fill is the number of non-NULL keys; di_used is the number
+of non-NULL, non-dummy keys.
+To avoid slowing down lookups on a near-full table, we resize the table
+when it is more than half filled.
+*/
+typedef struct {
+ OB_HEAD
+ int di_fill;
+ int di_used;
+ int di_size;
+ dictentry *di_table;
+} dictobject;
+
+object *
+newdictobject()
+{
+ register dictobject *dp;
+ if (dummy == NULL) { /* Auto-initialize dummy */
+ dummy = (stringobject *) newstringobject("");
+ if (dummy == NULL)
+ return NULL;
+ }
+ dp = NEWOBJ(dictobject, &Dicttype);
+ if (dp == NULL)
+ return NULL;
+ dp->di_size = primes[0];
+ dp->di_table = (dictentry *) calloc(sizeof(dictentry), dp->di_size);
+ if (dp->di_table == NULL) {
+ DEL(dp);
+ return err_nomem();
+ }
+ dp->di_fill = 0;
+ dp->di_used = 0;
+ return (object *)dp;
+}
+
+/*
+The basic lookup function used by all operations.
+This is essentially Algorithm D from Knuth Vol. 3, Sec. 6.4.
+Open addressing is preferred over chaining since the link overhead for
+chaining would be substantial (100% with typical malloc overhead).
+
+First a 32-bit hash value, 'sum', is computed from the key string.
+The first character is added an extra time shifted by 8 to avoid hashing
+single-character keys (often heavily used variables) too close together.
+All arithmetic on sum should ignore overflow.
+
+The initial probe index is then computed as sum mod the table size.
+Subsequent probe indices are incr apart (mod table size), where incr
+is also derived from sum, with the additional requirement that it is
+relative prime to the table size (i.e., 1 <= incr < size, since the size
+is a prime number). My choice for incr is somewhat arbitrary.
+*/
+static dictentry *lookdict PROTO((dictobject *, char *));
+static dictentry *
+lookdict(dp, key)
+ register dictobject *dp;
+ char *key;
+{
+ register int i, incr;
+ register dictentry *freeslot = NULL;
+ register unsigned char *p = (unsigned char *) key;
+ register unsigned long sum = *p << 7;
+ while (*p != '\0')
+ sum = sum + sum + *p++;
+ i = sum % dp->di_size;
+ do {
+ sum = sum + sum + 1;
+ incr = sum % dp->di_size;
+ } while (incr == 0);
+ for (;;) {
+ register dictentry *ep = &dp->di_table[i];
+ if (ep->de_key == NULL) {
+ if (freeslot != NULL)
+ return freeslot;
+ else
+ return ep;
+ }
+ if (ep->de_key == dummy) {
+ if (freeslot != NULL)
+ freeslot = ep;
+ }
+ else if (GETSTRINGVALUE(ep->de_key)[0] == key[0]) {
+ if (strcmp(GETSTRINGVALUE(ep->de_key), key) == 0) {
+ return ep;
+ }
+ }
+ i = (i + incr) % dp->di_size;
+ }
+}
+
+/*
+Internal routine to insert a new item into the table.
+Used both by the internal resize routine and by the public insert routine.
+Eats a reference to key and one to value.
+*/
+static void insertdict PROTO((dictobject *, stringobject *, object *));
+static void
+insertdict(dp, key, value)
+ register dictobject *dp;
+ stringobject *key;
+ object *value;
+{
+ register dictentry *ep;
+ ep = lookdict(dp, GETSTRINGVALUE(key));
+ if (ep->de_value != NULL) {
+ DECREF(ep->de_value);
+ DECREF(key);
+ }
+ else {
+ if (ep->de_key == NULL)
+ dp->di_fill++;
+ else
+ DECREF(ep->de_key);
+ ep->de_key = key;
+ dp->di_used++;
+ }
+ ep->de_value = value;
+}
+
+/*
+Restructure the table by allocating a new table and reinserting all
+items again. When entries have been deleted, the new table may
+actually be smaller than the old one.
+*/
+static int dictresize PROTO((dictobject *));
+static int
+dictresize(dp)
+ dictobject *dp;
+{
+ register int oldsize = dp->di_size;
+ register int newsize;
+ register dictentry *oldtable = dp->di_table;
+ register dictentry *newtable;
+ register dictentry *ep;
+ register int i;
+ newsize = dp->di_size;
+ for (i = 0; ; i++) {
+ if (primes[i] > dp->di_used*2) {
+ newsize = primes[i];
+ break;
+ }
+ }
+ newtable = (dictentry *) calloc(sizeof(dictentry), newsize);
+ if (newtable == NULL) {
+ err_nomem();
+ return -1;
+ }
+ dp->di_size = newsize;
+ dp->di_table = newtable;
+ dp->di_fill = 0;
+ dp->di_used = 0;
+ for (i = 0, ep = oldtable; i < oldsize; i++, ep++) {
+ if (ep->de_value != NULL)
+ insertdict(dp, ep->de_key, ep->de_value);
+ else if (ep->de_key != NULL)
+ DECREF(ep->de_key);
+ }
+ DEL(oldtable);
+ return 0;
+}
+
+object *
+dictlookup(op, key)
+ object *op;
+ char *key;
+{
+ if (!is_dictobject(op))
+ fatal("dictlookup on non-dictionary");
+ return lookdict((dictobject *)op, key) -> de_value;
+}
+
+#ifdef NOT_USED
+static object *
+dict2lookup(op, key)
+ register object *op;
+ register object *key;
+{
+ register object *res;
+ if (!is_dictobject(op)) {
+ err_badcall();
+ return NULL;
+ }
+ if (!is_stringobject(key)) {
+ err_badarg();
+ return NULL;
+ }
+ res = lookdict((dictobject *)op, ((stringobject *)key)->ob_sval)
+ -> de_value;
+ if (res == NULL)
+ err_setstr(KeyError, "key not in dictionary");
+ return res;
+}
+#endif
+
+static int
+dict2insert(op, key, value)
+ register object *op;
+ object *key;
+ object *value;
+{
+ register dictobject *dp;
+ register stringobject *keyobj;
+ if (!is_dictobject(op)) {
+ err_badcall();
+ return -1;
+ }
+ dp = (dictobject *)op;
+ if (!is_stringobject(key)) {
+ err_badarg();
+ return -1;
+ }
+ keyobj = (stringobject *)key;
+ /* if fill >= 2/3 size, resize */
+ if (dp->di_fill*3 >= dp->di_size*2) {
+ if (dictresize(dp) != 0) {
+ if (dp->di_fill+1 > dp->di_size)
+ return -1;
+ }
+ }
+ INCREF(keyobj);
+ INCREF(value);
+ insertdict(dp, keyobj, value);
+ return 0;
+}
+
+int
+dictinsert(op, key, value)
+ object *op;
+ char *key;
+ object *value;
+{
+ register object *keyobj;
+ register int err;
+ keyobj = newstringobject(key);
+ if (keyobj == NULL) {
+ err_nomem();
+ return -1;
+ }
+ err = dict2insert(op, keyobj, value);
+ DECREF(keyobj);
+ return err;
+}
+
+int
+dictremove(op, key)
+ object *op;
+ char *key;
+{
+ register dictobject *dp;
+ register dictentry *ep;
+ if (!is_dictobject(op)) {
+ err_badcall();
+ return -1;
+ }
+ dp = (dictobject *)op;
+ ep = lookdict(dp, key);
+ if (ep->de_value == NULL) {
+ err_setstr(KeyError, "key not in dictionary");
+ return -1;
+ }
+ DECREF(ep->de_key);
+ INCREF(dummy);
+ ep->de_key = dummy;
+ DECREF(ep->de_value);
+ ep->de_value = NULL;
+ dp->di_used--;
+ return 0;
+}
+
+static int
+dict2remove(op, key)
+ object *op;
+ register object *key;
+{
+ if (!is_stringobject(key)) {
+ err_badarg();
+ return -1;
+ }
+ return dictremove(op, GETSTRINGVALUE((stringobject *)key));
+}
+
+int
+getdictsize(op)
+ register object *op;
+{
+ if (!is_dictobject(op)) {
+ err_badcall();
+ return -1;
+ }
+ return ((dictobject *)op) -> di_size;
+}
+
+static object *
+getdict2key(op, i)
+ object *op;
+ register int i;
+{
+ /* XXX This can't return errors since its callers assume
+ that NULL means there was no key at that point */
+ register dictobject *dp;
+ if (!is_dictobject(op)) {
+ /* err_badcall(); */
+ return NULL;
+ }
+ dp = (dictobject *)op;
+ if (i < 0 || i >= dp->di_size) {
+ /* err_badarg(); */
+ return NULL;
+ }
+ if (dp->di_table[i].de_value == NULL) {
+ /* Not an error! */
+ return NULL;
+ }
+ return (object *) dp->di_table[i].de_key;
+}
+
+char *
+getdictkey(op, i)
+ object *op;
+ int i;
+{
+ register object *keyobj = getdict2key(op, i);
+ if (keyobj == NULL)
+ return NULL;
+ return GETSTRINGVALUE((stringobject *)keyobj);
+}
+
+/* Methods */
+
+static void
+dict_dealloc(dp)
+ register dictobject *dp;
+{
+ register int i;
+ register dictentry *ep;
+ for (i = 0, ep = dp->di_table; i < dp->di_size; i++, ep++) {
+ if (ep->de_key != NULL)
+ DECREF(ep->de_key);
+ if (ep->de_value != NULL)
+ DECREF(ep->de_value);
+ }
+ if (dp->di_table != NULL)
+ DEL(dp->di_table);
+ DEL(dp);
+}
+
+static void
+dict_print(dp, fp, flags)
+ register dictobject *dp;
+ register FILE *fp;
+ register int flags;
+{
+ register int i;
+ register int any;
+ register dictentry *ep;
+ fprintf(fp, "{");
+ any = 0;
+ for (i = 0, ep = dp->di_table; i < dp->di_size && !StopPrint;
+ i++, ep++) {
+ if (ep->de_value != NULL) {
+ if (any++ > 0)
+ fprintf(fp, "; ");
+ printobject((object *)ep->de_key, fp, flags);
+ fprintf(fp, ": ");
+ printobject(ep->de_value, fp, flags);
+ }
+ }
+ fprintf(fp, "}");
+}
+
+static void
+js(pv, w)
+ object **pv;
+ object *w;
+{
+ joinstring(pv, w);
+ if (w != NULL)
+ DECREF(w);
+}
+
+static object *
+dict_repr(dp)
+ dictobject *dp;
+{
+ auto object *v;
+ register object *w;
+ object *semi, *colon;
+ register int i;
+ register int any;
+ register dictentry *ep;
+ v = newstringobject("{");
+ semi = newstringobject("; ");
+ colon = newstringobject(": ");
+ any = 0;
+ for (i = 0, ep = dp->di_table; i < dp->di_size && !StopPrint;
+ i++, ep++) {
+ if (ep->de_value != NULL) {
+ if (any++)
+ joinstring(&v, semi);
+ js(&v, w = reprobject((object *)ep->de_key));
+ joinstring(&v, colon);
+ js(&v, w = reprobject(ep->de_value));
+ }
+ }
+ js(&v, w = newstringobject("}"));
+ if (semi != NULL)
+ DECREF(semi);
+ if (colon != NULL)
+ DECREF(colon);
+ return v;
+}
+
+static int
+dict_length(dp)
+ dictobject *dp;
+{
+ return dp->di_used;
+}
+
+static object *
+dict_subscript(dp, v)
+ dictobject *dp;
+ register object *v;
+{
+ if (!is_stringobject(v)) {
+ err_badarg();
+ return NULL;
+ }
+ v = lookdict(dp, GETSTRINGVALUE((stringobject *)v)) -> de_value;
+ if (v == NULL)
+ err_setstr(KeyError, "key not in dictionary");
+ else
+ INCREF(v);
+ return v;
+}
+
+static int
+dict_ass_sub(dp, v, w)
+ dictobject *dp;
+ object *v, *w;
+{
+ if (w == NULL)
+ return dict2remove((object *)dp, v);
+ else
+ return dict2insert((object *)dp, v, w);
+}
+
+static mapping_methods dict_as_mapping = {
+ dict_length, /*mp_length*/
+ dict_subscript, /*mp_subscript*/
+ dict_ass_sub, /*mp_ass_subscript*/
+};
+
+static object *
+dict_keys(dp, args)
+ register dictobject *dp;
+ object *args;
+{
+ register object *v;
+ register int i, j;
+ if (!getnoarg(args))
+ return NULL;
+ v = newlistobject(dp->di_used);
+ if (v == NULL)
+ return NULL;
+ for (i = 0, j = 0; i < dp->di_size; i++) {
+ if (dp->di_table[i].de_value != NULL) {
+ stringobject *key = dp->di_table[i].de_key;
+ INCREF(key);
+ setlistitem(v, j, (object *)key);
+ j++;
+ }
+ }
+ return v;
+}
+
+object *
+getdictkeys(dp)
+ object *dp;
+{
+ if (dp == NULL || !is_dictobject(dp)) {
+ err_badcall();
+ return NULL;
+ }
+ return dict_keys((dictobject *)dp, (object *)NULL);
+}
+
+static object *
+dict_has_key(dp, args)
+ register dictobject *dp;
+ object *args;
+{
+ object *key;
+ register long ok;
+ if (!getstrarg(args, &key))
+ return NULL;
+ ok = lookdict(dp, GETSTRINGVALUE((stringobject *)key))->de_value
+ != NULL;
+ return newintobject(ok);
+}
+
+static struct methodlist dict_methods[] = {
+ {"keys", dict_keys},
+ {"has_key", dict_has_key},
+ {NULL, NULL} /* sentinel */
+};
+
+static object *
+dict_getattr(dp, name)
+ dictobject *dp;
+ char *name;
+{
+ return findmethod(dict_methods, (object *)dp, name);
+}
+
+typeobject Dicttype = {
+ OB_HEAD_INIT(&Typetype)
+ 0,
+ "dictionary",
+ sizeof(dictobject),
+ 0,
+ dict_dealloc, /*tp_dealloc*/
+ dict_print, /*tp_print*/
+ dict_getattr, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ dict_repr, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ &dict_as_mapping, /*tp_as_mapping*/
+};
diff --git a/src/dictobject.h b/src/dictobject.h
new file mode 100644
index 0000000..d665aa5
--- /dev/null
+++ b/src/dictobject.h
@@ -0,0 +1,44 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/*
+Dictionary object type -- mapping from char * to object.
+NB: the key is given as a char *, not as a stringobject.
+These functions set errno for errors. Functions dictremove() and
+dictinsert() return nonzero for errors, getdictsize() returns -1,
+the others NULL. A successful call to dictinsert() calls INCREF()
+for the inserted item.
+*/
+
+extern typeobject Dicttype;
+
+#define is_dictobject(op) ((op)->ob_type == &Dicttype)
+
+extern object *newdictobject PROTO((void));
+extern object *dictlookup PROTO((object *dp, char *key));
+extern int dictinsert PROTO((object *dp, char *key, object *item));
+extern int dictremove PROTO((object *dp, char *key));
+extern int getdictsize PROTO((object *dp));
+extern char *getdictkey PROTO((object *dp, int i));
+extern object *getdictkeys PROTO((object *dp));
diff --git a/src/errcode.h b/src/errcode.h
new file mode 100644
index 0000000..3324489
--- /dev/null
+++ b/src/errcode.h
@@ -0,0 +1,36 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* Error codes passed around between file input, tokenizer, parser and
+ interpreter. This was necessary so we can turn them into Python
+ exceptions at a higher level. */
+
+#define E_OK 10 /* No error */
+#define E_EOF 11 /* (Unexpected) EOF read */
+#define E_INTR 12 /* Interrupted */
+#define E_TOKEN 13 /* Bad token */
+#define E_SYNTAX 14 /* Syntax error */
+#define E_NOMEM 15 /* Ran out of memory */
+#define E_DONE 16 /* Parsing complete */
+#define E_ERROR 17 /* Execution error */
diff --git a/src/errors.c b/src/errors.c
new file mode 100644
index 0000000..b3e6aa3
--- /dev/null
+++ b/src/errors.c
@@ -0,0 +1,196 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* Error handling -- see also run.c */
+
+/* New error handling interface.
+
+ The following problem exists (existed): methods of built-in modules
+ are called with 'self' and 'args' arguments, but without a context
+ argument, so they have no way to raise a specific exception.
+ The same is true for the object implementations: no context argument.
+ The old convention was to set 'errno' and to return NULL.
+ The caller (usually call_function() in eval.c) detects the NULL
+ return value and then calls puterrno(ctx) to turn the errno value
+ into a true exception. Problems with this approach are:
+ - it used standard errno values to indicate Python-specific errors,
+ but this means that when such an error code is reported by a system
+ call (e.g., in module posix), the user gets a confusing message
+ - errno is a global variable, which makes extensions to a multi-
+ threading environment difficult; e.g., in IRIX, multi-threaded
+ programs must use the function oserror() instead of looking in errno
+ - there is no portable way to add new error numbers for specic
+ situations -- the value space for errno is reserved to the OS, yet
+ the way to turn module-specific errors into a module-specific
+ exception requires module-specific values for errno
+ - there is no way to add a more situation-specific message to an
+ error.
+
+ The new interface solves all these problems. To return an error, a
+ built-in function calls err_set(exception), err_setval(exception,
+ value) or err_setstr(exception, string), and returns NULL. These
+ functions save the value for later use by puterrno(). To adapt this
+ scheme to a multi-threaded environment, only the implementation of
+ err_setval() has to be changed.
+*/
+
+#include "allobjects.h"
+
+#include <errno.h>
+#ifndef errno
+extern int errno;
+#endif
+
+#include "errcode.h"
+
+extern char *strerror PROTO((int));
+
+/* Last exception stored by err_setval() */
+
+static object *last_exception;
+static object *last_exc_val;
+
+void
+err_setval(exception, value)
+ object *exception;
+ object *value;
+{
+ XDECREF(last_exception);
+ XINCREF(exception);
+ last_exception = exception;
+
+ XDECREF(last_exc_val);
+ XINCREF(value);
+ last_exc_val = value;
+}
+
+void
+err_set(exception)
+ object *exception;
+{
+ err_setval(exception, (object *)NULL);
+}
+
+void
+err_setstr(exception, string)
+ object *exception;
+ char *string;
+{
+ object *value = newstringobject(string);
+ err_setval(exception, value);
+ XDECREF(value);
+}
+
+int
+err_occurred()
+{
+ return last_exception != NULL;
+}
+
+void
+err_get(p_exc, p_val)
+ object **p_exc;
+ object **p_val;
+{
+ *p_exc = last_exception;
+ last_exception = NULL;
+ *p_val = last_exc_val;
+ last_exc_val = NULL;
+}
+
+void
+err_clear()
+{
+ XDECREF(last_exception);
+ last_exception = NULL;
+ XDECREF(last_exc_val);
+ last_exc_val = NULL;
+}
+
+/* Convenience functions to set a type error exception and return 0 */
+
+int
+err_badarg()
+{
+ err_setstr(TypeError, "illegal argument type for built-in operation");
+ return 0;
+}
+
+object *
+err_nomem()
+{
+ err_set(MemoryError);
+ return NULL;
+}
+
+object *
+err_errno(exc)
+ object *exc;
+{
+ object *v = newtupleobject(2);
+ if (v != NULL) {
+ settupleitem(v, 0, newintobject((long)errno));
+ settupleitem(v, 1, newstringobject(strerror(errno)));
+ }
+ err_setval(exc, v);
+ XDECREF(v);
+ return NULL;
+}
+
+void
+err_badcall()
+{
+ err_setstr(SystemError, "bad argument to internal function");
+}
+
+/* Set the error appropriate to the given input error code (see errcode.h) */
+
+void
+err_input(err)
+ int err;
+{
+ switch (err) {
+ case E_DONE:
+ case E_OK:
+ break;
+ case E_SYNTAX:
+ err_setstr(RuntimeError, "syntax error");
+ break;
+ case E_TOKEN:
+ err_setstr(RuntimeError, "illegal token");
+ break;
+ case E_INTR:
+ err_set(KeyboardInterrupt);
+ break;
+ case E_NOMEM:
+ err_nomem();
+ break;
+ case E_EOF:
+ err_set(EOFError);
+ break;
+ default:
+ err_setstr(RuntimeError, "unknown input error");
+ break;
+ }
+}
diff --git a/src/errors.h b/src/errors.h
new file mode 100644
index 0000000..4baa142
--- /dev/null
+++ b/src/errors.h
@@ -0,0 +1,58 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* Error handling definitions */
+
+void err_set PROTO((object *));
+void err_setval PROTO((object *, object *));
+void err_setstr PROTO((object *, char *));
+int err_occurred PROTO((void));
+void err_get PROTO((object **, object **));
+void err_clear PROTO((void));
+
+/* Predefined exceptions */
+
+extern object *RuntimeError;
+extern object *EOFError;
+extern object *TypeError;
+extern object *MemoryError;
+extern object *NameError;
+extern object *SystemError;
+extern object *KeyboardInterrupt;
+
+/* Some more planned for the future */
+
+#define IndexError RuntimeError
+#define KeyError RuntimeError
+#define ZeroDivisionError RuntimeError
+#define OverflowError RuntimeError
+
+/* Convenience functions */
+
+extern int err_badarg PROTO((void));
+extern object *err_nomem PROTO((void));
+extern object *err_errno PROTO((object *));
+extern void err_input PROTO((int));
+
+extern void err_badcall PROTO((void));
diff --git a/src/fgetsintr.c b/src/fgetsintr.c
new file mode 100644
index 0000000..bda1ed8
--- /dev/null
+++ b/src/fgetsintr.c
@@ -0,0 +1,94 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* Interruptable version of fgets().
+ Return < 0 for interrupted, 1 for EOF, 0 for valid input. */
+
+/* XXX This uses longjmp() from a signal out of fgets().
+ Should use read() instead?! */
+
+#include "pgenheaders.h"
+
+#include <signal.h>
+#include <setjmp.h>
+
+#include "errcode.h"
+#include "sigtype.h"
+#include "fgetsintr.h"
+
+#ifndef AMOEBA
+#define sig_block() /*empty*/
+#define sig_unblock() /*empty*/
+#endif
+
+static jmp_buf jback;
+
+static void catcher PROTO((int));
+
+static void
+catcher(sig)
+ int sig;
+{
+ longjmp(jback, 1);
+}
+
+int
+fgets_intr(buf, size, fp)
+ char *buf;
+ int size;
+ FILE *fp;
+{
+ int ret;
+ SIGTYPE (*sigsave)();
+
+ if (setjmp(jback)) {
+ clearerr(fp);
+ signal(SIGINT, sigsave);
+#ifdef THINK_C_3_0
+ Set_Echo(1);
+#endif
+ return E_INTR;
+ }
+
+ /* The casts to (SIGTYPE(*)()) are needed by THINK_C only */
+
+ sigsave = signal(SIGINT, (SIGTYPE(*)()) SIG_IGN);
+ if (sigsave != (SIGTYPE(*)()) SIG_IGN)
+ signal(SIGINT, (SIGTYPE(*)()) catcher);
+
+#ifndef THINK_C
+ if (intrcheck())
+ ret = E_INTR;
+ else
+#endif
+ {
+ sig_block();
+ ret = (fgets(buf, size, fp) == NULL) ? E_EOF : E_OK;
+ sig_unblock();
+ }
+
+ if (sigsave != (SIGTYPE(*)()) SIG_IGN)
+ signal(SIGINT, (SIGTYPE(*)()) sigsave);
+ return ret;
+}
diff --git a/src/fgetsintr.h b/src/fgetsintr.h
new file mode 100644
index 0000000..87f1d2a
--- /dev/null
+++ b/src/fgetsintr.h
@@ -0,0 +1,25 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+extern int fgets_intr PROTO((char *, int, FILE *));
diff --git a/src/fileobject.c b/src/fileobject.c
new file mode 100644
index 0000000..640e27b
--- /dev/null
+++ b/src/fileobject.c
@@ -0,0 +1,293 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* File object implementation */
+
+/* XXX This should become a built-in module 'io'. It should support more
+ functionality, better exception handling for invalid calls, etc.
+ (Especially reading on a write-only file or vice versa!)
+ It should also cooperate with posix to support popen(), which should
+ share most code but have a special close function. */
+
+#include "allobjects.h"
+
+#include "errno.h"
+#ifndef errno
+extern int errno;
+#endif
+
+typedef struct {
+ OB_HEAD
+ FILE *f_fp;
+ object *f_name;
+ object *f_mode;
+ /* XXX Should move the 'need space' on printing flag here */
+} fileobject;
+
+FILE *
+getfilefile(f)
+ object *f;
+{
+ if (!is_fileobject(f)) {
+ err_badcall();
+ return NULL;
+ }
+ return ((fileobject *)f)->f_fp;
+}
+
+object *
+newopenfileobject(fp, name, mode)
+ FILE *fp;
+ char *name;
+ char *mode;
+{
+ fileobject *f = NEWOBJ(fileobject, &Filetype);
+ if (f == NULL)
+ return NULL;
+ f->f_fp = NULL;
+ f->f_name = newstringobject(name);
+ f->f_mode = newstringobject(mode);
+ if (f->f_name == NULL || f->f_mode == NULL) {
+ DECREF(f);
+ return NULL;
+ }
+ f->f_fp = fp;
+ return (object *) f;
+}
+
+object *
+newfileobject(name, mode)
+ char *name, *mode;
+{
+ fileobject *f;
+ FILE *fp;
+ f = (fileobject *) newopenfileobject((FILE *)NULL, name, mode);
+ if (f == NULL)
+ return NULL;
+#ifdef THINK_C
+ if (*mode == '*') {
+ FILE *fopenRF();
+ f->f_fp = fopenRF(name, mode+1);
+ }
+ else
+#endif
+ f->f_fp = fopen(name, mode);
+ if (f->f_fp == NULL) {
+ err_errno(RuntimeError);
+ DECREF(f);
+ return NULL;
+ }
+ return (object *)f;
+}
+
+/* Methods */
+
+static void
+file_dealloc(f)
+ fileobject *f;
+{
+ if (f->f_fp != NULL)
+ fclose(f->f_fp);
+ if (f->f_name != NULL)
+ DECREF(f->f_name);
+ if (f->f_mode != NULL)
+ DECREF(f->f_mode);
+ free((char *)f);
+}
+
+static void
+file_print(f, fp, flags)
+ fileobject *f;
+ FILE *fp;
+ int flags;
+{
+ fprintf(fp, "<%s file ", f->f_fp == NULL ? "closed" : "open");
+ printobject(f->f_name, fp, flags);
+ fprintf(fp, ", mode ");
+ printobject(f->f_mode, fp, flags);
+ fprintf(fp, ">");
+}
+
+static object *
+file_repr(f)
+ fileobject *f;
+{
+ char buf[300];
+ /* XXX This differs from file_print if the filename contains
+ quotes or other funny characters. */
+ sprintf(buf, "<%s file '%.256s', mode '%.10s'>",
+ f->f_fp == NULL ? "closed" : "open",
+ getstringvalue(f->f_name),
+ getstringvalue(f->f_mode));
+ return newstringobject(buf);
+}
+
+static object *
+file_close(f, args)
+ fileobject *f;
+ object *args;
+{
+ if (args != NULL) {
+ err_badarg();
+ return NULL;
+ }
+ if (f->f_fp != NULL) {
+ fclose(f->f_fp);
+ f->f_fp = NULL;
+ }
+ INCREF(None);
+ return None;
+}
+
+static object *
+file_read(f, args)
+ fileobject *f;
+ object *args;
+{
+ int n;
+ object *v;
+ if (f->f_fp == NULL) {
+ err_badarg();
+ return NULL;
+ }
+ if (args == NULL || !is_intobject(args)) {
+ err_badarg();
+ return NULL;
+ }
+ n = getintvalue(args);
+ if (n < 0) {
+ err_badarg();
+ return NULL;
+ }
+ v = newsizedstringobject((char *)NULL, n);
+ if (v == NULL)
+ return NULL;
+ n = fread(getstringvalue(v), 1, n, f->f_fp);
+ /* EOF is reported as an empty string */
+ /* XXX should detect real I/O errors? */
+ resizestring(&v, n);
+ return v;
+}
+
+/* XXX Should this be unified with raw_input()? */
+
+static object *
+file_readline(f, args)
+ fileobject *f;
+ object *args;
+{
+ int n;
+ object *v;
+ if (f->f_fp == NULL) {
+ err_badarg();
+ return NULL;
+ }
+ if (args == NULL) {
+ n = 10000; /* XXX should really be unlimited */
+ }
+ else if (is_intobject(args)) {
+ n = getintvalue(args);
+ if (n < 0) {
+ err_badarg();
+ return NULL;
+ }
+ }
+ else {
+ err_badarg();
+ return NULL;
+ }
+ v = newsizedstringobject((char *)NULL, n);
+ if (v == NULL)
+ return NULL;
+#ifndef THINK_C_3_0
+ /* XXX Think C 3.0 wrongly reads up to n characters... */
+ n = n+1;
+#endif
+ if (fgets(getstringvalue(v), n, f->f_fp) == NULL) {
+ /* EOF is reported as an empty string */
+ /* XXX should detect real I/O errors? */
+ n = 0;
+ }
+ else {
+ n = strlen(getstringvalue(v));
+ }
+ resizestring(&v, n);
+ return v;
+}
+
+static object *
+file_write(f, args)
+ fileobject *f;
+ object *args;
+{
+ int n, n2;
+ if (f->f_fp == NULL) {
+ err_badarg();
+ return NULL;
+ }
+ if (args == NULL || !is_stringobject(args)) {
+ err_badarg();
+ return NULL;
+ }
+ errno = 0;
+ n2 = fwrite(getstringvalue(args), 1, n = getstringsize(args), f->f_fp);
+ if (n2 != n) {
+ if (errno == 0)
+ errno = EIO;
+ err_errno(RuntimeError);
+ return NULL;
+ }
+ INCREF(None);
+ return None;
+}
+
+static struct methodlist file_methods[] = {
+ {"write", file_write},
+ {"read", file_read},
+ {"readline", file_readline},
+ {"close", file_close},
+ {NULL, NULL} /* sentinel */
+};
+
+static object *
+file_getattr(f, name)
+ fileobject *f;
+ char *name;
+{
+ return findmethod(file_methods, (object *)f, name);
+}
+
+typeobject Filetype = {
+ OB_HEAD_INIT(&Typetype)
+ 0,
+ "file",
+ sizeof(fileobject),
+ 0,
+ file_dealloc, /*tp_dealloc*/
+ file_print, /*tp_print*/
+ file_getattr, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ file_repr, /*tp_repr*/
+};
diff --git a/src/fileobject.h b/src/fileobject.h
new file mode 100644
index 0000000..eefae74
--- /dev/null
+++ b/src/fileobject.h
@@ -0,0 +1,33 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* File object interface */
+
+extern typeobject Filetype;
+
+#define is_fileobject(op) ((op)->ob_type == &Filetype)
+
+extern object *newfileobject PROTO((char *, char *));
+extern object *newopenfileobject PROTO((FILE *, char *, char *));
+extern FILE *getfilefile PROTO((object *));
diff --git a/src/firstsets.c b/src/firstsets.c
new file mode 100644
index 0000000..6bd7ce0
--- /dev/null
+++ b/src/firstsets.c
@@ -0,0 +1,133 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* Computation of FIRST stets */
+
+#include "pgenheaders.h"
+#include "grammar.h"
+#include "token.h"
+
+extern int debugging;
+
+/* Forward */
+static void calcfirstset PROTO((grammar *, dfa *));
+
+void
+addfirstsets(g)
+ grammar *g;
+{
+ int i;
+ dfa *d;
+
+ printf("Adding FIRST sets ...\n");
+ for (i = 0; i < g->g_ndfas; i++) {
+ d = &g->g_dfa[i];
+ if (d->d_first == NULL)
+ calcfirstset(g, d);
+ }
+}
+
+static void
+calcfirstset(g, d)
+ grammar *g;
+ dfa *d;
+{
+ int i, j;
+ state *s;
+ arc *a;
+ int nsyms;
+ int *sym;
+ int nbits;
+ static bitset dummy;
+ bitset result;
+ int type;
+ dfa *d1;
+ label *l0;
+
+ if (debugging)
+ printf("Calculate FIRST set for '%s'\n", d->d_name);
+
+ if (dummy == NULL)
+ dummy = newbitset(1);
+ if (d->d_first == dummy) {
+ fprintf(stderr, "Left-recursion for '%s'\n", d->d_name);
+ return;
+ }
+ if (d->d_first != NULL) {
+ fprintf(stderr, "Re-calculating FIRST set for '%s' ???\n",
+ d->d_name);
+ }
+ d->d_first = dummy;
+
+ l0 = g->g_ll.ll_label;
+ nbits = g->g_ll.ll_nlabels;
+ result = newbitset(nbits);
+
+ sym = NEW(int, 1);
+ if (sym == NULL)
+ fatal("no mem for new sym in calcfirstset");
+ nsyms = 1;
+ sym[0] = findlabel(&g->g_ll, d->d_type, (char *)NULL);
+
+ s = &d->d_state[d->d_initial];
+ for (i = 0; i < s->s_narcs; i++) {
+ a = &s->s_arc[i];
+ for (j = 0; j < nsyms; j++) {
+ if (sym[j] == a->a_lbl)
+ break;
+ }
+ if (j >= nsyms) { /* New label */
+ RESIZE(sym, int, nsyms + 1);
+ if (sym == NULL)
+ fatal("no mem to resize sym in calcfirstset");
+ sym[nsyms++] = a->a_lbl;
+ type = l0[a->a_lbl].lb_type;
+ if (ISNONTERMINAL(type)) {
+ d1 = finddfa(g, type);
+ if (d1->d_first == dummy) {
+ fprintf(stderr,
+ "Left-recursion below '%s'\n",
+ d->d_name);
+ }
+ else {
+ if (d1->d_first == NULL)
+ calcfirstset(g, d1);
+ mergebitset(result, d1->d_first, nbits);
+ }
+ }
+ else if (ISTERMINAL(type)) {
+ addbit(result, a->a_lbl);
+ }
+ }
+ }
+ d->d_first = result;
+ if (debugging) {
+ printf("FIRST set for '%s': {", d->d_name);
+ for (i = 0; i < nbits; i++) {
+ if (testbit(result, i))
+ printf(" %s", labelrepr(&l0[i]));
+ }
+ printf(" }\n");
+ }
+}
diff --git a/src/floatobject.c b/src/floatobject.c
new file mode 100644
index 0000000..c637989
--- /dev/null
+++ b/src/floatobject.c
@@ -0,0 +1,271 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* Float object implementation */
+
+/* XXX There should be overflow checks here, but it's hard to check
+ for any kind of float exception without losing portability. */
+
+#include "allobjects.h"
+
+#include <errno.h>
+#ifndef errno
+extern int errno;
+#endif
+
+#include <ctype.h>
+#include <math.h>
+
+#ifndef THINK_C
+extern double fmod PROTO((double, double));
+extern double pow PROTO((double, double));
+#endif
+
+object *
+newfloatobject(fval)
+ double fval;
+{
+ /* For efficiency, this code is copied from newobject() */
+ register floatobject *op = (floatobject *) malloc(sizeof(floatobject));
+ if (op == NULL)
+ return err_nomem();
+ NEWREF(op);
+ op->ob_type = &Floattype;
+ op->ob_fval = fval;
+ return (object *) op;
+}
+
+double
+getfloatvalue(op)
+ object *op;
+{
+ if (!is_floatobject(op)) {
+ err_badarg();
+ return -1;
+ }
+ else
+ return ((floatobject *)op) -> ob_fval;
+}
+
+/* Methods */
+
+static void
+float_buf_repr(buf, v)
+ char *buf;
+ floatobject *v;
+{
+ register char *cp;
+ /* Subroutine for float_repr and float_print.
+ We want float numbers to be recognizable as such,
+ i.e., they should contain a decimal point or an exponent.
+ However, %g may print the number as an integer;
+ in such cases, we append ".0" to the string. */
+ sprintf(buf, "%.12g", v->ob_fval);
+ cp = buf;
+ if (*cp == '-')
+ cp++;
+ for (; *cp != '\0'; cp++) {
+ /* Any non-digit means it's not an integer;
+ this takes care of NAN and INF as well. */
+ if (!isdigit(*cp))
+ break;
+ }
+ if (*cp == '\0') {
+ *cp++ = '.';
+ *cp++ = '0';
+ *cp++ = '\0';
+ }
+}
+
+static void
+float_print(v, fp, flags)
+ floatobject *v;
+ FILE *fp;
+ int flags;
+{
+ char buf[100];
+ float_buf_repr(buf, v);
+ fputs(buf, fp);
+}
+
+static object *
+float_repr(v)
+ floatobject *v;
+{
+ char buf[100];
+ float_buf_repr(buf, v);
+ return newstringobject(buf);
+}
+
+static int
+float_compare(v, w)
+ floatobject *v, *w;
+{
+ double i = v->ob_fval;
+ double j = w->ob_fval;
+ return (i < j) ? -1 : (i > j) ? 1 : 0;
+}
+
+static object *
+float_add(v, w)
+ floatobject *v;
+ object *w;
+{
+ if (!is_floatobject(w)) {
+ err_badarg();
+ return NULL;
+ }
+ return newfloatobject(v->ob_fval + ((floatobject *)w) -> ob_fval);
+}
+
+static object *
+float_sub(v, w)
+ floatobject *v;
+ object *w;
+{
+ if (!is_floatobject(w)) {
+ err_badarg();
+ return NULL;
+ }
+ return newfloatobject(v->ob_fval - ((floatobject *)w) -> ob_fval);
+}
+
+static object *
+float_mul(v, w)
+ floatobject *v;
+ object *w;
+{
+ if (!is_floatobject(w)) {
+ err_badarg();
+ return NULL;
+ }
+ return newfloatobject(v->ob_fval * ((floatobject *)w) -> ob_fval);
+}
+
+static object *
+float_div(v, w)
+ floatobject *v;
+ object *w;
+{
+ if (!is_floatobject(w)) {
+ err_badarg();
+ return NULL;
+ }
+ if (((floatobject *)w) -> ob_fval == 0) {
+ err_setstr(ZeroDivisionError, "float division by zero");
+ return NULL;
+ }
+ return newfloatobject(v->ob_fval / ((floatobject *)w) -> ob_fval);
+}
+
+static object *
+float_rem(v, w)
+ floatobject *v;
+ object *w;
+{
+ double wx;
+ if (!is_floatobject(w)) {
+ err_badarg();
+ return NULL;
+ }
+ wx = ((floatobject *)w) -> ob_fval;
+ if (wx == 0.0) {
+ err_setstr(ZeroDivisionError, "float division by zero");
+ return NULL;
+ }
+ return newfloatobject(fmod(v->ob_fval, wx));
+}
+
+static object *
+float_pow(v, w)
+ floatobject *v;
+ object *w;
+{
+ double iv, iw, ix;
+ if (!is_floatobject(w)) {
+ err_badarg();
+ return NULL;
+ }
+ iv = v->ob_fval;
+ iw = ((floatobject *)w)->ob_fval;
+ if (iw == 0.0)
+ return newfloatobject(1.0); /* x**0 is always 1, even 0**0 */
+ errno = 0;
+ ix = pow(iv, iw);
+ if (errno != 0) {
+ /* XXX could it be another type of error? */
+ err_errno(OverflowError);
+ return NULL;
+ }
+ return newfloatobject(ix);
+}
+
+static object *
+float_neg(v)
+ floatobject *v;
+{
+ return newfloatobject(-v->ob_fval);
+}
+
+static object *
+float_pos(v)
+ floatobject *v;
+{
+ return newfloatobject(v->ob_fval);
+}
+
+static number_methods float_as_number = {
+ float_add, /*tp_add*/
+ float_sub, /*tp_subtract*/
+ float_mul, /*tp_multiply*/
+ float_div, /*tp_divide*/
+ float_rem, /*tp_remainder*/
+ float_pow, /*tp_power*/
+ float_neg, /*tp_negate*/
+ float_pos, /*tp_plus*/
+};
+
+typeobject Floattype = {
+ OB_HEAD_INIT(&Typetype)
+ 0,
+ "float",
+ sizeof(floatobject),
+ 0,
+ free, /*tp_dealloc*/
+ float_print, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ float_compare, /*tp_compare*/
+ float_repr, /*tp_repr*/
+ &float_as_number, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+};
+
+/*
+XXX This is not enough. Need:
+- automatic casts for mixed arithmetic (3.1 * 4)
+- mixed comparisons (!)
+- look at other uses of ints that could be extended to floats
+*/
diff --git a/src/floatobject.h b/src/floatobject.h
new file mode 100644
index 0000000..52db73e
--- /dev/null
+++ b/src/floatobject.h
@@ -0,0 +1,44 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* Float object interface */
+
+/*
+floatobject represents a (double precision) floating point number.
+*/
+
+typedef struct {
+ OB_HEAD
+ double ob_fval;
+} floatobject;
+
+extern typeobject Floattype;
+
+#define is_floatobject(op) ((op)->ob_type == &Floattype)
+
+extern object *newfloatobject PROTO((double));
+extern double getfloatvalue PROTO((object *));
+
+/* Macro, trading safety for speed */
+#define GETFLOATVALUE(op) ((op)->ob_fval)
diff --git a/src/fmod.c b/src/fmod.c
new file mode 100644
index 0000000..fe90e07
--- /dev/null
+++ b/src/fmod.c
@@ -0,0 +1,51 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* Portable fmod(x, y) implementation for systems that don't have it */
+
+#include <math.h>
+#include <errno.h>
+
+extern int errno;
+
+double
+fmod(x, y)
+ double x, y;
+{
+ double i, f;
+
+ if (y == 0.0) {
+ errno = EDOM;
+ return 0.0;
+ }
+
+ /* return f such that x = i*y + f for some integer i
+ such that |f| < |y| and f has the same sign as x */
+
+ i = floor(x/y);
+ f = x - i*y;
+ if ((x < 0.0) != (y < 0.0))
+ f = f-y;
+ return f;
+}
diff --git a/src/frameobject.c b/src/frameobject.c
new file mode 100644
index 0000000..4f9e250
--- /dev/null
+++ b/src/frameobject.c
@@ -0,0 +1,156 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* Frame object implementation */
+
+#include "allobjects.h"
+
+#include "compile.h"
+#include "frameobject.h"
+#include "opcode.h"
+#include "structmember.h"
+
+#define OFF(x) offsetof(frameobject, x)
+
+static struct memberlist frame_memberlist[] = {
+ {"f_back", T_OBJECT, OFF(f_back)},
+ {"f_code", T_OBJECT, OFF(f_code)},
+ {"f_globals", T_OBJECT, OFF(f_globals)},
+ {"f_locals", T_OBJECT, OFF(f_locals)},
+ {NULL} /* Sentinel */
+};
+
+static object *
+frame_getattr(f, name)
+ frameobject *f;
+ char *name;
+{
+ return getmember((char *)f, frame_memberlist, name);
+}
+
+static void
+frame_dealloc(f)
+ frameobject *f;
+{
+ XDECREF(f->f_back);
+ XDECREF(f->f_code);
+ XDECREF(f->f_globals);
+ XDECREF(f->f_locals);
+ XDEL(f->f_valuestack);
+ XDEL(f->f_blockstack);
+ DEL(f);
+}
+
+typeobject Frametype = {
+ OB_HEAD_INIT(&Typetype)
+ 0,
+ "frame",
+ sizeof(frameobject),
+ 0,
+ frame_dealloc, /*tp_dealloc*/
+ 0, /*tp_print*/
+ frame_getattr, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+};
+
+frameobject *
+newframeobject(back, code, globals, locals, nvalues, nblocks)
+ frameobject *back;
+ codeobject *code;
+ object *globals;
+ object *locals;
+ int nvalues;
+ int nblocks;
+{
+ frameobject *f;
+ if ((back != NULL && !is_frameobject(back)) ||
+ code == NULL || !is_codeobject(code) ||
+ globals == NULL || !is_dictobject(globals) ||
+ locals == NULL || !is_dictobject(locals) ||
+ nvalues < 0 || nblocks < 0) {
+ err_badcall();
+ return NULL;
+ }
+ f = NEWOBJ(frameobject, &Frametype);
+ if (f != NULL) {
+ if (back)
+ INCREF(back);
+ f->f_back = back;
+ INCREF(code);
+ f->f_code = code;
+ INCREF(globals);
+ f->f_globals = globals;
+ INCREF(locals);
+ f->f_locals = locals;
+ f->f_valuestack = NEW(object *, nvalues+1);
+ f->f_blockstack = NEW(block, nblocks+1);
+ f->f_nvalues = nvalues;
+ f->f_nblocks = nblocks;
+ f->f_iblock = 0;
+ if (f->f_valuestack == NULL || f->f_blockstack == NULL) {
+ err_nomem();
+ DECREF(f);
+ f = NULL;
+ }
+ }
+ return f;
+}
+
+/* Block management */
+
+void
+setup_block(f, type, handler, level)
+ frameobject *f;
+ int type;
+ int handler;
+ int level;
+{
+ block *b;
+ if (f->f_iblock >= f->f_nblocks) {
+ fprintf(stderr, "XXX block stack overflow\n");
+ abort();
+ }
+ b = &f->f_blockstack[f->f_iblock++];
+ b->b_type = type;
+ b->b_level = level;
+ b->b_handler = handler;
+}
+
+block *
+pop_block(f)
+ frameobject *f;
+{
+ block *b;
+ if (f->f_iblock <= 0) {
+ fprintf(stderr, "XXX block stack underflow\n");
+ abort();
+ }
+ b = &f->f_blockstack[--f->f_iblock];
+ return b;
+}
diff --git a/src/frameobject.h b/src/frameobject.h
new file mode 100644
index 0000000..8ea0fa2
--- /dev/null
+++ b/src/frameobject.h
@@ -0,0 +1,80 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* Frame object interface */
+
+typedef struct {
+ int b_type; /* what kind of block this is */
+ int b_handler; /* where to jump to find handler */
+ int b_level; /* value stack level to pop to */
+} block;
+
+typedef struct _frame {
+ OB_HEAD
+ struct _frame *f_back; /* previous frame, or NULL */
+ codeobject *f_code; /* code segment */
+ object *f_globals; /* global symbol table (dictobject) */
+ object *f_locals; /* local symbol table (dictobject) */
+ object **f_valuestack; /* malloc'ed array */
+ block *f_blockstack; /* malloc'ed array */
+ int f_nvalues; /* size of f_valuestack */
+ int f_nblocks; /* size of f_blockstack */
+ int f_iblock; /* index in f_blockstack */
+} frameobject;
+
+
+/* Standard object interface */
+
+extern typeobject Frametype;
+
+#define is_frameobject(op) ((op)->ob_type == &Frametype)
+
+frameobject * newframeobject PROTO(
+ (frameobject *, codeobject *, object *, object *, int, int));
+
+
+/* The rest of the interface is specific for frame objects */
+
+/* List access macros */
+
+#ifdef NDEBUG
+#define GETITEM(v, i) GETLISTITEM((listobject *)(v), (i))
+#define GETITEMNAME(v, i) GETSTRINGVALUE((stringobject *)GETITEM((v), (i)))
+#else
+#define GETITEM(v, i) getlistitem((v), (i))
+#define GETITEMNAME(v, i) getstringvalue(getlistitem((v), (i)))
+#endif
+
+#define GETUSTRINGVALUE(s) ((unsigned char *)GETSTRINGVALUE(s))
+
+/* Code access macros */
+
+#define Getconst(f, i) (GETITEM((f)->f_code->co_consts, (i)))
+#define Getname(f, i) (GETITEMNAME((f)->f_code->co_names, (i)))
+
+
+/* Block management functions */
+
+void setup_block PROTO((frameobject *, int, int, int));
+block *pop_block PROTO((frameobject *));
diff --git a/src/funcobject.c b/src/funcobject.c
new file mode 100644
index 0000000..1088d7b
--- /dev/null
+++ b/src/funcobject.c
@@ -0,0 +1,113 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* Function object implementation */
+
+#include "allobjects.h"
+
+#include "structmember.h"
+
+typedef struct {
+ OB_HEAD
+ object *func_code;
+ object *func_globals;
+} funcobject;
+
+object *
+newfuncobject(code, globals)
+ object *code;
+ object *globals;
+{
+ funcobject *op = NEWOBJ(funcobject, &Functype);
+ if (op != NULL) {
+ INCREF(code);
+ op->func_code = code;
+ INCREF(globals);
+ op->func_globals = globals;
+ }
+ return (object *)op;
+}
+
+object *
+getfunccode(op)
+ object *op;
+{
+ if (!is_funcobject(op)) {
+ err_badcall();
+ return NULL;
+ }
+ return ((funcobject *) op) -> func_code;
+}
+
+object *
+getfuncglobals(op)
+ object *op;
+{
+ if (!is_funcobject(op)) {
+ err_badcall();
+ return NULL;
+ }
+ return ((funcobject *) op) -> func_globals;
+}
+
+/* Methods */
+
+#define OFF(x) offsetof(funcobject, x)
+
+static struct memberlist func_memberlist[] = {
+ {"func_code", T_OBJECT, OFF(func_code)},
+ {"func_globals",T_OBJECT, OFF(func_globals)},
+ {NULL} /* Sentinel */
+};
+
+static object *
+func_getattr(op, name)
+ funcobject *op;
+ char *name;
+{
+ return getmember((char *)op, func_memberlist, name);
+}
+
+static void
+func_dealloc(op)
+ funcobject *op;
+{
+ DECREF(op->func_code);
+ DECREF(op->func_globals);
+ DEL(op);
+}
+
+typeobject Functype = {
+ OB_HEAD_INIT(&Typetype)
+ 0,
+ "function",
+ sizeof(funcobject),
+ 0,
+ func_dealloc, /*tp_dealloc*/
+ 0, /*tp_print*/
+ func_getattr, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+};
diff --git a/src/funcobject.h b/src/funcobject.h
new file mode 100644
index 0000000..de8b1a7
--- /dev/null
+++ b/src/funcobject.h
@@ -0,0 +1,33 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* Function object interface */
+
+extern typeobject Functype;
+
+#define is_funcobject(op) ((op)->ob_type == &Functype)
+
+extern object *newfuncobject PROTO((object *, object *));
+extern object *getfunccode PROTO((object *));
+extern object *getfuncglobals PROTO((object *));
diff --git a/src/getcwd.c b/src/getcwd.c
new file mode 100644
index 0000000..3de6291
--- /dev/null
+++ b/src/getcwd.c
@@ -0,0 +1,102 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* Two PD getcwd() implementations.
+ Author: Guido van Rossum, CWI Amsterdam, Jan 1991, <[email protected]>. */
+
+/* #define NO_GETWD /* Turn this on to popen pwd instead of calling getwd() */
+
+#include <stdio.h>
+#include <errno.h>
+
+extern int errno;
+
+#ifndef NO_GETWD
+
+/* Default: Version for BSD systems -- use getwd() */
+
+#include "sys/param.h"
+
+extern char *getwd();
+
+char *
+getcwd(buf, size)
+ char *buf;
+ int size;
+{
+ char localbuf[MAXPATHLEN+1];
+ char *ret;
+
+ if (size <= 0) {
+ errno = EINVAL;
+ return NULL;
+ }
+ ret = getwd(localbuf);
+ if (ret != NULL && strlen(localbuf) >= size) {
+ errno = ERANGE;
+ return NULL;
+ }
+ if (ret == NULL) {
+ errno = EACCES; /* Most likely error */
+ return NULL;
+ }
+ strncpy(buf, localbuf, size);
+ return buf;
+}
+
+#else
+
+/* NO_GETWD defined: Version for backward UNIXes -- popen /bin/pwd */
+
+#define PWD_CMD "/bin/pwd"
+
+char *
+getcwd(buf, size)
+ char *buf;
+ int size;
+{
+ FILE *fp;
+ char *p;
+ int sts;
+ if (size <= 0) {
+ errno = EINVAL;
+ return NULL;
+ }
+ if ((fp = popen(PWD_CMD, "r")) == NULL)
+ return NULL;
+ if (fgets(buf, size, fp) == NULL || (sts = pclose(fp)) != 0) {
+ errno = EACCES; /* Most likely error */
+ return NULL;
+ }
+ for (p = buf; *p != '\n'; p++) {
+ if (*p == '\0') {
+ errno = ERANGE;
+ return NULL;
+ }
+ }
+ *p = '\0';
+ return buf;
+}
+
+#endif
diff --git a/src/graminit.c b/src/graminit.c
new file mode 100644
index 0000000..2f18183
--- /dev/null
+++ b/src/graminit.c
@@ -0,0 +1,1094 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+#include "pgenheaders.h"
+#include "grammar.h"
+static arc arcs_0_0[3] = {
+ {2, 1},
+ {3, 1},
+ {4, 2},
+};
+static arc arcs_0_1[1] = {
+ {0, 1},
+};
+static arc arcs_0_2[1] = {
+ {2, 1},
+};
+static state states_0[3] = {
+ {3, arcs_0_0},
+ {1, arcs_0_1},
+ {1, arcs_0_2},
+};
+static arc arcs_1_0[3] = {
+ {2, 0},
+ {6, 0},
+ {7, 1},
+};
+static arc arcs_1_1[1] = {
+ {0, 1},
+};
+static state states_1[2] = {
+ {3, arcs_1_0},
+ {1, arcs_1_1},
+};
+static arc arcs_2_0[1] = {
+ {9, 1},
+};
+static arc arcs_2_1[1] = {
+ {2, 2},
+};
+static arc arcs_2_2[1] = {
+ {0, 2},
+};
+static state states_2[3] = {
+ {1, arcs_2_0},
+ {1, arcs_2_1},
+ {1, arcs_2_2},
+};
+static arc arcs_3_0[1] = {
+ {9, 1},
+};
+static arc arcs_3_1[1] = {
+ {7, 2},
+};
+static arc arcs_3_2[1] = {
+ {0, 2},
+};
+static state states_3[3] = {
+ {1, arcs_3_0},
+ {1, arcs_3_1},
+ {1, arcs_3_2},
+};
+static arc arcs_4_0[1] = {
+ {12, 1},
+};
+static arc arcs_4_1[1] = {
+ {13, 2},
+};
+static arc arcs_4_2[1] = {
+ {14, 3},
+};
+static arc arcs_4_3[1] = {
+ {15, 4},
+};
+static arc arcs_4_4[1] = {
+ {16, 5},
+};
+static arc arcs_4_5[1] = {
+ {0, 5},
+};
+static state states_4[6] = {
+ {1, arcs_4_0},
+ {1, arcs_4_1},
+ {1, arcs_4_2},
+ {1, arcs_4_3},
+ {1, arcs_4_4},
+ {1, arcs_4_5},
+};
+static arc arcs_5_0[1] = {
+ {17, 1},
+};
+static arc arcs_5_1[2] = {
+ {18, 2},
+ {19, 3},
+};
+static arc arcs_5_2[1] = {
+ {19, 3},
+};
+static arc arcs_5_3[1] = {
+ {0, 3},
+};
+static state states_5[4] = {
+ {1, arcs_5_0},
+ {2, arcs_5_1},
+ {1, arcs_5_2},
+ {1, arcs_5_3},
+};
+static arc arcs_6_0[1] = {
+ {20, 1},
+};
+static arc arcs_6_1[2] = {
+ {21, 0},
+ {0, 1},
+};
+static state states_6[2] = {
+ {1, arcs_6_0},
+ {2, arcs_6_1},
+};
+static arc arcs_7_0[2] = {
+ {13, 1},
+ {17, 2},
+};
+static arc arcs_7_1[1] = {
+ {0, 1},
+};
+static arc arcs_7_2[1] = {
+ {18, 3},
+};
+static arc arcs_7_3[1] = {
+ {19, 1},
+};
+static state states_7[4] = {
+ {2, arcs_7_0},
+ {1, arcs_7_1},
+ {1, arcs_7_2},
+ {1, arcs_7_3},
+};
+static arc arcs_8_0[2] = {
+ {3, 1},
+ {4, 1},
+};
+static arc arcs_8_1[1] = {
+ {0, 1},
+};
+static state states_8[2] = {
+ {2, arcs_8_0},
+ {1, arcs_8_1},
+};
+static arc arcs_9_0[6] = {
+ {22, 1},
+ {23, 1},
+ {24, 1},
+ {25, 1},
+ {26, 1},
+ {27, 1},
+};
+static arc arcs_9_1[1] = {
+ {0, 1},
+};
+static state states_9[2] = {
+ {6, arcs_9_0},
+ {1, arcs_9_1},
+};
+static arc arcs_10_0[1] = {
+ {28, 1},
+};
+static arc arcs_10_1[2] = {
+ {29, 0},
+ {2, 2},
+};
+static arc arcs_10_2[1] = {
+ {0, 2},
+};
+static state states_10[3] = {
+ {1, arcs_10_0},
+ {2, arcs_10_1},
+ {1, arcs_10_2},
+};
+static arc arcs_11_0[1] = {
+ {30, 1},
+};
+static arc arcs_11_1[2] = {
+ {31, 2},
+ {2, 3},
+};
+static arc arcs_11_2[2] = {
+ {21, 1},
+ {2, 3},
+};
+static arc arcs_11_3[1] = {
+ {0, 3},
+};
+static state states_11[4] = {
+ {1, arcs_11_0},
+ {2, arcs_11_1},
+ {2, arcs_11_2},
+ {1, arcs_11_3},
+};
+static arc arcs_12_0[1] = {
+ {32, 1},
+};
+static arc arcs_12_1[1] = {
+ {28, 2},
+};
+static arc arcs_12_2[1] = {
+ {2, 3},
+};
+static arc arcs_12_3[1] = {
+ {0, 3},
+};
+static state states_12[4] = {
+ {1, arcs_12_0},
+ {1, arcs_12_1},
+ {1, arcs_12_2},
+ {1, arcs_12_3},
+};
+static arc arcs_13_0[1] = {
+ {33, 1},
+};
+static arc arcs_13_1[1] = {
+ {2, 2},
+};
+static arc arcs_13_2[1] = {
+ {0, 2},
+};
+static state states_13[3] = {
+ {1, arcs_13_0},
+ {1, arcs_13_1},
+ {1, arcs_13_2},
+};
+static arc arcs_14_0[3] = {
+ {34, 1},
+ {35, 1},
+ {36, 1},
+};
+static arc arcs_14_1[1] = {
+ {0, 1},
+};
+static state states_14[2] = {
+ {3, arcs_14_0},
+ {1, arcs_14_1},
+};
+static arc arcs_15_0[1] = {
+ {37, 1},
+};
+static arc arcs_15_1[1] = {
+ {2, 2},
+};
+static arc arcs_15_2[1] = {
+ {0, 2},
+};
+static state states_15[3] = {
+ {1, arcs_15_0},
+ {1, arcs_15_1},
+ {1, arcs_15_2},
+};
+static arc arcs_16_0[1] = {
+ {38, 1},
+};
+static arc arcs_16_1[2] = {
+ {9, 2},
+ {2, 3},
+};
+static arc arcs_16_2[1] = {
+ {2, 3},
+};
+static arc arcs_16_3[1] = {
+ {0, 3},
+};
+static state states_16[4] = {
+ {1, arcs_16_0},
+ {2, arcs_16_1},
+ {1, arcs_16_2},
+ {1, arcs_16_3},
+};
+static arc arcs_17_0[1] = {
+ {39, 1},
+};
+static arc arcs_17_1[1] = {
+ {40, 2},
+};
+static arc arcs_17_2[2] = {
+ {21, 3},
+ {2, 4},
+};
+static arc arcs_17_3[1] = {
+ {40, 5},
+};
+static arc arcs_17_4[1] = {
+ {0, 4},
+};
+static arc arcs_17_5[1] = {
+ {2, 4},
+};
+static state states_17[6] = {
+ {1, arcs_17_0},
+ {1, arcs_17_1},
+ {2, arcs_17_2},
+ {1, arcs_17_3},
+ {1, arcs_17_4},
+ {1, arcs_17_5},
+};
+static arc arcs_18_0[2] = {
+ {41, 1},
+ {42, 2},
+};
+static arc arcs_18_1[1] = {
+ {13, 3},
+};
+static arc arcs_18_2[1] = {
+ {13, 4},
+};
+static arc arcs_18_3[2] = {
+ {21, 1},
+ {2, 5},
+};
+static arc arcs_18_4[1] = {
+ {41, 6},
+};
+static arc arcs_18_5[1] = {
+ {0, 5},
+};
+static arc arcs_18_6[2] = {
+ {43, 7},
+ {13, 8},
+};
+static arc arcs_18_7[1] = {
+ {2, 5},
+};
+static arc arcs_18_8[2] = {
+ {21, 9},
+ {2, 5},
+};
+static arc arcs_18_9[1] = {
+ {13, 8},
+};
+static state states_18[10] = {
+ {2, arcs_18_0},
+ {1, arcs_18_1},
+ {1, arcs_18_2},
+ {2, arcs_18_3},
+ {1, arcs_18_4},
+ {1, arcs_18_5},
+ {2, arcs_18_6},
+ {1, arcs_18_7},
+ {2, arcs_18_8},
+ {1, arcs_18_9},
+};
+static arc arcs_19_0[6] = {
+ {44, 1},
+ {45, 1},
+ {46, 1},
+ {47, 1},
+ {11, 1},
+ {48, 1},
+};
+static arc arcs_19_1[1] = {
+ {0, 1},
+};
+static state states_19[2] = {
+ {6, arcs_19_0},
+ {1, arcs_19_1},
+};
+static arc arcs_20_0[1] = {
+ {49, 1},
+};
+static arc arcs_20_1[1] = {
+ {31, 2},
+};
+static arc arcs_20_2[1] = {
+ {15, 3},
+};
+static arc arcs_20_3[1] = {
+ {16, 4},
+};
+static arc arcs_20_4[3] = {
+ {50, 1},
+ {51, 5},
+ {0, 4},
+};
+static arc arcs_20_5[1] = {
+ {15, 6},
+};
+static arc arcs_20_6[1] = {
+ {16, 7},
+};
+static arc arcs_20_7[1] = {
+ {0, 7},
+};
+static state states_20[8] = {
+ {1, arcs_20_0},
+ {1, arcs_20_1},
+ {1, arcs_20_2},
+ {1, arcs_20_3},
+ {3, arcs_20_4},
+ {1, arcs_20_5},
+ {1, arcs_20_6},
+ {1, arcs_20_7},
+};
+static arc arcs_21_0[1] = {
+ {52, 1},
+};
+static arc arcs_21_1[1] = {
+ {31, 2},
+};
+static arc arcs_21_2[1] = {
+ {15, 3},
+};
+static arc arcs_21_3[1] = {
+ {16, 4},
+};
+static arc arcs_21_4[2] = {
+ {51, 5},
+ {0, 4},
+};
+static arc arcs_21_5[1] = {
+ {15, 6},
+};
+static arc arcs_21_6[1] = {
+ {16, 7},
+};
+static arc arcs_21_7[1] = {
+ {0, 7},
+};
+static state states_21[8] = {
+ {1, arcs_21_0},
+ {1, arcs_21_1},
+ {1, arcs_21_2},
+ {1, arcs_21_3},
+ {2, arcs_21_4},
+ {1, arcs_21_5},
+ {1, arcs_21_6},
+ {1, arcs_21_7},
+};
+static arc arcs_22_0[1] = {
+ {53, 1},
+};
+static arc arcs_22_1[1] = {
+ {28, 2},
+};
+static arc arcs_22_2[1] = {
+ {54, 3},
+};
+static arc arcs_22_3[1] = {
+ {28, 4},
+};
+static arc arcs_22_4[1] = {
+ {15, 5},
+};
+static arc arcs_22_5[1] = {
+ {16, 6},
+};
+static arc arcs_22_6[2] = {
+ {51, 7},
+ {0, 6},
+};
+static arc arcs_22_7[1] = {
+ {15, 8},
+};
+static arc arcs_22_8[1] = {
+ {16, 9},
+};
+static arc arcs_22_9[1] = {
+ {0, 9},
+};
+static state states_22[10] = {
+ {1, arcs_22_0},
+ {1, arcs_22_1},
+ {1, arcs_22_2},
+ {1, arcs_22_3},
+ {1, arcs_22_4},
+ {1, arcs_22_5},
+ {2, arcs_22_6},
+ {1, arcs_22_7},
+ {1, arcs_22_8},
+ {1, arcs_22_9},
+};
+static arc arcs_23_0[1] = {
+ {55, 1},
+};
+static arc arcs_23_1[1] = {
+ {15, 2},
+};
+static arc arcs_23_2[1] = {
+ {16, 3},
+};
+static arc arcs_23_3[3] = {
+ {56, 1},
+ {57, 4},
+ {0, 3},
+};
+static arc arcs_23_4[1] = {
+ {15, 5},
+};
+static arc arcs_23_5[1] = {
+ {16, 6},
+};
+static arc arcs_23_6[1] = {
+ {0, 6},
+};
+static state states_23[7] = {
+ {1, arcs_23_0},
+ {1, arcs_23_1},
+ {1, arcs_23_2},
+ {3, arcs_23_3},
+ {1, arcs_23_4},
+ {1, arcs_23_5},
+ {1, arcs_23_6},
+};
+static arc arcs_24_0[1] = {
+ {58, 1},
+};
+static arc arcs_24_1[2] = {
+ {40, 2},
+ {0, 1},
+};
+static arc arcs_24_2[2] = {
+ {21, 3},
+ {0, 2},
+};
+static arc arcs_24_3[1] = {
+ {40, 4},
+};
+static arc arcs_24_4[1] = {
+ {0, 4},
+};
+static state states_24[5] = {
+ {1, arcs_24_0},
+ {2, arcs_24_1},
+ {2, arcs_24_2},
+ {1, arcs_24_3},
+ {1, arcs_24_4},
+};
+static arc arcs_25_0[2] = {
+ {3, 1},
+ {2, 2},
+};
+static arc arcs_25_1[1] = {
+ {0, 1},
+};
+static arc arcs_25_2[1] = {
+ {59, 3},
+};
+static arc arcs_25_3[2] = {
+ {2, 3},
+ {6, 4},
+};
+static arc arcs_25_4[3] = {
+ {6, 4},
+ {2, 4},
+ {60, 1},
+};
+static state states_25[5] = {
+ {2, arcs_25_0},
+ {1, arcs_25_1},
+ {1, arcs_25_2},
+ {2, arcs_25_3},
+ {3, arcs_25_4},
+};
+static arc arcs_26_0[1] = {
+ {61, 1},
+};
+static arc arcs_26_1[2] = {
+ {62, 0},
+ {0, 1},
+};
+static state states_26[2] = {
+ {1, arcs_26_0},
+ {2, arcs_26_1},
+};
+static arc arcs_27_0[1] = {
+ {63, 1},
+};
+static arc arcs_27_1[2] = {
+ {64, 0},
+ {0, 1},
+};
+static state states_27[2] = {
+ {1, arcs_27_0},
+ {2, arcs_27_1},
+};
+static arc arcs_28_0[2] = {
+ {65, 1},
+ {66, 2},
+};
+static arc arcs_28_1[1] = {
+ {63, 2},
+};
+static arc arcs_28_2[1] = {
+ {0, 2},
+};
+static state states_28[3] = {
+ {2, arcs_28_0},
+ {1, arcs_28_1},
+ {1, arcs_28_2},
+};
+static arc arcs_29_0[1] = {
+ {40, 1},
+};
+static arc arcs_29_1[2] = {
+ {67, 0},
+ {0, 1},
+};
+static state states_29[2] = {
+ {1, arcs_29_0},
+ {2, arcs_29_1},
+};
+static arc arcs_30_0[6] = {
+ {68, 1},
+ {69, 2},
+ {29, 3},
+ {54, 3},
+ {65, 4},
+ {70, 5},
+};
+static arc arcs_30_1[3] = {
+ {29, 3},
+ {69, 3},
+ {0, 1},
+};
+static arc arcs_30_2[2] = {
+ {29, 3},
+ {0, 2},
+};
+static arc arcs_30_3[1] = {
+ {0, 3},
+};
+static arc arcs_30_4[1] = {
+ {54, 3},
+};
+static arc arcs_30_5[2] = {
+ {65, 3},
+ {0, 5},
+};
+static state states_30[6] = {
+ {6, arcs_30_0},
+ {3, arcs_30_1},
+ {2, arcs_30_2},
+ {1, arcs_30_3},
+ {1, arcs_30_4},
+ {2, arcs_30_5},
+};
+static arc arcs_31_0[1] = {
+ {71, 1},
+};
+static arc arcs_31_1[3] = {
+ {72, 0},
+ {73, 0},
+ {0, 1},
+};
+static state states_31[2] = {
+ {1, arcs_31_0},
+ {3, arcs_31_1},
+};
+static arc arcs_32_0[1] = {
+ {74, 1},
+};
+static arc arcs_32_1[4] = {
+ {43, 0},
+ {75, 0},
+ {76, 0},
+ {0, 1},
+};
+static state states_32[2] = {
+ {1, arcs_32_0},
+ {4, arcs_32_1},
+};
+static arc arcs_33_0[3] = {
+ {72, 1},
+ {73, 1},
+ {77, 2},
+};
+static arc arcs_33_1[1] = {
+ {74, 3},
+};
+static arc arcs_33_2[2] = {
+ {78, 2},
+ {0, 2},
+};
+static arc arcs_33_3[1] = {
+ {0, 3},
+};
+static state states_33[4] = {
+ {3, arcs_33_0},
+ {1, arcs_33_1},
+ {2, arcs_33_2},
+ {1, arcs_33_3},
+};
+static arc arcs_34_0[7] = {
+ {17, 1},
+ {79, 2},
+ {81, 3},
+ {83, 4},
+ {13, 5},
+ {84, 5},
+ {85, 5},
+};
+static arc arcs_34_1[2] = {
+ {9, 6},
+ {19, 5},
+};
+static arc arcs_34_2[2] = {
+ {9, 7},
+ {80, 5},
+};
+static arc arcs_34_3[1] = {
+ {82, 5},
+};
+static arc arcs_34_4[1] = {
+ {9, 8},
+};
+static arc arcs_34_5[1] = {
+ {0, 5},
+};
+static arc arcs_34_6[1] = {
+ {19, 5},
+};
+static arc arcs_34_7[1] = {
+ {80, 5},
+};
+static arc arcs_34_8[1] = {
+ {83, 5},
+};
+static state states_34[9] = {
+ {7, arcs_34_0},
+ {2, arcs_34_1},
+ {2, arcs_34_2},
+ {1, arcs_34_3},
+ {1, arcs_34_4},
+ {1, arcs_34_5},
+ {1, arcs_34_6},
+ {1, arcs_34_7},
+ {1, arcs_34_8},
+};
+static arc arcs_35_0[3] = {
+ {17, 1},
+ {79, 2},
+ {87, 3},
+};
+static arc arcs_35_1[2] = {
+ {9, 4},
+ {19, 5},
+};
+static arc arcs_35_2[1] = {
+ {86, 6},
+};
+static arc arcs_35_3[1] = {
+ {13, 5},
+};
+static arc arcs_35_4[1] = {
+ {19, 5},
+};
+static arc arcs_35_5[1] = {
+ {0, 5},
+};
+static arc arcs_35_6[1] = {
+ {80, 5},
+};
+static state states_35[7] = {
+ {3, arcs_35_0},
+ {2, arcs_35_1},
+ {1, arcs_35_2},
+ {1, arcs_35_3},
+ {1, arcs_35_4},
+ {1, arcs_35_5},
+ {1, arcs_35_6},
+};
+static arc arcs_36_0[2] = {
+ {40, 1},
+ {15, 2},
+};
+static arc arcs_36_1[2] = {
+ {15, 2},
+ {0, 1},
+};
+static arc arcs_36_2[2] = {
+ {40, 3},
+ {0, 2},
+};
+static arc arcs_36_3[1] = {
+ {0, 3},
+};
+static state states_36[4] = {
+ {2, arcs_36_0},
+ {2, arcs_36_1},
+ {2, arcs_36_2},
+ {1, arcs_36_3},
+};
+static arc arcs_37_0[1] = {
+ {40, 1},
+};
+static arc arcs_37_1[2] = {
+ {21, 2},
+ {0, 1},
+};
+static arc arcs_37_2[2] = {
+ {40, 1},
+ {0, 2},
+};
+static state states_37[3] = {
+ {1, arcs_37_0},
+ {2, arcs_37_1},
+ {2, arcs_37_2},
+};
+static arc arcs_38_0[1] = {
+ {31, 1},
+};
+static arc arcs_38_1[2] = {
+ {21, 2},
+ {0, 1},
+};
+static arc arcs_38_2[2] = {
+ {31, 1},
+ {0, 2},
+};
+static state states_38[3] = {
+ {1, arcs_38_0},
+ {2, arcs_38_1},
+ {2, arcs_38_2},
+};
+static arc arcs_39_0[1] = {
+ {88, 1},
+};
+static arc arcs_39_1[1] = {
+ {13, 2},
+};
+static arc arcs_39_2[1] = {
+ {14, 3},
+};
+static arc arcs_39_3[2] = {
+ {29, 4},
+ {15, 5},
+};
+static arc arcs_39_4[1] = {
+ {89, 6},
+};
+static arc arcs_39_5[1] = {
+ {16, 7},
+};
+static arc arcs_39_6[1] = {
+ {15, 5},
+};
+static arc arcs_39_7[1] = {
+ {0, 7},
+};
+static state states_39[8] = {
+ {1, arcs_39_0},
+ {1, arcs_39_1},
+ {1, arcs_39_2},
+ {2, arcs_39_3},
+ {1, arcs_39_4},
+ {1, arcs_39_5},
+ {1, arcs_39_6},
+ {1, arcs_39_7},
+};
+static arc arcs_40_0[1] = {
+ {77, 1},
+};
+static arc arcs_40_1[1] = {
+ {90, 2},
+};
+static arc arcs_40_2[2] = {
+ {21, 0},
+ {0, 2},
+};
+static state states_40[3] = {
+ {1, arcs_40_0},
+ {1, arcs_40_1},
+ {2, arcs_40_2},
+};
+static arc arcs_41_0[1] = {
+ {17, 1},
+};
+static arc arcs_41_1[2] = {
+ {9, 2},
+ {19, 3},
+};
+static arc arcs_41_2[1] = {
+ {19, 3},
+};
+static arc arcs_41_3[1] = {
+ {0, 3},
+};
+static state states_41[4] = {
+ {1, arcs_41_0},
+ {2, arcs_41_1},
+ {1, arcs_41_2},
+ {1, arcs_41_3},
+};
+static dfa dfas[42] = {
+ {256, "single_input", 0, 3, states_0,
+ "\004\060\002\100\343\006\262\000\000\203\072\001"},
+ {257, "file_input", 0, 2, states_1,
+ "\204\060\002\100\343\006\262\000\000\203\072\001"},
+ {258, "expr_input", 0, 3, states_2,
+ "\000\040\002\000\000\000\000\000\002\203\072\000"},
+ {259, "eval_input", 0, 3, states_3,
+ "\000\040\002\000\000\000\000\000\002\203\072\000"},
+ {260, "funcdef", 0, 6, states_4,
+ "\000\020\000\000\000\000\000\000\000\000\000\000"},
+ {261, "parameters", 0, 4, states_5,
+ "\000\000\002\000\000\000\000\000\000\000\000\000"},
+ {262, "fplist", 0, 2, states_6,
+ "\000\040\002\000\000\000\000\000\000\000\000\000"},
+ {263, "fpdef", 0, 4, states_7,
+ "\000\040\002\000\000\000\000\000\000\000\000\000"},
+ {264, "stmt", 0, 2, states_8,
+ "\000\060\002\100\343\006\262\000\000\203\072\001"},
+ {265, "simple_stmt", 0, 2, states_9,
+ "\000\040\002\100\343\006\000\000\000\203\072\000"},
+ {266, "expr_stmt", 0, 3, states_10,
+ "\000\040\002\000\000\000\000\000\000\203\072\000"},
+ {267, "print_stmt", 0, 4, states_11,
+ "\000\000\000\100\000\000\000\000\000\000\000\000"},
+ {268, "del_stmt", 0, 4, states_12,
+ "\000\000\000\000\001\000\000\000\000\000\000\000"},
+ {269, "pass_stmt", 0, 3, states_13,
+ "\000\000\000\000\002\000\000\000\000\000\000\000"},
+ {270, "flow_stmt", 0, 2, states_14,
+ "\000\000\000\000\340\000\000\000\000\000\000\000"},
+ {271, "break_stmt", 0, 3, states_15,
+ "\000\000\000\000\040\000\000\000\000\000\000\000"},
+ {272, "return_stmt", 0, 4, states_16,
+ "\000\000\000\000\100\000\000\000\000\000\000\000"},
+ {273, "raise_stmt", 0, 6, states_17,
+ "\000\000\000\000\200\000\000\000\000\000\000\000"},
+ {274, "import_stmt", 0, 10, states_18,
+ "\000\000\000\000\000\006\000\000\000\000\000\000"},
+ {275, "compound_stmt", 0, 2, states_19,
+ "\000\020\000\000\000\000\262\000\000\000\000\001"},
+ {276, "if_stmt", 0, 8, states_20,
+ "\000\000\000\000\000\000\002\000\000\000\000\000"},
+ {277, "while_stmt", 0, 8, states_21,
+ "\000\000\000\000\000\000\020\000\000\000\000\000"},
+ {278, "for_stmt", 0, 10, states_22,
+ "\000\000\000\000\000\000\040\000\000\000\000\000"},
+ {279, "try_stmt", 0, 7, states_23,
+ "\000\000\000\000\000\000\200\000\000\000\000\000"},
+ {280, "except_clause", 0, 5, states_24,
+ "\000\000\000\000\000\000\000\004\000\000\000\000"},
+ {281, "suite", 0, 5, states_25,
+ "\004\040\002\100\343\006\000\000\000\203\072\000"},
+ {282, "test", 0, 2, states_26,
+ "\000\040\002\000\000\000\000\000\002\203\072\000"},
+ {283, "and_test", 0, 2, states_27,
+ "\000\040\002\000\000\000\000\000\002\203\072\000"},
+ {284, "not_test", 0, 3, states_28,
+ "\000\040\002\000\000\000\000\000\002\203\072\000"},
+ {285, "comparison", 0, 2, states_29,
+ "\000\040\002\000\000\000\000\000\000\203\072\000"},
+ {286, "comp_op", 0, 6, states_30,
+ "\000\000\000\040\000\000\100\000\162\000\000\000"},
+ {287, "expr", 0, 2, states_31,
+ "\000\040\002\000\000\000\000\000\000\203\072\000"},
+ {288, "term", 0, 2, states_32,
+ "\000\040\002\000\000\000\000\000\000\203\072\000"},
+ {289, "factor", 0, 4, states_33,
+ "\000\040\002\000\000\000\000\000\000\203\072\000"},
+ {290, "atom", 0, 9, states_34,
+ "\000\040\002\000\000\000\000\000\000\200\072\000"},
+ {291, "trailer", 0, 7, states_35,
+ "\000\000\002\000\000\000\000\000\000\200\200\000"},
+ {292, "subscript", 0, 4, states_36,
+ "\000\240\002\000\000\000\000\000\000\203\072\000"},
+ {293, "exprlist", 0, 3, states_37,
+ "\000\040\002\000\000\000\000\000\000\203\072\000"},
+ {294, "testlist", 0, 3, states_38,
+ "\000\040\002\000\000\000\000\000\002\203\072\000"},
+ {295, "classdef", 0, 8, states_39,
+ "\000\000\000\000\000\000\000\000\000\000\000\001"},
+ {296, "baselist", 0, 3, states_40,
+ "\000\040\002\000\000\000\000\000\000\200\072\000"},
+ {297, "arguments", 0, 4, states_41,
+ "\000\000\002\000\000\000\000\000\000\000\000\000"},
+};
+static label labels[91] = {
+ {0, "EMPTY"},
+ {256, 0},
+ {4, 0},
+ {265, 0},
+ {275, 0},
+ {257, 0},
+ {264, 0},
+ {0, 0},
+ {258, 0},
+ {294, 0},
+ {259, 0},
+ {260, 0},
+ {1, "def"},
+ {1, 0},
+ {261, 0},
+ {11, 0},
+ {281, 0},
+ {7, 0},
+ {262, 0},
+ {8, 0},
+ {263, 0},
+ {12, 0},
+ {266, 0},
+ {267, 0},
+ {269, 0},
+ {268, 0},
+ {270, 0},
+ {274, 0},
+ {293, 0},
+ {22, 0},
+ {1, "print"},
+ {282, 0},
+ {1, "del"},
+ {1, "pass"},
+ {271, 0},
+ {272, 0},
+ {273, 0},
+ {1, "break"},
+ {1, "return"},
+ {1, "raise"},
+ {287, 0},
+ {1, "import"},
+ {1, "from"},
+ {16, 0},
+ {276, 0},
+ {277, 0},
+ {278, 0},
+ {279, 0},
+ {295, 0},
+ {1, "if"},
+ {1, "elif"},
+ {1, "else"},
+ {1, "while"},
+ {1, "for"},
+ {1, "in"},
+ {1, "try"},
+ {280, 0},
+ {1, "finally"},
+ {1, "except"},
+ {5, 0},
+ {6, 0},
+ {283, 0},
+ {1, "or"},
+ {284, 0},
+ {1, "and"},
+ {1, "not"},
+ {285, 0},
+ {286, 0},
+ {20, 0},
+ {21, 0},
+ {1, "is"},
+ {288, 0},
+ {14, 0},
+ {15, 0},
+ {289, 0},
+ {17, 0},
+ {24, 0},
+ {290, 0},
+ {291, 0},
+ {9, 0},
+ {10, 0},
+ {26, 0},
+ {27, 0},
+ {25, 0},
+ {2, 0},
+ {3, 0},
+ {292, 0},
+ {23, 0},
+ {1, "class"},
+ {296, 0},
+ {297, 0},
+};
+grammar gram = {
+ 42,
+ dfas,
+ {91, labels},
+ 256
+};
diff --git a/src/graminit.h b/src/graminit.h
new file mode 100644
index 0000000..051b549
--- /dev/null
+++ b/src/graminit.h
@@ -0,0 +1,66 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+#define single_input 256
+#define file_input 257
+#define expr_input 258
+#define eval_input 259
+#define funcdef 260
+#define parameters 261
+#define fplist 262
+#define fpdef 263
+#define stmt 264
+#define simple_stmt 265
+#define expr_stmt 266
+#define print_stmt 267
+#define del_stmt 268
+#define pass_stmt 269
+#define flow_stmt 270
+#define break_stmt 271
+#define return_stmt 272
+#define raise_stmt 273
+#define import_stmt 274
+#define compound_stmt 275
+#define if_stmt 276
+#define while_stmt 277
+#define for_stmt 278
+#define try_stmt 279
+#define except_clause 280
+#define suite 281
+#define test 282
+#define and_test 283
+#define not_test 284
+#define comparison 285
+#define comp_op 286
+#define expr 287
+#define term 288
+#define factor 289
+#define atom 290
+#define trailer 291
+#define subscript 292
+#define exprlist 293
+#define testlist 294
+#define classdef 295
+#define baselist 296
+#define arguments 297
diff --git a/src/grammar.c b/src/grammar.c
new file mode 100644
index 0000000..4ba4a1a
--- /dev/null
+++ b/src/grammar.c
@@ -0,0 +1,233 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* Grammar implementation */
+
+#include "pgenheaders.h"
+
+#include <ctype.h>
+
+#include "assert.h"
+#include "token.h"
+#include "grammar.h"
+
+extern int debugging;
+
+grammar *
+newgrammar(start)
+ int start;
+{
+ grammar *g;
+
+ g = NEW(grammar, 1);
+ if (g == NULL)
+ fatal("no mem for new grammar");
+ g->g_ndfas = 0;
+ g->g_dfa = NULL;
+ g->g_start = start;
+ g->g_ll.ll_nlabels = 0;
+ g->g_ll.ll_label = NULL;
+ return g;
+}
+
+dfa *
+adddfa(g, type, name)
+ grammar *g;
+ int type;
+ char *name;
+{
+ dfa *d;
+
+ RESIZE(g->g_dfa, dfa, g->g_ndfas + 1);
+ if (g->g_dfa == NULL)
+ fatal("no mem to resize dfa in adddfa");
+ d = &g->g_dfa[g->g_ndfas++];
+ d->d_type = type;
+ d->d_name = name;
+ d->d_nstates = 0;
+ d->d_state = NULL;
+ d->d_initial = -1;
+ d->d_first = NULL;
+ return d; /* Only use while fresh! */
+}
+
+int
+addstate(d)
+ dfa *d;
+{
+ state *s;
+
+ RESIZE(d->d_state, state, d->d_nstates + 1);
+ if (d->d_state == NULL)
+ fatal("no mem to resize state in addstate");
+ s = &d->d_state[d->d_nstates++];
+ s->s_narcs = 0;
+ s->s_arc = NULL;
+ return s - d->d_state;
+}
+
+void
+addarc(d, from, to, lbl)
+ dfa *d;
+ int lbl;
+{
+ state *s;
+ arc *a;
+
+ assert(0 <= from && from < d->d_nstates);
+ assert(0 <= to && to < d->d_nstates);
+
+ s = &d->d_state[from];
+ RESIZE(s->s_arc, arc, s->s_narcs + 1);
+ if (s->s_arc == NULL)
+ fatal("no mem to resize arc list in addarc");
+ a = &s->s_arc[s->s_narcs++];
+ a->a_lbl = lbl;
+ a->a_arrow = to;
+}
+
+int
+addlabel(ll, type, str)
+ labellist *ll;
+ int type;
+ char *str;
+{
+ int i;
+ label *lb;
+
+ for (i = 0; i < ll->ll_nlabels; i++) {
+ if (ll->ll_label[i].lb_type == type &&
+ strcmp(ll->ll_label[i].lb_str, str) == 0)
+ return i;
+ }
+ RESIZE(ll->ll_label, label, ll->ll_nlabels + 1);
+ if (ll->ll_label == NULL)
+ fatal("no mem to resize labellist in addlabel");
+ lb = &ll->ll_label[ll->ll_nlabels++];
+ lb->lb_type = type;
+ lb->lb_str = str; /* XXX strdup(str) ??? */
+ return lb - ll->ll_label;
+}
+
+/* Same, but rather dies than adds */
+
+int
+findlabel(ll, type, str)
+ labellist *ll;
+ int type;
+ char *str;
+{
+ int i;
+ label *lb;
+
+ for (i = 0; i < ll->ll_nlabels; i++) {
+ if (ll->ll_label[i].lb_type == type /*&&
+ strcmp(ll->ll_label[i].lb_str, str) == 0*/)
+ return i;
+ }
+ fprintf(stderr, "Label %d/'%s' not found\n", type, str);
+ abort();
+}
+
+/* Forward */
+static void translabel PROTO((grammar *, label *));
+
+void
+translatelabels(g)
+ grammar *g;
+{
+ int i;
+
+ printf("Translating labels ...\n");
+ /* Don't translate EMPTY */
+ for (i = EMPTY+1; i < g->g_ll.ll_nlabels; i++)
+ translabel(g, &g->g_ll.ll_label[i]);
+}
+
+static void
+translabel(g, lb)
+ grammar *g;
+ label *lb;
+{
+ int i;
+
+ if (debugging)
+ printf("Translating label %s ...\n", labelrepr(lb));
+
+ if (lb->lb_type == NAME) {
+ for (i = 0; i < g->g_ndfas; i++) {
+ if (strcmp(lb->lb_str, g->g_dfa[i].d_name) == 0) {
+ if (debugging)
+ printf("Label %s is non-terminal %d.\n",
+ lb->lb_str,
+ g->g_dfa[i].d_type);
+ lb->lb_type = g->g_dfa[i].d_type;
+ lb->lb_str = NULL;
+ return;
+ }
+ }
+ for (i = 0; i < (int)N_TOKENS; i++) {
+ if (strcmp(lb->lb_str, tok_name[i]) == 0) {
+ if (debugging)
+ printf("Label %s is terminal %d.\n",
+ lb->lb_str, i);
+ lb->lb_type = i;
+ lb->lb_str = NULL;
+ return;
+ }
+ }
+ printf("Can't translate NAME label '%s'\n", lb->lb_str);
+ return;
+ }
+
+ if (lb->lb_type == STRING) {
+ if (isalpha(lb->lb_str[1])) {
+ char *p, *strchr();
+ if (debugging)
+ printf("Label %s is a keyword\n", lb->lb_str);
+ lb->lb_type = NAME;
+ lb->lb_str++;
+ p = strchr(lb->lb_str, '\'');
+ if (p)
+ *p = '\0';
+ }
+ else {
+ if (lb->lb_str[2] == lb->lb_str[0]) {
+ int type = (int) tok_1char(lb->lb_str[1]);
+ if (type != OP) {
+ lb->lb_type = type;
+ lb->lb_str = NULL;
+ }
+ else
+ printf("Unknown OP label %s\n",
+ lb->lb_str);
+ }
+ else
+ printf("Can't translate STRING label %s\n",
+ lb->lb_str);
+ }
+ }
+ else
+ printf("Can't translate label '%s'\n", labelrepr(lb));
+}
diff --git a/src/grammar.h b/src/grammar.h
new file mode 100644
index 0000000..82f34c3
--- /dev/null
+++ b/src/grammar.h
@@ -0,0 +1,105 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* Grammar interface */
+
+#include "bitset.h" /* Sigh... */
+
+/* A label of an arc */
+
+typedef struct _label {
+ int lb_type;
+ char *lb_str;
+} label;
+
+#define EMPTY 0 /* Label number 0 is by definition the empty label */
+
+/* A list of labels */
+
+typedef struct _labellist {
+ int ll_nlabels;
+ label *ll_label;
+} labellist;
+
+/* An arc from one state to another */
+
+typedef struct _arc {
+ short a_lbl; /* Label of this arc */
+ short a_arrow; /* State where this arc goes to */
+} arc;
+
+/* A state in a DFA */
+
+typedef struct _state {
+ int s_narcs;
+ arc *s_arc; /* Array of arcs */
+
+ /* Optional accelerators */
+ int s_lower; /* Lowest label index */
+ int s_upper; /* Highest label index */
+ int *s_accel; /* Accelerator */
+ int s_accept; /* Nonzero for accepting state */
+} state;
+
+/* A DFA */
+
+typedef struct _dfa {
+ int d_type; /* Non-terminal this represents */
+ char *d_name; /* For printing */
+ int d_initial; /* Initial state */
+ int d_nstates;
+ state *d_state; /* Array of states */
+ bitset d_first;
+} dfa;
+
+/* A grammar */
+
+typedef struct _grammar {
+ int g_ndfas;
+ dfa *g_dfa; /* Array of DFAs */
+ labellist g_ll;
+ int g_start; /* Start symbol of the grammar */
+ int g_accel; /* Set if accelerators present */
+} grammar;
+
+/* FUNCTIONS */
+
+grammar *newgrammar PROTO((int start));
+dfa *adddfa PROTO((grammar *g, int type, char *name));
+int addstate PROTO((dfa *d));
+void addarc PROTO((dfa *d, int from, int to, int lbl));
+dfa *finddfa PROTO((grammar *g, int type));
+char *typename PROTO((grammar *g, int lbl));
+
+int addlabel PROTO((labellist *ll, int type, char *str));
+int findlabel PROTO((labellist *ll, int type, char *str));
+char *labelrepr PROTO((label *lb));
+void translatelabels PROTO((grammar *g));
+
+void addfirstsets PROTO((grammar *g));
+
+void addaccellerators PROTO((grammar *g));
+
+void printgrammar PROTO((grammar *g, FILE *fp));
+void printnonterminals PROTO((grammar *g, FILE *fp));
diff --git a/src/grammar1.c b/src/grammar1.c
new file mode 100644
index 0000000..eafe4fe
--- /dev/null
+++ b/src/grammar1.c
@@ -0,0 +1,75 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* Grammar subroutines needed by parser */
+
+#include "pgenheaders.h"
+#include "assert.h"
+#include "grammar.h"
+#include "token.h"
+
+/* Return the DFA for the given type */
+
+dfa *
+finddfa(g, type)
+ grammar *g;
+ register int type;
+{
+ register int i;
+ register dfa *d;
+
+ for (i = g->g_ndfas, d = g->g_dfa; --i >= 0; d++) {
+ if (d->d_type == type)
+ return d;
+ }
+ assert(0);
+ /* NOTREACHED */
+}
+
+char *
+labelrepr(lb)
+ label *lb;
+{
+ static char buf[100];
+
+ if (lb->lb_type == ENDMARKER)
+ return "EMPTY";
+ else if (ISNONTERMINAL(lb->lb_type)) {
+ if (lb->lb_str == NULL) {
+ sprintf(buf, "NT%d", lb->lb_type);
+ return buf;
+ }
+ else
+ return lb->lb_str;
+ }
+ else {
+ if (lb->lb_str == NULL)
+ return tok_name[lb->lb_type];
+ else {
+ sprintf(buf, "%.32s(%.32s)",
+ tok_name[lb->lb_type], lb->lb_str);
+ return buf;
+ }
+ }
+}
diff --git a/src/import.c b/src/import.c
new file mode 100644
index 0000000..d461007
--- /dev/null
+++ b/src/import.c
@@ -0,0 +1,259 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* Module definition and import implementation */
+
+#include "allobjects.h"
+
+#include "node.h"
+#include "token.h"
+#include "graminit.h"
+#include "import.h"
+#include "errcode.h"
+#include "sysmodule.h"
+#include "pythonrun.h"
+
+/* Define pathname separator used in file names */
+
+#ifdef THINK_C
+#define SEP ':'
+#endif
+
+#ifndef SEP
+#define SEP '/'
+#endif
+
+static object *modules;
+
+/* Initialization */
+
+void
+initimport()
+{
+ if ((modules = newdictobject()) == NULL)
+ fatal("no mem for dictionary of modules");
+}
+
+object *
+get_modules()
+{
+ return modules;
+}
+
+object *
+add_module(name)
+ char *name;
+{
+ object *m;
+ if ((m = dictlookup(modules, name)) != NULL && is_moduleobject(m))
+ return m;
+ m = newmoduleobject(name);
+ if (m == NULL)
+ return NULL;
+ if (dictinsert(modules, name, m) != 0) {
+ DECREF(m);
+ return NULL;
+ }
+ DECREF(m); /* Yes, it still exists, in modules! */
+ return m;
+}
+
+static FILE *
+open_module(name, suffix, namebuf)
+ char *name;
+ char *suffix;
+ char *namebuf; /* XXX No buffer overflow checks! */
+{
+ object *path;
+ FILE *fp;
+
+ path = sysget("path");
+ if (path == NULL || !is_listobject(path)) {
+ strcpy(namebuf, name);
+ strcat(namebuf, suffix);
+ fp = fopen(namebuf, "r");
+ }
+ else {
+ int npath = getlistsize(path);
+ int i;
+ fp = NULL;
+ for (i = 0; i < npath; i++) {
+ object *v = getlistitem(path, i);
+ int len;
+ if (!is_stringobject(v))
+ continue;
+ strcpy(namebuf, getstringvalue(v));
+ len = getstringsize(v);
+ if (len > 0 && namebuf[len-1] != SEP)
+ namebuf[len++] = SEP;
+ strcpy(namebuf+len, name);
+ strcat(namebuf, suffix);
+ fp = fopen(namebuf, "r");
+ if (fp != NULL)
+ break;
+ }
+ }
+ return fp;
+}
+
+static object *
+get_module(m, name, m_ret)
+ /*module*/object *m;
+ char *name;
+ object **m_ret;
+{
+ object *d;
+ FILE *fp;
+ node *n;
+ int err;
+ char namebuf[256];
+
+ fp = open_module(name, ".py", namebuf);
+ if (fp == NULL) {
+ if (m == NULL)
+ err_setstr(NameError, name);
+ else
+ err_setstr(RuntimeError, "no module source file");
+ return NULL;
+ }
+ err = parse_file(fp, namebuf, file_input, &n);
+ fclose(fp);
+ if (err != E_DONE) {
+ err_input(err);
+ return NULL;
+ }
+ if (m == NULL) {
+ m = add_module(name);
+ if (m == NULL) {
+ freetree(n);
+ return NULL;
+ }
+ *m_ret = m;
+ }
+ d = getmoduledict(m);
+ return run_node(n, namebuf, d, d);
+}
+
+static object *
+load_module(name)
+ char *name;
+{
+ object *m, *v;
+ v = get_module((object *)NULL, name, &m);
+ if (v == NULL)
+ return NULL;
+ DECREF(v);
+ return m;
+}
+
+object *
+import_module(name)
+ char *name;
+{
+ object *m;
+ if ((m = dictlookup(modules, name)) == NULL) {
+ if (init_builtin(name)) {
+ if ((m = dictlookup(modules, name)) == NULL)
+ err_setstr(SystemError, "builtin module missing");
+ }
+ else {
+ m = load_module(name);
+ }
+ }
+ return m;
+}
+
+object *
+reload_module(m)
+ object *m;
+{
+ if (m == NULL || !is_moduleobject(m)) {
+ err_setstr(TypeError, "reload() argument must be module");
+ return NULL;
+ }
+ /* XXX Ought to check for builtin modules -- can't reload these... */
+ return get_module(m, getmodulename(m), (object **)NULL);
+}
+
+static void
+cleardict(d)
+ object *d;
+{
+ int i;
+ for (i = getdictsize(d); --i >= 0; ) {
+ char *k;
+ k = getdictkey(d, i);
+ if (k != NULL)
+ (void) dictremove(d, k);
+ }
+}
+
+void
+doneimport()
+{
+ if (modules != NULL) {
+ int i;
+ /* Explicitly erase all modules; this is the safest way
+ to get rid of at least *some* circular dependencies */
+ for (i = getdictsize(modules); --i >= 0; ) {
+ char *k;
+ k = getdictkey(modules, i);
+ if (k != NULL) {
+ object *m;
+ m = dictlookup(modules, k);
+ if (m != NULL && is_moduleobject(m)) {
+ object *d;
+ d = getmoduledict(m);
+ if (d != NULL && is_dictobject(d)) {
+ cleardict(d);
+ }
+ }
+ }
+ }
+ cleardict(modules);
+ }
+ DECREF(modules);
+}
+
+
+/* Initialize built-in modules when first imported */
+
+extern struct {
+ char *name;
+ void (*initfunc)();
+} inittab[];
+
+static int
+init_builtin(name)
+ char *name;
+{
+ int i;
+ for (i = 0; inittab[i].name != NULL; i++) {
+ if (strcmp(name, inittab[i].name) == 0) {
+ (*inittab[i].initfunc)();
+ return 1;
+ }
+ }
+ return 0;
+}
diff --git a/src/import.h b/src/import.h
new file mode 100644
index 0000000..0923395
--- /dev/null
+++ b/src/import.h
@@ -0,0 +1,31 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* Module definition and import interface */
+
+object *get_modules PROTO((void));
+object *add_module PROTO((char *name));
+object *import_module PROTO((char *name));
+object *reload_module PROTO((object *m));
+void doneimport PROTO((void));
diff --git a/src/intobject.c b/src/intobject.c
new file mode 100644
index 0000000..dba9cc6
--- /dev/null
+++ b/src/intobject.c
@@ -0,0 +1,307 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* Integer object implementation */
+
+#include "allobjects.h"
+
+/* Standard Booleans */
+
+intobject FalseObject = {
+ OB_HEAD_INIT(&Inttype)
+ 0
+};
+
+intobject TrueObject = {
+ OB_HEAD_INIT(&Inttype)
+ 1
+};
+
+static object *
+err_ovf()
+{
+ err_setstr(OverflowError, "integer overflow");
+ return NULL;
+}
+
+static object *
+err_zdiv()
+{
+ err_setstr(ZeroDivisionError, "integer division by zero");
+ return NULL;
+}
+
+/* Integers are quite normal objects, to make object handling uniform.
+ (Using odd pointers to represent integers would save much space
+ but require extra checks for this special case throughout the code.)
+ Since, a typical Python program spends much of its time allocating
+ and deallocating integers, these operations should be very fast.
+ Therefore we use a dedicated allocation scheme with a much lower
+ overhead (in space and time) than straight malloc(): a simple
+ dedicated free list, filled when necessary with memory from malloc().
+*/
+
+#define BLOCK_SIZE 1000 /* 1K less typical malloc overhead */
+#define N_INTOBJECTS (BLOCK_SIZE / sizeof(intobject))
+
+static intobject *
+fill_free_list()
+{
+ intobject *p, *q;
+ p = NEW(intobject, N_INTOBJECTS);
+ if (p == NULL)
+ return (intobject *)err_nomem();
+ q = p + N_INTOBJECTS;
+ while (--q > p)
+ *(intobject **)q = q-1;
+ *(intobject **)q = NULL;
+ return p + N_INTOBJECTS - 1;
+}
+
+static intobject *free_list = NULL;
+
+object *
+newintobject(ival)
+ long ival;
+{
+ register intobject *v;
+ if (free_list == NULL) {
+ if ((free_list = fill_free_list()) == NULL)
+ return NULL;
+ }
+ v = free_list;
+ free_list = *(intobject **)free_list;
+ NEWREF(v);
+ v->ob_type = &Inttype;
+ v->ob_ival = ival;
+ return (object *) v;
+}
+
+static void
+int_dealloc(v)
+ intobject *v;
+{
+ *(intobject **)v = free_list;
+ free_list = v;
+}
+
+long
+getintvalue(op)
+ register object *op;
+{
+ if (!is_intobject(op)) {
+ err_badcall();
+ return -1;
+ }
+ else
+ return ((intobject *)op) -> ob_ival;
+}
+
+/* Methods */
+
+static void
+int_print(v, fp, flags)
+ intobject *v;
+ FILE *fp;
+ int flags;
+{
+ fprintf(fp, "%ld", v->ob_ival);
+}
+
+static object *
+int_repr(v)
+ intobject *v;
+{
+ char buf[20];
+ sprintf(buf, "%ld", v->ob_ival);
+ return newstringobject(buf);
+}
+
+static int
+int_compare(v, w)
+ intobject *v, *w;
+{
+ register long i = v->ob_ival;
+ register long j = w->ob_ival;
+ return (i < j) ? -1 : (i > j) ? 1 : 0;
+}
+
+static object *
+int_add(v, w)
+ intobject *v;
+ register object *w;
+{
+ register long a, b, x;
+ if (!is_intobject(w)) {
+ err_badarg();
+ return NULL;
+ }
+ a = v->ob_ival;
+ b = ((intobject *)w) -> ob_ival;
+ x = a + b;
+ if ((x^a) < 0 && (x^b) < 0)
+ return err_ovf();
+ return newintobject(x);
+}
+
+static object *
+int_sub(v, w)
+ intobject *v;
+ register object *w;
+{
+ register long a, b, x;
+ if (!is_intobject(w)) {
+ err_badarg();
+ return NULL;
+ }
+ a = v->ob_ival;
+ b = ((intobject *)w) -> ob_ival;
+ x = a - b;
+ if ((x^a) < 0 && (x^~b) < 0)
+ return err_ovf();
+ return newintobject(x);
+}
+
+static object *
+int_mul(v, w)
+ intobject *v;
+ register object *w;
+{
+ register long a, b;
+ double x;
+ if (!is_intobject(w)) {
+ err_badarg();
+ return NULL;
+ }
+ a = v->ob_ival;
+ b = ((intobject *)w) -> ob_ival;
+ x = (double)a * (double)b;
+ if (x > 0x7fffffff || x < (double) (long) 0x80000000)
+ return err_ovf();
+ return newintobject(a * b);
+}
+
+static object *
+int_div(v, w)
+ intobject *v;
+ register object *w;
+{
+ if (!is_intobject(w)) {
+ err_badarg();
+ return NULL;
+ }
+ if (((intobject *)w) -> ob_ival == 0)
+ return err_zdiv();
+ return newintobject(v->ob_ival / ((intobject *)w) -> ob_ival);
+}
+
+static object *
+int_rem(v, w)
+ intobject *v;
+ register object *w;
+{
+ if (!is_intobject(w)) {
+ err_badarg();
+ return NULL;
+ }
+ if (((intobject *)w) -> ob_ival == 0)
+ return err_zdiv();
+ return newintobject(v->ob_ival % ((intobject *)w) -> ob_ival);
+}
+
+static object *
+int_pow(v, w)
+ intobject *v;
+ register object *w;
+{
+ register long iv, iw, ix;
+ register int neg;
+ if (!is_intobject(w)) {
+ err_badarg();
+ return NULL;
+ }
+ iv = v->ob_ival;
+ iw = ((intobject *)w)->ob_ival;
+ neg = 0;
+ if (iw < 0)
+ neg = 1, iw = -iw;
+ ix = 1;
+ for (; iw > 0; iw--)
+ ix = ix * iv;
+ if (neg) {
+ if (ix == 0)
+ return err_zdiv();
+ ix = 1/ix;
+ }
+ /* XXX How to check for overflow? */
+ return newintobject(ix);
+}
+
+static object *
+int_neg(v)
+ intobject *v;
+{
+ register long a, x;
+ a = v->ob_ival;
+ x = -a;
+ if (a < 0 && x < 0)
+ return err_ovf();
+ return newintobject(x);
+}
+
+static object *
+int_pos(v)
+ intobject *v;
+{
+ INCREF(v);
+ return (object *)v;
+}
+
+static number_methods int_as_number = {
+ int_add, /*tp_add*/
+ int_sub, /*tp_subtract*/
+ int_mul, /*tp_multiply*/
+ int_div, /*tp_divide*/
+ int_rem, /*tp_remainder*/
+ int_pow, /*tp_power*/
+ int_neg, /*tp_negate*/
+ int_pos, /*tp_plus*/
+};
+
+typeobject Inttype = {
+ OB_HEAD_INIT(&Typetype)
+ 0,
+ "int",
+ sizeof(intobject),
+ 0,
+ int_dealloc, /*tp_dealloc*/
+ int_print, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ int_compare, /*tp_compare*/
+ int_repr, /*tp_repr*/
+ &int_as_number, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+};
diff --git a/src/intobject.h b/src/intobject.h
new file mode 100644
index 0000000..8a5330d
--- /dev/null
+++ b/src/intobject.h
@@ -0,0 +1,72 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* Integer object interface */
+
+/*
+123456789-123456789-123456789-123456789-123456789-123456789-123456789-12
+
+intobject represents a (long) integer. This is an immutable object;
+an integer cannot change its value after creation.
+
+There are functions to create new integer objects, to test an object
+for integer-ness, and to get the integer value. The latter functions
+returns -1 and sets errno to EBADF if the object is not an intobject.
+None of the functions should be applied to nil objects.
+
+The type intobject is (unfortunately) exposed bere so we can declare
+TrueObject and FalseObject below; don't use this.
+*/
+
+typedef struct {
+ OB_HEAD
+ long ob_ival;
+} intobject;
+
+extern typeobject Inttype;
+
+#define is_intobject(op) ((op)->ob_type == &Inttype)
+
+extern object *newintobject PROTO((long));
+extern long getintvalue PROTO((object *));
+
+
+/*
+123456789-123456789-123456789-123456789-123456789-123456789-123456789-12
+
+False and True are special intobjects used by Boolean expressions.
+All values of type Boolean must point to either of these; but in
+contexts where integers are required they are integers (valued 0 and 1).
+Hope these macros don't conflict with other people's.
+
+Don't forget to apply INCREF() when returning True or False!!!
+*/
+
+extern intobject FalseObject, TrueObject; /* Don't use these directly */
+
+#define False ((object *) &FalseObject)
+#define True ((object *) &TrueObject)
+
+/* Macro, trading safety for speed */
+#define GETINTVALUE(op) ((op)->ob_ival)
diff --git a/src/intrcheck.c b/src/intrcheck.c
new file mode 100644
index 0000000..8e2fb5b
--- /dev/null
+++ b/src/intrcheck.c
@@ -0,0 +1,144 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* Check for interrupts */
+
+#ifdef MSDOS
+
+/* This might work for MS-DOS (untested though): */
+
+void
+initintr()
+{
+}
+
+int
+intrcheck()
+{
+ int interrupted = 0;
+ while (kbhit()) {
+ if (getch() == '\003')
+ interrupted = 1;
+ }
+ return interrupted;
+}
+
+#define OK
+
+#endif
+
+
+#ifdef THINK_C
+
+/* This is for THINK C 4.0.
+ For 3.0, you may have to remove the signal stuff. */
+
+#include <MacHeaders>
+#include <signal.h>
+#include "sigtype.h"
+
+static int interrupted;
+
+static SIGTYPE
+intcatcher(sig)
+ int sig;
+{
+ interrupted = 1;
+ signal(SIGINT, intcatcher);
+}
+
+void
+initintr()
+{
+ if (signal(SIGINT, SIG_IGN) != SIG_IGN)
+ signal(SIGINT, intcatcher);
+}
+
+int
+intrcheck()
+{
+ register EvQElPtr q;
+
+ /* This is like THINK C 4.0's <console.h>.
+ I'm not sure why FlushEvents must be called from asm{}. */
+ for (q = (EvQElPtr)EventQueue.qHead; q; q = (EvQElPtr)q->qLink) {
+ if (q->evtQWhat == keyDown &&
+ (char)q->evtQMessage == '.' &&
+ (q->evtQModifiers & cmdKey) != 0) {
+
+ asm {
+ moveq #keyDownMask,d0
+ _FlushEvents
+ }
+ interrupted = 1;
+ break;
+ }
+ }
+ if (interrupted) {
+ interrupted = 0;
+ return 1;
+ }
+ return 0;
+}
+
+#define OK
+
+#endif /* THINK_C */
+
+
+#ifndef OK
+
+/* Default version -- for real operating systems and for Standard C */
+
+#include <stdio.h>
+#include <signal.h>
+#include "sigtype.h"
+
+static int interrupted;
+
+static SIGTYPE
+intcatcher(sig)
+ int sig;
+{
+ interrupted = 1;
+ signal(SIGINT, intcatcher);
+}
+
+void
+initintr()
+{
+ if (signal(SIGINT, SIG_IGN) != SIG_IGN)
+ signal(SIGINT, intcatcher);
+}
+
+int
+intrcheck()
+{
+ if (!interrupted)
+ return 0;
+ interrupted = 0;
+ return 1;
+}
+
+#endif /* !OK */
diff --git a/src/listnode.c b/src/listnode.c
new file mode 100644
index 0000000..333d01f
--- /dev/null
+++ b/src/listnode.c
@@ -0,0 +1,93 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* List a node on a file */
+
+#include "pgenheaders.h"
+#include "token.h"
+#include "node.h"
+
+/* Forward */
+static void list1node PROTO((FILE *, node *));
+
+void
+listtree(n)
+ node *n;
+{
+ listnode(stdout, n);
+}
+
+static int level, atbol;
+
+void
+listnode(fp, n)
+ FILE *fp;
+ node *n;
+{
+ level = 0;
+ atbol = 1;
+ list1node(fp, n);
+}
+
+static void
+list1node(fp, n)
+ FILE *fp;
+ node *n;
+{
+ if (n == 0)
+ return;
+ if (ISNONTERMINAL(TYPE(n))) {
+ int i;
+ for (i = 0; i < NCH(n); i++)
+ list1node(fp, CHILD(n, i));
+ }
+ else if (ISTERMINAL(TYPE(n))) {
+ switch (TYPE(n)) {
+ case INDENT:
+ ++level;
+ break;
+ case DEDENT:
+ --level;
+ break;
+ default:
+ if (atbol) {
+ int i;
+ for (i = 0; i < level; ++i)
+ fprintf(fp, "\t");
+ atbol = 0;
+ }
+ if (TYPE(n) == NEWLINE) {
+ if (STR(n) != NULL)
+ fprintf(fp, "%s", STR(n));
+ fprintf(fp, "\n");
+ atbol = 1;
+ }
+ else
+ fprintf(fp, "%s ", STR(n));
+ break;
+ }
+ }
+ else
+ fprintf(fp, "? ");
+}
diff --git a/src/listobject.c b/src/listobject.c
new file mode 100644
index 0000000..be1382c
--- /dev/null
+++ b/src/listobject.c
@@ -0,0 +1,519 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* List object implementation */
+
+#include "allobjects.h"
+
+object *
+newlistobject(size)
+ int size;
+{
+ int i;
+ listobject *op;
+ if (size < 0) {
+ err_badcall();
+ return NULL;
+ }
+ op = (listobject *) malloc(sizeof(listobject));
+ if (op == NULL) {
+ return err_nomem();
+ }
+ if (size <= 0) {
+ op->ob_item = NULL;
+ }
+ else {
+ op->ob_item = (object **) malloc(size * sizeof(object *));
+ if (op->ob_item == NULL) {
+ free((ANY *)op);
+ return err_nomem();
+ }
+ }
+ NEWREF(op);
+ op->ob_type = &Listtype;
+ op->ob_size = size;
+ for (i = 0; i < size; i++)
+ op->ob_item[i] = NULL;
+ return (object *) op;
+}
+
+int
+getlistsize(op)
+ object *op;
+{
+ if (!is_listobject(op)) {
+ err_badcall();
+ return -1;
+ }
+ else
+ return ((listobject *)op) -> ob_size;
+}
+
+object *
+getlistitem(op, i)
+ object *op;
+ int i;
+{
+ if (!is_listobject(op)) {
+ err_badcall();
+ return NULL;
+ }
+ if (i < 0 || i >= ((listobject *)op) -> ob_size) {
+ err_setstr(IndexError, "list index out of range");
+ return NULL;
+ }
+ return ((listobject *)op) -> ob_item[i];
+}
+
+int
+setlistitem(op, i, newitem)
+ register object *op;
+ register int i;
+ register object *newitem;
+{
+ register object *olditem;
+ if (!is_listobject(op)) {
+ if (newitem != NULL)
+ DECREF(newitem);
+ err_badcall();
+ return -1;
+ }
+ if (i < 0 || i >= ((listobject *)op) -> ob_size) {
+ if (newitem != NULL)
+ DECREF(newitem);
+ err_setstr(IndexError, "list assignment index out of range");
+ return -1;
+ }
+ olditem = ((listobject *)op) -> ob_item[i];
+ ((listobject *)op) -> ob_item[i] = newitem;
+ if (olditem != NULL)
+ DECREF(olditem);
+ return 0;
+}
+
+static int
+ins1(self, where, v)
+ listobject *self;
+ int where;
+ object *v;
+{
+ int i;
+ object **items;
+ if (v == NULL) {
+ err_badcall();
+ return -1;
+ }
+ items = self->ob_item;
+ RESIZE(items, object *, self->ob_size+1);
+ if (items == NULL) {
+ err_nomem();
+ return -1;
+ }
+ if (where < 0)
+ where = 0;
+ if (where > self->ob_size)
+ where = self->ob_size;
+ for (i = self->ob_size; --i >= where; )
+ items[i+1] = items[i];
+ INCREF(v);
+ items[where] = v;
+ self->ob_item = items;
+ self->ob_size++;
+ return 0;
+}
+
+int
+inslistitem(op, where, newitem)
+ object *op;
+ int where;
+ object *newitem;
+{
+ if (!is_listobject(op)) {
+ err_badcall();
+ return -1;
+ }
+ return ins1((listobject *)op, where, newitem);
+}
+
+int
+addlistitem(op, newitem)
+ object *op;
+ object *newitem;
+{
+ if (!is_listobject(op)) {
+ err_badcall();
+ return -1;
+ }
+ return ins1((listobject *)op,
+ (int) ((listobject *)op)->ob_size, newitem);
+}
+
+/* Methods */
+
+static void
+list_dealloc(op)
+ listobject *op;
+{
+ int i;
+ for (i = 0; i < op->ob_size; i++) {
+ if (op->ob_item[i] != NULL)
+ DECREF(op->ob_item[i]);
+ }
+ if (op->ob_item != NULL)
+ free((ANY *)op->ob_item);
+ free((ANY *)op);
+}
+
+static void
+list_print(op, fp, flags)
+ listobject *op;
+ FILE *fp;
+ int flags;
+{
+ int i;
+ fprintf(fp, "[");
+ for (i = 0; i < op->ob_size && !StopPrint; i++) {
+ if (i > 0) {
+ fprintf(fp, ", ");
+ }
+ printobject(op->ob_item[i], fp, flags);
+ }
+ fprintf(fp, "]");
+}
+
+object *
+list_repr(v)
+ listobject *v;
+{
+ object *s, *t, *comma;
+ int i;
+ s = newstringobject("[");
+ comma = newstringobject(", ");
+ for (i = 0; i < v->ob_size && s != NULL; i++) {
+ if (i > 0)
+ joinstring(&s, comma);
+ t = reprobject(v->ob_item[i]);
+ joinstring(&s, t);
+ DECREF(t);
+ }
+ DECREF(comma);
+ t = newstringobject("]");
+ joinstring(&s, t);
+ DECREF(t);
+ return s;
+}
+
+static int
+list_compare(v, w)
+ listobject *v, *w;
+{
+ int len = (v->ob_size < w->ob_size) ? v->ob_size : w->ob_size;
+ int i;
+ for (i = 0; i < len; i++) {
+ int cmp = cmpobject(v->ob_item[i], w->ob_item[i]);
+ if (cmp != 0)
+ return cmp;
+ }
+ return v->ob_size - w->ob_size;
+}
+
+static int
+list_length(a)
+ listobject *a;
+{
+ return a->ob_size;
+}
+
+static object *
+list_item(a, i)
+ listobject *a;
+ int i;
+{
+ if (i < 0 || i >= a->ob_size) {
+ err_setstr(IndexError, "list index out of range");
+ return NULL;
+ }
+ INCREF(a->ob_item[i]);
+ return a->ob_item[i];
+}
+
+static object *
+list_slice(a, ilow, ihigh)
+ listobject *a;
+ int ilow, ihigh;
+{
+ listobject *np;
+ int i;
+ if (ilow < 0)
+ ilow = 0;
+ else if (ilow > a->ob_size)
+ ilow = a->ob_size;
+ if (ihigh < 0)
+ ihigh = 0;
+ if (ihigh < ilow)
+ ihigh = ilow;
+ else if (ihigh > a->ob_size)
+ ihigh = a->ob_size;
+ np = (listobject *) newlistobject(ihigh - ilow);
+ if (np == NULL)
+ return NULL;
+ for (i = ilow; i < ihigh; i++) {
+ object *v = a->ob_item[i];
+ INCREF(v);
+ np->ob_item[i - ilow] = v;
+ }
+ return (object *)np;
+}
+
+static object *
+list_concat(a, bb)
+ listobject *a;
+ object *bb;
+{
+ int size;
+ int i;
+ listobject *np;
+ if (!is_listobject(bb)) {
+ err_badarg();
+ return NULL;
+ }
+#define b ((listobject *)bb)
+ size = a->ob_size + b->ob_size;
+ np = (listobject *) newlistobject(size);
+ if (np == NULL) {
+ return err_nomem();
+ }
+ for (i = 0; i < a->ob_size; i++) {
+ object *v = a->ob_item[i];
+ INCREF(v);
+ np->ob_item[i] = v;
+ }
+ for (i = 0; i < b->ob_size; i++) {
+ object *v = b->ob_item[i];
+ INCREF(v);
+ np->ob_item[i + a->ob_size] = v;
+ }
+ return (object *)np;
+#undef b
+}
+
+static int
+list_ass_item(a, i, v)
+ listobject *a;
+ int i;
+ object *v;
+{
+ if (i < 0 || i >= a->ob_size) {
+ err_setstr(IndexError, "list assignment index out of range");
+ return -1;
+ }
+ if (v == NULL)
+ return list_ass_slice(a, i, i+1, v);
+ INCREF(v);
+ DECREF(a->ob_item[i]);
+ a->ob_item[i] = v;
+ return 0;
+}
+
+static int
+list_ass_slice(a, ilow, ihigh, v)
+ listobject *a;
+ int ilow, ihigh;
+ object *v;
+{
+ object **item;
+ int n; /* Size of replacement list */
+ int d; /* Change in size */
+ int k; /* Loop index */
+#define b ((listobject *)v)
+ if (v == NULL)
+ n = 0;
+ else if (is_listobject(v))
+ n = b->ob_size;
+ else {
+ err_badarg();
+ return -1;
+ }
+ if (ilow < 0)
+ ilow = 0;
+ else if (ilow > a->ob_size)
+ ilow = a->ob_size;
+ if (ihigh < 0)
+ ihigh = 0;
+ if (ihigh < ilow)
+ ihigh = ilow;
+ else if (ihigh > a->ob_size)
+ ihigh = a->ob_size;
+ item = a->ob_item;
+ d = n - (ihigh-ilow);
+ if (d <= 0) { /* Delete -d items; DECREF ihigh-ilow items */
+ for (k = ilow; k < ihigh; k++)
+ DECREF(item[k]);
+ if (d < 0) {
+ for (/*k = ihigh*/; k < a->ob_size; k++)
+ item[k+d] = item[k];
+ a->ob_size += d;
+ RESIZE(item, object *, a->ob_size); /* Can't fail */
+ a->ob_item = item;
+ }
+ }
+ else { /* Insert d items; DECREF ihigh-ilow items */
+ RESIZE(item, object *, a->ob_size + d);
+ if (item == NULL) {
+ err_nomem();
+ return -1;
+ }
+ for (k = a->ob_size; --k >= ihigh; )
+ item[k+d] = item[k];
+ for (/*k = ihigh-1*/; k >= ilow; --k)
+ DECREF(item[k]);
+ a->ob_item = item;
+ a->ob_size += d;
+ }
+ for (k = 0; k < n; k++, ilow++) {
+ object *w = b->ob_item[k];
+ INCREF(w);
+ item[ilow] = w;
+ }
+ return 0;
+#undef b
+}
+
+static object *
+ins(self, where, v)
+ listobject *self;
+ int where;
+ object *v;
+{
+ if (ins1(self, where, v) != 0)
+ return NULL;
+ INCREF(None);
+ return None;
+}
+
+static object *
+listinsert(self, args)
+ listobject *self;
+ object *args;
+{
+ int i;
+ if (args == NULL || !is_tupleobject(args) || gettuplesize(args) != 2) {
+ err_badarg();
+ return NULL;
+ }
+ if (!getintarg(gettupleitem(args, 0), &i))
+ return NULL;
+ return ins(self, i, gettupleitem(args, 1));
+}
+
+static object *
+listappend(self, args)
+ listobject *self;
+ object *args;
+{
+ return ins(self, (int) self->ob_size, args);
+}
+
+static int
+cmp(v, w)
+ char *v, *w;
+{
+ return cmpobject(* (object **) v, * (object **) w);
+}
+
+static object *
+listsort(self, args)
+ listobject *self;
+ object *args;
+{
+ if (args != NULL) {
+ err_badarg();
+ return NULL;
+ }
+ err_clear();
+ if (self->ob_size > 1)
+ qsort((char *)self->ob_item,
+ (int) self->ob_size, sizeof(object *), cmp);
+ if (err_occurred())
+ return NULL;
+ INCREF(None);
+ return None;
+}
+
+int
+sortlist(v)
+ object *v;
+{
+ if (v == NULL || !is_listobject(v)) {
+ err_badcall();
+ return -1;
+ }
+ v = listsort((listobject *)v, (object *)NULL);
+ if (v == NULL)
+ return -1;
+ DECREF(v);
+ return 0;
+}
+
+static struct methodlist list_methods[] = {
+ {"append", listappend},
+ {"insert", listinsert},
+ {"sort", listsort},
+ {NULL, NULL} /* sentinel */
+};
+
+static object *
+list_getattr(f, name)
+ listobject *f;
+ char *name;
+{
+ return findmethod(list_methods, (object *)f, name);
+}
+
+static sequence_methods list_as_sequence = {
+ list_length, /*sq_length*/
+ list_concat, /*sq_concat*/
+ 0, /*sq_repeat*/
+ list_item, /*sq_item*/
+ list_slice, /*sq_slice*/
+ list_ass_item, /*sq_ass_item*/
+ list_ass_slice, /*sq_ass_slice*/
+};
+
+typeobject Listtype = {
+ OB_HEAD_INIT(&Typetype)
+ 0,
+ "list",
+ sizeof(listobject),
+ 0,
+ list_dealloc, /*tp_dealloc*/
+ list_print, /*tp_print*/
+ list_getattr, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ list_compare, /*tp_compare*/
+ list_repr, /*tp_repr*/
+ 0, /*tp_as_number*/
+ &list_as_sequence, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+};
diff --git a/src/listobject.h b/src/listobject.h
new file mode 100644
index 0000000..103ceb6
--- /dev/null
+++ b/src/listobject.h
@@ -0,0 +1,59 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* List object interface */
+
+/*
+123456789-123456789-123456789-123456789-123456789-123456789-123456789-12
+
+Another generally useful object type is an list of object pointers.
+This is a mutable type: the list items can be changed, and items can be
+added or removed. Out-of-range indices or non-list objects are ignored.
+
+*** WARNING *** setlistitem does not increment the new item's reference
+count, but does decrement the reference count of the item it replaces,
+if not nil. It does *decrement* the reference count if it is *not*
+inserted in the list. Similarly, getlistitem does not increment the
+returned item's reference count.
+*/
+
+typedef struct {
+ OB_VARHEAD
+ object **ob_item;
+} listobject;
+
+extern typeobject Listtype;
+
+#define is_listobject(op) ((op)->ob_type == &Listtype)
+
+extern object *newlistobject PROTO((int size));
+extern int getlistsize PROTO((object *));
+extern object *getlistitem PROTO((object *, int));
+extern int setlistitem PROTO((object *, int, object *));
+extern int inslistitem PROTO((object *, int, object *));
+extern int addlistitem PROTO((object *, object *));
+extern int sortlist PROTO((object *));
+
+/* Macro, trading safety for speed */
+#define GETLISTITEM(op, i) ((op)->ob_item[i])
diff --git a/src/macmodule.c b/src/macmodule.c
new file mode 100644
index 0000000..4f20914
--- /dev/null
+++ b/src/macmodule.c
@@ -0,0 +1,246 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* Macintosh OS module implementation */
+
+#include "allobjects.h"
+
+#include "import.h"
+#include "modsupport.h"
+
+#include "sigtype.h"
+
+#include "::unixemu:dir.h"
+#include "::unixemu:stat.h"
+
+static object *MacError; /* Exception */
+
+
+static object *
+mac_chdir(self, args)
+ object *self;
+ object *args;
+{
+ object *path;
+ if (!getstrarg(args, &path))
+ return NULL;
+ if (chdir(getstringvalue(path)) != 0)
+ return err_errno(MacError);
+ INCREF(None);
+ return None;
+}
+
+
+static object *
+mac_getcwd(self, args)
+ object *self;
+ object *args;
+{
+ extern char *getwd();
+ char buf[1025];
+ if (!getnoarg(args))
+ return NULL;
+ strcpy(buf, "mac.getcwd() failed"); /* In case getwd() doesn't set a msg */
+ if (getwd(buf) == NULL) {
+ err_setstr(MacError, buf);
+ return NULL;
+ }
+ return newstringobject(buf);
+}
+
+
+static object *
+mac_listdir(self, args)
+ object *self;
+ object *args;
+{
+ object *name, *d, *v;
+ DIR *dirp;
+ struct direct *ep;
+ if (!getstrarg(args, &name))
+ return NULL;
+ if ((dirp = opendir(getstringvalue(name))) == NULL)
+ return err_errno(MacError);
+ if ((d = newlistobject(0)) == NULL) {
+ closedir(dirp);
+ return NULL;
+ }
+ while ((ep = readdir(dirp)) != NULL) {
+ v = newstringobject(ep->d_name);
+ if (v == NULL) {
+ DECREF(d);
+ d = NULL;
+ break;
+ }
+ if (addlistitem(d, v) != 0) {
+ DECREF(v);
+ DECREF(d);
+ d = NULL;
+ break;
+ }
+ DECREF(v);
+ }
+ closedir(dirp);
+ return d;
+}
+
+
+static object *
+mac_mkdir(self, args)
+ object *self;
+ object *args;
+{
+ object *path;
+ int mode;
+ if (!getstrintarg(args, &path, &mode))
+ return NULL;
+ if (mkdir(getstringvalue(path), mode) != 0)
+ return err_errno(MacError);
+ INCREF(None);
+ return None;
+}
+
+
+static object *
+mac_rename(self, args)
+ object *self;
+ object *args;
+{
+ object *src, *dst;
+ if (!getstrstrarg(args, &src, &dst))
+ return NULL;
+ if (rename(getstringvalue(src), getstringvalue(dst)) != 0)
+ return err_errno(MacError);
+ INCREF(None);
+ return None;
+}
+
+
+static object *
+mac_rmdir(self, args)
+ object *self;
+ object *args;
+{
+ object *path;
+ if (!getstrarg(args, &path))
+ return NULL;
+ if (rmdir(getstringvalue(path)) != 0)
+ return err_errno(MacError);
+ INCREF(None);
+ return None;
+}
+
+
+static object *
+mac_stat(self, args)
+ object *self;
+ object *args;
+{
+ struct stat st;
+ object *path;
+ object *v;
+ if (!getstrarg(args, &path))
+ return NULL;
+ if (stat(getstringvalue(path), &st) != 0)
+ return err_errno(MacError);
+ v = newtupleobject(11);
+ if (v == NULL)
+ return NULL;
+#define SET(i, val) settupleitem(v, i, newintobject((long)(val)))
+#define XXX(i, val) SET(i, 0) /* For values my Mac stat doesn't support */
+ SET(0, st.st_mode);
+ XXX(1, st.st_ino);
+ XXX(2, st.st_dev);
+ XXX(3, st.st_nlink);
+ XXX(4, st.st_uid);
+ XXX(5, st.st_gid);
+ SET(6, st.st_size);
+ XXX(7, st.st_atime);
+ SET(8, st.st_mtime);
+ XXX(9, st.st_ctime);
+ SET(10, st.st_rsize); /* Mac-specific: resource size */
+#undef SET
+ if (err_occurred()) {
+ DECREF(v);
+ return NULL;
+ }
+ return v;
+}
+
+
+static object *
+mac_sync(self, args)
+ object *self;
+ object *args;
+{
+ if (!getnoarg(args))
+ return NULL;
+ sync();
+ INCREF(None);
+ return None;
+}
+
+
+static object *
+mac_unlink(self, args)
+ object *self;
+ object *args;
+{
+ object *path;
+ if (!getstrarg(args, &path))
+ return NULL;
+ if (unlink(getstringvalue(path)) != 0)
+ return err_errno(MacError);
+ INCREF(None);
+ return None;
+}
+
+
+static struct methodlist mac_methods[] = {
+ {"chdir", mac_chdir},
+ {"getcwd", mac_getcwd},
+ {"listdir", mac_listdir},
+ {"mkdir", mac_mkdir},
+ {"rename", mac_rename},
+ {"rmdir", mac_rmdir},
+ {"stat", mac_stat},
+ {"sync", mac_sync},
+ {"unlink", mac_unlink},
+ {NULL, NULL} /* Sentinel */
+};
+
+
+void
+initmac()
+{
+ object *m, *d;
+
+ m = initmodule("mac", mac_methods);
+ d = getmoduledict(m);
+
+ /* Initialize mac.error exception */
+ MacError = newstringobject("mac.error");
+ if (MacError == NULL || dictinsert(d, "error", MacError) != 0)
+ fatal("can't define mac.error");
+}
diff --git a/src/malloc.h b/src/malloc.h
new file mode 100644
index 0000000..c2d9969
--- /dev/null
+++ b/src/malloc.h
@@ -0,0 +1,63 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* Lowest-level memory allocation interface */
+
+#ifdef THINK_C
+#define ANY void
+#ifndef THINK_C_3_0
+#define HAVE_STDLIB
+#endif
+#endif
+
+#ifdef __STD_C__
+#define ANY void
+#define HAVE_STDLIB
+#endif
+
+#ifndef ANY
+#define ANY char
+#endif
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+#define NEW(type, n) ( (type *) malloc((n) * sizeof(type)) )
+#define RESIZE(p, type, n) \
+ if ((p) == NULL) \
+ (p) = (type *) malloc((n) * sizeof(type)); \
+ else \
+ (p) = (type *) realloc((char *)(p), (n) * sizeof(type))
+#define DEL(p) free((char *)p)
+#define XDEL(p) if ((p) == NULL) ; else DEL(p)
+
+#ifdef HAVE_STDLIB
+#include <stdlib.h>
+#else
+extern ANY *malloc PROTO((unsigned int));
+extern ANY *calloc PROTO((unsigned int, unsigned int));
+extern ANY *realloc PROTO((ANY *, unsigned int));
+extern void free PROTO((ANY *)); /* XXX sometimes int on Unix old systems */
+#endif
diff --git a/src/mathmodule.c b/src/mathmodule.c
new file mode 100644
index 0000000..3fa8d03
--- /dev/null
+++ b/src/mathmodule.c
@@ -0,0 +1,180 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* Math module -- standard C math library functions, pi and e */
+
+#include "allobjects.h"
+
+#include <errno.h>
+#ifndef errno
+extern int errno;
+#endif
+
+#include "modsupport.h"
+
+#include <math.h>
+
+static int
+getdoublearg(args, px)
+ register object *args;
+ double *px;
+{
+ if (args == NULL)
+ return err_badarg();
+ if (is_floatobject(args)) {
+ *px = getfloatvalue(args);
+ return 1;
+ }
+ if (is_intobject(args)) {
+ *px = getintvalue(args);
+ return 1;
+ }
+ return err_badarg();
+}
+
+static int
+get2doublearg(args, px, py)
+ register object *args;
+ double *px, *py;
+{
+ if (args == NULL || !is_tupleobject(args) || gettuplesize(args) != 2)
+ return err_badarg();
+ return getdoublearg(gettupleitem(args, 0), px) &&
+ getdoublearg(gettupleitem(args, 1), py);
+}
+
+static object *
+math_1(args, func)
+ object *args;
+ double (*func) FPROTO((double));
+{
+ double x;
+ if (!getdoublearg(args, &x))
+ return NULL;
+ errno = 0;
+ x = (*func)(x);
+ if (errno != 0)
+ return NULL;
+ else
+ return newfloatobject(x);
+}
+
+static object *
+math_2(args, func)
+ object *args;
+ double (*func) FPROTO((double, double));
+{
+ double x, y;
+ if (!get2doublearg(args, &x, &y))
+ return NULL;
+ errno = 0;
+ x = (*func)(x, y);
+ if (errno != 0)
+ return NULL;
+ else
+ return newfloatobject(x);
+}
+
+#define FUNC1(stubname, func) \
+ static object * stubname(self, args) object *self, *args; { \
+ return math_1(args, func); \
+ }
+
+#define FUNC2(stubname, func) \
+ static object * stubname(self, args) object *self, *args; { \
+ return math_2(args, func); \
+ }
+
+FUNC1(math_acos, acos)
+FUNC1(math_asin, asin)
+FUNC1(math_atan, atan)
+FUNC2(math_atan2, atan2)
+FUNC1(math_ceil, ceil)
+FUNC1(math_cos, cos)
+FUNC1(math_cosh, cosh)
+FUNC1(math_exp, exp)
+FUNC1(math_fabs, fabs)
+FUNC1(math_floor, floor)
+#if 0
+/* XXX This one is not in the Amoeba library yet, so what the heck... */
+FUNC2(math_fmod, fmod)
+#endif
+FUNC1(math_log, log)
+FUNC1(math_log10, log10)
+FUNC2(math_pow, pow)
+FUNC1(math_sin, sin)
+FUNC1(math_sinh, sinh)
+FUNC1(math_sqrt, sqrt)
+FUNC1(math_tan, tan)
+FUNC1(math_tanh, tanh)
+
+#if 0
+/* What about these? */
+double frexp(double x, int *i);
+double ldexp(double x, int n);
+double modf(double x, double *i);
+#endif
+
+static struct methodlist math_methods[] = {
+ {"acos", math_acos},
+ {"asin", math_asin},
+ {"atan", math_atan},
+ {"atan2", math_atan2},
+ {"ceil", math_ceil},
+ {"cos", math_cos},
+ {"cosh", math_cosh},
+ {"exp", math_exp},
+ {"fabs", math_fabs},
+ {"floor", math_floor},
+#if 0
+ {"fmod", math_fmod},
+ {"frexp", math_freqp},
+ {"ldexp", math_ldexp},
+#endif
+ {"log", math_log},
+ {"log10", math_log10},
+#if 0
+ {"modf", math_modf},
+#endif
+ {"pow", math_pow},
+ {"sin", math_sin},
+ {"sinh", math_sinh},
+ {"sqrt", math_sqrt},
+ {"tan", math_tan},
+ {"tanh", math_tanh},
+ {NULL, NULL} /* sentinel */
+};
+
+void
+initmath()
+{
+ object *m, *d, *v;
+
+ m = initmodule("math", math_methods);
+ d = getmoduledict(m);
+ dictinsert(d, "pi", v = newfloatobject(atan(1.0) * 4.0));
+ DECREF(v);
+ dictinsert(d, "e", v = newfloatobject(exp(1.0)));
+ DECREF(v);
+}
diff --git a/src/metagrammar.c b/src/metagrammar.c
new file mode 100644
index 0000000..57d47cb
--- /dev/null
+++ b/src/metagrammar.c
@@ -0,0 +1,176 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+#include "pgenheaders.h"
+#include "metagrammar.h"
+#include "grammar.h"
+#include "pgen.h"
+static arc arcs_0_0[3] = {
+ {2, 0},
+ {3, 0},
+ {4, 1},
+};
+static arc arcs_0_1[1] = {
+ {0, 1},
+};
+static state states_0[2] = {
+ {3, arcs_0_0},
+ {1, arcs_0_1},
+};
+static arc arcs_1_0[1] = {
+ {5, 1},
+};
+static arc arcs_1_1[1] = {
+ {6, 2},
+};
+static arc arcs_1_2[1] = {
+ {7, 3},
+};
+static arc arcs_1_3[1] = {
+ {3, 4},
+};
+static arc arcs_1_4[1] = {
+ {0, 4},
+};
+static state states_1[5] = {
+ {1, arcs_1_0},
+ {1, arcs_1_1},
+ {1, arcs_1_2},
+ {1, arcs_1_3},
+ {1, arcs_1_4},
+};
+static arc arcs_2_0[1] = {
+ {8, 1},
+};
+static arc arcs_2_1[2] = {
+ {9, 0},
+ {0, 1},
+};
+static state states_2[2] = {
+ {1, arcs_2_0},
+ {2, arcs_2_1},
+};
+static arc arcs_3_0[1] = {
+ {10, 1},
+};
+static arc arcs_3_1[2] = {
+ {10, 1},
+ {0, 1},
+};
+static state states_3[2] = {
+ {1, arcs_3_0},
+ {2, arcs_3_1},
+};
+static arc arcs_4_0[2] = {
+ {11, 1},
+ {13, 2},
+};
+static arc arcs_4_1[1] = {
+ {7, 3},
+};
+static arc arcs_4_2[3] = {
+ {14, 4},
+ {15, 4},
+ {0, 2},
+};
+static arc arcs_4_3[1] = {
+ {12, 4},
+};
+static arc arcs_4_4[1] = {
+ {0, 4},
+};
+static state states_4[5] = {
+ {2, arcs_4_0},
+ {1, arcs_4_1},
+ {3, arcs_4_2},
+ {1, arcs_4_3},
+ {1, arcs_4_4},
+};
+static arc arcs_5_0[3] = {
+ {5, 1},
+ {16, 1},
+ {17, 2},
+};
+static arc arcs_5_1[1] = {
+ {0, 1},
+};
+static arc arcs_5_2[1] = {
+ {7, 3},
+};
+static arc arcs_5_3[1] = {
+ {18, 1},
+};
+static state states_5[4] = {
+ {3, arcs_5_0},
+ {1, arcs_5_1},
+ {1, arcs_5_2},
+ {1, arcs_5_3},
+};
+static dfa dfas[6] = {
+ {256, "MSTART", 0, 2, states_0,
+ "\070\000\000"},
+ {257, "RULE", 0, 5, states_1,
+ "\040\000\000"},
+ {258, "RHS", 0, 2, states_2,
+ "\040\010\003"},
+ {259, "ALT", 0, 2, states_3,
+ "\040\010\003"},
+ {260, "ITEM", 0, 5, states_4,
+ "\040\010\003"},
+ {261, "ATOM", 0, 4, states_5,
+ "\040\000\003"},
+};
+static label labels[19] = {
+ {0, "EMPTY"},
+ {256, 0},
+ {257, 0},
+ {4, 0},
+ {0, 0},
+ {1, 0},
+ {11, 0},
+ {258, 0},
+ {259, 0},
+ {18, 0},
+ {260, 0},
+ {9, 0},
+ {10, 0},
+ {261, 0},
+ {16, 0},
+ {14, 0},
+ {3, 0},
+ {7, 0},
+ {8, 0},
+};
+static grammar gram = {
+ 6,
+ dfas,
+ {19, labels},
+ 256
+};
+
+grammar *
+meta_grammar()
+{
+ return &gram;
+}
diff --git a/src/metagrammar.h b/src/metagrammar.h
new file mode 100644
index 0000000..a937b64
--- /dev/null
+++ b/src/metagrammar.h
@@ -0,0 +1,30 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+#define MSTART 256
+#define RULE 257
+#define RHS 258
+#define ALT 259
+#define ITEM 260
+#define ATOM 261
diff --git a/src/methodobject.c b/src/methodobject.c
new file mode 100644
index 0000000..68a0217
--- /dev/null
+++ b/src/methodobject.c
@@ -0,0 +1,147 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* Method object implementation */
+
+#include "allobjects.h"
+
+#include "token.h"
+
+typedef struct {
+ OB_HEAD
+ char *m_name;
+ method m_meth;
+ object *m_self;
+} methodobject;
+
+object *
+newmethodobject(name, meth, self)
+ char *name; /* static string */
+ method meth;
+ object *self;
+{
+ methodobject *op = NEWOBJ(methodobject, &Methodtype);
+ if (op != NULL) {
+ op->m_name = name;
+ op->m_meth = meth;
+ if (self != NULL)
+ INCREF(self);
+ op->m_self = self;
+ }
+ return (object *)op;
+}
+
+method
+getmethod(op)
+ object *op;
+{
+ if (!is_methodobject(op)) {
+ err_badcall();
+ return NULL;
+ }
+ return ((methodobject *)op) -> m_meth;
+}
+
+object *
+getself(op)
+ object *op;
+{
+ if (!is_methodobject(op)) {
+ err_badcall();
+ return NULL;
+ }
+ return ((methodobject *)op) -> m_self;
+}
+
+/* Methods (the standard built-in methods, that is) */
+
+static void
+meth_dealloc(m)
+ methodobject *m;
+{
+ if (m->m_self != NULL)
+ DECREF(m->m_self);
+ free((char *)m);
+}
+
+static void
+meth_print(m, fp, flags)
+ methodobject *m;
+ FILE *fp;
+ int flags;
+{
+ if (m->m_self == NULL)
+ fprintf(fp, "<built-in function '%s'>", m->m_name);
+ else
+ fprintf(fp, "<built-in method '%s' of some %s object>",
+ m->m_name, m->m_self->ob_type->tp_name);
+}
+
+static object *
+meth_repr(m)
+ methodobject *m;
+{
+ char buf[200];
+ if (m->m_self == NULL)
+ sprintf(buf, "<built-in function '%.80s'>", m->m_name);
+ else
+ sprintf(buf,
+ "<built-in method '%.80s' of some %.80s object>",
+ m->m_name, m->m_self->ob_type->tp_name);
+ return newstringobject(buf);
+}
+
+typeobject Methodtype = {
+ OB_HEAD_INIT(&Typetype)
+ 0,
+ "method",
+ sizeof(methodobject),
+ 0,
+ meth_dealloc, /*tp_dealloc*/
+ meth_print, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ meth_repr, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+};
+
+/* Find a method in a module's method table.
+ Usually called from an object's getattr method. */
+
+object *
+findmethod(ml, op, name)
+ struct methodlist *ml;
+ object *op;
+ char *name;
+{
+ for (; ml->ml_name != NULL; ml++) {
+ if (strcmp(name, ml->ml_name) == 0)
+ return newmethodobject(ml->ml_name, ml->ml_meth, op);
+ }
+ err_setstr(NameError, name);
+ return NULL;
+}
diff --git a/src/methodobject.h b/src/methodobject.h
new file mode 100644
index 0000000..674ed7d
--- /dev/null
+++ b/src/methodobject.h
@@ -0,0 +1,42 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* Method object interface */
+
+extern typeobject Methodtype;
+
+#define is_methodobject(op) ((op)->ob_type == &Methodtype)
+
+typedef object *(*method) FPROTO((object *, object *));
+
+extern object *newmethodobject PROTO((char *, method, object *));
+extern method getmethod PROTO((object *));
+extern object *getself PROTO((object *));
+
+struct methodlist {
+ char *ml_name;
+ method ml_meth;
+};
+
+extern object *findmethod PROTO((struct methodlist *, object *, char *));
diff --git a/src/modsupport.c b/src/modsupport.c
new file mode 100644
index 0000000..1044268
--- /dev/null
+++ b/src/modsupport.c
@@ -0,0 +1,381 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* Module support implementation */
+
+#include "allobjects.h"
+#include "modsupport.h"
+#include "import.h"
+
+
+object *
+initmodule(name, methods)
+ char *name;
+ struct methodlist *methods;
+{
+ object *m, *d, *v;
+ struct methodlist *ml;
+ char namebuf[256];
+ if ((m = add_module(name)) == NULL) {
+ fprintf(stderr, "initializing module: %s\n", name);
+ fatal("can't create a module");
+ }
+ d = getmoduledict(m);
+ for (ml = methods; ml->ml_name != NULL; ml++) {
+ sprintf(namebuf, "%s.%s", name, ml->ml_name);
+ v = newmethodobject(strdup(namebuf), ml->ml_meth,
+ (object *)NULL);
+ /* XXX The strdup'ed memory is never freed */
+ if (v == NULL || dictinsert(d, ml->ml_name, v) != 0) {
+ fprintf(stderr, "initializing module: %s\n", name);
+ fatal("can't initialize module");
+ }
+ DECREF(v);
+ }
+ return m;
+}
+
+
+/* Argument list handling tools.
+ All return 1 for success, or call err_set*() and return 0 for failure */
+
+int
+getnoarg(v)
+ object *v;
+{
+ if (v != NULL) {
+ return err_badarg();
+ }
+ return 1;
+}
+
+int
+getintarg(v, a)
+ object *v;
+ int *a;
+{
+ if (v == NULL || !is_intobject(v)) {
+ return err_badarg();
+ }
+ *a = getintvalue(v);
+ return 1;
+}
+
+int
+getintintarg(v, a, b)
+ object *v;
+ int *a;
+ int *b;
+{
+ if (v == NULL || !is_tupleobject(v) || gettuplesize(v) != 2) {
+ return err_badarg();
+ }
+ return getintarg(gettupleitem(v, 0), a) &&
+ getintarg(gettupleitem(v, 1), b);
+}
+
+int
+getlongarg(v, a)
+ object *v;
+ long *a;
+{
+ if (v == NULL || !is_intobject(v)) {
+ return err_badarg();
+ }
+ *a = getintvalue(v);
+ return 1;
+}
+
+int
+getlonglongargs(v, a, b)
+ object *v;
+ long *a, *b;
+{
+ if (v == NULL || !is_tupleobject(v) || gettuplesize(v) != 2) {
+ return err_badarg();
+ }
+ return getlongarg(gettupleitem(v, 0), a) &&
+ getlongarg(gettupleitem(v, 1), b);
+}
+
+int
+getlonglongobjectargs(v, a, b, c)
+ object *v;
+ long *a, *b;
+ object **c;
+{
+ if (v == NULL || !is_tupleobject(v) || gettuplesize(v) != 3) {
+ return err_badarg();
+ }
+ if (getlongarg(gettupleitem(v, 0), a) &&
+ getlongarg(gettupleitem(v, 1), b)) {
+ *c = gettupleitem(v, 2);
+ return 1;
+ }
+ else {
+ return err_badarg();
+ }
+}
+
+int
+getstrarg(v, a)
+ object *v;
+ object **a;
+{
+ if (v == NULL || !is_stringobject(v)) {
+ return err_badarg();
+ }
+ *a = v;
+ return 1;
+}
+
+int
+getstrstrarg(v, a, b)
+ object *v;
+ object **a;
+ object **b;
+{
+ if (v == NULL || !is_tupleobject(v) || gettuplesize(v) != 2) {
+ return err_badarg();
+ }
+ return getstrarg(gettupleitem(v, 0), a) &&
+ getstrarg(gettupleitem(v, 1), b);
+}
+
+int
+getstrstrintarg(v, a, b, c)
+ object *v;
+ object **a;
+ object **b;
+ int *c;
+{
+ if (v == NULL || !is_tupleobject(v) || gettuplesize(v) != 3) {
+ return err_badarg();
+ }
+ return getstrarg(gettupleitem(v, 0), a) &&
+ getstrarg(gettupleitem(v, 1), b) &&
+ getintarg(gettupleitem(v, 2), c);
+}
+
+int
+getstrintarg(v, a, b)
+ object *v;
+ object **a;
+ int *b;
+{
+ if (v == NULL || !is_tupleobject(v) || gettuplesize(v) != 2) {
+ return err_badarg();
+ }
+ return getstrarg(gettupleitem(v, 0), a) &&
+ getintarg(gettupleitem(v, 1), b);
+}
+
+int
+getintstrarg(v, a, b)
+ object *v;
+ int *a;
+ object **b;
+{
+ if (v == NULL || !is_tupleobject(v) || gettuplesize(v) != 2) {
+ return err_badarg();
+ }
+ return getintarg(gettupleitem(v, 0), a) &&
+ getstrarg(gettupleitem(v, 1), b);
+}
+
+int
+getpointarg(v, a)
+ object *v;
+ int *a; /* [2] */
+{
+ return getintintarg(v, a, a+1);
+}
+
+int
+get3pointarg(v, a)
+ object *v;
+ int *a; /* [6] */
+{
+ if (v == NULL || !is_tupleobject(v) || gettuplesize(v) != 3) {
+ return err_badarg();
+ }
+ return getpointarg(gettupleitem(v, 0), a) &&
+ getpointarg(gettupleitem(v, 1), a+2) &&
+ getpointarg(gettupleitem(v, 2), a+4);
+}
+
+int
+getrectarg(v, a)
+ object *v;
+ int *a; /* [2+2] */
+{
+ if (v == NULL || !is_tupleobject(v) || gettuplesize(v) != 2) {
+ return err_badarg();
+ }
+ return getpointarg(gettupleitem(v, 0), a) &&
+ getpointarg(gettupleitem(v, 1), a+2);
+}
+
+int
+getrectintarg(v, a)
+ object *v;
+ int *a; /* [4+1] */
+{
+ if (v == NULL || !is_tupleobject(v) || gettuplesize(v) != 2) {
+ return err_badarg();
+ }
+ return getrectarg(gettupleitem(v, 0), a) &&
+ getintarg(gettupleitem(v, 1), a+4);
+}
+
+int
+getpointintarg(v, a)
+ object *v;
+ int *a; /* [2+1] */
+{
+ if (v == NULL || !is_tupleobject(v) || gettuplesize(v) != 2) {
+ return err_badarg();
+ }
+ return getpointarg(gettupleitem(v, 0), a) &&
+ getintarg(gettupleitem(v, 1), a+2);
+}
+
+int
+getpointstrarg(v, a, b)
+ object *v;
+ int *a; /* [2] */
+ object **b;
+{
+ if (v == NULL || !is_tupleobject(v) || gettuplesize(v) != 2) {
+ return err_badarg();
+ }
+ return getpointarg(gettupleitem(v, 0), a) &&
+ getstrarg(gettupleitem(v, 1), b);
+}
+
+int
+getstrintintarg(v, a, b, c)
+ object *v;
+ object *a;
+ int *b, *c;
+{
+ if (v == NULL || !is_tupleobject(v) || gettuplesize(v) != 3) {
+ return err_badarg();
+ }
+ return getstrarg(gettupleitem(v, 0), a) &&
+ getintarg(gettupleitem(v, 1), b) &&
+ getintarg(gettupleitem(v, 2), c);
+}
+
+int
+getrectpointarg(v, a)
+ object *v;
+ int *a; /* [4+2] */
+{
+ if (v == NULL || !is_tupleobject(v) || gettuplesize(v) != 2) {
+ return err_badarg();
+ }
+ return getrectarg(gettupleitem(v, 0), a) &&
+ getpointarg(gettupleitem(v, 1), a+4);
+}
+
+int
+getlongtuplearg(args, a, n)
+ object *args;
+ long *a; /* [n] */
+ int n;
+{
+ int i;
+ if (!is_tupleobject(args) || gettuplesize(args) != n) {
+ return err_badarg();
+ }
+ for (i = 0; i < n; i++) {
+ object *v = gettupleitem(args, i);
+ if (!is_intobject(v)) {
+ return err_badarg();
+ }
+ a[i] = getintvalue(v);
+ }
+ return 1;
+}
+
+int
+getshorttuplearg(args, a, n)
+ object *args;
+ short *a; /* [n] */
+ int n;
+{
+ int i;
+ if (!is_tupleobject(args) || gettuplesize(args) != n) {
+ return err_badarg();
+ }
+ for (i = 0; i < n; i++) {
+ object *v = gettupleitem(args, i);
+ if (!is_intobject(v)) {
+ return err_badarg();
+ }
+ a[i] = getintvalue(v);
+ }
+ return 1;
+}
+
+int
+getlonglistarg(args, a, n)
+ object *args;
+ long *a; /* [n] */
+ int n;
+{
+ int i;
+ if (!is_listobject(args) || getlistsize(args) != n) {
+ return err_badarg();
+ }
+ for (i = 0; i < n; i++) {
+ object *v = getlistitem(args, i);
+ if (!is_intobject(v)) {
+ return err_badarg();
+ }
+ a[i] = getintvalue(v);
+ }
+ return 1;
+}
+
+int
+getshortlistarg(args, a, n)
+ object *args;
+ short *a; /* [n] */
+ int n;
+{
+ int i;
+ if (!is_listobject(args) || getlistsize(args) != n) {
+ return err_badarg();
+ }
+ for (i = 0; i < n; i++) {
+ object *v = getlistitem(args, i);
+ if (!is_intobject(v)) {
+ return err_badarg();
+ }
+ a[i] = getintvalue(v);
+ }
+ return 1;
+}
diff --git a/src/modsupport.h b/src/modsupport.h
new file mode 100644
index 0000000..843b209
--- /dev/null
+++ b/src/modsupport.h
@@ -0,0 +1,27 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* Module support interface */
+
+extern object *initmodule PROTO((char *, struct methodlist *));
diff --git a/src/moduleobject.c b/src/moduleobject.c
new file mode 100644
index 0000000..82599f9
--- /dev/null
+++ b/src/moduleobject.c
@@ -0,0 +1,154 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* Module object implementation */
+
+#include "allobjects.h"
+
+typedef struct {
+ OB_HEAD
+ object *md_name;
+ object *md_dict;
+} moduleobject;
+
+object *
+newmoduleobject(name)
+ char *name;
+{
+ moduleobject *m = NEWOBJ(moduleobject, &Moduletype);
+ if (m == NULL)
+ return NULL;
+ m->md_name = newstringobject(name);
+ m->md_dict = newdictobject();
+ if (m->md_name == NULL || m->md_dict == NULL) {
+ DECREF(m);
+ return NULL;
+ }
+ return (object *)m;
+}
+
+object *
+getmoduledict(m)
+ object *m;
+{
+ if (!is_moduleobject(m)) {
+ err_badcall();
+ return NULL;
+ }
+ return ((moduleobject *)m) -> md_dict;
+}
+
+char *
+getmodulename(m)
+ object *m;
+{
+ if (!is_moduleobject(m)) {
+ err_badarg();
+ return NULL;
+ }
+ return getstringvalue(((moduleobject *)m) -> md_name);
+}
+
+/* Methods */
+
+static void
+module_dealloc(m)
+ moduleobject *m;
+{
+ if (m->md_name != NULL)
+ DECREF(m->md_name);
+ if (m->md_dict != NULL)
+ DECREF(m->md_dict);
+ free((char *)m);
+}
+
+static void
+module_print(m, fp, flags)
+ moduleobject *m;
+ FILE *fp;
+ int flags;
+{
+ fprintf(fp, "<module '%s'>", getstringvalue(m->md_name));
+}
+
+static object *
+module_repr(m)
+ moduleobject *m;
+{
+ char buf[100];
+ sprintf(buf, "<module '%.80s'>", getstringvalue(m->md_name));
+ return newstringobject(buf);
+}
+
+static object *
+module_getattr(m, name)
+ moduleobject *m;
+ char *name;
+{
+ object *res;
+ if (strcmp(name, "__dict__") == 0) {
+ INCREF(m->md_dict);
+ return m->md_dict;
+ }
+ if (strcmp(name, "__name__") == 0) {
+ INCREF(m->md_name);
+ return m->md_name;
+ }
+ res = dictlookup(m->md_dict, name);
+ if (res == NULL)
+ err_setstr(NameError, name);
+ else
+ INCREF(res);
+ return res;
+}
+
+static int
+module_setattr(m, name, v)
+ moduleobject *m;
+ char *name;
+ object *v;
+{
+ if (strcmp(name, "__dict__") == 0 || strcmp(name, "__name__") == 0) {
+ err_setstr(NameError, "can't assign to reserved member name");
+ return -1;
+ }
+ if (v == NULL)
+ return dictremove(m->md_dict, name);
+ else
+ return dictinsert(m->md_dict, name, v);
+}
+
+typeobject Moduletype = {
+ OB_HEAD_INIT(&Typetype)
+ 0, /*ob_size*/
+ "module", /*tp_name*/
+ sizeof(moduleobject), /*tp_size*/
+ 0, /*tp_itemsize*/
+ module_dealloc, /*tp_dealloc*/
+ module_print, /*tp_print*/
+ module_getattr, /*tp_getattr*/
+ module_setattr, /*tp_setattr*/
+ 0, /*tp_compare*/
+ module_repr, /*tp_repr*/
+};
diff --git a/src/moduleobject.h b/src/moduleobject.h
new file mode 100644
index 0000000..4657c22
--- /dev/null
+++ b/src/moduleobject.h
@@ -0,0 +1,33 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* Module object interface */
+
+extern typeobject Moduletype;
+
+#define is_moduleobject(op) ((op)->ob_type == &Moduletype)
+
+extern object *newmoduleobject PROTO((char *));
+extern object *getmoduledict PROTO((object *));
+extern char *getmodulename PROTO((object *));
diff --git a/src/node.c b/src/node.c
new file mode 100644
index 0000000..2b76ae8
--- /dev/null
+++ b/src/node.c
@@ -0,0 +1,100 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* Parse tree node implementation */
+
+#include "pgenheaders.h"
+#include "node.h"
+
+node *
+newtree(type)
+ int type;
+{
+ node *n = NEW(node, 1);
+ if (n == NULL)
+ return NULL;
+ n->n_type = type;
+ n->n_str = NULL;
+ n->n_lineno = 0;
+ n->n_nchildren = 0;
+ n->n_child = NULL;
+ return n;
+}
+
+#define XXX 3 /* Node alignment factor to speed up realloc */
+#define XXXROUNDUP(n) ((n) == 1 ? 1 : ((n) + XXX - 1) / XXX * XXX)
+
+node *
+addchild(n1, type, str, lineno)
+ register node *n1;
+ int type;
+ char *str;
+ int lineno;
+{
+ register int nch = n1->n_nchildren;
+ register int nch1 = nch+1;
+ register node *n;
+ if (XXXROUNDUP(nch) < nch1) {
+ n = n1->n_child;
+ nch1 = XXXROUNDUP(nch1);
+ RESIZE(n, node, nch1);
+ if (n == NULL)
+ return NULL;
+ n1->n_child = n;
+ }
+ n = &n1->n_child[n1->n_nchildren++];
+ n->n_type = type;
+ n->n_str = str;
+ n->n_lineno = lineno;
+ n->n_nchildren = 0;
+ n->n_child = NULL;
+ return n;
+}
+
+/* Forward */
+static void freechildren PROTO((node *));
+
+
+void
+freetree(n)
+ node *n;
+{
+ if (n != NULL) {
+ freechildren(n);
+ DEL(n);
+ }
+}
+
+static void
+freechildren(n)
+ node *n;
+{
+ int i;
+ for (i = NCH(n); --i >= 0; )
+ freechildren(CHILD(n, i));
+ if (n->n_child != NULL)
+ DEL(n->n_child);
+ if (STR(n) != NULL)
+ DEL(STR(n));
+}
diff --git a/src/node.h b/src/node.h
new file mode 100644
index 0000000..5b43f8f
--- /dev/null
+++ b/src/node.h
@@ -0,0 +1,58 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* Parse tree node interface */
+
+typedef struct _node {
+ int n_type;
+ char *n_str;
+ int n_lineno;
+ int n_nchildren;
+ struct _node *n_child;
+} node;
+
+extern node *newtree PROTO((int type));
+extern node *addchild PROTO((node *n, int type, char *str, int lineno));
+extern void freetree PROTO((node *n));
+
+/* Node access functions */
+#define NCH(n) ((n)->n_nchildren)
+#define CHILD(n, i) (&(n)->n_child[i])
+#define TYPE(n) ((n)->n_type)
+#define STR(n) ((n)->n_str)
+
+/* Assert that the type of a node is what we expect */
+#ifndef DEBUG
+#define REQ(n, type) { /*pass*/ ; }
+#else
+#define REQ(n, type) \
+ { if (TYPE(n) != (type)) { \
+ fprintf(stderr, "FATAL: node type %d, required %d\n", \
+ TYPE(n), type); \
+ abort(); \
+ } }
+#endif
+
+extern void listtree PROTO((node *));
+extern void listnode PROTO((FILE *, node *));
diff --git a/src/object.c b/src/object.c
new file mode 100644
index 0000000..37e2b26
--- /dev/null
+++ b/src/object.c
@@ -0,0 +1,290 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* Generic object operations; and implementation of None (NoObject) */
+
+#include "allobjects.h"
+
+#ifdef REF_DEBUG
+long ref_total;
+#endif
+
+/* Object allocation routines used by NEWOBJ and NEWVAROBJ macros.
+ These are used by the individual routines for object creation.
+ Do not call them otherwise, they do not initialize the object! */
+
+object *
+newobject(tp)
+ typeobject *tp;
+{
+ object *op = (object *) malloc(tp->tp_basicsize);
+ if (op == NULL)
+ return err_nomem();
+ NEWREF(op);
+ op->ob_type = tp;
+ return op;
+}
+
+#if 0 /* unused */
+
+varobject *
+newvarobject(tp, size)
+ typeobject *tp;
+ unsigned int size;
+{
+ varobject *op = (varobject *)
+ malloc(tp->tp_basicsize + size * tp->tp_itemsize);
+ if (op == NULL)
+ return err_nomem();
+ NEWREF(op);
+ op->ob_type = tp;
+ op->ob_size = size;
+ return op;
+}
+
+#endif
+
+int StopPrint; /* Flag to indicate printing must be stopped */
+
+static int prlevel;
+
+void
+printobject(op, fp, flags)
+ object *op;
+ FILE *fp;
+ int flags;
+{
+ /* Hacks to make printing a long or recursive object interruptible */
+ /* XXX Interrupts should leave a more permanent error */
+ prlevel++;
+ if (!StopPrint && intrcheck()) {
+ fprintf(fp, "\n[print interrupted]\n");
+ StopPrint = 1;
+ }
+ if (!StopPrint) {
+ if (op == NULL) {
+ fprintf(fp, "<nil>");
+ }
+ else {
+ if (op->ob_refcnt <= 0)
+ fprintf(fp, "(refcnt %d):", op->ob_refcnt);
+ if (op->ob_type->tp_print == NULL) {
+ fprintf(fp, "<%s object at %lx>",
+ op->ob_type->tp_name, (long)op);
+ }
+ else {
+ (*op->ob_type->tp_print)(op, fp, flags);
+ }
+ }
+ }
+ prlevel--;
+ if (prlevel == 0)
+ StopPrint = 0;
+}
+
+object *
+reprobject(v)
+ object *v;
+{
+ object *w = NULL;
+ /* Hacks to make converting a long or recursive object interruptible */
+ prlevel++;
+ if (!StopPrint && intrcheck()) {
+ StopPrint = 1;
+ err_set(KeyboardInterrupt);
+ }
+ if (!StopPrint) {
+ if (v == NULL) {
+ w = newstringobject("<NULL>");
+ }
+ else if (v->ob_type->tp_repr == NULL) {
+ char buf[100];
+ sprintf(buf, "<%.80s object at %lx>",
+ v->ob_type->tp_name, (long)v);
+ w = newstringobject(buf);
+ }
+ else {
+ w = (*v->ob_type->tp_repr)(v);
+ }
+ if (StopPrint) {
+ XDECREF(w);
+ w = NULL;
+ }
+ }
+ prlevel--;
+ if (prlevel == 0)
+ StopPrint = 0;
+ return w;
+}
+
+int
+cmpobject(v, w)
+ object *v, *w;
+{
+ typeobject *tp;
+ if (v == w)
+ return 0;
+ if (v == NULL)
+ return -1;
+ if (w == NULL)
+ return 1;
+ if ((tp = v->ob_type) != w->ob_type)
+ return strcmp(tp->tp_name, w->ob_type->tp_name);
+ if (tp->tp_compare == NULL)
+ return (v < w) ? -1 : 1;
+ return ((*tp->tp_compare)(v, w));
+}
+
+object *
+getattr(v, name)
+ object *v;
+ char *name;
+{
+ if (v->ob_type->tp_getattr == NULL) {
+ err_setstr(TypeError, "attribute-less object");
+ return NULL;
+ }
+ else {
+ return (*v->ob_type->tp_getattr)(v, name);
+ }
+}
+
+int
+setattr(v, name, w)
+ object *v;
+ char *name;
+ object *w;
+{
+ if (v->ob_type->tp_setattr == NULL) {
+ if (v->ob_type->tp_getattr == NULL)
+ err_setstr(TypeError, "attribute-less object");
+ else
+ err_setstr(TypeError, "object has read-only attributes");
+ return -1;
+ }
+ else {
+ return (*v->ob_type->tp_setattr)(v, name, w);
+ }
+}
+
+
+/*
+NoObject is usable as a non-NULL undefined value, used by the macro None.
+There is (and should be!) no way to create other objects of this type,
+so there is exactly one (which is indestructible, by the way).
+*/
+
+static void
+none_print(op, fp, flags)
+ object *op;
+ FILE *fp;
+ int flags;
+{
+ fprintf(fp, "None");
+}
+
+static object *
+none_repr(op)
+ object *op;
+{
+ return newstringobject("None");
+}
+
+static typeobject Notype = {
+ OB_HEAD_INIT(&Typetype)
+ 0,
+ "None",
+ 0,
+ 0,
+ 0, /*tp_dealloc*/ /*never called*/
+ none_print, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ none_repr, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+};
+
+object NoObject = {
+ OB_HEAD_INIT(&Notype)
+};
+
+
+#ifdef TRACE_REFS
+
+static object refchain = {&refchain, &refchain};
+
+NEWREF(op)
+ object *op;
+{
+ ref_total++;
+ op->ob_refcnt = 1;
+ op->_ob_next = refchain._ob_next;
+ op->_ob_prev = &refchain;
+ refchain._ob_next->_ob_prev = op;
+ refchain._ob_next = op;
+}
+
+UNREF(op)
+ register object *op;
+{
+ register object *p;
+ if (op->ob_refcnt < 0) {
+ fprintf(stderr, "UNREF negative refcnt\n");
+ abort();
+ }
+ for (p = refchain._ob_next; p != &refchain; p = p->_ob_next) {
+ if (p == op)
+ break;
+ }
+ if (p == &refchain) { /* Not found */
+ fprintf(stderr, "UNREF unknown object\n");
+ abort();
+ }
+ op->_ob_next->_ob_prev = op->_ob_prev;
+ op->_ob_prev->_ob_next = op->_ob_next;
+}
+
+DELREF(op)
+ object *op;
+{
+ UNREF(op);
+ (*(op)->ob_type->tp_dealloc)(op);
+}
+
+printrefs(fp)
+ FILE *fp;
+{
+ object *op;
+ fprintf(fp, "Remaining objects:\n");
+ for (op = refchain._ob_next; op != &refchain; op = op->_ob_next) {
+ fprintf(fp, "[%d] ", op->ob_refcnt);
+ printobject(op, fp, 0);
+ putc('\n', fp);
+ }
+}
+
+#endif
diff --git a/src/object.h b/src/object.h
new file mode 100644
index 0000000..f0266c4
--- /dev/null
+++ b/src/object.h
@@ -0,0 +1,324 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+#define NDEBUG
+/* Object and type object interface */
+
+/*
+123456789-123456789-123456789-123456789-123456789-123456789-123456789-12
+
+Objects are structures allocated on the heap. Special rules apply to
+the use of objects to ensure they are properly garbage-collected.
+Objects are never allocated statically or on the stack; they must be
+accessed through special macros and functions only. (Type objects are
+exceptions to the first rule; the standard types are represented by
+statically initialized type objects.)
+
+An object has a 'reference count' that is increased or decreased when a
+pointer to the object is copied or deleted; when the reference count
+reaches zero there are no references to the object left and it can be
+removed from the heap.
+
+An object has a 'type' that determines what it represents and what kind
+of data it contains. An object's type is fixed when it is created.
+Types themselves are represented as objects; an object contains a
+pointer to the corresponding type object. The type itself has a type
+pointer pointing to the object representing the type 'type', which
+contains a pointer to itself!).
+
+Objects do not float around in memory; once allocated an object keeps
+the same size and address. Objects that must hold variable-size data
+can contain pointers to variable-size parts of the object. Not all
+objects of the same type have the same size; but the size cannot change
+after allocation. (These restrictions are made so a reference to an
+object can be simply a pointer -- moving an object would require
+updating all the pointers, and changing an object's size would require
+moving it if there was another object right next to it.)
+
+Objects are always accessed through pointers of the type 'object *'.
+The type 'object' is a structure that only contains the reference count
+and the type pointer. The actual memory allocated for an object
+contains other data that can only be accessed after casting the pointer
+to a pointer to a longer structure type. This longer type must start
+with the reference count and type fields; the macro OB_HEAD should be
+used for this (to accomodate for future changes). The implementation
+of a particular object type can cast the object pointer to the proper
+type and back.
+
+A standard interface exists for objects that contain an array of items
+whose size is determined when the object is allocated.
+
+123456789-123456789-123456789-123456789-123456789-123456789-123456789-12
+*/
+
+#ifndef NDEBUG
+
+/* Turn on heavy reference debugging */
+#define TRACE_REFS
+
+/* Turn on reference counting */
+#define REF_DEBUG
+
+#endif /* NDEBUG */
+
+#ifdef TRACE_REFS
+#define OB_HEAD \
+ struct _object *_ob_next, *_ob_prev; \
+ int ob_refcnt; \
+ struct _typeobject *ob_type;
+#define OB_HEAD_INIT(type) 0, 0, 1, type,
+#else
+#define OB_HEAD \
+ unsigned int ob_refcnt; \
+ struct _typeobject *ob_type;
+#define OB_HEAD_INIT(type) 1, type,
+#endif
+
+#define OB_VARHEAD \
+ OB_HEAD \
+ unsigned int ob_size; /* Number of items in variable part */
+
+typedef struct _object {
+ OB_HEAD
+} object;
+
+typedef struct {
+ OB_VARHEAD
+} varobject;
+
+
+/*
+123456789-123456789-123456789-123456789-123456789-123456789-123456789-12
+
+Type objects contain a string containing the type name (to help somewhat
+in debugging), the allocation parameters (see newobj() and newvarobj()),
+and methods for accessing objects of the type. Methods are optional,a
+nil pointer meaning that particular kind of access is not available for
+this type. The DECREF() macro uses the tp_dealloc method without
+checking for a nil pointer; it should always be implemented except if
+the implementation can guarantee that the reference count will never
+reach zero (e.g., for type objects).
+
+NB: the methods for certain type groups are now contained in separate
+method blocks.
+*/
+
+typedef struct {
+ object *(*nb_add) FPROTO((object *, object *));
+ object *(*nb_subtract) FPROTO((object *, object *));
+ object *(*nb_multiply) FPROTO((object *, object *));
+ object *(*nb_divide) FPROTO((object *, object *));
+ object *(*nb_remainder) FPROTO((object *, object *));
+ object *(*nb_power) FPROTO((object *, object *));
+ object *(*nb_negative) FPROTO((object *));
+ object *(*nb_positive) FPROTO((object *));
+} number_methods;
+
+typedef struct {
+ int (*sq_length) FPROTO((object *));
+ object *(*sq_concat) FPROTO((object *, object *));
+ object *(*sq_repeat) FPROTO((object *, int));
+ object *(*sq_item) FPROTO((object *, int));
+ object *(*sq_slice) FPROTO((object *, int, int));
+ int (*sq_ass_item) FPROTO((object *, int, object *));
+ int (*sq_ass_slice) FPROTO((object *, int, int, object *));
+} sequence_methods;
+
+typedef struct {
+ int (*mp_length) FPROTO((object *));
+ object *(*mp_subscript) FPROTO((object *, object *));
+ int (*mp_ass_subscript) FPROTO((object *, object *, object *));
+} mapping_methods;
+
+typedef struct _typeobject {
+ OB_VARHEAD
+ char *tp_name; /* For printing */
+ unsigned int tp_basicsize, tp_itemsize; /* For allocation */
+
+ /* Methods to implement standard operations */
+
+ void (*tp_dealloc) FPROTO((object *));
+ void (*tp_print) FPROTO((object *, FILE *, int));
+ object *(*tp_getattr) FPROTO((object *, char *));
+ int (*tp_setattr) FPROTO((object *, char *, object *));
+ int (*tp_compare) FPROTO((object *, object *));
+ object *(*tp_repr) FPROTO((object *));
+
+ /* Method suites for standard classes */
+
+ number_methods *tp_as_number;
+ sequence_methods *tp_as_sequence;
+ mapping_methods *tp_as_mapping;
+} typeobject;
+
+extern typeobject Typetype; /* The type of type objects */
+
+#define is_typeobject(op) ((op)->ob_type == &Typetype)
+
+/* Generic operations on objects */
+extern void printobject PROTO((object *, FILE *, int));
+extern object * reprobject PROTO((object *));
+extern int cmpobject PROTO((object *, object *));
+extern object *getattr PROTO((object *, char *));
+extern int setattr PROTO((object *, char *, object *));
+
+/* Flag bits for printing: */
+#define PRINT_RAW 1 /* No string quotes etc. */
+
+/*
+123456789-123456789-123456789-123456789-123456789-123456789-123456789-12
+
+The macros INCREF(op) and DECREF(op) are used to increment or decrement
+reference counts. DECREF calls the object's deallocator function; for
+objects that don't contain references to other objects or heap memory
+this can be the standard function free(). Both macros can be used
+whereever a void expression is allowed. The argument shouldn't be a
+NIL pointer. The macro NEWREF(op) is used only to initialize reference
+counts to 1; it is defined here for convenience.
+
+We assume that the reference count field can never overflow; this can
+be proven when the size of the field is the same as the pointer size
+but even with a 16-bit reference count field it is pretty unlikely so
+we ignore the possibility. (If you are paranoid, make it a long.)
+
+Type objects should never be deallocated; the type pointer in an object
+is not considered to be a reference to the type object, to save
+complications in the deallocation function. (This is actually a
+decision that's up to the implementer of each new type so if you want,
+you can count such references to the type object.)
+
+*** WARNING*** The DECREF macro must have a side-effect-free argument
+since it may evaluate its argument multiple times. (The alternative
+would be to mace it a proper function or assign it to a global temporary
+variable first, both of which are slower; and in a multi-threaded
+environment the global variable trick is not safe.)
+*/
+
+#ifdef TRACE_REFS
+#ifndef REF_DEBUG
+#define REF_DEBUG
+#endif
+#endif
+
+#ifndef TRACE_REFS
+#define DELREF(op) (*(op)->ob_type->tp_dealloc)((object *)(op))
+#define UNREF(op) /*empty*/
+#endif
+
+#ifdef REF_DEBUG
+extern long ref_total;
+#ifndef TRACE_REFS
+#define NEWREF(op) (ref_total++, (op)->ob_refcnt = 1)
+#endif
+#define INCREF(op) (ref_total++, (op)->ob_refcnt++)
+#define DECREF(op) \
+ if (--ref_total, --(op)->ob_refcnt > 0) \
+ ; \
+ else \
+ DELREF(op)
+#else
+#define NEWREF(op) ((op)->ob_refcnt = 1)
+#define INCREF(op) ((op)->ob_refcnt++)
+#define DECREF(op) \
+ if (--(op)->ob_refcnt > 0) \
+ ; \
+ else \
+ DELREF(op)
+#endif
+
+/* Macros to use in case the object pointer may be NULL: */
+
+#define XINCREF(op) if ((op) == NULL) ; else INCREF(op)
+#define XDECREF(op) if ((op) == NULL) ; else DECREF(op)
+
+/* Definition of NULL, so you don't have to include <stdio.h> */
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+
+/*
+NoObject is an object of undefined type which can be used in contexts
+where NULL (nil) is not suitable (since NULL often means 'error').
+
+Don't forget to apply INCREF() when returning this value!!!
+*/
+
+extern object NoObject; /* Don't use this directly */
+
+#define None (&NoObject)
+
+
+/*
+123456789-123456789-123456789-123456789-123456789-123456789-123456789-12
+
+More conventions
+================
+
+Argument Checking
+-----------------
+
+Functions that take objects as arguments normally don't check for nil
+arguments, but they do check the type of the argument, and return an
+error if the function doesn't apply to the type.
+
+Failure Modes
+-------------
+
+Functions may fail for a variety of reasons, including running out of
+memory. This is communicated to the caller in two ways: an error string
+is set (see errors.h), and the function result differs: functions that
+normally return a pointer return NULL for failure, functions returning
+an integer return -1 (which could be a legal return value too!), and
+other functions return 0 for success and -1 for failure.
+Callers should always check for errors before using the result.
+
+Reference Counts
+----------------
+
+It takes a while to get used to the proper usage of reference counts.
+
+Functions that create an object set the reference count to 1; such new
+objects must be stored somewhere or destroyed again with DECREF().
+Functions that 'store' objects such as settupleitem() and dictinsert()
+don't increment the reference count of the object, since the most
+frequent use is to store a fresh object. Functions that 'retrieve'
+objects such as gettupleitem() and dictlookup() also don't increment
+the reference count, since most frequently the object is only looked at
+quickly. Thus, to retrieve an object and store it again, the caller
+must call INCREF() explicitly.
+
+NOTE: functions that 'consume' a reference count like dictinsert() even
+consume the reference if the object wasn't stored, to simplify error
+handling.
+
+It seems attractive to make other functions that take an object as
+argument consume a reference count; however this may quickly get
+confusing (even the current practice is already confusing). Consider
+it carefully, it may safe lots of calls to INCREF() and DECREF() at
+times.
+
+123456789-123456789-123456789-123456789-123456789-123456789-123456789-12
+*/
diff --git a/src/objimpl.h b/src/objimpl.h
new file mode 100644
index 0000000..7d40718
--- /dev/null
+++ b/src/objimpl.h
@@ -0,0 +1,50 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/*
+123456789-123456789-123456789-123456789-123456789-123456789-123456789-12
+
+Additional macros for modules that implement new object types.
+You must first include "object.h".
+
+NEWOBJ(type, typeobj) allocates memory for a new object of the given
+type; here 'type' must be the C structure type used to represent the
+object and 'typeobj' the address of the corresponding type object.
+Reference count and type pointer are filled in; the rest of the bytes of
+the object are *undefined*! The resulting expression type is 'type *'.
+The size of the object is actually determined by the tp_basicsize field
+of the type object.
+
+NEWVAROBJ(type, typeobj, n) is similar but allocates a variable-size
+object with n extra items. The size is computer as tp_basicsize plus
+n * tp_itemsize. This fills in the ob_size field as well.
+*/
+
+extern object *newobject PROTO((typeobject *));
+extern varobject *newvarobject PROTO((typeobject *, unsigned int));
+
+#define NEWOBJ(type, typeobj) ((type *) newobject(typeobj))
+#define NEWVAROBJ(type, typeobj, n) ((type *) newvarobject(typeobj, n))
+
+extern int StopPrint; /* Set when printing is interrupted */
diff --git a/src/opcode.h b/src/opcode.h
new file mode 100644
index 0000000..ad6d712
--- /dev/null
+++ b/src/opcode.h
@@ -0,0 +1,109 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* Instruction opcodes for compiled code */
+
+#define STOP_CODE 0
+#define POP_TOP 1
+#define ROT_TWO 2
+#define ROT_THREE 3
+#define DUP_TOP 4
+
+#define UNARY_POSITIVE 10
+#define UNARY_NEGATIVE 11
+#define UNARY_NOT 12
+#define UNARY_CONVERT 13
+#define UNARY_CALL 14
+
+#define BINARY_MULTIPLY 20
+#define BINARY_DIVIDE 21
+#define BINARY_MODULO 22
+#define BINARY_ADD 23
+#define BINARY_SUBTRACT 24
+#define BINARY_SUBSCR 25
+#define BINARY_CALL 26
+
+#define SLICE 30
+/* Also uses 31-33 */
+
+#define STORE_SLICE 40
+/* Also uses 41-43 */
+
+#define DELETE_SLICE 50
+/* Also uses 51-53 */
+
+#define STORE_SUBSCR 60
+#define DELETE_SUBSCR 61
+
+#define PRINT_EXPR 70
+#define PRINT_ITEM 71
+#define PRINT_NEWLINE 72
+
+#define BREAK_LOOP 80
+#define RAISE_EXCEPTION 81
+#define LOAD_LOCALS 82
+#define RETURN_VALUE 83
+#define REQUIRE_ARGS 84
+#define REFUSE_ARGS 85
+#define BUILD_FUNCTION 86
+#define POP_BLOCK 87
+#define END_FINALLY 88
+#define BUILD_CLASS 89
+
+#define HAVE_ARGUMENT 90 /* Opcodes from here have an argument: */
+
+#define STORE_NAME 90 /* Index in name list */
+#define DELETE_NAME 91 /* "" */
+#define UNPACK_TUPLE 92 /* Number of tuple items */
+#define UNPACK_LIST 93 /* Number of list items */
+/* unused: 94 */
+#define STORE_ATTR 95 /* Index in name list */
+#define DELETE_ATTR 96 /* "" */
+
+#define LOAD_CONST 100 /* Index in const list */
+#define LOAD_NAME 101 /* Index in name list */
+#define BUILD_TUPLE 102 /* Number of tuple items */
+#define BUILD_LIST 103 /* Number of list items */
+#define BUILD_MAP 104 /* Always zero for now */
+#define LOAD_ATTR 105 /* Index in name list */
+#define COMPARE_OP 106 /* Comparison operator */
+#define IMPORT_NAME 107 /* Index in name list */
+#define IMPORT_FROM 108 /* Index in name list */
+
+#define JUMP_FORWARD 110 /* Number of bytes to skip */
+#define JUMP_IF_FALSE 111 /* "" */
+#define JUMP_IF_TRUE 112 /* "" */
+#define JUMP_ABSOLUTE 113 /* Target byte offset from beginning of code */
+#define FOR_LOOP 114 /* Number of bytes to skip */
+
+#define SETUP_LOOP 120 /* Target address (absolute) */
+#define SETUP_EXCEPT 121 /* "" */
+#define SETUP_FINALLY 122 /* "" */
+
+#define SET_LINENO 127 /* Current line number */
+
+/* Comparison operator codes (argument to COMPARE_OP) */
+enum cmp_op {LT, LE, EQ, NE, GT, GE, IN, NOT_IN, IS, IS_NOT, EXC_MATCH, BAD};
+
+#define HAS_ARG(op) ((op) >= HAVE_ARGUMENT)
diff --git a/src/panelmodule.c b/src/panelmodule.c
new file mode 100644
index 0000000..9edde6b
--- /dev/null
+++ b/src/panelmodule.c
@@ -0,0 +1,1090 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* Panel module.
+ Interface to the NASA Ames "panel library" for the SGI Graphics Library
+ by David Tristram.
+
+ NOTE: the panel library dumps core if you don't create a window before
+ calling pnl.mkpanel(). A call to gl.winopen() suffices.
+ If you don't want a window to be created, call gl.noport() before
+ gl.winopen().
+*/
+
+#include <gl.h>
+#include <device.h>
+#include <panel.h>
+
+#include "allobjects.h"
+#include "import.h"
+#include "modsupport.h"
+#include "cgensupport.h"
+
+
+/* The offsetof() macro calculates the offset of a structure member
+ in its structure. Unfortunately this cannot be written down portably,
+ hence it is standardized by ANSI C. For pre-ANSI C compilers,
+ we give a version here that works usually (but watch out!): */
+
+#ifndef offsetof
+#define offsetof(type, member) ( (int) & ((type*)0) -> member )
+#endif
+
+
+/* Panel objects */
+
+typedef struct {
+ OB_HEAD
+ Panel *ob_panel;
+ object *ob_paneldict;
+} panelobject;
+
+extern typeobject Paneltype; /* Really static, forward */
+
+#define is_panelobject(v) ((v)->ob_type == &Paneltype)
+
+
+/* Actuator objects */
+
+typedef struct {
+ OB_HEAD
+ Actuator *ob_actuator;
+} actuatorobject;
+
+extern typeobject Actuatortype; /* Really static, forward */
+
+#define is_actuatorobject(v) ((v)->ob_type == &Actuatortype)
+
+static object *newactuatorobject(); /* Forward */
+
+
+/* Since we allow different types of members than the functions from
+ structmember.c, the memberlist stuff is replicated here.
+ (Historically, it originated in this file and later became a generic
+ feature.) */
+
+/* An array of memberlist structures defines the name, type and offset
+ of selected members of a C structure. These can be read by
+ panel_getmember() and set by panel_setmember() (except if their
+ READONLY flag is set). The array must be terminated with an entry
+ whose name pointer is NULL. */
+
+struct memberlist {
+ char *name;
+ int type;
+ int offset;
+ int readonly;
+};
+
+/* Types */
+#define T_SHORT 0
+#define T_DEVICE T_SHORT
+#define T_LONG 1
+#define T_INT T_LONG
+#define T_BOOL T_LONG
+#define T_FLOAT 2
+#define T_COORD T_FLOAT
+#define T_STRING 3
+#define T_FUNC 4
+#define T_ACTUATOR 5
+
+/* Readonly flag */
+#define READONLY 1
+#define RO READONLY /* Shorthand */
+
+static object *
+panel_getmember(addr, mlist, name)
+ char *addr;
+ struct memberlist *mlist;
+ char *name;
+{
+ object *v;
+ register struct memberlist *l;
+
+ for (l = mlist; l->name != NULL; l++) {
+ if (strcmp(l->name, name) == 0) {
+ addr += l->offset;
+ switch (l->type) {
+ case T_SHORT:
+ v = newintobject((long) *(short*)addr);
+ break;
+ case T_LONG:
+ v = newintobject(*(long*)addr);
+ break;
+ case T_FLOAT:
+ v = newfloatobject(*(float*)addr);
+ break;
+ case T_STRING:
+ if (*(char**)addr == NULL) {
+ INCREF(None);
+ v = None;
+ }
+ else
+ v = newstringobject(*(char**)addr);
+ break;
+ case T_ACTUATOR:
+ v = newactuatorobject(*(Actuator**)addr);
+ break;
+ default:
+ err_badarg();
+ v = NULL;
+ }
+ return v;
+ }
+ }
+ err_setstr(NameError, name);
+ return NULL;
+}
+
+/* Attempt to set a member. Return: 0 if OK; 1 if not found; -1 if error */
+
+static int
+panel_setmember(addr, mlist, name, v)
+ char *addr;
+ struct memberlist *mlist;
+ char *name;
+ object *v;
+{
+ register struct memberlist *l;
+
+ for (l = mlist; l->name != NULL; l++) {
+ if (strcmp(l->name, name) == 0) {
+ if (l->readonly) {
+ err_setstr(TypeError, "read-only member");
+ return -1;
+ }
+ addr += l->offset;
+ switch (l->type) {
+ case T_SHORT:
+ if (!is_intobject(v)) {
+ err_setstr(TypeError, "int expected");
+ return -1;
+ }
+ *(short*)addr = getintvalue(v);
+ break;
+ case T_LONG:
+ if (!is_intobject(v)) {
+ err_setstr(TypeError, "int expected");
+ return -1;
+ }
+ *(long*)addr = getintvalue(v);
+ break;
+ case T_FLOAT:
+ if (is_intobject(v))
+ *(float*)addr = getintvalue(v);
+ else if (is_floatobject(v))
+ *(float*)addr = getfloatvalue(v);
+ else {
+ err_setstr(TypeError,"float expected");
+ return -1;
+ }
+ break;
+ case T_STRING:
+ /* XXX Should free(*(char**)addr) here
+ but it's dangerous since we don't know
+ if we set the label ourselves */
+ if (v == None)
+ *(char**)addr = NULL;
+ else if (!is_stringobject(v)) {
+ err_setstr(TypeError,
+ "string expected");
+ return -1;
+ }
+ else
+ *(char**)addr =
+ strdup(getstringvalue(v));
+ break;
+ case T_ACTUATOR:
+ if (v == None)
+ *(Actuator**)addr = NULL;
+ else if (!is_actuatorobject(v)) {
+ err_setstr(TypeError,
+ "actuator expected");
+ return -1;
+ }
+ else
+ *(Actuator**)addr =
+ ((actuatorobject *)v)->ob_actuator;
+ break;
+ default:
+ err_setstr(SystemError, "unknown member type");
+ return -1;
+ }
+ return 0; /* Found it */
+ }
+ }
+
+ return 1; /* Not found */
+}
+
+
+/* Panel object methods */
+
+static object *
+panel_addpanel(self, args)
+ panelobject *self;
+ object *args;
+{
+ if (!getnoarg(args))
+ return NULL;
+ pnl_addpanel(self->ob_panel);
+ INCREF(None);
+ return None;
+}
+
+static object *
+panel_endgroup(self, args)
+ panelobject *self;
+ object *args;
+{
+ if (!getnoarg(args))
+ return NULL;
+ pnl_endgroup(self->ob_panel);
+ INCREF(None);
+ return None;
+}
+
+static object *
+panel_fixpanel(self, args)
+ panelobject *self;
+ object *args;
+{
+ if (!getnoarg(args))
+ return NULL;
+ pnl_fixpanel(self->ob_panel);
+ INCREF(None);
+ return None;
+}
+
+static object *
+panel_strwidth(self, args)
+ panelobject *self;
+ object *args;
+{
+ object *v;
+ double width;
+ if (!getstrarg(args, &v))
+ return NULL;
+ width = pnl_strwidth(self->ob_panel, getstringvalue(v));
+ return newfloatobject(width);
+}
+
+static struct methodlist panel_methods[] = {
+ {"addpanel", panel_addpanel},
+ {"endgroup", panel_endgroup},
+ {"fixpanel", panel_fixpanel},
+ {"strwidth", panel_strwidth},
+ {NULL, NULL} /* sentinel */
+};
+
+static object *
+newpanelobject()
+{
+ panelobject *p;
+ p = NEWOBJ(panelobject, &Paneltype);
+ if (p == NULL)
+ return NULL;
+ p->ob_panel = pnl_mkpanel();
+ if ((p->ob_paneldict = newdictobject()) == NULL) {
+ DECREF(p);
+ return NULL;
+ }
+ return (object *)p;
+}
+
+static void
+panel_dealloc(p)
+ panelobject *p;
+{
+ pnl_delpanel(p->ob_panel);
+ if (p->ob_paneldict != NULL)
+ DECREF(p->ob_paneldict);
+ DEL(p);
+}
+
+
+/* Table of panel members */
+
+#define PANOFF(member) offsetof(Panel, member)
+
+static struct memberlist panel_memberlist[] = {
+ {"id", T_SHORT, PANOFF(id), READONLY},
+ {"a", T_ACTUATOR, PANOFF(a), READONLY},
+ {"al", T_ACTUATOR, PANOFF(al), READONLY},
+ {"lastgroup", T_ACTUATOR, PANOFF(lastgroup), READONLY},
+
+ {"active", T_BOOL, PANOFF(active)},
+ {"selectable", T_BOOL, PANOFF(selectable)},
+
+ {"x", T_LONG, PANOFF(x)},
+ {"y", T_LONG, PANOFF(y)},
+ {"w", T_LONG, PANOFF(w)},
+ {"h", T_LONG, PANOFF(h)},
+
+ {"minx", T_COORD, PANOFF(minx)},
+ {"maxx", T_COORD, PANOFF(maxx)},
+ {"miny", T_COORD, PANOFF(miny)},
+ {"maxy", T_COORD, PANOFF(maxy)},
+
+ {"cw", T_COORD, PANOFF(cw)},
+ {"ch", T_COORD, PANOFF(ch)},
+
+ {"gid", T_LONG, PANOFF(gid), READONLY},
+ {"usergid", T_LONG, PANOFF(usergid), READONLY},
+
+ {"vobj", T_LONG, PANOFF(vobj), READONLY},
+ {"ppu", T_FLOAT, PANOFF(ppu)},
+
+ {"label", T_STRING, PANOFF(label)},
+
+ /* Panel callbacks are not supported */
+
+ {"visible", T_BOOL, PANOFF(visible)},
+ {"somedirty", T_INT, PANOFF(somedirty)},
+ {"dirtycnt", T_INT, PANOFF(dirtycnt)},
+
+ /* T_PANEL is not supported */
+ /*
+ {"next", T_PANEL, PANOFF(next), READONLY},
+ */
+
+ {NULL, 0, 0} /* Sentinel */
+};
+
+static object *
+panel_getattr(p, name)
+ panelobject *p;
+ char *name;
+{
+ object *v;
+
+ v = dictlookup(p->ob_paneldict, name);
+ if (v != NULL) {
+ INCREF(v);
+ return v;
+ }
+
+ v = findmethod(panel_methods, (object *)p, name);
+ if (v != NULL)
+ return v;
+ err_clear();
+ return panel_getmember((char *)p->ob_panel, panel_memberlist, name);
+}
+
+static int
+panel_setattr(p, name, v)
+ panelobject *p;
+ char *name;
+ object *v;
+{
+ int err;
+
+ /* We don't allow deletion of attributes */
+ if (v == NULL) {
+ err_setstr(TypeError, "read-only panel attribute");
+ return -1;
+ }
+ err = panel_setmember((char *)p->ob_panel, panel_memberlist, name, v);
+ if (err != 1)
+ return err;
+ return dictinsert(p->ob_paneldict, name, v);
+}
+
+static typeobject Paneltype = {
+ OB_HEAD_INIT(&Typetype)
+ 0, /*ob_size*/
+ "panel", /*tp_name*/
+ sizeof(panelobject), /*tp_size*/
+ 0, /*tp_itemsize*/
+ /* methods */
+ panel_dealloc, /*tp_dealloc*/
+ 0, /*tp_print*/
+ panel_getattr, /*tp_getattr*/
+ panel_setattr, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+};
+
+
+/* Descriptions of actuator-specific data members */
+
+struct memberlist slider_spec[] = {
+ {"mode", T_INT, offsetof(Slider, mode)},
+ {"finefactor", T_FLOAT, offsetof(Slider, finefactor)},
+ {"differentialfactor",
+ T_FLOAT, offsetof(Slider, differentialfactor)},
+ {"valsave", T_FLOAT, offsetof(Slider, valsave), RO},
+ {"wsave", T_COORD, offsetof(Slider, wsave)},
+ {"bh", T_COORD, offsetof(Slider, bh)},
+ {NULL}
+};
+
+#define palette_spec slider_spec
+
+struct memberlist puck_spec[] = {
+ /* Actuators already have members x and y, so the Puck's x and y
+ have different names */
+ {"puck_x", T_FLOAT, offsetof(Puck, x)},
+ {"puck_y", T_FLOAT, offsetof(Puck, y)},
+ {NULL}
+};
+
+struct memberlist dial_spec[] = {
+ {"mode", T_INT, offsetof(Dial, mode)},
+ {"finefactor", T_FLOAT, offsetof(Dial, finefactor)},
+ {"valsave", T_FLOAT, offsetof(Dial, valsave), RO},
+ {"wsave", T_COORD, offsetof(Dial, wsave)},
+ {"winds", T_FLOAT, offsetof(Dial, winds)},
+ {NULL}
+};
+
+struct memberlist slideroid_spec[] = {
+ {"mode", T_INT, offsetof(Slideroid, mode)},
+ {"finemode", T_BOOL, offsetof(Slideroid, finemode)},
+ {"resetmode", T_BOOL, offsetof(Slideroid, resetmode)},
+ /* XXX Can't do resettarget (pointer to float) */
+ /* XXX This makes resetval pretty useless... */
+ /*
+ {"resetval", T_FLOAT, offsetof(Slideroid, resetval)},
+ */
+ {"valsave", T_FLOAT, offsetof(Slideroid, valsave), RO},
+ {"wsave", T_COORD, offsetof(Slideroid, wsave)},
+ {NULL}
+};
+
+struct memberlist stripchart_spec[] = {
+ {"firstpt", T_INT, offsetof(Stripchart, firstpt), RO},
+ {"lastpt", T_INT, offsetof(Stripchart, lastpt), RO},
+ {"Bind_Low", T_BOOL, offsetof(Stripchart, Bind_Low)},
+ {"Bind_High", T_BOOL, offsetof(Stripchart, Bind_High)},
+ /* XXX Can't do y (array of floats) */
+ {"lowlabel", T_ACTUATOR, offsetof(Stripchart, lowlabel), RO},
+ {"highlabel", T_ACTUATOR, offsetof(Stripchart, highlabel), RO},
+ {NULL}
+};
+
+struct memberlist typein_spec[] = {
+ /* Note: these should be readonly after the actuator is added
+ to a panel */
+ {"str", T_STRING, offsetof(Typein, str)},
+ {"len", T_INT, offsetof(Typein, len)},
+ {NULL}
+};
+
+struct memberlist typeout_spec[] = {
+ {"mode", T_INT, offsetof(Typeout, mode)},
+ /* XXX The buffer is managed by the actuator; but how do we
+ add text? */
+ {"buf", T_STRING, offsetof(Typeout, buf), READONLY},
+ {"delimstr", T_STRING, offsetof(Typeout, delimstr)},
+ {"start", T_INT, offsetof(Typeout, start)},
+ {"dot", T_INT, offsetof(Typeout, dot)},
+ {"mark", T_INT, offsetof(Typeout, mark)},
+ {"col", T_INT, offsetof(Typeout, col)},
+ {"lin", T_INT, offsetof(Typeout, lin)},
+ {"len", T_INT, offsetof(Typeout, len)},
+ {"size", T_INT, offsetof(Typeout, size)},
+ {NULL}
+};
+
+struct memberlist mouse_spec[] = {
+ /* Actuators already have members x and y, so the Mouse's x and y
+ have different names */
+ {"mouse_x", T_FLOAT, offsetof(Mouse, x)},
+ {"mouse_y", T_FLOAT, offsetof(Mouse, y)},
+ {NULL}
+};
+
+#define MULOFF(member) offsetof(Multislider, member)
+
+struct memberlist multislider_spec[] = {
+ {"mode", T_INT, MULOFF(mode)},
+ {"n", T_INT, MULOFF(n)},
+ {"finefactor", T_FLOAT, MULOFF(finefactor)},
+ {"wsave", T_COORD, MULOFF(wsave)},
+ {"sa", T_ACTUATOR, MULOFF(sa)},
+ {"bh", T_COORD, MULOFF(bh)},
+ {"clrx", T_COORD, MULOFF(clrx)},
+ {"clry", T_COORD, MULOFF(clry)},
+ {"clrw", T_COORD, MULOFF(clrw)},
+ {"clrh", T_COORD, MULOFF(clrh)},
+ /* XXX acttype? */
+ {NULL}
+};
+
+/* XXX Still to do:
+ Frame
+ Icon
+ Cycle
+ Scroll
+ Menu
+*/
+
+/* List of known actuator initializer functions */
+
+struct {
+ char *name;
+ void (*func)();
+ struct memberlist *spec;
+} initializerlist[] = {
+ {"analog_bar", pnl_analog_bar},
+ {"analog_meter", pnl_analog_meter},
+ {"button", pnl_button},
+ {"cycle", pnl_cycle},
+ /* Doesn't exist: */
+/* {"dhslider", pnl_dhslider, slider_spec}, */
+ {"dial", pnl_dial, dial_spec},
+ {"down_arrow_button", pnl_down_arrow_button},
+ {"down_double_arrow_button", pnl_down_double_arrow_button},
+ {"dvslider", pnl_dvslider, slider_spec},
+ {"filled_hslider", pnl_filled_hslider, slider_spec},
+ {"filled_slider", pnl_filled_slider, slider_spec},
+ {"filled_vslider", pnl_filled_vslider, slider_spec},
+ {"floating_puck", pnl_floating_puck, puck_spec},
+ {"frame", pnl_frame},
+ {"graphframe", pnl_graphframe},
+ {"hmultislider", pnl_hmultislider, multislider_spec},
+ {"hmultislider_bar", pnl_hmultislider_bar},
+ {"hmultislider_open_bar", pnl_hmultislider_open_bar},
+ {"hpalette", pnl_hpalette, palette_spec},
+ {"hslider", pnl_hslider, slider_spec},
+ {"icon", pnl_icon},
+ {"icon_menu", pnl_icon_menu},
+ {"label", pnl_label},
+ {"left_arrow_button", pnl_left_arrow_button},
+ {"left_double_arrow_button", pnl_left_double_arrow_button},
+ {"menu", pnl_menu},
+ {"menu_item", pnl_menu_item},
+ {"meter", pnl_meter},
+ {"mouse", pnl_mouse, mouse_spec},
+ {"multislider", pnl_multislider, multislider_spec},
+ {"multislider_bar", pnl_multislider_bar},
+ {"multislider_open_bar", pnl_multislider_open_bar},
+ {"palette", pnl_palette, palette_spec},
+ {"puck", pnl_puck, puck_spec},
+ {"radio_button", pnl_radio_button},
+ {"radio_check_button", pnl_radio_check_button},
+ {"right_arrow_button", pnl_right_arrow_button},
+ {"right_double_arrow_button", pnl_right_double_arrow_button},
+ {"rubber_puck", pnl_rubber_puck, puck_spec},
+ {"scale_chart", pnl_scale_chart, stripchart_spec},
+ {"scroll", pnl_scroll},
+ {"signal", pnl_signal},
+ {"slider", pnl_slider, slider_spec},
+ {"slideroid", pnl_slideroid, slideroid_spec},
+ {"strip_chart", pnl_strip_chart, stripchart_spec},
+ {"sub_menu", pnl_sub_menu},
+ {"toggle_button", pnl_toggle_button},
+ {"typein", pnl_typein, typein_spec},
+ {"typeout", pnl_typeout, typeout_spec},
+ {"up_arrow_button", pnl_up_arrow_button},
+ {"up_double_arrow_button", pnl_up_double_arrow_button},
+ {"viewframe", pnl_viewframe},
+ {"vmultislider", pnl_vmultislider, multislider_spec},
+ {"vmultislider_bar", pnl_vmultislider_bar},
+ {"vmultislider_open_bar", pnl_vmultislider_open_bar},
+ {"vpalette", pnl_vpalette, palette_spec},
+ {"vslider", pnl_vslider, slider_spec},
+ {"wide_button", pnl_wide_button},
+ {NULL, NULL} /* Sentinel */
+};
+
+
+/* Pseudo downfunc etc. */
+
+static Actuator *down_pend, *active_pend, *up_pend;
+
+static void
+downfunc(a)
+ Actuator *a;
+{
+ if (down_pend == NULL)
+ down_pend = a;
+}
+
+static void
+activefunc(a)
+ Actuator *a;
+{
+ if (active_pend == NULL)
+ active_pend = a;
+}
+
+static void
+upfunc(a)
+ Actuator *a;
+{
+ if (up_pend == NULL)
+ up_pend = a;
+}
+
+
+/* Lay-out for the user data */
+
+struct userdata {
+ object *dict; /* Dictionary object for additional attributes */
+ struct memberlist *spec; /* Actuator-specific members */
+};
+
+
+/* Create a new actuator; the actuator type is given as a string */
+
+static Actuator *
+makeactuator(name)
+ char *name;
+{
+ Actuator *act;
+ void (*initializer)() = NULL;
+ int i;
+ struct userdata *u;
+ for (i = 0; initializerlist[i].name != NULL; i++) {
+ if (strcmp(initializerlist[i].name, name) == 0) {
+ initializer = initializerlist[i].func;
+ break;
+ }
+ }
+ if (initializerlist[i].name == NULL) {
+ err_badarg();
+ return NULL;
+ }
+ u = NEW(struct userdata, 1);
+ if (u == NULL) {
+ err_nomem();
+ return NULL;
+ }
+ u->dict = NULL;
+ u->spec = initializerlist[i].spec;
+ act = pnl_mkact(initializer);
+ act->u = (char *)u;
+ act->downfunc = downfunc;
+ act->activefunc = activefunc;
+ act->upfunc = upfunc;
+ return act;
+}
+
+
+/* Actuator objects methods */
+
+static object *
+actuator_addact(self, args)
+ actuatorobject *self;
+ object *args;
+{
+ Panel *p;
+ if (!is_panelobject(args)) {
+ err_badarg();
+ return NULL;
+ }
+ p = ((panelobject *)args) -> ob_panel;
+ pnl_addact(self->ob_actuator, p);
+ INCREF(None);
+ return None;
+}
+
+static object *
+actuator_addsubact(self, args)
+ actuatorobject *self;
+ object *args;
+{
+ Actuator *a;
+ if (!is_actuatorobject(args)) {
+ err_badarg();
+ return NULL;
+ }
+ a = ((actuatorobject *)args) -> ob_actuator;
+ pnl_addsubact(self->ob_actuator, a);
+ INCREF(None);
+ return None;
+}
+
+static object *
+actuator_delact(self, args)
+ actuatorobject *self;
+ object *args;
+{
+ Panel *p;
+ if (!getnoarg(args))
+ return NULL;
+ pnl_delact(self->ob_actuator);
+ INCREF(None);
+ return None;
+}
+
+static object *
+actuator_fixact(self, args)
+ actuatorobject *self;
+ object *args;
+{
+ Panel *p;
+ if (!getnoarg(args))
+ return NULL;
+ pnl_fixact(self->ob_actuator);
+ INCREF(None);
+ return None;
+}
+
+static object *
+actuator_tprint(self, args)
+ actuatorobject *self;
+ object *args;
+{
+ object *str;
+ if (self->ob_actuator->type != PNL_TYPEOUT) {
+ err_setstr(TypeError, "tprint for non-typeout panel");
+ return NULL;
+ }
+ if (!getstrarg(args, &str))
+ return NULL;
+ tprint(self->ob_actuator, getstringvalue(str));
+ /* XXX Can't turn tprint's errors into exceptions, sorry */
+ INCREF(None);
+ return None;
+}
+
+static struct methodlist actuator_methods[] = {
+ {"addact", actuator_addact},
+ {"addsubact", actuator_addsubact},
+ {"delact", actuator_delact},
+ {"fixact", actuator_fixact},
+ {"tprint", actuator_tprint},
+ {NULL, NULL} /* sentinel */
+};
+
+static object *
+newactuatorobject(act)
+ Actuator *act;
+{
+ actuatorobject *a;
+ if (act == NULL) {
+ INCREF(None);
+ return None;
+ }
+ a = NEWOBJ(actuatorobject, &Actuatortype);
+ if (a == NULL)
+ return NULL;
+ a->ob_actuator = act;
+ return (object *)a;
+}
+
+static void
+actuator_dealloc(a)
+ actuatorobject *a;
+{
+ /* Do NOT delete the actuator; most actuator objects are created
+ to hold a temporary reference to an actuator, like one gotten
+ from pnl_dopanel(). */
+
+ DEL(a);
+}
+
+
+/* Table of actuator members */
+
+#define ACTOFF(member) offsetof(Actuator, member)
+
+struct memberlist act_memberlist[] = {
+ {"id", T_SHORT, ACTOFF(id), READONLY},
+
+ /* T_PANEL is not defined */
+ /*
+ {"p", T_PANEL, ACTOFF(p), READONLY},
+ */
+
+ {"pa", T_ACTUATOR, ACTOFF(pa), READONLY},
+ {"ca", T_ACTUATOR, ACTOFF(ca), READONLY},
+ {"al", T_ACTUATOR, ACTOFF(al), READONLY},
+ {"na", T_INT, ACTOFF(na), READONLY},
+ {"type", T_INT, ACTOFF(type), READONLY},
+ {"active", T_BOOL, ACTOFF(active)},
+
+ {"x", T_COORD, ACTOFF(x)},
+ {"y", T_COORD, ACTOFF(y)},
+ {"w", T_COORD, ACTOFF(w)},
+ {"h", T_COORD, ACTOFF(h)},
+
+ {"lx", T_COORD, ACTOFF(lx)},
+ {"ly", T_COORD, ACTOFF(ly)},
+ {"lw", T_COORD, ACTOFF(lw)},
+ {"lh", T_COORD, ACTOFF(lh)},
+ {"ld", T_COORD, ACTOFF(ld)},
+
+ {"val", T_FLOAT, ACTOFF(val)},
+ {"extval", T_FLOAT, ACTOFF(extval)},
+ {"initval", T_FLOAT, ACTOFF(initval)},
+ {"maxval", T_FLOAT, ACTOFF(maxval)},
+ {"minval", T_FLOAT, ACTOFF(minval)},
+ {"scalefactor", T_FLOAT, ACTOFF(scalefactor)},
+
+ {"label", T_STRING, ACTOFF(label)},
+ {"key", T_DEVICE, ACTOFF(key)},
+ {"labeltype", T_INT, ACTOFF(labeltype)},
+
+ /* Internal callbacks are not supported;
+ user callbacks are treated special! */
+
+ {"dirtycnt", T_INT, ACTOFF(dirtycnt)},
+
+ /* members u and data are accessed differently */
+
+ {"automatic", T_BOOL, ACTOFF(automatic)},
+ {"selectable", T_BOOL, ACTOFF(selectable)},
+ {"visible", T_BOOL, ACTOFF(visible)},
+ {"beveled", T_BOOL, ACTOFF(beveled)},
+
+ {"group", T_ACTUATOR, ACTOFF(group), READONLY},
+ {"next", T_ACTUATOR, ACTOFF(next), READONLY},
+
+ {NULL, 0, 0} /* Sentinel */
+};
+
+
+/* Potential name conflicts between attributes are solved as follows.
+ - Actuator-specific attributes always override generic attributes.
+ - When reading, the dictionary has overrides everything else;
+ when writing, everything else overrides the dictionary.
+ - When reading, methods are tried last.
+*/
+
+static object *
+actuator_getattr(a, name)
+ actuatorobject *a;
+ char *name;
+{
+ Actuator *act = a->ob_actuator;
+ struct userdata *u = (struct userdata *) act->u;
+ object *v;
+
+ if (u != NULL) {
+ /* 1. Try the dictionary */
+ if (u->dict != NULL) {
+ v = dictlookup(u->dict, name);
+ if (v != NULL) {
+ INCREF(v);
+ return v;
+ }
+ }
+
+ /* 2. Try actuator-specific attributes */
+ if (u->spec != NULL) {
+ v = panel_getmember(act->data, u->spec, name);
+ if (v != NULL)
+ return v;
+ err_clear();
+ }
+ }
+
+ /* 3. Try generic actuator attributes */
+ v = panel_getmember((char *)act, act_memberlist, name);
+ if (v != NULL)
+ return v;
+
+ /* 4. Try methods */
+ err_clear();
+ return findmethod(actuator_methods, (object *)a, name);
+}
+
+static int
+actuator_setattr(a, name, v)
+ actuatorobject *a;
+ char *name;
+ object *v;
+{
+ Actuator *act = a->ob_actuator;
+ struct userdata *u = (struct userdata *) act->u;
+ int err;
+
+ /* 0. We don't allow deletion of attributes */
+ if (v == NULL) {
+ err_setstr(TypeError, "read-only actuator attribute");
+ return -1;
+ }
+
+ /* 1. Try actuator-specific attributes */
+ if (u != NULL && u->spec != NULL) {
+ err = panel_setmember(act->data, u->spec, name, v);
+ if (err != 1)
+ return err;
+ }
+
+ /* 2. Try generic actuator attributes */
+ err = panel_setmember((char *)act, act_memberlist, name, v);
+ if (err != 1)
+ return err;
+
+ /* 3. Try the dictionary */
+ if (u != NULL) {
+ if (u->dict == NULL && (u->dict = newdictobject()) == NULL)
+ return NULL;
+ return dictinsert(u->dict, name, v);
+ }
+
+ err_setstr(NameError, name);
+ return -1;
+}
+
+static int
+actuator_compare(v, w)
+ actuatorobject *v, *w;
+{
+ long i = (long)v->ob_actuator;
+ long j = (long)w->ob_actuator;
+ return (i < j) ? -1 : (i > j) ? 1 : 0;
+}
+
+static typeobject Actuatortype = {
+ OB_HEAD_INIT(&Typetype)
+ 0, /*ob_size*/
+ "actuator", /*tp_name*/
+ sizeof(actuatorobject), /*tp_size*/
+ 0, /*tp_itemsize*/
+ /* methods */
+ actuator_dealloc, /*tp_dealloc*/
+ 0, /*tp_print*/
+ actuator_getattr, /*tp_getattr*/
+ actuator_setattr, /*tp_setattr*/
+ actuator_compare, /*tp_compare*/
+ 0, /*tp_repr*/
+};
+
+
+/* The panel module itself */
+
+static object *
+module_mkpanel(self, args)
+ object *self;
+ object *args;
+{
+ if (!getnoarg(args))
+ return NULL;
+ return newpanelobject();
+}
+
+static object *
+module_mkact(self, args)
+ object *self;
+ object *args;
+{
+ object *v;
+ Actuator *a;
+ if (!getstrarg(args, &v))
+ return NULL;
+ a = makeactuator(getstringvalue(v));
+ if (a == NULL)
+ return NULL;
+ return newactuatorobject(a);
+}
+
+static object *
+module_dopanel(self, args)
+ object *self;
+ object *args;
+{
+ Actuator *a;
+ object *v, *w;
+ if (!getnoarg(args))
+ return NULL;
+ a = pnl_dopanel();
+ v = newtupleobject(4);
+ if (v == NULL)
+ return NULL;
+ settupleitem(v, 0, newactuatorobject(a));
+ settupleitem(v, 1, newactuatorobject(down_pend));
+ settupleitem(v, 2, newactuatorobject(active_pend));
+ settupleitem(v, 3, newactuatorobject(up_pend));
+ down_pend = active_pend = up_pend = NULL;
+ return v;
+}
+
+static object *
+module_drawpanel(self, args)
+ object *self;
+ object *args;
+{
+ if (!getnoarg(args))
+ return NULL;
+ pnl_drawpanel();
+ INCREF(None);
+ return None;
+}
+
+static object *
+module_needredraw(self, args)
+ object *self;
+ object *args;
+{
+ if (!getnoarg(args))
+ return NULL;
+ pnl_needredraw();
+ INCREF(None);
+ return None;
+}
+
+static object *
+module_userredraw(self, args)
+ object *self;
+ object *args;
+{
+ short wid;
+ if (!getnoarg(args))
+ return NULL;
+ wid = pnl_userredraw();
+ return newintobject((long)wid);
+}
+
+static object *
+module_block(self, args)
+ object *self;
+ object *args;
+{
+ int flag;
+ if (!getintarg(args, &flag))
+ return NULL;
+ pnl_block = flag;
+ INCREF(None);
+ return None;
+}
+
+static struct methodlist module_methods[] = {
+ {"block", module_block},
+ {"dopanel", module_dopanel},
+ {"drawpanel", module_drawpanel},
+ {"mkpanel", module_mkpanel},
+ {"mkact", module_mkact},
+ {"needredraw", module_needredraw},
+ {"userredraw", module_userredraw},
+ {NULL, NULL} /* sentinel */
+};
+
+void
+initpanel()
+{
+ /* Setting pnl_block to 1 would greatly reduce the CPU usage
+ of an idle application. Unfortunately it also breaks our
+ little hacks to get callback functions in Python called.
+ So we clear pnl_block here. You can set/clear pnl_block
+ from Python using pnl.block(flag). It works if you have
+ no upfuncs. */
+ pnl_block = 0;
+ initmodule("pnl", module_methods);
+}
diff --git a/src/parser.c b/src/parser.c
new file mode 100644
index 0000000..8ee7e2c
--- /dev/null
+++ b/src/parser.c
@@ -0,0 +1,423 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* Parser implementation */
+
+/* For a description, see the comments at end of this file */
+
+/* XXX To do: error recovery */
+
+#include "pgenheaders.h"
+#include "assert.h"
+#include "token.h"
+#include "grammar.h"
+#include "node.h"
+#include "parser.h"
+#include "errcode.h"
+
+
+#ifdef DEBUG
+extern int debugging;
+#define D(x) if (!debugging); else x
+#else
+#define D(x)
+#endif
+
+
+/* STACK DATA TYPE */
+
+static void s_reset PROTO((stack *));
+
+static void
+s_reset(s)
+ stack *s;
+{
+ s->s_top = &s->s_base[MAXSTACK];
+}
+
+#define s_empty(s) ((s)->s_top == &(s)->s_base[MAXSTACK])
+
+static int s_push PROTO((stack *, dfa *, node *));
+
+static int
+s_push(s, d, parent)
+ register stack *s;
+ dfa *d;
+ node *parent;
+{
+ register stackentry *top;
+ if (s->s_top == s->s_base) {
+ fprintf(stderr, "s_push: parser stack overflow\n");
+ return -1;
+ }
+ top = --s->s_top;
+ top->s_dfa = d;
+ top->s_parent = parent;
+ top->s_state = 0;
+ return 0;
+}
+
+#ifdef DEBUG
+
+static void s_pop PROTO((stack *));
+
+static void
+s_pop(s)
+ register stack *s;
+{
+ if (s_empty(s)) {
+ fprintf(stderr, "s_pop: parser stack underflow -- FATAL\n");
+ abort();
+ }
+ s->s_top++;
+}
+
+#else /* !DEBUG */
+
+#define s_pop(s) (s)->s_top++
+
+#endif
+
+
+/* PARSER CREATION */
+
+parser_state *
+newparser(g, start)
+ grammar *g;
+ int start;
+{
+ parser_state *ps;
+
+ if (!g->g_accel)
+ addaccelerators(g);
+ ps = NEW(parser_state, 1);
+ if (ps == NULL)
+ return NULL;
+ ps->p_grammar = g;
+ ps->p_tree = newtree(start);
+ if (ps->p_tree == NULL) {
+ DEL(ps);
+ return NULL;
+ }
+ s_reset(&ps->p_stack);
+ (void) s_push(&ps->p_stack, finddfa(g, start), ps->p_tree);
+ return ps;
+}
+
+void
+delparser(ps)
+ parser_state *ps;
+{
+ /* NB If you want to save the parse tree,
+ you must set p_tree to NULL before calling delparser! */
+ freetree(ps->p_tree);
+ DEL(ps);
+}
+
+
+/* PARSER STACK OPERATIONS */
+
+static int shift PROTO((stack *, int, char *, int, int));
+
+static int
+shift(s, type, str, newstate, lineno)
+ register stack *s;
+ int type;
+ char *str;
+ int newstate;
+ int lineno;
+{
+ assert(!s_empty(s));
+ if (addchild(s->s_top->s_parent, type, str, lineno) == NULL) {
+ fprintf(stderr, "shift: no mem in addchild\n");
+ return -1;
+ }
+ s->s_top->s_state = newstate;
+ return 0;
+}
+
+static int push PROTO((stack *, int, dfa *, int, int));
+
+static int
+push(s, type, d, newstate, lineno)
+ register stack *s;
+ int type;
+ dfa *d;
+ int newstate;
+ int lineno;
+{
+ register node *n;
+ n = s->s_top->s_parent;
+ assert(!s_empty(s));
+ if (addchild(n, type, (char *)NULL, lineno) == NULL) {
+ fprintf(stderr, "push: no mem in addchild\n");
+ return -1;
+ }
+ s->s_top->s_state = newstate;
+ return s_push(s, d, CHILD(n, NCH(n)-1));
+}
+
+
+/* PARSER PROPER */
+
+static int classify PROTO((grammar *, int, char *));
+
+static int
+classify(g, type, str)
+ grammar *g;
+ register int type;
+ char *str;
+{
+ register int n = g->g_ll.ll_nlabels;
+
+ if (type == NAME) {
+ register char *s = str;
+ register label *l = g->g_ll.ll_label;
+ register int i;
+ for (i = n; i > 0; i--, l++) {
+ if (l->lb_type == NAME && l->lb_str != NULL &&
+ l->lb_str[0] == s[0] &&
+ strcmp(l->lb_str, s) == 0) {
+ D(printf("It's a keyword\n"));
+ return n - i;
+ }
+ }
+ }
+
+ {
+ register label *l = g->g_ll.ll_label;
+ register int i;
+ for (i = n; i > 0; i--, l++) {
+ if (l->lb_type == type && l->lb_str == NULL) {
+ D(printf("It's a token we know\n"));
+ return n - i;
+ }
+ }
+ }
+
+ D(printf("Illegal token\n"));
+ return -1;
+}
+
+int
+addtoken(ps, type, str, lineno)
+ register parser_state *ps;
+ register int type;
+ char *str;
+ int lineno;
+{
+ register int ilabel;
+
+ D(printf("Token %s/'%s' ... ", tok_name[type], str));
+
+ /* Find out which label this token is */
+ ilabel = classify(ps->p_grammar, type, str);
+ if (ilabel < 0)
+ return E_SYNTAX;
+
+ /* Loop until the token is shifted or an error occurred */
+ for (;;) {
+ /* Fetch the current dfa and state */
+ register dfa *d = ps->p_stack.s_top->s_dfa;
+ register state *s = &d->d_state[ps->p_stack.s_top->s_state];
+
+ D(printf(" DFA '%s', state %d:",
+ d->d_name, ps->p_stack.s_top->s_state));
+
+ /* Check accelerator */
+ if (s->s_lower <= ilabel && ilabel < s->s_upper) {
+ register int x = s->s_accel[ilabel - s->s_lower];
+ if (x != -1) {
+ if (x & (1<<7)) {
+ /* Push non-terminal */
+ int nt = (x >> 8) + NT_OFFSET;
+ int arrow = x & ((1<<7)-1);
+ dfa *d1 = finddfa(ps->p_grammar, nt);
+ if (push(&ps->p_stack, nt, d1,
+ arrow, lineno) < 0) {
+ D(printf(" MemError: push.\n"));
+ return E_NOMEM;
+ }
+ D(printf(" Push ...\n"));
+ continue;
+ }
+
+ /* Shift the token */
+ if (shift(&ps->p_stack, type, str,
+ x, lineno) < 0) {
+ D(printf(" MemError: shift.\n"));
+ return E_NOMEM;
+ }
+ D(printf(" Shift.\n"));
+ /* Pop while we are in an accept-only state */
+ while (s = &d->d_state
+ [ps->p_stack.s_top->s_state],
+ s->s_accept && s->s_narcs == 1) {
+ D(printf(" Direct pop.\n"));
+ s_pop(&ps->p_stack);
+ if (s_empty(&ps->p_stack)) {
+ D(printf(" ACCEPT.\n"));
+ return E_DONE;
+ }
+ d = ps->p_stack.s_top->s_dfa;
+ }
+ return E_OK;
+ }
+ }
+
+ if (s->s_accept) {
+ /* Pop this dfa and try again */
+ s_pop(&ps->p_stack);
+ D(printf(" Pop ...\n"));
+ if (s_empty(&ps->p_stack)) {
+ D(printf(" Error: bottom of stack.\n"));
+ return E_SYNTAX;
+ }
+ continue;
+ }
+
+ /* Stuck, report syntax error */
+ D(printf(" Error.\n"));
+ return E_SYNTAX;
+ }
+}
+
+
+#ifdef DEBUG
+
+/* DEBUG OUTPUT */
+
+void
+dumptree(g, n)
+ grammar *g;
+ node *n;
+{
+ int i;
+
+ if (n == NULL)
+ printf("NIL");
+ else {
+ label l;
+ l.lb_type = TYPE(n);
+ l.lb_str = TYPE(str);
+ printf("%s", labelrepr(&l));
+ if (ISNONTERMINAL(TYPE(n))) {
+ printf("(");
+ for (i = 0; i < NCH(n); i++) {
+ if (i > 0)
+ printf(",");
+ dumptree(g, CHILD(n, i));
+ }
+ printf(")");
+ }
+ }
+}
+
+void
+showtree(g, n)
+ grammar *g;
+ node *n;
+{
+ int i;
+
+ if (n == NULL)
+ return;
+ if (ISNONTERMINAL(TYPE(n))) {
+ for (i = 0; i < NCH(n); i++)
+ showtree(g, CHILD(n, i));
+ }
+ else if (ISTERMINAL(TYPE(n))) {
+ printf("%s", tok_name[TYPE(n)]);
+ if (TYPE(n) == NUMBER || TYPE(n) == NAME)
+ printf("(%s)", STR(n));
+ printf(" ");
+ }
+ else
+ printf("? ");
+}
+
+void
+printtree(ps)
+ parser_state *ps;
+{
+ if (debugging) {
+ printf("Parse tree:\n");
+ dumptree(ps->p_grammar, ps->p_tree);
+ printf("\n");
+ printf("Tokens:\n");
+ showtree(ps->p_grammar, ps->p_tree);
+ printf("\n");
+ }
+ printf("Listing:\n");
+ listtree(ps->p_tree);
+ printf("\n");
+}
+
+#endif /* DEBUG */
+
+/*
+
+Description
+-----------
+
+The parser's interface is different than usual: the function addtoken()
+must be called for each token in the input. This makes it possible to
+turn it into an incremental parsing system later. The parsing system
+constructs a parse tree as it goes.
+
+A parsing rule is represented as a Deterministic Finite-state Automaton
+(DFA). A node in a DFA represents a state of the parser; an arc represents
+a transition. Transitions are either labeled with terminal symbols or
+with non-terminals. When the parser decides to follow an arc labeled
+with a non-terminal, it is invoked recursively with the DFA representing
+the parsing rule for that as its initial state; when that DFA accepts,
+the parser that invoked it continues. The parse tree constructed by the
+recursively called parser is inserted as a child in the current parse tree.
+
+The DFA's can be constructed automatically from a more conventional
+language description. An extended LL(1) grammar (ELL(1)) is suitable.
+Certain restrictions make the parser's life easier: rules that can produce
+the empty string should be outlawed (there are other ways to put loops
+or optional parts in the language). To avoid the need to construct
+FIRST sets, we can require that all but the last alternative of a rule
+(really: arc going out of a DFA's state) must begin with a terminal
+symbol.
+
+As an example, consider this grammar:
+
+expr: term (OP term)*
+term: CONSTANT | '(' expr ')'
+
+The DFA corresponding to the rule for expr is:
+
+------->.---term-->.------->
+ ^ |
+ | |
+ \----OP----/
+
+The parse tree generated for the input a+b is:
+
+(expr: (term: (NAME: a)), (OP: +), (term: (NAME: b)))
+
+*/
diff --git a/src/parser.h b/src/parser.h
new file mode 100644
index 0000000..3e8090a
--- /dev/null
+++ b/src/parser.h
@@ -0,0 +1,50 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* Parser interface */
+
+#define MAXSTACK 100
+
+typedef struct _stackentry {
+ int s_state; /* State in current DFA */
+ dfa *s_dfa; /* Current DFA */
+ struct _node *s_parent; /* Where to add next node */
+} stackentry;
+
+typedef struct _stack {
+ stackentry *s_top; /* Top entry */
+ stackentry s_base[MAXSTACK];/* Array of stack entries */
+ /* NB The stack grows down */
+} stack;
+
+typedef struct {
+ struct _stack p_stack; /* Stack of parser states */
+ struct _grammar *p_grammar; /* Grammar to use */
+ struct _node *p_tree; /* Top of parse tree */
+} parser_state;
+
+parser_state *newparser PROTO((struct _grammar *g, int start));
+void delparser PROTO((parser_state *ps));
+int addtoken PROTO((parser_state *ps, int type, char *str, int lineno));
+void addaccelerators PROTO((grammar *g));
diff --git a/src/parsetok.c b/src/parsetok.c
new file mode 100644
index 0000000..e19a979
--- /dev/null
+++ b/src/parsetok.c
@@ -0,0 +1,158 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* Parser-tokenizer link implementation */
+
+#include "pgenheaders.h"
+#include "tokenizer.h"
+#include "node.h"
+#include "grammar.h"
+#include "parser.h"
+#include "parsetok.h"
+#include "errcode.h"
+
+
+/* Forward */
+static int parsetok PROTO((struct tok_state *, grammar *, int, node **));
+
+
+/* Parse input coming from a string. Return error code, print some errors. */
+
+int
+parsestring(s, g, start, n_ret)
+ char *s;
+ grammar *g;
+ int start;
+ node **n_ret;
+{
+ struct tok_state *tok = tok_setups(s);
+ int ret;
+
+ if (tok == NULL) {
+ fprintf(stderr, "no mem for tok_setups\n");
+ return E_NOMEM;
+ }
+ ret = parsetok(tok, g, start, n_ret);
+ if (ret == E_TOKEN || ret == E_SYNTAX) {
+ fprintf(stderr, "String parsing error at line %d\n",
+ tok->lineno);
+ }
+ tok_free(tok);
+ return ret;
+}
+
+
+/* Parse input coming from a file. Return error code, print some errors. */
+
+int
+parsefile(fp, filename, g, start, ps1, ps2, n_ret)
+ FILE *fp;
+ char *filename;
+ grammar *g;
+ int start;
+ char *ps1, *ps2;
+ node **n_ret;
+{
+ struct tok_state *tok = tok_setupf(fp, ps1, ps2);
+ int ret;
+
+ if (tok == NULL) {
+ fprintf(stderr, "no mem for tok_setupf\n");
+ return E_NOMEM;
+ }
+ ret = parsetok(tok, g, start, n_ret);
+ if (ret == E_TOKEN || ret == E_SYNTAX) {
+ char *p;
+ fprintf(stderr, "Parsing error: file %s, line %d:\n",
+ filename, tok->lineno);
+ *tok->inp = '\0';
+ if (tok->inp > tok->buf && tok->inp[-1] == '\n')
+ tok->inp[-1] = '\0';
+ fprintf(stderr, "%s\n", tok->buf);
+ for (p = tok->buf; p < tok->cur; p++) {
+ if (*p == '\t')
+ putc('\t', stderr);
+ else
+ putc(' ', stderr);
+ }
+ fprintf(stderr, "^\n");
+ }
+ tok_free(tok);
+ return ret;
+}
+
+
+/* Parse input coming from the given tokenizer structure.
+ Return error code. */
+
+static int
+parsetok(tok, g, start, n_ret)
+ struct tok_state *tok;
+ grammar *g;
+ int start;
+ node **n_ret;
+{
+ parser_state *ps;
+ int ret;
+
+ if ((ps = newparser(g, start)) == NULL) {
+ fprintf(stderr, "no mem for new parser\n");
+ return E_NOMEM;
+ }
+
+ for (;;) {
+ char *a, *b;
+ int type;
+ int len;
+ char *str;
+
+ type = tok_get(tok, &a, &b);
+ if (type == ERRORTOKEN) {
+ ret = tok->done;
+ break;
+ }
+ len = b - a;
+ str = NEW(char, len + 1);
+ if (str == NULL) {
+ fprintf(stderr, "no mem for next token\n");
+ ret = E_NOMEM;
+ break;
+ }
+ strncpy(str, a, len);
+ str[len] = '\0';
+ ret = addtoken(ps, (int)type, str, tok->lineno);
+ if (ret != E_OK) {
+ if (ret == E_DONE) {
+ *n_ret = ps->p_tree;
+ ps->p_tree = NULL;
+ }
+ else if (tok->lineno <= 1 && tok->done == E_EOF)
+ ret = E_EOF;
+ break;
+ }
+ }
+
+ delparser(ps);
+ return ret;
+}
diff --git a/src/parsetok.h b/src/parsetok.h
new file mode 100644
index 0000000..e05fdb5
--- /dev/null
+++ b/src/parsetok.h
@@ -0,0 +1,29 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* Parser-tokenizer link interface */
+
+extern int parsestring PROTO((char *, grammar *, int start, node **n_ret));
+extern int parsefile PROTO((FILE *, char *, grammar *, int start,
+ char *ps1, char *ps2, node **n_ret));
diff --git a/src/patchlevel.h b/src/patchlevel.h
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/src/patchlevel.h
@@ -0,0 +1 @@
+1
diff --git a/src/pgen.c b/src/pgen.c
new file mode 100644
index 0000000..6d3ecaf
--- /dev/null
+++ b/src/pgen.c
@@ -0,0 +1,751 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* Parser generator */
+/* XXX This file is not yet fully PROTOized */
+
+/* For a description, see the comments at end of this file */
+
+#include "pgenheaders.h"
+#include "assert.h"
+#include "token.h"
+#include "node.h"
+#include "grammar.h"
+#include "metagrammar.h"
+#include "pgen.h"
+
+extern int debugging;
+
+
+/* PART ONE -- CONSTRUCT NFA -- Cf. Algorithm 3.2 from [Aho&Ullman 77] */
+
+typedef struct _nfaarc {
+ int ar_label;
+ int ar_arrow;
+} nfaarc;
+
+typedef struct _nfastate {
+ int st_narcs;
+ nfaarc *st_arc;
+} nfastate;
+
+typedef struct _nfa {
+ int nf_type;
+ char *nf_name;
+ int nf_nstates;
+ nfastate *nf_state;
+ int nf_start, nf_finish;
+} nfa;
+
+static int
+addnfastate(nf)
+ nfa *nf;
+{
+ nfastate *st;
+
+ RESIZE(nf->nf_state, nfastate, nf->nf_nstates + 1);
+ if (nf->nf_state == NULL)
+ fatal("out of mem");
+ st = &nf->nf_state[nf->nf_nstates++];
+ st->st_narcs = 0;
+ st->st_arc = NULL;
+ return st - nf->nf_state;
+}
+
+static void
+addnfaarc(nf, from, to, lbl)
+ nfa *nf;
+ int from, to, lbl;
+{
+ nfastate *st;
+ nfaarc *ar;
+
+ st = &nf->nf_state[from];
+ RESIZE(st->st_arc, nfaarc, st->st_narcs + 1);
+ if (st->st_arc == NULL)
+ fatal("out of mem");
+ ar = &st->st_arc[st->st_narcs++];
+ ar->ar_label = lbl;
+ ar->ar_arrow = to;
+}
+
+static nfa *
+newnfa(name)
+ char *name;
+{
+ nfa *nf;
+ static type = NT_OFFSET; /* All types will be disjunct */
+
+ nf = NEW(nfa, 1);
+ if (nf == NULL)
+ fatal("no mem for new nfa");
+ nf->nf_type = type++;
+ nf->nf_name = name; /* XXX strdup(name) ??? */
+ nf->nf_nstates = 0;
+ nf->nf_state = NULL;
+ nf->nf_start = nf->nf_finish = -1;
+ return nf;
+}
+
+typedef struct _nfagrammar {
+ int gr_nnfas;
+ nfa **gr_nfa;
+ labellist gr_ll;
+} nfagrammar;
+
+static nfagrammar *
+newnfagrammar()
+{
+ nfagrammar *gr;
+
+ gr = NEW(nfagrammar, 1);
+ if (gr == NULL)
+ fatal("no mem for new nfa grammar");
+ gr->gr_nnfas = 0;
+ gr->gr_nfa = NULL;
+ gr->gr_ll.ll_nlabels = 0;
+ gr->gr_ll.ll_label = NULL;
+ addlabel(&gr->gr_ll, ENDMARKER, "EMPTY");
+ return gr;
+}
+
+static nfa *
+addnfa(gr, name)
+ nfagrammar *gr;
+ char *name;
+{
+ nfa *nf;
+
+ nf = newnfa(name);
+ RESIZE(gr->gr_nfa, nfa *, gr->gr_nnfas + 1);
+ if (gr->gr_nfa == NULL)
+ fatal("out of mem");
+ gr->gr_nfa[gr->gr_nnfas++] = nf;
+ addlabel(&gr->gr_ll, NAME, nf->nf_name);
+ return nf;
+}
+
+#ifdef DEBUG
+
+static char REQNFMT[] = "metacompile: less than %d children\n";
+
+#define REQN(i, count) \
+ if (i < count) { \
+ fprintf(stderr, REQNFMT, count); \
+ abort(); \
+ } else
+
+#else
+#define REQN(i, count) /* empty */
+#endif
+
+static nfagrammar *
+metacompile(n)
+ node *n;
+{
+ nfagrammar *gr;
+ int i;
+
+ printf("Compiling (meta-) parse tree into NFA grammar\n");
+ gr = newnfagrammar();
+ REQ(n, MSTART);
+ i = n->n_nchildren - 1; /* Last child is ENDMARKER */
+ n = n->n_child;
+ for (; --i >= 0; n++) {
+ if (n->n_type != NEWLINE)
+ compile_rule(gr, n);
+ }
+ return gr;
+}
+
+static
+compile_rule(gr, n)
+ nfagrammar *gr;
+ node *n;
+{
+ nfa *nf;
+
+ REQ(n, RULE);
+ REQN(n->n_nchildren, 4);
+ n = n->n_child;
+ REQ(n, NAME);
+ nf = addnfa(gr, n->n_str);
+ n++;
+ REQ(n, COLON);
+ n++;
+ REQ(n, RHS);
+ compile_rhs(&gr->gr_ll, nf, n, &nf->nf_start, &nf->nf_finish);
+ n++;
+ REQ(n, NEWLINE);
+}
+
+static
+compile_rhs(ll, nf, n, pa, pb)
+ labellist *ll;
+ nfa *nf;
+ node *n;
+ int *pa, *pb;
+{
+ int i;
+ int a, b;
+
+ REQ(n, RHS);
+ i = n->n_nchildren;
+ REQN(i, 1);
+ n = n->n_child;
+ REQ(n, ALT);
+ compile_alt(ll, nf, n, pa, pb);
+ if (--i <= 0)
+ return;
+ n++;
+ a = *pa;
+ b = *pb;
+ *pa = addnfastate(nf);
+ *pb = addnfastate(nf);
+ addnfaarc(nf, *pa, a, EMPTY);
+ addnfaarc(nf, b, *pb, EMPTY);
+ for (; --i >= 0; n++) {
+ REQ(n, VBAR);
+ REQN(i, 1);
+ --i;
+ n++;
+ REQ(n, ALT);
+ compile_alt(ll, nf, n, &a, &b);
+ addnfaarc(nf, *pa, a, EMPTY);
+ addnfaarc(nf, b, *pb, EMPTY);
+ }
+}
+
+static
+compile_alt(ll, nf, n, pa, pb)
+ labellist *ll;
+ nfa *nf;
+ node *n;
+ int *pa, *pb;
+{
+ int i;
+ int a, b;
+
+ REQ(n, ALT);
+ i = n->n_nchildren;
+ REQN(i, 1);
+ n = n->n_child;
+ REQ(n, ITEM);
+ compile_item(ll, nf, n, pa, pb);
+ --i;
+ n++;
+ for (; --i >= 0; n++) {
+ if (n->n_type == COMMA) { /* XXX Temporary */
+ REQN(i, 1);
+ --i;
+ n++;
+ }
+ REQ(n, ITEM);
+ compile_item(ll, nf, n, &a, &b);
+ addnfaarc(nf, *pb, a, EMPTY);
+ *pb = b;
+ }
+}
+
+static
+compile_item(ll, nf, n, pa, pb)
+ labellist *ll;
+ nfa *nf;
+ node *n;
+ int *pa, *pb;
+{
+ int i;
+ int a, b;
+
+ REQ(n, ITEM);
+ i = n->n_nchildren;
+ REQN(i, 1);
+ n = n->n_child;
+ if (n->n_type == LSQB) {
+ REQN(i, 3);
+ n++;
+ REQ(n, RHS);
+ *pa = addnfastate(nf);
+ *pb = addnfastate(nf);
+ addnfaarc(nf, *pa, *pb, EMPTY);
+ compile_rhs(ll, nf, n, &a, &b);
+ addnfaarc(nf, *pa, a, EMPTY);
+ addnfaarc(nf, b, *pb, EMPTY);
+ REQN(i, 1);
+ n++;
+ REQ(n, RSQB);
+ }
+ else {
+ compile_atom(ll, nf, n, pa, pb);
+ if (--i <= 0)
+ return;
+ n++;
+ addnfaarc(nf, *pb, *pa, EMPTY);
+ if (n->n_type == STAR)
+ *pb = *pa;
+ else
+ REQ(n, PLUS);
+ }
+}
+
+static
+compile_atom(ll, nf, n, pa, pb)
+ labellist *ll;
+ nfa *nf;
+ node *n;
+ int *pa, *pb;
+{
+ int i;
+
+ REQ(n, ATOM);
+ i = n->n_nchildren;
+ REQN(i, 1);
+ n = n->n_child;
+ if (n->n_type == LPAR) {
+ REQN(i, 3);
+ n++;
+ REQ(n, RHS);
+ compile_rhs(ll, nf, n, pa, pb);
+ n++;
+ REQ(n, RPAR);
+ }
+ else if (n->n_type == NAME || n->n_type == STRING) {
+ *pa = addnfastate(nf);
+ *pb = addnfastate(nf);
+ addnfaarc(nf, *pa, *pb, addlabel(ll, n->n_type, n->n_str));
+ }
+ else
+ REQ(n, NAME);
+}
+
+static void
+dumpstate(ll, nf, istate)
+ labellist *ll;
+ nfa *nf;
+ int istate;
+{
+ nfastate *st;
+ int i;
+ nfaarc *ar;
+
+ printf("%c%2d%c",
+ istate == nf->nf_start ? '*' : ' ',
+ istate,
+ istate == nf->nf_finish ? '.' : ' ');
+ st = &nf->nf_state[istate];
+ ar = st->st_arc;
+ for (i = 0; i < st->st_narcs; i++) {
+ if (i > 0)
+ printf("\n ");
+ printf("-> %2d %s", ar->ar_arrow,
+ labelrepr(&ll->ll_label[ar->ar_label]));
+ ar++;
+ }
+ printf("\n");
+}
+
+static void
+dumpnfa(ll, nf)
+ labellist *ll;
+ nfa *nf;
+{
+ int i;
+
+ printf("NFA '%s' has %d states; start %d, finish %d\n",
+ nf->nf_name, nf->nf_nstates, nf->nf_start, nf->nf_finish);
+ for (i = 0; i < nf->nf_nstates; i++)
+ dumpstate(ll, nf, i);
+}
+
+
+/* PART TWO -- CONSTRUCT DFA -- Algorithm 3.1 from [Aho&Ullman 77] */
+
+static int
+addclosure(ss, nf, istate)
+ bitset ss;
+ nfa *nf;
+ int istate;
+{
+ if (addbit(ss, istate)) {
+ nfastate *st = &nf->nf_state[istate];
+ nfaarc *ar = st->st_arc;
+ int i;
+
+ for (i = st->st_narcs; --i >= 0; ) {
+ if (ar->ar_label == EMPTY)
+ addclosure(ss, nf, ar->ar_arrow);
+ ar++;
+ }
+ }
+}
+
+typedef struct _ss_arc {
+ bitset sa_bitset;
+ int sa_arrow;
+ int sa_label;
+} ss_arc;
+
+typedef struct _ss_state {
+ bitset ss_ss;
+ int ss_narcs;
+ ss_arc *ss_arc;
+ int ss_deleted;
+ int ss_finish;
+ int ss_rename;
+} ss_state;
+
+typedef struct _ss_dfa {
+ int sd_nstates;
+ ss_state *sd_state;
+} ss_dfa;
+
+static
+makedfa(gr, nf, d)
+ nfagrammar *gr;
+ nfa *nf;
+ dfa *d;
+{
+ int nbits = nf->nf_nstates;
+ bitset ss;
+ int xx_nstates;
+ ss_state *xx_state, *yy;
+ ss_arc *zz;
+ int istate, jstate, iarc, jarc, ibit;
+ nfastate *st;
+ nfaarc *ar;
+
+ ss = newbitset(nbits);
+ addclosure(ss, nf, nf->nf_start);
+ xx_state = NEW(ss_state, 1);
+ if (xx_state == NULL)
+ fatal("no mem for xx_state in makedfa");
+ xx_nstates = 1;
+ yy = &xx_state[0];
+ yy->ss_ss = ss;
+ yy->ss_narcs = 0;
+ yy->ss_arc = NULL;
+ yy->ss_deleted = 0;
+ yy->ss_finish = testbit(ss, nf->nf_finish);
+ if (yy->ss_finish)
+ printf("Error: nonterminal '%s' may produce empty.\n",
+ nf->nf_name);
+
+ /* This algorithm is from a book written before
+ the invention of structured programming... */
+
+ /* For each unmarked state... */
+ for (istate = 0; istate < xx_nstates; ++istate) {
+ yy = &xx_state[istate];
+ ss = yy->ss_ss;
+ /* For all its states... */
+ for (ibit = 0; ibit < nf->nf_nstates; ++ibit) {
+ if (!testbit(ss, ibit))
+ continue;
+ st = &nf->nf_state[ibit];
+ /* For all non-empty arcs from this state... */
+ for (iarc = 0; iarc < st->st_narcs; iarc++) {
+ ar = &st->st_arc[iarc];
+ if (ar->ar_label == EMPTY)
+ continue;
+ /* Look up in list of arcs from this state */
+ for (jarc = 0; jarc < yy->ss_narcs; ++jarc) {
+ zz = &yy->ss_arc[jarc];
+ if (ar->ar_label == zz->sa_label)
+ goto found;
+ }
+ /* Add new arc for this state */
+ RESIZE(yy->ss_arc, ss_arc, yy->ss_narcs + 1);
+ if (yy->ss_arc == NULL)
+ fatal("out of mem");
+ zz = &yy->ss_arc[yy->ss_narcs++];
+ zz->sa_label = ar->ar_label;
+ zz->sa_bitset = newbitset(nbits);
+ zz->sa_arrow = -1;
+ found: ;
+ /* Add destination */
+ addclosure(zz->sa_bitset, nf, ar->ar_arrow);
+ }
+ }
+ /* Now look up all the arrow states */
+ for (jarc = 0; jarc < xx_state[istate].ss_narcs; jarc++) {
+ zz = &xx_state[istate].ss_arc[jarc];
+ for (jstate = 0; jstate < xx_nstates; jstate++) {
+ if (samebitset(zz->sa_bitset,
+ xx_state[jstate].ss_ss, nbits)) {
+ zz->sa_arrow = jstate;
+ goto done;
+ }
+ }
+ RESIZE(xx_state, ss_state, xx_nstates + 1);
+ if (xx_state == NULL)
+ fatal("out of mem");
+ zz->sa_arrow = xx_nstates;
+ yy = &xx_state[xx_nstates++];
+ yy->ss_ss = zz->sa_bitset;
+ yy->ss_narcs = 0;
+ yy->ss_arc = NULL;
+ yy->ss_deleted = 0;
+ yy->ss_finish = testbit(yy->ss_ss, nf->nf_finish);
+ done: ;
+ }
+ }
+
+ if (debugging)
+ printssdfa(xx_nstates, xx_state, nbits, &gr->gr_ll,
+ "before minimizing");
+
+ simplify(xx_nstates, xx_state);
+
+ if (debugging)
+ printssdfa(xx_nstates, xx_state, nbits, &gr->gr_ll,
+ "after minimizing");
+
+ convert(d, xx_nstates, xx_state);
+
+ /* XXX cleanup */
+}
+
+static
+printssdfa(xx_nstates, xx_state, nbits, ll, msg)
+ int xx_nstates;
+ ss_state *xx_state;
+ int nbits;
+ labellist *ll;
+ char *msg;
+{
+ int i, ibit, iarc;
+ ss_state *yy;
+ ss_arc *zz;
+
+ printf("Subset DFA %s\n", msg);
+ for (i = 0; i < xx_nstates; i++) {
+ yy = &xx_state[i];
+ if (yy->ss_deleted)
+ continue;
+ printf(" Subset %d", i);
+ if (yy->ss_finish)
+ printf(" (finish)");
+ printf(" { ");
+ for (ibit = 0; ibit < nbits; ibit++) {
+ if (testbit(yy->ss_ss, ibit))
+ printf("%d ", ibit);
+ }
+ printf("}\n");
+ for (iarc = 0; iarc < yy->ss_narcs; iarc++) {
+ zz = &yy->ss_arc[iarc];
+ printf(" Arc to state %d, label %s\n",
+ zz->sa_arrow,
+ labelrepr(&ll->ll_label[zz->sa_label]));
+ }
+ }
+}
+
+
+/* PART THREE -- SIMPLIFY DFA */
+
+/* Simplify the DFA by repeatedly eliminating states that are
+ equivalent to another oner. This is NOT Algorithm 3.3 from
+ [Aho&Ullman 77]. It does not always finds the minimal DFA,
+ but it does usually make a much smaller one... (For an example
+ of sub-optimal behaviour, try S: x a b+ | y a b+.)
+*/
+
+static int
+samestate(s1, s2)
+ ss_state *s1, *s2;
+{
+ int i;
+
+ if (s1->ss_narcs != s2->ss_narcs || s1->ss_finish != s2->ss_finish)
+ return 0;
+ for (i = 0; i < s1->ss_narcs; i++) {
+ if (s1->ss_arc[i].sa_arrow != s2->ss_arc[i].sa_arrow ||
+ s1->ss_arc[i].sa_label != s2->ss_arc[i].sa_label)
+ return 0;
+ }
+ return 1;
+}
+
+static void
+renamestates(xx_nstates, xx_state, from, to)
+ int xx_nstates;
+ ss_state *xx_state;
+ int from, to;
+{
+ int i, j;
+
+ if (debugging)
+ printf("Rename state %d to %d.\n", from, to);
+ for (i = 0; i < xx_nstates; i++) {
+ if (xx_state[i].ss_deleted)
+ continue;
+ for (j = 0; j < xx_state[i].ss_narcs; j++) {
+ if (xx_state[i].ss_arc[j].sa_arrow == from)
+ xx_state[i].ss_arc[j].sa_arrow = to;
+ }
+ }
+}
+
+static
+simplify(xx_nstates, xx_state)
+ int xx_nstates;
+ ss_state *xx_state;
+{
+ int changes;
+ int i, j, k;
+
+ do {
+ changes = 0;
+ for (i = 1; i < xx_nstates; i++) {
+ if (xx_state[i].ss_deleted)
+ continue;
+ for (j = 0; j < i; j++) {
+ if (xx_state[j].ss_deleted)
+ continue;
+ if (samestate(&xx_state[i], &xx_state[j])) {
+ xx_state[i].ss_deleted++;
+ renamestates(xx_nstates, xx_state, i, j);
+ changes++;
+ break;
+ }
+ }
+ }
+ } while (changes);
+}
+
+
+/* PART FOUR -- GENERATE PARSING TABLES */
+
+/* Convert the DFA into a grammar that can be used by our parser */
+
+static
+convert(d, xx_nstates, xx_state)
+ dfa *d;
+ int xx_nstates;
+ ss_state *xx_state;
+{
+ int i, j;
+ ss_state *yy;
+ ss_arc *zz;
+
+ for (i = 0; i < xx_nstates; i++) {
+ yy = &xx_state[i];
+ if (yy->ss_deleted)
+ continue;
+ yy->ss_rename = addstate(d);
+ }
+
+ for (i = 0; i < xx_nstates; i++) {
+ yy = &xx_state[i];
+ if (yy->ss_deleted)
+ continue;
+ for (j = 0; j < yy->ss_narcs; j++) {
+ zz = &yy->ss_arc[j];
+ addarc(d, yy->ss_rename,
+ xx_state[zz->sa_arrow].ss_rename,
+ zz->sa_label);
+ }
+ if (yy->ss_finish)
+ addarc(d, yy->ss_rename, yy->ss_rename, 0);
+ }
+
+ d->d_initial = 0;
+}
+
+
+/* PART FIVE -- GLUE IT ALL TOGETHER */
+
+static grammar *
+maketables(gr)
+ nfagrammar *gr;
+{
+ int i;
+ nfa *nf;
+ dfa *d;
+ grammar *g;
+
+ if (gr->gr_nnfas == 0)
+ return NULL;
+ g = newgrammar(gr->gr_nfa[0]->nf_type);
+ /* XXX first rule must be start rule */
+ g->g_ll = gr->gr_ll;
+
+ for (i = 0; i < gr->gr_nnfas; i++) {
+ nf = gr->gr_nfa[i];
+ if (debugging) {
+ printf("Dump of NFA for '%s' ...\n", nf->nf_name);
+ dumpnfa(&gr->gr_ll, nf);
+ }
+ printf("Making DFA for '%s' ...\n", nf->nf_name);
+ d = adddfa(g, nf->nf_type, nf->nf_name);
+ makedfa(gr, gr->gr_nfa[i], d);
+ }
+
+ return g;
+}
+
+grammar *
+pgen(n)
+ node *n;
+{
+ nfagrammar *gr;
+ grammar *g;
+
+ gr = metacompile(n);
+ g = maketables(gr);
+ translatelabels(g);
+ addfirstsets(g);
+ return g;
+}
+
+
+/*
+
+Description
+-----------
+
+Input is a grammar in extended BNF (using * for repetition, + for
+at-least-once repetition, [] for optional parts, | for alternatives and
+() for grouping). This has already been parsed and turned into a parse
+tree.
+
+Each rule is considered as a regular expression in its own right.
+It is turned into a Non-deterministic Finite Automaton (NFA), which
+is then turned into a Deterministic Finite Automaton (DFA), which is then
+optimized to reduce the number of states. See [Aho&Ullman 77] chapter 3,
+or similar compiler books (this technique is more often used for lexical
+analyzers).
+
+The DFA's are used by the parser as parsing tables in a special way
+that's probably unique. Before they are usable, the FIRST sets of all
+non-terminals are computed.
+
+Reference
+---------
+
+[Aho&Ullman 77]
+ Aho&Ullman, Principles of Compiler Design, Addison-Wesley 1977
+ (first edition)
+
+*/
diff --git a/src/pgen.h b/src/pgen.h
new file mode 100644
index 0000000..940bf9a
--- /dev/null
+++ b/src/pgen.h
@@ -0,0 +1,30 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* Parser generator interface */
+
+extern grammar gram;
+
+extern grammar *meta_grammar PROTO((void));
+extern grammar *pgen PROTO((struct _node *));
diff --git a/src/pgenheaders.h b/src/pgenheaders.h
new file mode 100644
index 0000000..059915a
--- /dev/null
+++ b/src/pgenheaders.h
@@ -0,0 +1,50 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* Include files and extern declarations used by most of the parser.
+ This is a precompiled header for THINK C. */
+
+#include <stdio.h>
+#include <string.h>
+
+#ifdef THINK_C
+/* #define THINK_C_3_0 /*** TURN THIS ON FOR THINK C 3.0 ****/
+#define label label_
+#undef label
+#endif
+
+#ifdef THINK_C_3_0
+#include <proto.h>
+#endif
+
+#ifdef THINK_C
+#ifndef THINK_C_3_0
+#include <stdlib.h>
+#endif
+#endif
+
+#include "PROTO.h"
+#include "malloc.h"
+
+extern void fatal PROTO((char *));
diff --git a/src/pgenmain.c b/src/pgenmain.c
new file mode 100644
index 0000000..80f6f2d
--- /dev/null
+++ b/src/pgenmain.c
@@ -0,0 +1,148 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* Parser generator main program */
+
+/* This expects a filename containing the grammar as argv[1] (UNIX)
+ or asks the console for such a file name (THINK C).
+ It writes its output on two files in the current directory:
+ - "graminit.c" gets the grammar as a bunch of initialized data
+ - "graminit.h" gets the grammar's non-terminals as #defines.
+ Error messages and status info during the generation process are
+ written to stdout, or sometimes to stderr. */
+
+#include "pgenheaders.h"
+#include "grammar.h"
+#include "node.h"
+#include "parsetok.h"
+#include "pgen.h"
+
+int debugging;
+
+/* Forward */
+grammar *getgrammar PROTO((char *filename));
+#ifdef THINK_C
+int main PROTO((int, char **));
+char *askfile PROTO((void));
+#endif
+
+int
+main(argc, argv)
+ int argc;
+ char **argv;
+{
+ grammar *g;
+ node *n;
+ FILE *fp;
+ char *filename;
+
+#ifdef THINK_C
+ filename = askfile();
+#else
+ if (argc != 2) {
+ fprintf(stderr, "usage: %s grammar\n", argv[0]);
+ exit(2);
+ }
+ filename = argv[1];
+#endif
+ g = getgrammar(filename);
+ fp = fopen("graminit.c", "w");
+ if (fp == NULL) {
+ perror("graminit.c");
+ exit(1);
+ }
+ printf("Writing graminit.c ...\n");
+ printgrammar(g, fp);
+ fclose(fp);
+ fp = fopen("graminit.h", "w");
+ if (fp == NULL) {
+ perror("graminit.h");
+ exit(1);
+ }
+ printf("Writing graminit.h ...\n");
+ printnonterminals(g, fp);
+ fclose(fp);
+ exit(0);
+}
+
+grammar *
+getgrammar(filename)
+ char *filename;
+{
+ FILE *fp;
+ node *n;
+ grammar *g0, *g;
+
+ fp = fopen(filename, "r");
+ if (fp == NULL) {
+ perror(filename);
+ exit(1);
+ }
+ g0 = meta_grammar();
+ n = NULL;
+ parsefile(fp, filename, g0, g0->g_start, (char *)NULL, (char *)NULL, &n);
+ fclose(fp);
+ if (n == NULL) {
+ fprintf(stderr, "Parsing error.\n");
+ exit(1);
+ }
+ g = pgen(n);
+ if (g == NULL) {
+ printf("Bad grammar.\n");
+ exit(1);
+ }
+ return g;
+}
+
+#ifdef THINK_C
+char *
+askfile()
+{
+ char buf[256];
+ static char name[256];
+ printf("Input file name: ");
+ if (fgets(buf, sizeof buf, stdin) == NULL) {
+ printf("EOF\n");
+ exit(1);
+ }
+ /* XXX The (unsigned char *) case is needed by THINK C 3.0 */
+ if (sscanf(/*(unsigned char *)*/buf, " %s ", name) != 1) {
+ printf("No file\n");
+ exit(1);
+ }
+ return name;
+}
+#endif
+
+void
+fatal(msg)
+ char *msg;
+{
+ fprintf(stderr, "pgen: FATAL ERROR: %s\n", msg);
+ exit(1);
+}
+
+/* XXX TO DO:
+ - check for duplicate definitions of names (instead of fatal err)
+*/
diff --git a/src/posixmodule.c b/src/posixmodule.c
new file mode 100644
index 0000000..9729376
--- /dev/null
+++ b/src/posixmodule.c
@@ -0,0 +1,427 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* POSIX module implementation */
+
+#include <signal.h>
+#include <string.h>
+#include <setjmp.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#ifdef SYSV
+#include <dirent.h>
+#define direct dirent
+#else
+#include <sys/dir.h>
+#endif
+
+#include "allobjects.h"
+#include "modsupport.h"
+
+extern char *strerror PROTO((int));
+
+#ifdef AMOEBA
+#define NO_LSTAT
+#endif
+
+
+/* Return a dictionary corresponding to the POSIX environment table */
+
+extern char **environ;
+
+static object *
+convertenviron()
+{
+ object *d;
+ char **e;
+ d = newdictobject();
+ if (d == NULL)
+ return NULL;
+ if (environ == NULL)
+ return d;
+ /* XXX This part ignores errors */
+ for (e = environ; *e != NULL; e++) {
+ object *v;
+ char *p = strchr(*e, '=');
+ if (p == NULL)
+ continue;
+ v = newstringobject(p+1);
+ if (v == NULL)
+ continue;
+ *p = '\0';
+ (void) dictinsert(d, *e, v);
+ *p = '=';
+ DECREF(v);
+ }
+ return d;
+}
+
+
+static object *PosixError; /* Exception posix.error */
+
+/* Set a POSIX-specific error from errno, and return NULL */
+
+static object *
+posix_error()
+{
+ return err_errno(PosixError);
+}
+
+
+/* POSIX generic methods */
+
+static object *
+posix_1str(args, func)
+ object *args;
+ int (*func) FPROTO((const char *));
+{
+ object *path1;
+ if (!getstrarg(args, &path1))
+ return NULL;
+ if ((*func)(getstringvalue(path1)) < 0)
+ return posix_error();
+ INCREF(None);
+ return None;
+}
+
+static object *
+posix_2str(args, func)
+ object *args;
+ int (*func) FPROTO((const char *, const char *));
+{
+ object *path1, *path2;
+ if (!getstrstrarg(args, &path1, &path2))
+ return NULL;
+ if ((*func)(getstringvalue(path1), getstringvalue(path2)) < 0)
+ return posix_error();
+ INCREF(None);
+ return None;
+}
+
+static object *
+posix_strint(args, func)
+ object *args;
+ int (*func) FPROTO((const char *, int));
+{
+ object *path1;
+ int i;
+ if (!getstrintarg(args, &path1, &i))
+ return NULL;
+ if ((*func)(getstringvalue(path1), i) < 0)
+ return posix_error();
+ INCREF(None);
+ return None;
+}
+
+static object *
+posix_do_stat(self, args, statfunc)
+ object *self;
+ object *args;
+ int (*statfunc) FPROTO((const char *, struct stat *));
+{
+ struct stat st;
+ object *path;
+ object *v;
+ if (!getstrarg(args, &path))
+ return NULL;
+ if ((*statfunc)(getstringvalue(path), &st) != 0)
+ return posix_error();
+ v = newtupleobject(10);
+ if (v == NULL)
+ return NULL;
+#define SET(i, st_member) settupleitem(v, i, newintobject((long)st.st_member))
+ SET(0, st_mode);
+ SET(1, st_ino);
+ SET(2, st_dev);
+ SET(3, st_nlink);
+ SET(4, st_uid);
+ SET(5, st_gid);
+ SET(6, st_size);
+ SET(7, st_atime);
+ SET(8, st_mtime);
+ SET(9, st_ctime);
+#undef SET
+ if (err_occurred()) {
+ DECREF(v);
+ return NULL;
+ }
+ return v;
+}
+
+
+/* POSIX methods */
+
+static object *
+posix_chdir(self, args)
+ object *self;
+ object *args;
+{
+ extern int chdir PROTO((const char *));
+ return posix_1str(args, chdir);
+}
+
+static object *
+posix_chmod(self, args)
+ object *self;
+ object *args;
+{
+ extern int chmod PROTO((const char *, mode_t));
+ return posix_strint(args, chmod);
+}
+
+static object *
+posix_getcwd(self, args)
+ object *self;
+ object *args;
+{
+ char buf[1026];
+ extern char *getcwd PROTO((char *, int));
+ if (!getnoarg(args))
+ return NULL;
+ if (getcwd(buf, sizeof buf) == NULL)
+ return posix_error();
+ return newstringobject(buf);
+}
+
+static object *
+posix_link(self, args)
+ object *self;
+ object *args;
+{
+ extern int link PROTO((const char *, const char *));
+ return posix_2str(args, link);
+}
+
+static object *
+posix_listdir(self, args)
+ object *self;
+ object *args;
+{
+ object *name, *d, *v;
+ DIR *dirp;
+ struct direct *ep;
+ if (!getstrarg(args, &name))
+ return NULL;
+ if ((dirp = opendir(getstringvalue(name))) == NULL)
+ return posix_error();
+ if ((d = newlistobject(0)) == NULL) {
+ closedir(dirp);
+ return NULL;
+ }
+ while ((ep = readdir(dirp)) != NULL) {
+ v = newstringobject(ep->d_name);
+ if (v == NULL) {
+ DECREF(d);
+ d = NULL;
+ break;
+ }
+ if (addlistitem(d, v) != 0) {
+ DECREF(v);
+ DECREF(d);
+ d = NULL;
+ break;
+ }
+ DECREF(v);
+ }
+ closedir(dirp);
+ return d;
+}
+
+static object *
+posix_mkdir(self, args)
+ object *self;
+ object *args;
+{
+ extern int mkdir PROTO((const char *, mode_t));
+ return posix_strint(args, mkdir);
+}
+
+static object *
+posix_rename(self, args)
+ object *self;
+ object *args;
+{
+ extern int rename PROTO((const char *, const char *));
+ return posix_2str(args, rename);
+}
+
+static object *
+posix_rmdir(self, args)
+ object *self;
+ object *args;
+{
+ extern int rmdir PROTO((const char *));
+ return posix_1str(args, rmdir);
+}
+
+static object *
+posix_stat(self, args)
+ object *self;
+ object *args;
+{
+ extern int stat PROTO((const char *, struct stat *));
+ return posix_do_stat(self, args, stat);
+}
+
+static object *
+posix_system(self, args)
+ object *self;
+ object *args;
+{
+ object *command;
+ int sts;
+ if (!getstrarg(args, &command))
+ return NULL;
+ sts = system(getstringvalue(command));
+ return newintobject((long)sts);
+}
+
+static object *
+posix_umask(self, args)
+ object *self;
+ object *args;
+{
+ int i;
+ if (!getintarg(args, &i))
+ return NULL;
+ i = umask(i);
+ if (i < 0)
+ return posix_error();
+ return newintobject((long)i);
+}
+
+static object *
+posix_unlink(self, args)
+ object *self;
+ object *args;
+{
+ extern int unlink PROTO((const char *));
+ return posix_1str(args, unlink);
+}
+
+static object *
+posix_utimes(self, args)
+ object *self;
+ object *args;
+{
+ object *path;
+ struct timeval tv[2];
+ if (args == NULL || !is_tupleobject(args) || gettuplesize(args) != 2) {
+ err_badarg();
+ return NULL;
+ }
+ if (!getstrarg(gettupleitem(args, 0), &path) ||
+ !getlonglongargs(gettupleitem(args, 1),
+ &tv[0].tv_sec, &tv[1].tv_sec))
+ return NULL;
+ tv[0].tv_usec = tv[1].tv_usec = 0;
+ if (utimes(getstringvalue(path), tv) < 0)
+ return posix_error();
+ INCREF(None);
+ return None;
+}
+
+
+#ifndef NO_LSTAT
+
+static object *
+posix_lstat(self, args)
+ object *self;
+ object *args;
+{
+ extern int lstat PROTO((const char *, struct stat *));
+ return posix_do_stat(self, args, lstat);
+}
+
+static object *
+posix_readlink(self, args)
+ object *self;
+ object *args;
+{
+ char buf[1024]; /* XXX Should use MAXPATHLEN */
+ object *path;
+ int n;
+ if (!getstrarg(args, &path))
+ return NULL;
+ n = readlink(getstringvalue(path), buf, sizeof buf);
+ if (n < 0)
+ return posix_error();
+ return newsizedstringobject(buf, n);
+}
+
+static object *
+posix_symlink(self, args)
+ object *self;
+ object *args;
+{
+ extern int symlink PROTO((const char *, const char *));
+ return posix_2str(args, symlink);
+}
+
+#endif /* NO_LSTAT */
+
+
+static struct methodlist posix_methods[] = {
+ {"chdir", posix_chdir},
+ {"chmod", posix_chmod},
+ {"getcwd", posix_getcwd},
+ {"link", posix_link},
+ {"listdir", posix_listdir},
+ {"mkdir", posix_mkdir},
+ {"rename", posix_rename},
+ {"rmdir", posix_rmdir},
+ {"stat", posix_stat},
+ {"system", posix_system},
+ {"umask", posix_umask},
+ {"unlink", posix_unlink},
+ {"utimes", posix_utimes},
+#ifndef NO_LSTAT
+ {"lstat", posix_lstat},
+ {"readlink", posix_readlink},
+ {"symlink", posix_symlink},
+#endif
+ {NULL, NULL} /* Sentinel */
+};
+
+
+void
+initposix()
+{
+ object *m, *d, *v;
+
+ m = initmodule("posix", posix_methods);
+ d = getmoduledict(m);
+
+ /* Initialize posix.environ dictionary */
+ v = convertenviron();
+ if (v == NULL || dictinsert(d, "environ", v) != 0)
+ fatal("can't define posix.environ");
+ DECREF(v);
+
+ /* Initialize posix.error exception */
+ PosixError = newstringobject("posix.error");
+ if (PosixError == NULL || dictinsert(d, "error", PosixError) != 0)
+ fatal("can't define posix.error");
+}
diff --git a/src/printgrammar.c b/src/printgrammar.c
new file mode 100644
index 0000000..c48262d
--- /dev/null
+++ b/src/printgrammar.c
@@ -0,0 +1,149 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* Print a bunch of C initializers that represent a grammar */
+
+#include "pgenheaders.h"
+#include "grammar.h"
+
+/* Forward */
+static void printarcs PROTO((int, dfa *, FILE *));
+static void printstates PROTO((grammar *, FILE *));
+static void printdfas PROTO((grammar *, FILE *));
+static void printlabels PROTO((grammar *, FILE *));
+
+void
+printgrammar(g, fp)
+ grammar *g;
+ FILE *fp;
+{
+ fprintf(fp, "#include \"pgenheaders.h\"\n");
+ fprintf(fp, "#include \"grammar.h\"\n");
+ printdfas(g, fp);
+ printlabels(g, fp);
+ fprintf(fp, "grammar gram = {\n");
+ fprintf(fp, "\t%d,\n", g->g_ndfas);
+ fprintf(fp, "\tdfas,\n");
+ fprintf(fp, "\t{%d, labels},\n", g->g_ll.ll_nlabels);
+ fprintf(fp, "\t%d\n", g->g_start);
+ fprintf(fp, "};\n");
+}
+
+void
+printnonterminals(g, fp)
+ grammar *g;
+ FILE *fp;
+{
+ dfa *d;
+ int i;
+
+ d = g->g_dfa;
+ for (i = g->g_ndfas; --i >= 0; d++)
+ fprintf(fp, "#define %s %d\n", d->d_name, d->d_type);
+}
+
+static void
+printarcs(i, d, fp)
+ int i;
+ dfa *d;
+ FILE *fp;
+{
+ arc *a;
+ state *s;
+ int j, k;
+
+ s = d->d_state;
+ for (j = 0; j < d->d_nstates; j++, s++) {
+ fprintf(fp, "static arc arcs_%d_%d[%d] = {\n",
+ i, j, s->s_narcs);
+ a = s->s_arc;
+ for (k = 0; k < s->s_narcs; k++, a++)
+ fprintf(fp, "\t{%d, %d},\n", a->a_lbl, a->a_arrow);
+ fprintf(fp, "};\n");
+ }
+}
+
+static void
+printstates(g, fp)
+ grammar *g;
+ FILE *fp;
+{
+ state *s;
+ dfa *d;
+ int i, j;
+
+ d = g->g_dfa;
+ for (i = 0; i < g->g_ndfas; i++, d++) {
+ printarcs(i, d, fp);
+ fprintf(fp, "static state states_%d[%d] = {\n",
+ i, d->d_nstates);
+ s = d->d_state;
+ for (j = 0; j < d->d_nstates; j++, s++)
+ fprintf(fp, "\t{%d, arcs_%d_%d},\n",
+ s->s_narcs, i, j);
+ fprintf(fp, "};\n");
+ }
+}
+
+static void
+printdfas(g, fp)
+ grammar *g;
+ FILE *fp;
+{
+ dfa *d;
+ int i, j;
+
+ printstates(g, fp);
+ fprintf(fp, "static dfa dfas[%d] = {\n", g->g_ndfas);
+ d = g->g_dfa;
+ for (i = 0; i < g->g_ndfas; i++, d++) {
+ fprintf(fp, "\t{%d, \"%s\", %d, %d, states_%d,\n",
+ d->d_type, d->d_name, d->d_initial, d->d_nstates, i);
+ fprintf(fp, "\t \"");
+ for (j = 0; j < NBYTES(g->g_ll.ll_nlabels); j++)
+ fprintf(fp, "\\%03o", d->d_first[j] & 0xff);
+ fprintf(fp, "\"},\n");
+ }
+ fprintf(fp, "};\n");
+}
+
+static void
+printlabels(g, fp)
+ grammar *g;
+ FILE *fp;
+{
+ label *l;
+ int i;
+
+ fprintf(fp, "static label labels[%d] = {\n", g->g_ll.ll_nlabels);
+ l = g->g_ll.ll_label;
+ for (i = g->g_ll.ll_nlabels; --i >= 0; l++) {
+ if (l->lb_str == NULL)
+ fprintf(fp, "\t{%d, 0},\n", l->lb_type);
+ else
+ fprintf(fp, "\t{%d, \"%s\"},\n",
+ l->lb_type, l->lb_str);
+ }
+ fprintf(fp, "};\n");
+}
diff --git a/src/profmain.c b/src/profmain.c
new file mode 100644
index 0000000..eff57bf
--- /dev/null
+++ b/src/profmain.c
@@ -0,0 +1,133 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+#include <stdio.h>
+#include "string.h"
+
+#include "PROTO.h"
+#include "grammar.h"
+#include "node.h"
+#include "parsetok.h"
+#include "graminit.h"
+#include "tokenizer.h"
+#include "errcode.h"
+#include "malloc.h"
+
+extern int _profile;
+
+extern grammar gram; /* From graminit.c */
+
+int debugging = 1;
+
+FILE *getopenfile()
+{
+ char buf[256];
+ char *p;
+ FILE *fp;
+ for (;;) {
+ fprintf(stderr, "File name: ");
+ if (fgets(buf, sizeof buf, stdin) == NULL) {
+ fprintf(stderr, "EOF\n");
+ exit(1);
+ }
+ p = strchr(buf, '\n');
+ if (p != NULL)
+ *p = '\0';
+ if ((fp = fopen(buf, "r")) != NULL)
+ break;
+ fprintf(stderr, "Sorry, try again.\n");
+ }
+ return fp;
+}
+
+main()
+{
+ FILE *fp;
+ _profile = 0;
+ fp = getopenfile();
+#if 0
+ askgo("Start tokenizing");
+ runtokenizer(fp);
+ fseek(fp, 0L, 0);
+#endif
+ if (!gram.g_accel)
+ addaccelerators(&gram);
+ askgo("Start parsing");
+ _profile = 1;
+ runparser(fp);
+ _profile = 0;
+ freopen("prof.out", "w", stdout);
+ DumpProfile();
+ fflush(stdout);
+ exit(0);
+}
+
+static int
+runtokenizer(fp)
+ FILE *fp;
+{
+ struct tok_state *tok;
+ tok = tok_setupf(fp, "Tokenizing", ".");
+ for (;;) {
+ char *a, *b;
+ register char *str;
+ register int len;
+ (void) tok_get(tok, &a, &b);
+ if (tok->done != E_OK)
+ break;
+ len = b - a;
+ str = NEW(char, len + 1);
+ if (str == NULL) {
+ fprintf(stderr, "no mem for next token");
+ break;
+ }
+ strncpy(str, a, len);
+ str[len] = '\0';
+ }
+ fprintf(stderr, "done (%d)\n", tok->done);
+}
+
+static
+runparser(fp, start)
+ FILE *fp;
+{
+ node *n;
+ int ret;
+ ret = parsefile(fp, &gram, module_input, "Parsing", ".", &n);
+ fprintf(stderr, "done (%d)\n", ret);
+#if 0
+ _profile = 0;
+ if (ret == E_DONE)
+ listtree(n);
+#endif
+}
+
+static int
+askgo(prompt)
+ char *prompt;
+{
+ char buf[256];
+ fprintf(stderr, "%s: hit return when ready: ", prompt);
+ fgets(buf, sizeof buf, stdin);
+}
diff --git a/src/pythonmain.c b/src/pythonmain.c
new file mode 100644
index 0000000..8c86d8c
--- /dev/null
+++ b/src/pythonmain.c
@@ -0,0 +1,440 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* Python interpreter main program */
+
+#include "patchlevel.h"
+
+#include "allobjects.h"
+
+#include "grammar.h"
+#include "node.h"
+#include "parsetok.h"
+#include "graminit.h"
+#include "errcode.h"
+#include "sysmodule.h"
+#include "compile.h"
+#include "ceval.h"
+#include "pythonrun.h"
+#include "import.h"
+
+extern char *getpythonpath();
+
+extern grammar gram; /* From graminit.c */
+
+#ifdef DEBUG
+int debugging; /* Needed by parser.c */
+#endif
+
+main(argc, argv)
+ int argc;
+ char **argv;
+{
+ char *filename = NULL;
+ FILE *fp = stdin;
+
+ initargs(&argc, &argv);
+
+ if (argc > 1 && strcmp(argv[1], "-") != 0)
+ filename = argv[1];
+
+ if (filename != NULL) {
+ if ((fp = fopen(filename, "r")) == NULL) {
+ fprintf(stderr, "python: can't open file '%s'\n",
+ filename);
+ exit(2);
+ }
+ }
+
+ initall();
+
+ setpythonpath(getpythonpath());
+ setpythonargv(argc-1, argv+1);
+
+ goaway(run(fp, filename == NULL ? "<stdin>" : filename));
+ /*NOTREACHED*/
+}
+
+/* Initialize all */
+
+void
+initall()
+{
+ static int inited;
+
+ if (inited)
+ return;
+ inited = 1;
+
+ initimport();
+
+ /* Modules 'builtin' and 'sys' are initialized here,
+ they are needed by random bits of the interpreter.
+ All other modules are optional and should be initialized
+ by the initcalls() of a specific configuration. */
+
+ initbuiltin(); /* Also initializes builtin exceptions */
+ initsys();
+
+ initcalls(); /* Configuration-dependent initializations */
+
+ initintr(); /* For intrcheck() */
+}
+
+/* Parse input from a file and execute it */
+
+int
+run(fp, filename)
+ FILE *fp;
+ char *filename;
+{
+ if (filename == NULL)
+ filename = "???";
+ if (isatty(fileno(fp)))
+ return run_tty_loop(fp, filename);
+ else
+ return run_script(fp, filename);
+}
+
+int
+run_tty_loop(fp, filename)
+ FILE *fp;
+ char *filename;
+{
+ object *v;
+ int ret;
+ v = sysget("ps1");
+ if (v == NULL) {
+ sysset("ps1", v = newstringobject(">>> "));
+ XDECREF(v);
+ }
+ v = sysget("ps2");
+ if (v == NULL) {
+ sysset("ps2", v = newstringobject("... "));
+ XDECREF(v);
+ }
+ for (;;) {
+ ret = run_tty_1(fp, filename);
+#ifdef REF_DEBUG
+ fprintf(stderr, "[%ld refs]\n", ref_total);
+#endif
+ if (ret == E_EOF)
+ return 0;
+ /*
+ if (ret == E_NOMEM)
+ return -1;
+ */
+ }
+}
+
+int
+run_tty_1(fp, filename)
+ FILE *fp;
+ char *filename;
+{
+ object *m, *d, *v, *w;
+ node *n;
+ char *ps1, *ps2;
+ int err;
+ v = sysget("ps1");
+ w = sysget("ps2");
+ if (v != NULL && is_stringobject(v)) {
+ INCREF(v);
+ ps1 = getstringvalue(v);
+ }
+ else {
+ v = NULL;
+ ps1 = "";
+ }
+ if (w != NULL && is_stringobject(w)) {
+ INCREF(w);
+ ps2 = getstringvalue(w);
+ }
+ else {
+ w = NULL;
+ ps2 = "";
+ }
+ err = parsefile(fp, filename, &gram, single_input, ps1, ps2, &n);
+ XDECREF(v);
+ XDECREF(w);
+ if (err == E_EOF)
+ return E_EOF;
+ if (err != E_DONE) {
+ err_input(err);
+ print_error();
+ return err;
+ }
+ m = add_module("__main__");
+ if (m == NULL)
+ return -1;
+ d = getmoduledict(m);
+ v = run_node(n, filename, d, d);
+ flushline();
+ if (v == NULL) {
+ print_error();
+ return -1;
+ }
+ DECREF(v);
+ return 0;
+}
+
+int
+run_script(fp, filename)
+ FILE *fp;
+ char *filename;
+{
+ object *m, *d, *v;
+ m = add_module("__main__");
+ if (m == NULL)
+ return -1;
+ d = getmoduledict(m);
+ v = run_file(fp, filename, file_input, d, d);
+ flushline();
+ if (v == NULL) {
+ print_error();
+ return -1;
+ }
+ DECREF(v);
+ return 0;
+}
+
+void
+print_error()
+{
+ object *exception, *v;
+ err_get(&exception, &v);
+ fprintf(stderr, "Unhandled exception: ");
+ printobject(exception, stderr, PRINT_RAW);
+ if (v != NULL && v != None) {
+ fprintf(stderr, ": ");
+ printobject(v, stderr, PRINT_RAW);
+ }
+ fprintf(stderr, "\n");
+ XDECREF(exception);
+ XDECREF(v);
+ printtraceback(stderr);
+}
+
+object *
+run_string(str, start, globals, locals)
+ char *str;
+ int start;
+ /*dict*/object *globals, *locals;
+{
+ node *n;
+ int err;
+ err = parse_string(str, start, &n);
+ return run_err_node(err, n, "<string>", globals, locals);
+}
+
+object *
+run_file(fp, filename, start, globals, locals)
+ FILE *fp;
+ char *filename;
+ int start;
+ /*dict*/object *globals, *locals;
+{
+ node *n;
+ int err;
+ err = parse_file(fp, filename, start, &n);
+ return run_err_node(err, n, filename, globals, locals);
+}
+
+object *
+run_err_node(err, n, filename, globals, locals)
+ int err;
+ node *n;
+ char *filename;
+ /*dict*/object *globals, *locals;
+{
+ if (err != E_DONE) {
+ err_input(err);
+ return NULL;
+ }
+ return run_node(n, filename, globals, locals);
+}
+
+object *
+run_node(n, filename, globals, locals)
+ node *n;
+ char *filename;
+ /*dict*/object *globals, *locals;
+{
+ if (globals == NULL) {
+ globals = getglobals();
+ if (locals == NULL)
+ locals = getlocals();
+ }
+ else {
+ if (locals == NULL)
+ locals = globals;
+ }
+ return eval_node(n, filename, globals, locals);
+}
+
+object *
+eval_node(n, filename, globals, locals)
+ node *n;
+ char *filename;
+ object *globals;
+ object *locals;
+{
+ codeobject *co;
+ object *v;
+ co = compile(n, filename);
+ freetree(n);
+ if (co == NULL)
+ return NULL;
+ v = eval_code(co, globals, locals, (object *)NULL);
+ DECREF(co);
+ return v;
+}
+
+/* Simplified interface to parsefile */
+
+int
+parse_file(fp, filename, start, n_ret)
+ FILE *fp;
+ char *filename;
+ int start;
+ node **n_ret;
+{
+ return parsefile(fp, filename, &gram, start,
+ (char *)0, (char *)0, n_ret);
+}
+
+/* Simplified interface to parsestring */
+
+int
+parse_string(str, start, n_ret)
+ char *str;
+ int start;
+ node **n_ret;
+{
+ int err = parsestring(str, &gram, start, n_ret);
+ /* Don't confuse early end of string with early end of input */
+ if (err == E_EOF)
+ err = E_SYNTAX;
+ return err;
+}
+
+/* Print fatal error message and abort */
+
+void
+fatal(msg)
+ char *msg;
+{
+ fprintf(stderr, "Fatal error: %s\n", msg);
+ abort();
+}
+
+/* Clean up and exit */
+
+void
+goaway(sts)
+ int sts;
+{
+ flushline();
+
+ /* XXX Call doneimport() before donecalls(), since donecalls()
+ calls wdone(), and doneimport() may close windows */
+ doneimport();
+ donecalls();
+
+ err_clear();
+
+#ifdef REF_DEBUG
+ fprintf(stderr, "[%ld refs]\n", ref_total);
+#endif
+
+#ifdef THINK_C_3_0
+ if (sts == 0)
+ Click_On(0);
+#endif
+
+#ifdef TRACE_REFS
+ if (askyesno("Print left references?")) {
+#ifdef THINK_C_3_0
+ Click_On(1);
+#endif
+ printrefs(stderr);
+ }
+#endif /* TRACE_REFS */
+
+ exit(sts);
+ /*NOTREACHED*/
+}
+
+static
+finaloutput()
+{
+#ifdef TRACE_REFS
+ if (!askyesno("Print left references?"))
+ return;
+#ifdef THINK_C_3_0
+ Click_On(1);
+#endif
+ printrefs(stderr);
+#endif /* TRACE_REFS */
+}
+
+/* Ask a yes/no question */
+
+static int
+askyesno(prompt)
+ char *prompt;
+{
+ char buf[256];
+
+ printf("%s [ny] ", prompt);
+ if (fgets(buf, sizeof buf, stdin) == NULL)
+ return 0;
+ return buf[0] == 'y' || buf[0] == 'Y';
+}
+
+#ifdef THINK_C_3_0
+
+/* Check for file descriptor connected to interactive device.
+ Pretend that stdin is always interactive, other files never. */
+
+int
+isatty(fd)
+ int fd;
+{
+ return fd == fileno(stdin);
+}
+
+#endif
+
+/* XXX WISH LIST
+
+ - possible new types:
+ - iterator (for range, keys, ...)
+ - improve interpreter error handling, e.g., true tracebacks
+ - save precompiled modules on file?
+ - fork threads, locking
+ - allow syntax extensions
+*/
+
+/* "Floccinaucinihilipilification" */
diff --git a/src/pythonrun.h b/src/pythonrun.h
new file mode 100644
index 0000000..30c8667
--- /dev/null
+++ b/src/pythonrun.h
@@ -0,0 +1,47 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* Interfaces to parse and execute pieces of python code */
+
+void initall PROTO((void));
+
+int run PROTO((FILE *, char *));
+
+int run_script PROTO((FILE *, char *));
+int run_tty_1 PROTO((FILE *, char *));
+int run_tty_loop PROTO((FILE *, char *));
+
+int parse_string PROTO((char *, int, struct _node **));
+int parse_file PROTO((FILE *, char *, int, struct _node **));
+
+object *eval_node PROTO((struct _node *, char *, object *, object *));
+
+object *run_string PROTO((char *, int, object *, object *));
+object *run_file PROTO((FILE *, char *, int, object *, object *));
+object *run_err_node PROTO((int, struct _node *, char *, object *, object *));
+object *run_node PROTO((struct _node *, char *, object *, object *));
+
+void print_error PROTO((void));
+
+void goaway PROTO((int));
diff --git a/src/regexp.c b/src/regexp.c
new file mode 100644
index 0000000..50ce9b6
--- /dev/null
+++ b/src/regexp.c
@@ -0,0 +1,1394 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/*
+ * regcomp and regexec -- regsub and regerror are elsewhere
+ *
+ * Copyright (c) 1986 by University of Toronto.
+ * Written by Henry Spencer. Not derived from licensed software.
+#ifdef MULTILINE
+ * Changed by Guido van Rossum, CWI, Amsterdam
+ * for multi-line support.
+#endif
+ *
+ * Permission is granted to anyone to use this software for any
+ * purpose on any computer system, and to redistribute it freely,
+ * subject to the following restrictions:
+ *
+ * 1. The author is not responsible for the consequences of use of
+ * this software, no matter how awful, even if they arise
+ * from defects in it.
+ *
+ * 2. The origin of this software must not be misrepresented, either
+ * by explicit claim or by omission.
+ *
+ * 3. Altered versions must be plainly marked as such, and must not
+ * be misrepresented as being the original software.
+ *
+ * Beware that some of this code is subtly aware of the way operator
+ * precedence is structured in regular expressions. Serious changes in
+ * regular-expression syntax might require a total rethink.
+ */
+#include <stdio.h>
+#include "PROTO.h"
+#include "malloc.h"
+#undef ANY /* Conflicting identifier defined in malloc.h */
+#include <string.h> /* XXX Remove if not found */
+#include "regexp.h"
+#include "regmagic.h"
+
+#ifdef MULTILINE
+/*
+ * Defining MULTILINE turns on the following changes in the semantics:
+ * 1. The '.' operator matches all characters except a newline.
+ * 2. The '^' operator matches at the beginning of the string or after
+ * a newline. (Anchored matches are retried after each newline.)
+ * 3. The '$' operator matches at the end of the string or before
+ * a newline.
+ * 4. A '\' followed by an 'n' matches a newline. (This is an
+ * unfortunate exception to the rule that '\' followed by a
+ * character matches that character...)
+ *
+ * Also, there is a new function reglexec(prog, string, offset)
+ * which searches for a match starting at 'string+offset';
+ * it differs from regexec(prog, string+offset) in assuming
+ * that the line begins at 'string'.
+ */
+#endif
+
+/*
+ * The "internal use only" fields in regexp.h are present to pass info from
+ * compile to execute that permits the execute phase to run lots faster on
+ * simple cases. They are:
+ *
+ * regstart char that must begin a match; '\0' if none obvious
+ * reganch is the match anchored (at beginning-of-line only)?
+ * regmust string (pointer into program) that match must include, or NULL
+ * regmlen length of regmust string
+ *
+ * Regstart and reganch permit very fast decisions on suitable starting points
+ * for a match, cutting down the work a lot. Regmust permits fast rejection
+ * of lines that cannot possibly match. The regmust tests are costly enough
+ * that regcomp() supplies a regmust only if the r.e. contains something
+ * potentially expensive (at present, the only such thing detected is * or +
+ * at the start of the r.e., which can involve a lot of backup). Regmlen is
+ * supplied because the test in regexec() needs it and regcomp() is computing
+ * it anyway.
+ */
+
+/*
+ * Structure for regexp "program". This is essentially a linear encoding
+ * of a nondeterministic finite-state machine (aka syntax charts or
+ * "railroad normal form" in parsing technology). Each node is an opcode
+ * plus a "next" pointer, possibly plus an operand. "Next" pointers of
+ * all nodes except BRANCH implement concatenation; a "next" pointer with
+ * a BRANCH on both ends of it is connecting two alternatives. (Here we
+ * have one of the subtle syntax dependencies: an individual BRANCH (as
+ * opposed to a collection of them) is never concatenated with anything
+ * because of operator precedence.) The operand of some types of node is
+ * a literal string; for others, it is a node leading into a sub-FSM. In
+ * particular, the operand of a BRANCH node is the first node of the branch.
+ * (NB this is *not* a tree structure: the tail of the branch connects
+ * to the thing following the set of BRANCHes.) The opcodes are:
+ */
+
+/* definition number opnd? meaning */
+#define END 0 /* no End of program. */
+#define BOL 1 /* no Match "" at beginning of line. */
+#define EOL 2 /* no Match "" at end of line. */
+#define ANY 3 /* no Match any one character. */
+#define ANYOF 4 /* str Match any character in this string. */
+#define ANYBUT 5 /* str Match any character not in this string. */
+#define BRANCH 6 /* node Match this alternative, or the next... */
+#define BACK 7 /* no Match "", "next" ptr points backward. */
+#define EXACTLY 8 /* str Match this string. */
+#define NOTHING 9 /* no Match empty string. */
+#define STAR 10 /* node Match this (simple) thing 0 or more times. */
+#define PLUS 11 /* node Match this (simple) thing 1 or more times. */
+#define OPEN 20 /* no Mark this point in input as start of #n. */
+ /* OPEN+1 is number 1, etc. */
+#define CLOSE 30 /* no Analogous to OPEN. */
+
+/*
+ * Opcode notes:
+ *
+ * BRANCH The set of branches constituting a single choice are hooked
+ * together with their "next" pointers, since precedence prevents
+ * anything being concatenated to any individual branch. The
+ * "next" pointer of the last BRANCH in a choice points to the
+ * thing following the whole choice. This is also where the
+ * final "next" pointer of each individual branch points; each
+ * branch starts with the operand node of a BRANCH node.
+ *
+ * BACK Normal "next" pointers all implicitly point forward; BACK
+ * exists to make loop structures possible.
+ *
+ * STAR,PLUS '?', and complex '*' and '+', are implemented as circular
+ * BRANCH structures using BACK. Simple cases (one character
+ * per match) are implemented with STAR and PLUS for speed
+ * and to minimize recursive plunges.
+ *
+ * OPEN,CLOSE ...are numbered at compile time.
+ */
+
+/*
+ * A node is one char of opcode followed by two chars of "next" pointer.
+ * "Next" pointers are stored as two 8-bit pieces, high order first. The
+ * value is a positive offset from the opcode of the node containing it.
+ * An operand, if any, simply follows the node. (Note that much of the
+ * code generation knows about this implicit relationship.)
+ *
+ * Using two bytes for the "next" pointer is vast overkill for most things,
+ * but allows patterns to get big without disasters.
+ */
+#define OP(p) (*(p))
+#define NEXT(p) (((*((p)+1)&0377)<<8) + (*((p)+2)&0377))
+#define OPERAND(p) ((p) + 3)
+
+/*
+ * See regmagic.h for one further detail of program structure.
+ */
+
+
+/*
+ * Utility definitions.
+ */
+#ifndef CHARBITS
+#define UCHARAT(p) ((int)*(unsigned char *)(p))
+#else
+#define UCHARAT(p) ((int)*(p)&CHARBITS)
+#endif
+
+#define FAIL(m) { regerror(m); return(NULL); }
+#define ISMULT(c) ((c) == '*' || (c) == '+' || (c) == '?')
+#define META "^$.[()|?+*\\"
+
+/*
+ * Flags to be passed up and down.
+ */
+#define HASWIDTH 01 /* Known never to match null string. */
+#define SIMPLE 02 /* Simple enough to be STAR/PLUS operand. */
+#define SPSTART 04 /* Starts with * or +. */
+#define WORST 0 /* Worst case. */
+
+/*
+ * Global work variables for regcomp().
+ */
+static char *regparse; /* Input-scan pointer. */
+static int regnpar; /* () count. */
+static char regdummy;
+static char *regcode; /* Code-emit pointer; &regdummy = don't. */
+static long regsize; /* Code size. */
+#ifdef MULTILINE
+static int regnl; /* '\n' detected. */
+#endif
+
+/*
+ * Forward declarations for regcomp()'s friends.
+ */
+#ifndef STATIC
+#define STATIC static
+#endif
+STATIC char *reg();
+STATIC char *regbranch();
+STATIC char *regpiece();
+STATIC char *regatom();
+STATIC char *regnode();
+STATIC char *regnext();
+STATIC void regc();
+STATIC void reginsert();
+STATIC void regtail();
+STATIC void regoptail();
+#ifdef STRCSPN
+STATIC int strcspn();
+#endif
+
+/*
+ - regcomp - compile a regular expression into internal code
+ *
+ * We can't allocate space until we know how big the compiled form will be,
+ * but we can't compile it (and thus know how big it is) until we've got a
+ * place to put the code. So we cheat: we compile it twice, once with code
+ * generation turned off and size counting turned on, and once "for real".
+ * This also means that we don't allocate space until we are sure that the
+ * thing really will compile successfully, and we never have to move the
+ * code and thus invalidate pointers into it. (Note that it has to be in
+ * one piece because free() must be able to free it all.)
+ *
+ * Beware that the optimization-preparation code in here knows about some
+ * of the structure of the compiled regexp.
+ */
+regexp *
+regcomp(exp)
+char *exp;
+{
+ register regexp *r;
+ register char *scan;
+ register char *longest;
+ register int len;
+ int flags;
+
+ if (exp == NULL)
+ FAIL("NULL argument");
+
+ /* First pass: determine size, legality. */
+ regparse = exp;
+ regnpar = 1;
+ regsize = 0L;
+ regcode = &regdummy;
+#ifdef MULTILINE
+ regnl = 0;
+#endif
+ regc(MAGIC);
+ if (reg(0, &flags) == NULL)
+ return(NULL);
+
+ /* Small enough for pointer-storage convention? */
+ if (regsize >= 32767L) /* Probably could be 65535L. */
+ FAIL("regexp too big");
+
+ /* Allocate space. */
+ r = (regexp *)malloc(sizeof(regexp) + (unsigned)regsize);
+ if (r == NULL)
+ FAIL("out of space");
+
+ /* Second pass: emit code. */
+ regparse = exp;
+ regnpar = 1;
+ regcode = r->program;
+ regc(MAGIC);
+ if (reg(0, &flags) == NULL)
+ return(NULL);
+
+ /* Dig out information for optimizations. */
+ r->regstart = '\0'; /* Worst-case defaults. */
+ r->reganch = 0;
+ r->regmust = NULL;
+ r->regmlen = 0;
+ scan = r->program+1; /* First BRANCH. */
+ if (OP(regnext(scan)) == END) { /* Only one top-level choice. */
+ scan = OPERAND(scan);
+
+ /* Starting-point info. */
+ if (OP(scan) == EXACTLY)
+ r->regstart = *OPERAND(scan);
+ else if (OP(scan) == BOL)
+ r->reganch++;
+
+ /*
+ * If there's something expensive in the r.e., find the
+ * longest literal string that must appear and make it the
+ * regmust. Resolve ties in favor of later strings, since
+ * the regstart check works with the beginning of the r.e.
+ * and avoiding duplication strengthens checking. Not a
+ * strong reason, but sufficient in the absence of others.
+ */
+#ifdef MULTILINE
+ if ((flags&SPSTART) && !regnl) {
+#else
+ if (flags&SPSTART) {
+#endif
+ longest = NULL;
+ len = 0;
+ for (; scan != NULL; scan = regnext(scan))
+ if (OP(scan) == EXACTLY && strlen(OPERAND(scan)) >= len) {
+ longest = OPERAND(scan);
+ len = strlen(OPERAND(scan));
+ }
+ r->regmust = longest;
+ r->regmlen = len;
+ }
+ }
+
+ return(r);
+}
+
+/*
+ - reg - regular expression, i.e. main body or parenthesized thing
+ *
+ * Caller must absorb opening parenthesis.
+ *
+ * Combining parenthesis handling with the base level of regular expression
+ * is a trifle forced, but the need to tie the tails of the branches to what
+ * follows makes it hard to avoid.
+ */
+static char *
+reg(paren, flagp)
+int paren; /* Parenthesized? */
+int *flagp;
+{
+ register char *ret;
+ register char *br;
+ register char *ender;
+ register int parno;
+ int flags;
+
+ *flagp = HASWIDTH; /* Tentatively. */
+
+ /* Make an OPEN node, if parenthesized. */
+ if (paren) {
+ if (regnpar >= NSUBEXP)
+ FAIL("too many ()");
+ parno = regnpar;
+ regnpar++;
+ ret = regnode(OPEN+parno);
+ } else
+ ret = NULL;
+
+ /* Pick up the branches, linking them together. */
+ br = regbranch(&flags);
+ if (br == NULL)
+ return(NULL);
+ if (ret != NULL)
+ regtail(ret, br); /* OPEN -> first. */
+ else
+ ret = br;
+ if (!(flags&HASWIDTH))
+ *flagp &= ~HASWIDTH;
+ *flagp |= flags&SPSTART;
+ while (*regparse == '|') {
+ regparse++;
+ br = regbranch(&flags);
+ if (br == NULL)
+ return(NULL);
+ regtail(ret, br); /* BRANCH -> BRANCH. */
+ if (!(flags&HASWIDTH))
+ *flagp &= ~HASWIDTH;
+ *flagp |= flags&SPSTART;
+ }
+
+ /* Make a closing node, and hook it on the end. */
+ ender = regnode((paren) ? CLOSE+parno : END);
+ regtail(ret, ender);
+
+ /* Hook the tails of the branches to the closing node. */
+ for (br = ret; br != NULL; br = regnext(br))
+ regoptail(br, ender);
+
+ /* Check for proper termination. */
+ if (paren && *regparse++ != ')') {
+ FAIL("unmatched ()");
+ } else if (!paren && *regparse != '\0') {
+ if (*regparse == ')') {
+ FAIL("unmatched ()");
+ } else
+ FAIL("junk on end"); /* "Can't happen". */
+ /* NOTREACHED */
+ }
+
+ return(ret);
+}
+
+/*
+ - regbranch - one alternative of an | operator
+ *
+ * Implements the concatenation operator.
+ */
+static char *
+regbranch(flagp)
+int *flagp;
+{
+ register char *ret;
+ register char *chain;
+ register char *latest;
+ int flags;
+
+ *flagp = WORST; /* Tentatively. */
+
+ ret = regnode(BRANCH);
+ chain = NULL;
+ while (*regparse != '\0' && *regparse != '|' && *regparse != ')') {
+ latest = regpiece(&flags);
+ if (latest == NULL)
+ return(NULL);
+ *flagp |= flags&HASWIDTH;
+ if (chain == NULL) /* First piece. */
+ *flagp |= flags&SPSTART;
+ else
+ regtail(chain, latest);
+ chain = latest;
+ }
+ if (chain == NULL) /* Loop ran zero times. */
+ (void) regnode(NOTHING);
+
+ return(ret);
+}
+
+/*
+ - regpiece - something followed by possible [*+?]
+ *
+ * Note that the branching code sequences used for ? and the general cases
+ * of * and + are somewhat optimized: they use the same NOTHING node as
+ * both the endmarker for their branch list and the body of the last branch.
+ * It might seem that this node could be dispensed with entirely, but the
+ * endmarker role is not redundant.
+ */
+static char *
+regpiece(flagp)
+int *flagp;
+{
+ register char *ret;
+ register char op;
+ register char *next;
+ int flags;
+
+ ret = regatom(&flags);
+ if (ret == NULL)
+ return(NULL);
+
+ op = *regparse;
+ if (!ISMULT(op)) {
+ *flagp = flags;
+ return(ret);
+ }
+
+ if (!(flags&HASWIDTH) && op != '?')
+ FAIL("*+ operand could be empty");
+ *flagp = (op != '+') ? (WORST|SPSTART) : (WORST|HASWIDTH);
+
+ if (op == '*' && (flags&SIMPLE))
+ reginsert(STAR, ret);
+ else if (op == '*') {
+ /* Emit x* as (x&|), where & means "self". */
+ reginsert(BRANCH, ret); /* Either x */
+ regoptail(ret, regnode(BACK)); /* and loop */
+ regoptail(ret, ret); /* back */
+ regtail(ret, regnode(BRANCH)); /* or */
+ regtail(ret, regnode(NOTHING)); /* null. */
+ } else if (op == '+' && (flags&SIMPLE))
+ reginsert(PLUS, ret);
+ else if (op == '+') {
+ /* Emit x+ as x(&|), where & means "self". */
+ next = regnode(BRANCH); /* Either */
+ regtail(ret, next);
+ regtail(regnode(BACK), ret); /* loop back */
+ regtail(next, regnode(BRANCH)); /* or */
+ regtail(ret, regnode(NOTHING)); /* null. */
+ } else if (op == '?') {
+ /* Emit x? as (x|) */
+ reginsert(BRANCH, ret); /* Either x */
+ regtail(ret, regnode(BRANCH)); /* or */
+ next = regnode(NOTHING); /* null. */
+ regtail(ret, next);
+ regoptail(ret, next);
+ }
+ regparse++;
+ if (ISMULT(*regparse))
+ FAIL("nested *?+");
+
+ return(ret);
+}
+
+/*
+ - regatom - the lowest level
+ *
+ * Optimization: gobbles an entire sequence of ordinary characters so that
+ * it can turn them into a single node, which is smaller to store and
+ * faster to run. Backslashed characters are exceptions, each becoming a
+ * separate node; the code is simpler that way and it's not worth fixing.
+ */
+static char *
+regatom(flagp)
+int *flagp;
+{
+ register char *ret;
+ int flags;
+
+ *flagp = WORST; /* Tentatively. */
+
+ switch (*regparse++) {
+ case '^':
+ ret = regnode(BOL);
+ break;
+ case '$':
+ ret = regnode(EOL);
+ break;
+ case '.':
+ ret = regnode(ANY);
+ *flagp |= HASWIDTH|SIMPLE;
+ break;
+ case '[': {
+ register int class;
+ register int classend;
+
+ if (*regparse == '^') { /* Complement of range. */
+ ret = regnode(ANYBUT);
+ regparse++;
+ } else
+ ret = regnode(ANYOF);
+ if (*regparse == ']' || *regparse == '-')
+ regc(*regparse++);
+ while (*regparse != '\0' && *regparse != ']') {
+ if (*regparse == '-') {
+ regparse++;
+ if (*regparse == ']' || *regparse == '\0')
+ regc('-');
+ else {
+ class = UCHARAT(regparse-2)+1;
+ classend = UCHARAT(regparse);
+ if (class > classend+1)
+ FAIL("invalid [] range");
+ for (; class <= classend; class++)
+ regc(class);
+ regparse++;
+ }
+ } else
+ regc(*regparse++);
+ }
+ regc('\0');
+ if (*regparse != ']')
+ FAIL("unmatched []");
+ regparse++;
+ *flagp |= HASWIDTH|SIMPLE;
+ }
+ break;
+ case '(':
+ ret = reg(1, &flags);
+ if (ret == NULL)
+ return(NULL);
+ *flagp |= flags&(HASWIDTH|SPSTART);
+ break;
+ case '\0':
+ case '|':
+ case ')':
+ FAIL("internal urp"); /* Supposed to be caught earlier. */
+ break;
+ case '?':
+ case '+':
+ case '*':
+ FAIL("?+* follows nothing");
+ break;
+ case '\\':
+ if (*regparse == '\0')
+ FAIL("trailing \\");
+ ret = regnode(EXACTLY);
+#ifdef MULTILINE
+ if (*regparse == 'n') {
+ regc('\n');
+ regparse++;
+ regnl++;
+ }
+ else
+#endif
+ regc(*regparse++);
+ regc('\0');
+ *flagp |= HASWIDTH|SIMPLE;
+ break;
+ default: {
+ register int len;
+ register char ender;
+
+ regparse--;
+ len = strcspn(regparse, META);
+ if (len <= 0)
+ FAIL("internal disaster");
+ ender = *(regparse+len);
+ if (len > 1 && ISMULT(ender))
+ len--; /* Back off clear of ?+* operand. */
+ *flagp |= HASWIDTH;
+ if (len == 1)
+ *flagp |= SIMPLE;
+ ret = regnode(EXACTLY);
+ while (len > 0) {
+#ifdef MULTILINE
+ if (*regparse == '\n')
+ regnl++;
+#endif
+ regc(*regparse++);
+ len--;
+ }
+ regc('\0');
+ }
+ break;
+ }
+
+ return(ret);
+}
+
+/*
+ - regnode - emit a node
+ */
+static char * /* Location. */
+regnode(op)
+char op;
+{
+ register char *ret;
+ register char *ptr;
+
+ ret = regcode;
+ if (ret == &regdummy) {
+ regsize += 3;
+ return(ret);
+ }
+
+ ptr = ret;
+ *ptr++ = op;
+ *ptr++ = '\0'; /* Null "next" pointer. */
+ *ptr++ = '\0';
+ regcode = ptr;
+
+ return(ret);
+}
+
+/*
+ - regc - emit (if appropriate) a byte of code
+ */
+static void
+regc(b)
+char b;
+{
+ if (regcode != &regdummy)
+ *regcode++ = b;
+ else
+ regsize++;
+}
+
+/*
+ - reginsert - insert an operator in front of already-emitted operand
+ *
+ * Means relocating the operand.
+ */
+static void
+reginsert(op, opnd)
+char op;
+char *opnd;
+{
+ register char *src;
+ register char *dst;
+ register char *place;
+
+ if (regcode == &regdummy) {
+ regsize += 3;
+ return;
+ }
+
+ src = regcode;
+ regcode += 3;
+ dst = regcode;
+ while (src > opnd)
+ *--dst = *--src;
+
+ place = opnd; /* Op node, where operand used to be. */
+ *place++ = op;
+ *place++ = '\0';
+ *place++ = '\0';
+}
+
+/*
+ - regtail - set the next-pointer at the end of a node chain
+ */
+static void
+regtail(p, val)
+char *p;
+char *val;
+{
+ register char *scan;
+ register char *temp;
+ register int offset;
+
+ if (p == &regdummy)
+ return;
+
+ /* Find last node. */
+ scan = p;
+ for (;;) {
+ temp = regnext(scan);
+ if (temp == NULL)
+ break;
+ scan = temp;
+ }
+
+ if (OP(scan) == BACK)
+ offset = scan - val;
+ else
+ offset = val - scan;
+ *(scan+1) = (offset>>8)&0377;
+ *(scan+2) = offset&0377;
+}
+
+/*
+ - regoptail - regtail on operand of first argument; nop if operandless
+ */
+static void
+regoptail(p, val)
+char *p;
+char *val;
+{
+ /* "Operandless" and "op != BRANCH" are synonymous in practice. */
+ if (p == NULL || p == &regdummy || OP(p) != BRANCH)
+ return;
+ regtail(OPERAND(p), val);
+}
+
+/*
+ * regexec and friends
+ */
+
+/*
+ * Global work variables for regexec().
+ */
+static char *reginput; /* String-input pointer. */
+static char *regbol; /* Beginning of input, for ^ check. */
+static char **regstartp; /* Pointer to startp array. */
+static char **regendp; /* Ditto for endp. */
+
+/*
+ * Forwards.
+ */
+STATIC int regtry();
+STATIC int regmatch();
+STATIC int regrepeat();
+
+#ifdef DEBUG
+int regnarrate = 0;
+void regdump();
+STATIC char *regprop();
+#endif
+
+/*
+ - regexec - match a regexp against a string
+ */
+int
+regexec(prog, string)
+register regexp *prog;
+register char *string;
+{
+ register char *s;
+ extern char *strchr();
+
+ /* Be paranoid... */
+ if (prog == NULL || string == NULL) {
+ regerror("NULL parameter");
+ return(0);
+ }
+
+#ifdef MULTILINE
+ /* Check for \n in string, and if so, call the more general routine. */
+ if (strchr(string, '\n') != NULL)
+ return reglexec(prog, string, 0);
+#endif
+
+ /* Check validity of program. */
+ if (UCHARAT(prog->program) != MAGIC) {
+ regerror("corrupted program");
+ return(0);
+ }
+
+ /* If there is a "must appear" string, look for it. */
+ if (prog->regmust != NULL) {
+ s = string;
+ while ((s = strchr(s, prog->regmust[0])) != NULL) {
+ if (strncmp(s, prog->regmust, prog->regmlen) == 0)
+ break; /* Found it. */
+ s++;
+ }
+ if (s == NULL) /* Not present. */
+ return(0);
+ }
+
+ /* Mark beginning of line for ^ . */
+ regbol = string;
+
+ /* Simplest case: anchored match need be tried only once. */
+ if (prog->reganch)
+ return(regtry(prog, string));
+
+ /* Messy cases: unanchored match. */
+ s = string;
+ if (prog->regstart != '\0')
+ /* We know what char it must start with. */
+ while ((s = strchr(s, prog->regstart)) != NULL) {
+ if (regtry(prog, s))
+ return(1);
+ s++;
+ }
+ else
+ /* We don't -- general case. */
+ do {
+ if (regtry(prog, s))
+ return(1);
+ } while (*s++ != '\0');
+
+ /* Failure. */
+ return(0);
+}
+
+#ifdef MULTILINE
+/*
+ - reglexec - match a regexp against a long string buffer, starting at offset
+ */
+int
+reglexec(prog, string, offset)
+register regexp *prog;
+register char *string;
+{
+ register char *s;
+ extern char *strchr();
+
+ /* Be paranoid... */
+ if (prog == NULL || string == NULL) {
+ regerror("NULL parameter");
+ return(0);
+ }
+
+ /* Check validity of program. */
+ if (UCHARAT(prog->program) != MAGIC) {
+ regerror("corrupted program");
+ return(0);
+ }
+
+ /* (Don't look for "must appear" string -- string can be long.) */
+
+ /* Mark beginning of line for ^ . */
+ regbol = string;
+
+ /* Apply offset.
+ Assume 0 <= offset <= strlen(string), but don't check,
+ as string can be long. */
+ s= string + offset;
+
+ /* Anchored match need be tried only at line starts. */
+ if (prog->reganch) {
+ while (!regtry(prog, s)) {
+ s = strchr(s, '\n');
+ if (s == NULL)
+ return(0);
+ s++;
+ }
+ return(1);
+ }
+
+ /* Messy cases: unanchored match. */
+ if (prog->regstart != '\0')
+ /* We know what char it must start with. */
+ while ((s = strchr(s, prog->regstart)) != NULL) {
+ if (regtry(prog, s))
+ return(1);
+ s++;
+ }
+ else
+ /* We don't -- general case. */
+ do {
+ if (regtry(prog, s))
+ return(1);
+ } while (*s++ != '\0');
+
+ /* Failure. */
+ return(0);
+}
+#endif
+
+/*
+ - regtry - try match at specific point
+ */
+static int /* 0 failure, 1 success */
+regtry(prog, string)
+regexp *prog;
+char *string;
+{
+ register int i;
+ register char **sp;
+ register char **ep;
+
+ reginput = string;
+ regstartp = prog->startp;
+ regendp = prog->endp;
+
+ sp = prog->startp;
+ ep = prog->endp;
+ for (i = NSUBEXP; i > 0; i--) {
+ *sp++ = NULL;
+ *ep++ = NULL;
+ }
+ if (regmatch(prog->program + 1)) {
+ prog->startp[0] = string;
+ prog->endp[0] = reginput;
+ return(1);
+ } else
+ return(0);
+}
+
+/*
+ - regmatch - main matching routine
+ *
+ * Conceptually the strategy is simple: check to see whether the current
+ * node matches, call self recursively to see whether the rest matches,
+ * and then act accordingly. In practice we make some effort to avoid
+ * recursion, in particular by going through "ordinary" nodes (that don't
+ * need to know whether the rest of the match failed) by a loop instead of
+ * by recursion.
+ */
+static int /* 0 failure, 1 success */
+regmatch(prog)
+char *prog;
+{
+ register char *scan; /* Current node. */
+ char *next; /* Next node. */
+ extern char *strchr();
+
+ scan = prog;
+#ifdef DEBUG
+ if (scan != NULL && regnarrate)
+ fprintf(stderr, "%s(\n", regprop(scan));
+#endif
+ while (scan != NULL) {
+#ifdef DEBUG
+ if (regnarrate)
+ fprintf(stderr, "%s...\n", regprop(scan));
+#endif
+ next = regnext(scan);
+
+ switch (OP(scan)) {
+ case BOL:
+#ifdef MULTILINE
+ if (!(reginput == regbol ||
+ reginput > regbol && *(reginput-1) == '\n'))
+#else
+ if (reginput != regbol)
+#endif
+ return(0);
+ break;
+ case EOL:
+#ifdef MULTILINE
+ if (*reginput != '\0' && *reginput != '\n')
+#else
+ if (*reginput != '\0')
+#endif
+ return(0);
+ break;
+ case ANY:
+#ifdef MULTILINE
+ if (*reginput == '\0' || *reginput == '\n')
+#else
+ if (*reginput == '\0')
+#endif
+ return(0);
+ reginput++;
+ break;
+ case EXACTLY: {
+ register int len;
+ register char *opnd;
+
+ opnd = OPERAND(scan);
+ /* Inline the first character, for speed. */
+ if (*opnd != *reginput)
+ return(0);
+ len = strlen(opnd);
+ if (len > 1 && strncmp(opnd, reginput, len) != 0)
+ return(0);
+ reginput += len;
+ }
+ break;
+ case ANYOF:
+ if (*reginput == '\0' || strchr(OPERAND(scan), *reginput) == NULL)
+ return(0);
+ reginput++;
+ break;
+ case ANYBUT:
+#ifdef MULTILINE
+ if (*reginput == '\0' || *reginput == '\n' ||
+ strchr(OPERAND(scan), *reginput) != NULL)
+#else
+ if (*reginput == '\0' || strchr(OPERAND(scan), *reginput) != NULL)
+#endif
+ return(0);
+ reginput++;
+ break;
+ case NOTHING:
+ break;
+ case BACK:
+ break;
+ case OPEN+1:
+ case OPEN+2:
+ case OPEN+3:
+ case OPEN+4:
+ case OPEN+5:
+ case OPEN+6:
+ case OPEN+7:
+ case OPEN+8:
+ case OPEN+9: {
+ register int no;
+ register char *save;
+
+ no = OP(scan) - OPEN;
+ save = reginput;
+
+ if (regmatch(next)) {
+ /*
+ * Don't set startp if some later
+ * invocation of the same parentheses
+ * already has.
+ */
+ if (regstartp[no] == NULL)
+ regstartp[no] = save;
+ return(1);
+ } else
+ return(0);
+ }
+ break;
+ case CLOSE+1:
+ case CLOSE+2:
+ case CLOSE+3:
+ case CLOSE+4:
+ case CLOSE+5:
+ case CLOSE+6:
+ case CLOSE+7:
+ case CLOSE+8:
+ case CLOSE+9: {
+ register int no;
+ register char *save;
+
+ no = OP(scan) - CLOSE;
+ save = reginput;
+
+ if (regmatch(next)) {
+ /*
+ * Don't set endp if some later
+ * invocation of the same parentheses
+ * already has.
+ */
+ if (regendp[no] == NULL)
+ regendp[no] = save;
+ return(1);
+ } else
+ return(0);
+ }
+ break;
+ case BRANCH: {
+ register char *save;
+
+ if (OP(next) != BRANCH) /* No choice. */
+ next = OPERAND(scan); /* Avoid recursion. */
+ else {
+ do {
+ save = reginput;
+ if (regmatch(OPERAND(scan)))
+ return(1);
+ reginput = save;
+ scan = regnext(scan);
+ } while (scan != NULL && OP(scan) == BRANCH);
+ return(0);
+ /* NOTREACHED */
+ }
+ }
+ break;
+ case STAR:
+ case PLUS: {
+ register char nextch;
+ register int no;
+ register char *save;
+ register int min;
+
+ /*
+ * Lookahead to avoid useless match attempts
+ * when we know what character comes next.
+ */
+ nextch = '\0';
+ if (OP(next) == EXACTLY)
+ nextch = *OPERAND(next);
+ min = (OP(scan) == STAR) ? 0 : 1;
+ save = reginput;
+ no = regrepeat(OPERAND(scan));
+ while (no >= min) {
+ /* If it could work, try it. */
+ if (nextch == '\0' || *reginput == nextch)
+ if (regmatch(next))
+ return(1);
+ /* Couldn't or didn't -- back up. */
+ no--;
+ reginput = save + no;
+ }
+ return(0);
+ }
+ break;
+ case END:
+ return(1); /* Success! */
+ break;
+ default:
+ regerror("memory corruption");
+ return(0);
+ break;
+ }
+
+ scan = next;
+ }
+
+ /*
+ * We get here only if there's trouble -- normally "case END" is
+ * the terminating point.
+ */
+ regerror("corrupted pointers");
+ return(0);
+}
+
+/*
+ - regrepeat - repeatedly match something simple, report how many
+ */
+static int
+regrepeat(p)
+char *p;
+{
+ register int count = 0;
+ register char *scan;
+ register char *opnd;
+#ifdef MULTILINE
+ register char *eol;
+#endif
+
+ scan = reginput;
+ opnd = OPERAND(p);
+ switch (OP(p)) {
+ case ANY:
+#ifdef MULTILINE
+ if ((eol = strchr(scan, '\n')) != NULL) {
+ count += eol - scan;
+ scan = eol;
+ break;
+ }
+#endif
+ count = strlen(scan);
+ scan += count;
+ break;
+ case EXACTLY:
+ while (*opnd == *scan) {
+ count++;
+ scan++;
+ }
+ break;
+ case ANYOF:
+ while (*scan != '\0' && strchr(opnd, *scan) != NULL) {
+ count++;
+ scan++;
+ }
+ break;
+ case ANYBUT:
+#ifdef MULTILINE
+ while (*scan != '\0' && *scan != '\n' &&
+ strchr(opnd, *scan) == NULL) {
+#else
+ while (*scan != '\0' && strchr(opnd, *scan) == NULL) {
+#endif
+ count++;
+ scan++;
+ }
+ break;
+ default: /* Oh dear. Called inappropriately. */
+ regerror("internal foulup");
+ count = 0; /* Best compromise. */
+ break;
+ }
+ reginput = scan;
+
+ return(count);
+}
+
+/*
+ - regnext - dig the "next" pointer out of a node
+ */
+static char *
+regnext(p)
+register char *p;
+{
+ register int offset;
+
+ if (p == &regdummy)
+ return(NULL);
+
+ offset = NEXT(p);
+ if (offset == 0)
+ return(NULL);
+
+ if (OP(p) == BACK)
+ return(p-offset);
+ else
+ return(p+offset);
+}
+
+#ifdef DEBUG
+
+STATIC char *regprop();
+
+/*
+ - regdump - dump a regexp onto stdout in vaguely comprehensible form
+ */
+void
+regdump(r)
+regexp *r;
+{
+ register char *s;
+ register char op = EXACTLY; /* Arbitrary non-END op. */
+ register char *next;
+ extern char *strchr();
+
+
+ s = r->program + 1;
+ while (op != END) { /* While that wasn't END last time... */
+ op = OP(s);
+ printf("%2d%s", (int)(s-r->program), regprop(s)); /* Where, what. */
+ next = regnext(s);
+ if (next == NULL) /* Next ptr. */
+ printf("(0)");
+ else
+ printf("(%d)", (int)((s-r->program)+(next-s)));
+ s += 3;
+ if (op == ANYOF || op == ANYBUT || op == EXACTLY) {
+ /* Literal string, where present. */
+ while (*s != '\0') {
+#ifdef MULTILINE
+ if (*s == '\n')
+ printf("\\n");
+ else
+#endif
+ putchar(*s);
+ s++;
+ }
+ s++;
+ }
+ putchar('\n');
+ }
+
+ /* Header fields of interest. */
+ if (r->regstart != '\0')
+ printf("start `%c' ", r->regstart);
+ if (r->reganch)
+ printf("anchored ");
+ if (r->regmust != NULL)
+ printf("must have \"%s\"", r->regmust);
+ printf("\n");
+}
+
+/*
+ - regprop - printable representation of opcode
+ */
+static char *
+regprop(op)
+char *op;
+{
+ register char *p;
+ static char buf[50];
+
+ (void) strcpy(buf, ":");
+
+ switch (OP(op)) {
+ case BOL:
+ p = "BOL";
+ break;
+ case EOL:
+ p = "EOL";
+ break;
+ case ANY:
+ p = "ANY";
+ break;
+ case ANYOF:
+ p = "ANYOF";
+ break;
+ case ANYBUT:
+ p = "ANYBUT";
+ break;
+ case BRANCH:
+ p = "BRANCH";
+ break;
+ case EXACTLY:
+ p = "EXACTLY";
+ break;
+ case NOTHING:
+ p = "NOTHING";
+ break;
+ case BACK:
+ p = "BACK";
+ break;
+ case END:
+ p = "END";
+ break;
+ case OPEN+1:
+ case OPEN+2:
+ case OPEN+3:
+ case OPEN+4:
+ case OPEN+5:
+ case OPEN+6:
+ case OPEN+7:
+ case OPEN+8:
+ case OPEN+9:
+ sprintf(buf+strlen(buf), "OPEN%d", (int)(OP(op)-OPEN));
+ p = NULL;
+ break;
+ case CLOSE+1:
+ case CLOSE+2:
+ case CLOSE+3:
+ case CLOSE+4:
+ case CLOSE+5:
+ case CLOSE+6:
+ case CLOSE+7:
+ case CLOSE+8:
+ case CLOSE+9:
+ sprintf(buf+strlen(buf), "CLOSE%d", (int)(OP(op)-CLOSE));
+ p = NULL;
+ break;
+ case STAR:
+ p = "STAR";
+ break;
+ case PLUS:
+ p = "PLUS";
+ break;
+ default:
+ regerror("corrupted opcode");
+ break;
+ }
+ if (p != NULL)
+ (void) strcat(buf, p);
+ return(buf);
+}
+#endif
+
+/*
+ * The following is provided for those people who do not have strcspn() in
+ * their C libraries. They should get off their butts and do something
+ * about it; at least one public-domain implementation of those (highly
+ * useful) string routines has been published on Usenet.
+ */
+#ifdef STRCSPN
+/*
+ * strcspn - find length of initial segment of s1 consisting entirely
+ * of characters not from s2
+ */
+
+static int
+strcspn(s1, s2)
+char *s1;
+char *s2;
+{
+ register char *scan1;
+ register char *scan2;
+ register int count;
+
+ count = 0;
+ for (scan1 = s1; *scan1 != '\0'; scan1++) {
+ for (scan2 = s2; *scan2 != '\0';) /* ++ moved down. */
+ if (*scan1 == *scan2++)
+ return(count);
+ count++;
+ }
+ return(count);
+}
+#endif
diff --git a/src/regexp.h b/src/regexp.h
new file mode 100644
index 0000000..cbb1856
--- /dev/null
+++ b/src/regexp.h
@@ -0,0 +1,51 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/*
+ * Definitions etc. for regexp(3) routines.
+ *
+ * Caveat: this is V8 regexp(3) [actually, a reimplementation thereof],
+ * not the System V one.
+ */
+
+#define MULTILINE
+
+#define NSUBEXP 10
+typedef struct regexp {
+ char *startp[NSUBEXP];
+ char *endp[NSUBEXP];
+ char regstart; /* Internal use only. */
+ char reganch; /* Internal use only. */
+ char *regmust; /* Internal use only. */
+ int regmlen; /* Internal use only. */
+ char program[1]; /* Unwarranted chumminess with compiler. */
+} regexp;
+
+extern regexp *regcomp();
+extern int regexec();
+#ifdef MULTILINE
+extern int reglexec();
+#endif
+extern void regsub();
+extern void regerror();
diff --git a/src/regexpmodule.c b/src/regexpmodule.c
new file mode 100644
index 0000000..7c87217
--- /dev/null
+++ b/src/regexpmodule.c
@@ -0,0 +1,191 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* Regular expression objects */
+/* This needs V8 or Henry Spencer's regexp! */
+
+#include "allobjects.h"
+#include "modsupport.h"
+
+#include "regexp.h"
+
+static object *RegexpError; /* Exception */
+
+typedef struct {
+ OB_HEAD
+ object *re_string; /* The string (for printing) */
+ regexp *re_prog; /* The compiled regular expression */
+} regexpobject;
+
+extern typeobject Regexptype; /* Really static, forward */
+
+static regexpobject *
+newregexpobject(string, prog)
+ object *string;
+ regexp *prog;
+{
+ regexpobject *re;
+ re = NEWOBJ(regexpobject, &Regexptype);
+ if (re != NULL) {
+ XINCREF(string);
+ re->re_string = string;
+ re->re_prog = prog;
+ }
+ return re;
+}
+
+/* Regexp methods */
+
+static void
+regexp_dealloc(re)
+ regexpobject *re;
+{
+ XDECREF(re->re_string);
+ XDEL(re->re_prog);
+ DEL(re);
+}
+
+static object *
+makeresult(prog, buffer)
+ regexp *prog;
+ char *buffer;
+{
+ int n;
+ object *v;
+ /* Count substrings found, including \0, the main one */
+ for (n = 0; n < 10 && prog->startp[n] != NULL; n++)
+ ;
+ v = newtupleobject(n);
+ if (v != NULL) {
+ int i;
+ for (i = 0; i < n; i++) {
+ object *w, *u;
+ long start, end;
+ start = prog->startp[i] - buffer;
+ end = prog->endp[i] - buffer;
+ if ( (w = newtupleobject(2)) == NULL ||
+ (u = newintobject(start)) == NULL ||
+ settupleitem(w, 0, u) != 0 ||
+ (u = newintobject(end)) == NULL ||
+ settupleitem(w, 1, u) != 0) {
+ XDECREF(w);
+ DECREF(v);
+ return NULL;
+ }
+ settupleitem(v, i, w);
+ }
+ }
+ return v;
+}
+
+static object *
+regexp_exec(re, args)
+ regexpobject *re;
+ object *args;
+{
+ object *v;
+ char *buffer;
+ int offset;
+ if (args != NULL && is_stringobject(args)) {
+ v = args;
+ offset = 0;
+ }
+ else if (!getstrintarg(args, &v, &offset))
+ return NULL;
+ buffer = getstringvalue(v);
+#ifndef MULTILINE
+#define reglexec(prog, str, offset) regexec((prog), (str)+(offset))
+#endif
+ if (!reglexec(re->re_prog, buffer, offset))
+ return newtupleobject(0);
+ return makeresult(re->re_prog, buffer);
+}
+
+static struct methodlist regexp_methods[] = {
+ "exec", regexp_exec,
+ {NULL, NULL} /* sentinel */
+};
+
+static object *
+regexp_getattr(re, name)
+ regexpobject *re;
+ char *name;
+{
+ return findmethod(regexp_methods, (object *)re, name);
+}
+
+static typeobject Regexptype = {
+ OB_HEAD_INIT(&Typetype)
+ 0, /*ob_size*/
+ "regexp", /*tp_name*/
+ sizeof(regexpobject), /*tp_size*/
+ 0, /*tp_itemsize*/
+ /* methods */
+ regexp_dealloc, /*tp_dealloc*/
+ 0, /*tp_print*/
+ regexp_getattr, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+};
+
+void
+regerror(str)
+ char *str;
+{
+ err_setstr(RegexpError, str);
+}
+
+static object *
+regexp_compile(self, args)
+ object *self;
+ object *args;
+{
+ object *string;
+ regexp *prog;
+ if (!getstrarg(args, &string))
+ return NULL;
+ prog = regcomp(getstringvalue(string));
+ if (prog == NULL)
+ return NULL; /* regerror() has called err_seterr() */
+ return (object *)newregexpobject(string, prog);
+}
+
+static struct methodlist regexp_global_methods[] = {
+ {"compile", regexp_compile},
+ {NULL, NULL} /* sentinel */
+};
+
+initregexp()
+{
+ object *m, *d;
+
+ m = initmodule("regexp", regexp_global_methods);
+ d = getmoduledict(m);
+
+ /* Initialize regexp.error exception */
+ RegexpError = newstringobject("regexp.error");
+ if (RegexpError == NULL || dictinsert(d, "error", RegexpError) != 0)
+ fatal("can't define regexp.error");
+}
diff --git a/src/regmagic.h b/src/regmagic.h
new file mode 100644
index 0000000..d9da879
--- /dev/null
+++ b/src/regmagic.h
@@ -0,0 +1,29 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/*
+ * The first byte of the regexp internal "program" is actually this magic
+ * number; the start node begins in the second byte.
+ */
+#define MAGIC 0234
diff --git a/src/regsub.c b/src/regsub.c
new file mode 100644
index 0000000..d589f26
--- /dev/null
+++ b/src/regsub.c
@@ -0,0 +1,115 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/*
+ * regsub
+ *
+ * Copyright (c) 1986 by University of Toronto.
+ * Written by Henry Spencer. Not derived from licensed software.
+#ifdef MULTILINE
+ * Changed by Guido van Rossum, CWI, Amsterdam
+ * for multi-line support.
+#endif
+ *
+ * Permission is granted to anyone to use this software for any
+ * purpose on any computer system, and to redistribute it freely,
+ * subject to the following restrictions:
+ *
+ * 1. The author is not responsible for the consequences of use of
+ * this software, no matter how awful, even if they arise
+ * from defects in it.
+ *
+ * 2. The origin of this software must not be misrepresented, either
+ * by explicit claim or by omission.
+ *
+ * 3. Altered versions must be plainly marked as such, and must not
+ * be misrepresented as being the original software.
+ */
+#include <stdio.h>
+#include "regexp.h"
+#include "regmagic.h"
+
+#ifndef CHARBITS
+#define UCHARAT(p) ((int)*(unsigned char *)(p))
+#else
+#define UCHARAT(p) ((int)*(p)&CHARBITS)
+#endif
+
+/*
+ - regsub - perform substitutions after a regexp match
+ */
+void
+regsub(prog, source, dest)
+regexp *prog;
+char *source;
+char *dest;
+{
+ register char *src;
+ register char *dst;
+ register char c;
+ register int no;
+ register int len;
+ extern char *strncpy();
+
+ if (prog == NULL || source == NULL || dest == NULL) {
+ regerror("NULL parm to regsub");
+ return;
+ }
+ if (UCHARAT(prog->program) != MAGIC) {
+ regerror("damaged regexp fed to regsub");
+ return;
+ }
+
+ src = source;
+ dst = dest;
+ while ((c = *src++) != '\0') {
+ if (c == '&')
+ no = 0;
+ else if (c == '\\' && '0' <= *src && *src <= '9')
+ no = *src++ - '0';
+ else
+ no = -1;
+
+ if (no < 0) { /* Ordinary character. */
+ if (c == '\\' && (*src == '\\' || *src == '&'))
+ c = *src++;
+#ifdef MULTILINE
+ else if (c == '\\' && *src == 'n') {
+ c = '\n';
+ src++;
+ }
+#endif
+ *dst++ = c;
+ } else if (prog->startp[no] != NULL && prog->endp[no] != NULL) {
+ len = prog->endp[no] - prog->startp[no];
+ (void) strncpy(dst, prog->startp[no], len);
+ dst += len;
+ if (len != 0 && *(dst-1) == '\0') { /* strncpy hit NUL. */
+ regerror("damaged match string");
+ return;
+ }
+ }
+ }
+ *dst++ = '\0';
+}
diff --git a/src/rltokenizer.c b/src/rltokenizer.c
new file mode 100644
index 0000000..6069148
--- /dev/null
+++ b/src/rltokenizer.c
@@ -0,0 +1,26 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+#define USE_READLINE
+#include "tokenizer.c"
diff --git a/src/sc_errors.c b/src/sc_errors.c
new file mode 100644
index 0000000..be815a1
--- /dev/null
+++ b/src/sc_errors.c
@@ -0,0 +1,145 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+
+#include <stdio.h>
+
+#include "PROTO.h"
+#include "object.h"
+#include "errors.h"
+#include "sc_errors.h"
+#include "stringobject.h"
+#include "tupleobject.h"
+
+object *
+err_scerr(sc_errno)
+ int sc_errno;
+{
+ switch(sc_errno) {
+
+ case NoBufSize:
+ err_setstr(StubcodeError, "Stubcode didn't start with BufSize");
+ break;
+
+ case TwoBufSize:
+ err_setstr(StubcodeError, "Stubcode can't have more then one BufSize");
+ break;
+
+ case ElementIsNull:
+ err_setstr(StubcodeError, "Trying to access an NIL object");
+ break;
+
+ case StackOverflow:
+ err_setstr(StubcodeError, "Stack overflow");
+ return NULL;
+
+ case StackUnderflow:
+ err_setstr(StubcodeError, "Stack underflow");
+ return NULL;
+
+ case NoEndLoop:
+ err_setstr(StubcodeError, "LoopXXX with no EndLoop");
+ return NULL;
+
+ case BufferOverflow:
+ err_setstr(StubcodeError, "Buffer overflow");
+ return NULL;
+
+ }
+ return NULL;
+}
+
+err_scerrset(sc_errno, value, instr)
+ int sc_errno;
+ object *value;
+ char *instr;
+{
+ object *str, *str1, *t;
+
+ if ((t = newtupleobject(3)) == NULL) {
+ return -1;
+ }
+ if ((str = newstringobject(instr)) == NULL) {
+ return -1;
+ }
+ if (settupleitem(t, 2, str) != 0) {
+ return -1;
+ }
+ INCREF(value);
+ if (settupleitem(t, 1, value) != 0) {
+ DECREF(t);
+ return -1;
+ }
+ switch(sc_errno) {
+
+ case TypeFailure:
+ if ((str1 = newstringobject("Unexpected type")) == NULL) {
+ DECREF(t);
+ return -1;
+ }
+ break;
+
+ case RangeError:
+ if ((str1 = newstringobject("Value out of range")) == NULL) {
+ DECREF(t);
+ return -1;
+ }
+ break;
+
+ case SizeError:
+ if ((str1 = newstringobject("Value doesn't have the right size")) == NULL) {
+ DECREF(t);
+ return -1;
+ }
+ break;
+
+ case FlagError:
+ if ((str1 = newstringobject("Illegal flag value")) == NULL) {
+ DECREF(t);
+ return -1;
+ }
+ break;
+
+ case TransError:
+ if ((str1 = newstringobject("hdr.h_status != 0")) == NULL) {
+ DECREF(t);
+ return -1;
+ }
+ break;
+
+ default:
+ if ((str1 = newstringobject("sc_errno not found")) == NULL) {
+ DECREF(t);
+ return -1;
+ }
+ break;
+ }
+ if (settupleitem(t, 0, str1) != 0) {
+ DECREF(t);
+ return -1;
+ }
+ err_setval(StubcodeError, t);
+ DECREF(t);
+ return -1;
+}
diff --git a/src/sc_errors.h b/src/sc_errors.h
new file mode 100644
index 0000000..d9fcd01
--- /dev/null
+++ b/src/sc_errors.h
@@ -0,0 +1,41 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+
+#define NoBufSize 1
+#define TwoBufSize 2
+#define StackOverflow 3
+#define StackUnderflow 4
+#define TypeFailure 5
+#define RangeError 6
+#define SizeError 7
+#define BufferOverflow 8
+#define NoEndLoop 9
+#define FlagError 10
+#define ElementIsNull 11
+#define TransError 12
+
+extern object *err_scerr PROTO((int sc_errno));
+extern err_scerrset PROTO((int sc_errno, object *value, char *instr));
+extern object *StubcodeError;
diff --git a/src/sc_global.h b/src/sc_global.h
new file mode 100644
index 0000000..ec03b15
--- /dev/null
+++ b/src/sc_global.h
@@ -0,0 +1,137 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+
+/*
+** This file contains the data used in Ail, Python and sc2txt.
+**
+** If you want to add an instuction to the instructions just define
+** it here and add the instruction in the function sc_interpreter in
+** the file sc_interpreter.c in the switch. You also have to make a
+** new function with the name x{instruction_name} in the file
+** sc_interpreter.
+*/
+
+/*
+** When you want to change the types of the opcode or the operand
+** you maybe need to adjust the options to mypf. And the defines :
+** SwapOpcode, SwapOperand.
+*/
+
+typedef unsigned char TscOpcode;
+typedef long TscOperand;
+
+#define SC_MAGIC 0x19901991
+
+#define SwapOpcode(x) x = x
+#define SwapOperand(l) ((l))=(((((l))>>24)&0xFF)|((((l))>>8)&0xFF00)|((((l))<<8)&0xFF0000)|((((l))<<24)&0xFF000000))
+
+#define STKSIZE 256
+
+#define OPERAND 0x80
+#define FLAGS 0x40
+
+/*
+** The headerfields. The value of the flag is the index of the fields
+** array from the file mhdr.c plus one
+*/
+
+#define H_EXTRA 0x00000001
+#define H_SIZE 0x00000002
+#define H_OFFSET 0x00000003
+#define H_PORT 0x00000004
+#define H_PRIV 0x00000005
+#define PSEUDOFIELD 0x00000006
+#define ALL_FIELDS 0x000000ff
+
+/*
+** The specefiers for the integers
+*/
+
+#define NOSIGN 0x00000100
+#define INT32 0x00000200
+#define ALLTYPES 0xffffff00
+
+/*
+** The opcode with no operand
+*/
+
+#define ListS 0x00
+#define PutVS 0x01
+#define GetVS 0x02
+#define StringS 0x03
+#define Equal 0x04
+#define NoArgs 0x05
+
+/*
+ * Between 0x10 and 0x3f there is space for predefined marshal
+ * and unmarshal functions or macros that do not have an operand
+ */
+
+#define MarshTC 0x10
+#define UnMarshTC 0x11
+
+/*
+** The opcode with a number as operand
+*/
+
+#define BufSize 0x80
+#define Trans 0x81
+#define TTupleS 0x82
+#define Unpack 0x83
+#define PutFS 0x84
+#define TStringSeq 0x85
+#define TStringSlt 0x86
+#define TListSeq 0x87
+#define TListSlt 0x88
+#define LoopPut 0x89
+#define EndLoop 0x8a
+#define Dup 0x8b
+#define Pop 0x8c
+#define Align 0x8d
+#define Pack 0x8e
+#define LoopGet 0x8f
+#define GetFS 0x90
+#define PushI 0x91
+
+/*
+** Between 0xa0 and 0xbf there is space for predefined marshal
+** and unmarshal functions or macros with a numberas operand
+*/
+
+
+/*
+** The opcodes with flags as operand
+*/
+
+#define AilWord 0xc0
+#define PutI 0xc1
+#define PutC 0xc2
+#define GetI 0xc3
+#define GetC 0xc4
+
+/*
+** Between 0xe0 and 0xff there is space for predefined marshal
+** and unmarshal functions or macros with flags as operand
+*/
diff --git a/src/sc_interpr.c b/src/sc_interpr.c
new file mode 100644
index 0000000..10eb1b2
--- /dev/null
+++ b/src/sc_interpr.c
@@ -0,0 +1,1352 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+#if 0
+#define STACK_TRACE
+#define SCDEBUG
+#endif
+#include <stdio.h>
+
+#include <ailamoeba.h>
+
+#include "PROTO.h"
+#include "sc_global.h"
+#include "object.h"
+#include "objimpl.h"
+#include "stringobject.h"
+#include "errors.h"
+#include "sc_errors.h"
+#include "stubcode.h"
+#include "tupleobject.h"
+#include "intobject.h"
+#include "listobject.h"
+
+typedef struct s_loopstruct {
+ struct s_loopstruct *l_next; /* Make a list of it */
+ TscOperand l_label; /* Indentify the loop */
+ int l_index; /* The index of the list */
+ int l_size; /* The size of the list */
+ int l_retaddr; /* Addres to jump back */
+ int l_endaddr; /* Addres to jump to end */
+ object *l_list; /* The list to append to */
+} TsLoop, *TpsLoop;
+
+
+/*
+** This file contains the Stubcode interpreter.
+** All the instructions have there own function. The interpreter
+** reads an instruction from the data and if needed also an operand.
+** After this it calls the function that executes the instruction.
+*/
+
+struct sc_ProcessBlock {
+ object **stack;
+ unsigned char *buffer, *data;
+ int sp, bp, pc, maxbufsize, datsize;
+ header hdr;
+ TpsLoop loops;
+};
+
+extern getcapability();
+
+/*
+ * Clean up the mess the loops make.
+ */
+
+static void
+xCleanUpLoops(sc_pb)
+ struct sc_ProcessBlock *sc_pb;
+{
+ TpsLoop prev, this;
+
+ if (sc_pb->loops == NULL)
+ return;
+ prev = sc_pb->loops;
+ this = sc_pb->loops->l_next;
+ while(this) {
+ free((char *)prev);
+ prev = this;
+ this = this->l_next;
+ }
+ free((char *)prev);
+}
+
+static int
+findendloop(label, sc_pb)
+ TscOperand label;
+ struct sc_ProcessBlock *sc_pb;
+{
+ TscOperand operand;
+ TscOpcode opcode;
+ int walk = sc_pb->pc, found = 0;
+
+ while (!found && (walk < sc_pb->datsize)) {
+ memcpy(&opcode, &sc_pb->data[walk], sizeof(TscOpcode));
+ walk += sizeof(TscOpcode);
+ if (opcode & (FLAGS | OPERAND)) {
+ memcpy(&operand, &sc_pb->data[walk], sizeof(TscOperand));
+ walk += sizeof(TscOperand);
+ }
+ if (opcode == EndLoop)
+ if (operand == label) found = 1;
+ }
+ if (found)
+ return walk;
+ return -1;
+}
+
+static int
+findloop(ret, label, sc_pb)
+ TpsLoop *ret;
+ TscOperand label;
+ struct sc_ProcessBlock *sc_pb;
+{
+ TpsLoop walk;
+
+ for (walk = sc_pb->loops; walk != NULL; walk = walk->l_next) {
+ if (walk->l_label == label) break;
+ }
+ if (walk == NULL) {
+ TpsLoop newloop;
+
+ newloop = (TpsLoop)malloc(sizeof(TsLoop));
+ if (newloop == NULL) {
+ err_nomem();
+ return -1;
+ }
+ newloop->l_label = label;
+ newloop->l_index = 0;
+ newloop->l_retaddr = sc_pb->pc - (sizeof(TscOpcode) + sizeof(TscOperand));
+ /*
+ ** We need a correction because the pc points to
+ ** the instruction after the XXXLoop.
+ */
+ if ((newloop->l_endaddr = findendloop(label, sc_pb)) < 0) {
+ free((char *)newloop);
+ err_scerr(NoEndLoop);
+ return -1;
+ }
+ newloop->l_list = NULL;
+ newloop->l_next = sc_pb->loops;
+ sc_pb->loops = newloop;
+ *ret = newloop;
+ return 1;
+ }
+ *ret = walk;
+ return 0;
+}
+
+#ifdef 0
+
+static void
+removeloop(this, sc_pb)
+ TpsLoop this;
+ struct sc_ProcessBlock *sc_pb;
+{
+ TpsLoop walk, prev = NULL;
+
+ for (walk = sc_pb->loops; walk != NULL; walk = walk->l_next) {
+ if (walk->l_label == this->l_label) {
+ if (prev != NULL) {
+ prev->l_next = walk->l_next;
+ } else {
+ loop = walk->l_next;
+ }
+ free((char *)this);
+ break;
+ }
+ prev = walk;
+ }
+}
+
+#endif
+
+static int
+init(self, sc_pb)
+ object *self;
+ struct sc_ProcessBlock *sc_pb;
+{
+object *string;
+int datasize;
+
+ string = gettupleitem(self, STUBC);
+ if (string == NULL)
+ return -1;
+ sc_pb->data = getstringvalue(string);
+ if (sc_pb->data == NULL)
+ return -1;
+ datasize = (int)getstringsize(string);
+ if (datasize == -1)
+ return -1;
+ sc_pb->stack = (object **)malloc(STKSIZE * sizeof(object *));
+ if (sc_pb->stack == NULL) {
+ err_nomem();
+ return -1;
+ }
+ sc_pb->bp = sc_pb->sp = sc_pb->pc = 0;
+ sc_pb->loops = NULL;
+ return datasize;
+}
+
+static void reinit(sc_pb)
+ struct sc_ProcessBlock *sc_pb;
+{
+ int i;
+
+ sc_pb->bp = 0;
+ for (i = 0; i < sc_pb->sp; i++) {
+ DECREF(sc_pb->stack[i]);
+ }
+ sc_pb->sp = 0;
+}
+
+static void UnInit(self, sc_pb)
+ object *self;
+ struct sc_ProcessBlock *sc_pb;
+{
+ int i;
+
+ free(sc_pb->buffer);
+ reinit(sc_pb);
+ free((char *)sc_pb->stack);
+ xCleanUpLoops(sc_pb);
+}
+
+static object *
+stacktop(sc_pb)
+ struct sc_ProcessBlock *sc_pb;
+{
+
+ if (sc_pb->sp == 0)
+ return err_scerr(StackUnderflow);
+ if (sc_pb->sp == (STKSIZE + 1))
+ return err_scerr(StackOverflow);
+ return sc_pb->stack[sc_pb->sp - 1];
+}
+
+/*
+ * Push an object on the stack.
+ */
+static int
+xPush(element, sc_pb)
+ object *element;
+ struct sc_ProcessBlock *sc_pb;
+{
+
+ if (sc_pb->sp >= STKSIZE) {
+ err_scerr(StackOverflow);
+ return -1;
+ }
+ if (element == NULL) {
+ err_scerr(ElementIsNull);
+ return -1;
+ }
+ INCREF(element);
+#ifdef STACK_TRACE
+ printf("pushed :");
+ printobject(element, stdout, 0);
+ printf("\n");
+#endif
+ sc_pb->stack[sc_pb->sp++] = element;
+ return 0;
+}
+
+/*
+ * Perform the RPC.
+ */
+static int
+xTrans(self,cmd, sc_pb)
+ object *self;
+ TscOperand cmd;
+ struct sc_ProcessBlock *sc_pb;
+{
+ short ret;
+ capability cap;
+ object *capobj;
+
+ if ((capobj = gettupleitem(self, CAP)) == NULL)
+ return -1;
+ if (getcapability(capobj, &cap) == -1)
+ return -1;
+ sc_pb->hdr.h_port = cap.cap_port;
+ sc_pb->hdr.h_priv = cap.cap_priv;
+ sc_pb->hdr.h_command = (command)cmd;
+#ifdef SCDEBUG
+ printf("bp = %d maxbufsize = %d\n",sc_pb->bp, sc_pb->maxbufsize);
+ {
+ int i;
+
+ for (i = 0; i < sc_pb->bp; i++) {
+ printf("%x ", sc_pb->buffer[i]);
+ }
+ }
+ printf("\n");
+#endif
+ ret = trans(&sc_pb->hdr, sc_pb->buffer, (bufsize) sc_pb->bp,
+ &sc_pb->hdr, sc_pb->buffer, (bufsize)sc_pb->maxbufsize);
+#ifdef SCDEBUG
+ printf("after Trans:ret = %d\n",ret);
+ {
+ int i;
+
+ for (i = 0; i < ret; i++) {
+ printf("%x ", sc_pb->buffer[i]);
+ }
+ }
+ printf("\n");
+#endif
+ if (ERR_STATUS(ret)) {
+ amoeba_error(ERR_CONVERT(ret));
+ return -1;
+ }
+ if (sc_pb->hdr.h_status != 0) {
+ object *v;
+
+ if ((v = newintobject(sc_pb->hdr.h_status)) == NULL)
+ return -1;
+ err_scerrset(TransError, v, "Trans");
+ DECREF(v);
+ return -1;
+ }
+ reinit(sc_pb);
+ return 0;
+}
+
+/*
+ * Test the tuple size.
+ */
+static int
+xTTupleS(size, sc_pb)
+ TscOperand size;
+ struct sc_ProcessBlock *sc_pb;
+{
+ object *tuple;
+
+ if ((tuple = stacktop(sc_pb)) == NULL)
+ return -1;
+ if (!is_tupleobject(tuple))
+ return err_scerrset(TypeFailure, tuple, "TTupleS");
+ if (gettuplesize(tuple) != (unsigned int)size)
+ return err_scerrset(SizeError, tuple, "TTupleS");
+ return 0;
+}
+
+/*
+ * Unpack a tuple
+ */
+static int
+xUnpack(size, sc_pb)
+ TscOperand size;
+ struct sc_ProcessBlock *sc_pb;
+{
+ object *tuple, *element;
+ int i;
+
+ if (size < (TscOperand)2) {
+ element = newintobject(size);
+ if (element == NULL)
+ return -1;
+ return err_scerrset(SizeError, element, "Unpack");
+ }
+ if ((tuple = stacktop(sc_pb)) == NULL)
+ return -1;
+ INCREF(tuple);
+ if (xPop((TscOperand) 1, sc_pb) != 0) {
+ DECREF(tuple);
+ return -1;
+ }
+ for (i = 0; i < (int)size; i++) {
+ if ((element = gettupleitem(tuple, i)) == NULL) {
+ DECREF(tuple);
+ return -1;
+ }
+ if (xPush(element, sc_pb) != 0) {
+ DECREF(tuple);
+ return -1;
+ }
+ }
+ DECREF(tuple);
+ return 0;
+}
+
+/*
+ * Marshal the Ailword to a headerfiels.
+ */
+static int
+xAilword(headerfield, sc_pb)
+ TscOperand headerfield;
+ struct sc_ProcessBlock *sc_pb;
+{
+
+ switch(headerfield) {
+
+ case H_EXTRA:
+ sc_pb->hdr.h_extra = (uint16)_ailword;
+ return 0;
+
+ case H_SIZE:
+ sc_pb->hdr.h_size = (bufsize)_ailword;
+ return 0;
+
+ case H_OFFSET:
+ sc_pb->hdr.h_offset = (int32)_ailword;
+ return 0;
+
+ default:
+ {
+ object *v;
+
+ if ((v = newintobject(headerfield)) == NULL)
+ return -1;
+ return err_scerrset(FlagError, v, "Ailword");
+ }
+ }
+}
+
+static int
+xStringS(sc_pb)
+ struct sc_ProcessBlock *sc_pb;
+{
+ object *size, *string;
+ int s;
+
+ if ((string = stacktop(sc_pb)) == NULL)
+ return -1;
+ if (!is_stringobject(string))
+ return err_scerrset(TypeFailure, string, "StringS");
+ if ((s = getstringsize(string)) < 0)
+ return -1;
+ if (xPop((TscOperand) 1, sc_pb) != 0)
+ return -1;
+ if ((size = newintobject(s)) == NULL)
+ return -1;
+ if (xPush(size, sc_pb) != 0) {
+ DECREF(size);
+ return -1;
+ }
+ DECREF(size);
+ return 0;
+}
+
+/*
+ *
+ */
+static int
+xListS(sc_pb)
+ struct sc_ProcessBlock *sc_pb;
+{
+ object *size, *list;
+ int s;
+
+ if ((list = stacktop(sc_pb)) == NULL)
+ return -1;
+ if (!is_listobject(list))
+ return err_scerrset(TypeFailure, list, "ListS");
+ if ((s = getlistsize(list)) < 0)
+ return -1;
+ if (xPop((TscOperand) 1, sc_pb) != 0)
+ return -1;
+ if ((size = newintobject(s)) == NULL)
+ return -1;
+ if (xPush(size, sc_pb) != 0) {
+ DECREF(size);
+ return -1;
+ }
+ DECREF(size);
+ return 0;
+}
+
+/*
+ * Marshal a fixed string to the buffer.
+ */
+static int
+xPutFS(size, sc_pb)
+ TscOperand size;
+ struct sc_ProcessBlock *sc_pb;
+{
+ object *string;
+ char *str;
+
+ if ((string = stacktop(sc_pb)) == NULL) {
+ return -1;
+ }
+ if (!is_stringobject(string))
+ return err_scerrset(TypeFailure, string, "PutFS");
+ if (getstringsize(string) != size)
+ return err_scerrset(SizeError, string, "PutFS");
+ if ((str = getstringvalue(string)) == NULL)
+ return -1;
+ if ((size + sc_pb->bp) > sc_pb->maxbufsize) {
+ err_scerr(BufferOverflow);
+ return -1;
+ }
+ memcpy(&sc_pb->buffer[sc_pb->bp], str, (int)size);
+ sc_pb->bp += size;
+ return xPop((TscOperand) 1, sc_pb);
+}
+
+
+/*
+ * Test the size of a string or list
+ */
+static int
+xTStringSeq(size, sc_pb)
+ TscOperand size;
+ struct sc_ProcessBlock *sc_pb;
+{
+ object *string;
+
+ if ((string = stacktop(sc_pb)) == NULL)
+ return -1;
+ if (!is_stringobject(string))
+ return err_scerrset(TypeFailure, string, "TStringSeq");
+ if (getstringsize(string) != size)
+ return err_scerrset(SizeError, string, "TStringSeq");
+ return 0;
+}
+
+static int
+xTStringSlt(size, sc_pb)
+ TscOperand size;
+ struct sc_ProcessBlock *sc_pb;
+{
+ object *string;
+
+ if ((string = stacktop(sc_pb)) == NULL)
+ return -1;
+ if (!is_stringobject(string))
+ return err_scerrset(TypeFailure, string, "TStringSlt");
+ if (getstringsize(string) > size)
+ return err_scerrset(SizeError, string, "TStringSlt");
+ return 0;
+}
+
+static int
+xTListSeq(size, sc_pb)
+ TscOperand size;
+ struct sc_ProcessBlock *sc_pb;
+{
+ object *list;
+
+ if ((list = stacktop(sc_pb)) == NULL)
+ return -1;
+ if (!is_listobject(list))
+ return err_scerrset(TypeFailure, list, "TListSeq");
+ if (getlistsize(list) != size)
+ return err_scerrset(SizeError, list, "TListSeq");
+ return 0;
+}
+
+static int
+xTListSlt(size, sc_pb)
+ TscOperand size;
+ struct sc_ProcessBlock *sc_pb;
+{
+ object *list;
+
+ if ((list = stacktop(sc_pb)) == NULL)
+ return -1;
+ if (!is_listobject(list))
+ return err_scerrset(TypeFailure, list, "TListSlt");
+ if (getlistsize(list) > size)
+ return err_scerrset(SizeError, list, "TListSlt");
+ return 0;
+}
+
+static int
+xPutVS(sc_pb)
+ struct sc_ProcessBlock *sc_pb;
+{
+ object *string;
+ char *str;
+ int size;
+
+ if ((string = stacktop(sc_pb)) == NULL)
+ return -1;
+ if ((size = getstringsize(string)) < 0)
+ return (size == -1 ? -1 : err_scerrset(SizeError, string, "PutVS"));
+ if ((str = getstringvalue(string)) == NULL)
+ return -1;
+ if (sc_pb->bp + size > sc_pb->maxbufsize) {
+ err_scerr(BufferOverflow);
+ return -1;
+ }
+ memcpy(&sc_pb->buffer[sc_pb->bp], str, size);
+ sc_pb->bp += size;
+ return xPop((TscOperand) 1, sc_pb);
+}
+
+/*
+ * The loop instructions.
+ */
+static int
+xLoopPut(label, sc_pb)
+ TscOperand label;
+ struct sc_ProcessBlock *sc_pb;
+{
+ TpsLoop this;
+ object *list, *element;
+
+ if (findloop(&this, label, sc_pb) < 0)
+ return -1;
+ if ((list = stacktop(sc_pb)) == NULL)
+ return -1;
+ if (!is_listobject(list))
+ return err_scerrset(TypeFailure, list, "LoopPut");
+ if (this->l_index >= getlistsize(list)) {
+ sc_pb->pc = this->l_endaddr;
+ /*
+ ** Pop the list from the stack
+ */
+ return xPop((TscOperand)1, sc_pb);
+ }
+ if ((element = getlistitem(list, this->l_index)) == NULL)
+ return -1;
+ return xPush(element, sc_pb);
+}
+
+static int
+xLoopGet(label, sc_pb)
+ TscOperand label;
+ struct sc_ProcessBlock *sc_pb;
+{
+ TpsLoop this;
+ object *element, *integer;
+ int i;
+
+ if ((i = findloop(&this, label, sc_pb)) < 0)
+ return -1;
+ else if (i == 1) {
+ /*
+ * It is the first time we enter LoopGet label
+ */
+ if ((this->l_list = newlistobject(0)) == NULL)
+ return -1;
+ if ((integer = stacktop(sc_pb)) == NULL)
+ return -1;
+ if (!is_intobject(integer))
+ return err_scerrset(TypeFailure, integer, "LoopGet");
+ this->l_size = getintvalue(integer);
+ if (xPop((TscOperand) 1, sc_pb) != 0)
+ return -1;
+ } else {
+ if ((element = stacktop(sc_pb)) == NULL)
+ return -1;
+ if (addlistitem(this->l_list, element) != 0)
+ return -1;
+ if (xPop((TscOperand) 1, sc_pb) != 0)
+ return -1;
+ }
+ if (this->l_index >= this->l_size) {
+ int ret;
+
+ sc_pb->pc = this->l_endaddr;
+ ret = xPush(this->l_list, sc_pb);
+ DECREF(this->l_list);
+ return ret;
+ }
+ return 0;
+}
+
+static int
+xEndLoop(label, sc_pb)
+ TscOperand label;
+ struct sc_ProcessBlock *sc_pb;
+{
+ TpsLoop this;
+
+ if (findloop(&this, label, sc_pb) < 0)
+ return -1;
+ this ->l_index += 1;
+ sc_pb->pc = this->l_retaddr;
+ return 0;
+}
+
+static int
+xPutI(flags, sc_pb)
+ TscOperand flags;
+ struct sc_ProcessBlock *sc_pb;
+{
+ object *integer;
+
+ if ((integer = stacktop(sc_pb)) == NULL)
+ return -1;
+ if (!is_intobject(integer))
+ return err_scerrset(TypeFailure, integer, "PutI");
+ if (flags & ALL_FIELDS) {
+ long i;
+
+ /*
+ * The integer must be marshalles in the header.
+ * No type casting according to the type flag because
+ * we have to cast to the headerfield types.
+ */
+ i = getintvalue(integer);
+ switch(flags & ALL_FIELDS) {
+
+ case H_EXTRA:
+ sc_pb->hdr.h_extra = (uint16)i;
+ break;
+
+ case H_SIZE:
+ sc_pb->hdr.h_size = (bufsize)i;
+ break;
+
+ case H_OFFSET:
+ sc_pb->hdr.h_offset = (int32)i;
+ break;
+
+ default:
+ if ((integer = newintobject(flags & ALL_FIELDS)) == NULL)
+ return -1;
+ err_scerrset(FlagError, integer, "Ailword");
+ DECREF(integer);
+ return -1;
+ }
+ } else {
+ long i;
+
+ i = getintvalue(integer);
+ switch(flags & ALLTYPES) {
+
+ case 0:
+ {
+ int16 x;
+
+ x = (int16)i;
+ if ((sc_pb->bp + sizeof(int16)) > sc_pb->maxbufsize) {
+ err_scerr(BufferOverflow);
+ return -1;
+ }
+ memcpy(&sc_pb->buffer[sc_pb->bp], &x, sizeof(int16));
+ sc_pb->bp += sizeof(int16);
+ break;
+ }
+
+ case NOSIGN:
+ {
+ uint16 x;
+
+ x = (uint16)i;
+ if ((sc_pb->bp + sizeof(uint16)) > sc_pb->maxbufsize) {
+ err_scerr(BufferOverflow);
+ return -1;
+ }
+ memcpy(&sc_pb->buffer[sc_pb->bp], &x, sizeof(uint16));
+ sc_pb->bp += sizeof(uint16);
+ break;
+ }
+
+ case INT32:
+ {
+ int32 x;
+
+ x = (int32)i;
+ if ((sc_pb->bp + sizeof(int32)) > sc_pb->maxbufsize) {
+ err_scerr(BufferOverflow);
+ return -1;
+ }
+ memcpy(&sc_pb->buffer[sc_pb->bp], &x, sizeof(int32));
+ sc_pb->bp += sizeof(int32);
+ break;
+ }
+
+ case INT32 | NOSIGN:
+ {
+ uint32 x;
+
+ x = (uint32)i;
+ if ((sc_pb->bp + sizeof(uint32)) > sc_pb->maxbufsize) {
+ err_scerr(BufferOverflow);
+ return -1;
+ }
+ memcpy(&sc_pb->buffer[sc_pb->bp], &x, sizeof(uint32));
+ sc_pb->bp += sizeof(uint32);
+ break;
+ }
+ default:
+ {
+ object *x;
+
+ if ((x = newintobject(flags)) == NULL)
+ return -1;
+ err_scerrset(FlagError, x, "PutI");
+ DECREF(x);
+ return -1;
+ }
+ }
+ }
+ return xPop((TscOperand)1, sc_pb);
+}
+
+static int
+xPutC(sc_pb)
+ struct sc_ProcessBlock *sc_pb;
+{
+ capability cap;
+ object *capobj;
+
+ if ((capobj = stacktop(sc_pb)) == NULL)
+ return -1;
+ if (!is_capobj(capobj))
+ return err_scerrset(TypeFailure, capobj, "xPutC");
+ if (getcapability(capobj, &cap) != 0)
+ return -1;
+ if ((sc_pb->bp + CAPSIZE) > sc_pb->maxbufsize) {
+ err_scerr(BufferOverflow);
+ return -1;
+ }
+ memcpy(&sc_pb->buffer[sc_pb->bp], &cap, CAPSIZE);
+ sc_pb->bp += CAPSIZE;
+ return xPop((TscOperand) 1, sc_pb);
+}
+
+static int
+xDup(n, sc_pb)
+ TscOperand n;
+ struct sc_ProcessBlock *sc_pb;
+{
+
+ if ((int)n > sc_pb->sp) {
+ object *i;
+
+ if ((i = newintobject((long)n)) == NULL)
+ return -1;
+ err_scerrset(RangeError, i, "Dup");
+ DECREF(i);
+ return -1;
+ }
+ return xPush(sc_pb->stack[sc_pb->sp - n], sc_pb);
+}
+
+static int
+xPop(n, sc_pb)
+ TscOperand n;
+ struct sc_ProcessBlock *sc_pb;
+{
+ int i;
+
+ if ((sc_pb->sp - (int)n) < 0) {
+ err_scerr(StackUnderflow);
+ return -1;
+ }
+ for (i = 0; i < (int)n; i++) {
+ sc_pb->sp--;
+#ifdef STACK_TRACE
+ printf("popped :");
+ printobject(sc_pb->stack[sc_pb->sp], stdout, 0);
+ printf("\n");
+#endif
+ DECREF(sc_pb->stack[sc_pb->sp]);
+ }
+ return 0;
+}
+
+static int
+xAlign(n, sc_pb)
+ TscOperand n;
+ struct sc_ProcessBlock *sc_pb;
+{
+ int align = sc_pb->bp % (int)n;
+
+#ifdef SCDEBUG
+ printf("Old bp = %d\n", sc_pb->bp);
+#endif
+ sc_pb->bp += (align == 0) ? 0 : ((int)n - align);
+#ifdef SCDEBUG
+ printf("New bp = %d\n", sc_pb->bp);
+#endif
+ return 0;
+}
+
+static int
+xPack(size, sc_pb)
+ TscOperand size;
+ struct sc_ProcessBlock *sc_pb;
+{
+ object *element, *tuple;
+ int i, ret;
+
+ if ((tuple = newtupleobject((int)size)) == NULL)
+ return -1;
+ for (i = 0; i < (int)size; i++) {
+ if ((element = stacktop(sc_pb)) == NULL)
+ return -1;
+ if (settupleitem(tuple, (int)size - i - 1, element) != 0)
+ return -1;
+ INCREF(element);
+ if (xPop((TscOperand) 1, sc_pb) != 0)
+ return -1;
+ }
+ ret = xPush(tuple, sc_pb);
+ DECREF(tuple);
+ return ret;
+}
+
+static int
+xGetVS(sc_pb)
+ struct sc_ProcessBlock *sc_pb;
+{
+ object *string, *integer;
+ int size;
+
+ if ((integer = stacktop(sc_pb)) == NULL)
+ return -1;
+ if (!is_intobject(integer))
+ return err_scerrset(TypeFailure, integer, "GetVS");
+ size = getintvalue(integer);
+ if ((sc_pb->bp + size) > sc_pb->maxbufsize) {
+ err_scerr(BufferOverflow);
+ return -1;
+ }
+ if ((string = newsizedstringobject(&sc_pb->buffer[sc_pb->bp], size)) == NULL)
+ return -1;
+ sc_pb->bp += size;
+ if (xPop((TscOperand) 1, sc_pb) != 0)
+ return -1;
+ if (xPush(string, sc_pb) != 0) {
+ return -1;
+ }
+ DECREF(string);
+ return 0;
+}
+
+static int
+xGetFS(size, sc_pb)
+ TscOperand size;
+ struct sc_ProcessBlock *sc_pb;
+{
+ object *string;
+
+ if ((sc_pb->bp + (int)size) > sc_pb->maxbufsize) {
+ err_scerr(BufferOverflow);
+ return -1;
+ }
+ if ((string = newsizedstringobject(&sc_pb->buffer[sc_pb->bp], (int)size)) == NULL)
+ return -1;
+ sc_pb->bp += (int)size;
+ if(xPush(string, sc_pb) != 0) {
+ return -1;
+ }
+ DECREF(string);
+ return 0;
+}
+
+static int
+xGetI(flags, sc_pb)
+ TscOperand flags;
+ struct sc_ProcessBlock *sc_pb;
+{
+ object *integer;
+ long i;
+
+ if (flags & ALL_FIELDS) {
+
+ switch(flags & ALL_FIELDS) {
+
+ case H_EXTRA:
+ i = (long)sc_pb->hdr.h_extra;
+ break;
+
+ case H_SIZE:
+ i = (long)sc_pb->hdr.h_size;
+ break;
+
+ case H_OFFSET:
+ i = (long)sc_pb->hdr.h_offset;
+ break;
+
+ default:
+ if ((integer = newintobject(flags & ALL_FIELDS)) == NULL)
+ return -1;
+ err_scerrset(FlagError, integer, "Ailword");
+ DECREF(integer);
+ return -1;
+ }
+ } else {
+ switch(flags & ALLTYPES) {
+
+ case 0:
+ {
+ int16 x;
+
+ if ((sc_pb->bp + sizeof(int16)) > sc_pb->maxbufsize) {
+ err_scerr(BufferOverflow);
+ return -1;
+ }
+ memcpy(&x, &sc_pb->buffer[sc_pb->bp], sizeof(int16));
+ sc_pb->bp += sizeof(int16);
+ i = (long)x;
+ break;
+ }
+
+ case NOSIGN:
+ {
+ uint16 x;
+
+ if ((sc_pb->bp + sizeof(uint16)) > sc_pb->maxbufsize) {
+ err_scerr(BufferOverflow);
+ return -1;
+ }
+ memcpy(&x, &sc_pb->buffer[sc_pb->bp], sizeof(uint16));
+ sc_pb->bp += sizeof(uint16);
+ i = (long)x;
+ break;
+ }
+
+ case INT32:
+ {
+ int32 x;
+
+ if ((sc_pb->bp + sizeof(int32)) > sc_pb->maxbufsize) {
+ err_scerr(BufferOverflow);
+ return -1;
+ }
+ memcpy(&x, &sc_pb->buffer[sc_pb->bp], sizeof(int32));
+ sc_pb->bp += sizeof(int32);
+ i = (long)x;
+ break;
+ }
+
+ case INT32 | NOSIGN:
+ {
+ uint32 x;
+
+ if ((sc_pb->bp + sizeof(uint32)) > sc_pb->maxbufsize) {
+ err_scerr(BufferOverflow);
+ return -1;
+ }
+ memcpy(&x, &sc_pb->buffer[sc_pb->bp], sizeof(uint32));
+ sc_pb->bp += sizeof(uint32);
+ i = (long)x;
+ break;
+ }
+ default:
+ {
+ if ((integer = newintobject(flags)) == NULL)
+ return -1;
+ err_scerrset(FlagError, integer, "GetI");
+ DECREF(integer);
+ return -1;
+ }
+ }
+ }
+ if ((integer = newintobject(i)) == NULL)
+ return -1;
+ if (xPush(integer, sc_pb) != 0) {
+ DECREF(integer);
+ return -1;
+ }
+ DECREF(integer);
+ return 0;
+}
+
+static int
+xGetC(flags, sc_pb)
+ TscOperand flags;
+ struct sc_ProcessBlock *sc_pb;
+{
+ extern object *newcapobject();
+ object *capobj;
+ capability cap;
+
+ if ((int)flags != 0) {
+ switch ((int)flags) {
+
+ case PSEUDOFIELD:
+ cap.cap_port = sc_pb->hdr.h_port;
+ cap.cap_priv = sc_pb->hdr.h_priv;
+ break;
+ }
+ } else {
+ if ((CAPSIZE + sc_pb->bp) > sc_pb->maxbufsize) {
+ err_scerr(BufferOverflow);
+ return -1;
+ }
+ memcpy(&cap, &sc_pb->buffer[sc_pb->bp], CAPSIZE);
+ }
+ if ((capobj = newcapobject(&cap)) == NULL)
+ return -1;
+ return xPush(capobj, sc_pb);
+}
+
+static int
+xEqual(sc_pb)
+ struct sc_ProcessBlock *sc_pb;
+{
+ object *int1, *int2;
+
+ if (sc_pb->sp < 2) {
+ err_scerr(StackUnderflow);
+ return -1;
+ }
+ int1 = sc_pb->stack[sc_pb->sp - 1];
+ int2 = sc_pb->stack[sc_pb->sp - 2];
+ if ((int1 == NULL) || (int2 == NULL))
+ return -1;
+ if (!is_intobject(int1))
+ return err_scerrset(TypeFailure, int1, "Equal");
+ if (!is_intobject(int2))
+ return err_scerrset(TypeFailure, int2, "Equal");
+ if (getintvalue(int1) != getintvalue(int2)) {
+ object *tmptuple;
+
+ if ((tmptuple = newtupleobject(2)) == NULL)
+ return -1;
+ INCREF(int1);
+ if (settupleitem(tmptuple, 0, int1) != 0) {
+ DECREF(tmptuple);
+ DECREF(int1);
+ return -1;
+ }
+ if (settupleitem(tmptuple, 1, int2) != 0) {
+ DECREF(tmptuple);
+ DECREF(int2);
+ return -1;
+ }
+ return err_scerrset(SizeError, tmptuple, "Equal");
+ }
+ return 0;
+}
+
+object *
+sc_interpreter(self, args)
+ object *self, *args;
+{
+TscOpcode opcode;
+TscOperand operand;
+int datasize, ret;
+object *returnobject;
+struct sc_ProcessBlock sc_pb;
+
+ if ((datasize = init(self, &sc_pb)) < 0)
+ return NULL;
+ memcpy(&opcode, sc_pb.data, sizeof(TscOpcode));
+ sc_pb.datsize = datasize;
+ sc_pb.pc += sizeof(TscOpcode);
+ if (opcode != BufSize) {
+ free((char *)sc_pb.stack);
+ return err_scerr(NoBufSize);
+ }
+ memcpy(&operand, &sc_pb.data[sc_pb.pc], sizeof(TscOperand));
+ sc_pb.pc += sizeof(TscOperand);
+ sc_pb.buffer = (unsigned char *)malloc(operand);
+ sc_pb.maxbufsize = (int)operand;
+ if (sc_pb.buffer == NULL) {
+ free((char *)sc_pb.stack);
+ return err_nomem();
+ }
+ memcpy(&opcode, &sc_pb.data[sc_pb.pc], sizeof(TscOpcode));
+ if (opcode != NoArgs) {
+ if (xPush(args, &sc_pb) != 0) {
+ UnInit(self, &sc_pb);
+ return NULL;
+ }
+ }
+ while (sc_pb.pc < datasize) {
+ memcpy(&opcode, &sc_pb.data[sc_pb.pc], sizeof(TscOpcode));
+ sc_pb.pc += sizeof(TscOpcode);
+ if (opcode & (OPERAND | FLAGS)) {
+ memcpy(&operand, &sc_pb.data[sc_pb.pc], sizeof(TscOperand));
+ sc_pb.pc += sizeof(TscOperand);
+ }
+#ifdef SCDEBUG
+ xPrintCode(opcode);
+ if ((opcode & FLAGS) && (opcode & OPERAND))
+ xPrintFlags(operand);
+ else if (opcode & OPERAND)
+ xPrintNum(operand);
+ printf("\n");
+ fflush(stdout);
+#endif
+#ifdef STACK_TRACE
+ {
+ register i;
+
+ printf("Stack trace :\n");
+ for(i = 0; i < sc_pb.sp; i++) {
+ printobject(sc_pb.stack[i], stdout, 0);
+ printf("\n");
+ }
+ }
+#endif
+ switch(opcode) {
+
+ case NoArgs:
+ ret = 0;
+ if (args != NULL) {
+ err_scerrset(TypeFailure, args, "NoArgs");
+ ret = -1;
+ }
+ break;
+
+ case BufSize:
+ UnInit(self, &sc_pb);
+ return err_scerr(TwoBufSize);
+
+ case Trans:
+ ret = xTrans(self, operand, &sc_pb);
+ break;
+
+ case TTupleS:
+ ret = xTTupleS(operand, &sc_pb);
+ break;
+
+ case Unpack:
+ ret = xUnpack(operand, &sc_pb);
+ break;
+
+ case AilWord:
+ ret = xAilword(operand, &sc_pb);
+ break;
+
+ case StringS:
+ ret = xStringS(&sc_pb);
+ break;
+
+ case ListS:
+ ret = xListS(&sc_pb);
+ break;
+
+ case PutFS:
+ ret = xPutFS(operand, &sc_pb);
+ break;
+
+ case TStringSeq:
+ ret = xTStringSeq(operand, &sc_pb);
+ break;
+
+ case TStringSlt:
+ ret = xTStringSlt(operand, &sc_pb);
+ break;
+
+ case PutVS:
+ ret = xPutVS(&sc_pb);
+ break;
+
+ case TListSeq:
+ ret = xTListSeq(operand, &sc_pb);
+ break;
+
+ case TListSlt:
+
+ret = xTListSlt(operand, &sc_pb);
+ break;
+
+ case LoopPut:
+ ret = xLoopPut(operand, &sc_pb);
+ break;
+
+ case EndLoop:
+ ret = xEndLoop(operand, &sc_pb);
+ break;
+
+ case PutI:
+ ret = xPutI(operand, &sc_pb);
+ break;
+
+ case PutC:
+ ret = xPutC(&sc_pb);
+ break;
+
+ case Dup:
+ ret = xDup(operand, &sc_pb);
+ break;
+
+ case Pop:
+ ret = xPop(operand, &sc_pb);
+ break;
+
+ case Align:
+ ret = xAlign(operand, &sc_pb);
+ break;
+
+ case Pack:
+ ret = xPack(operand, &sc_pb);
+ break;
+
+ case GetVS:
+ ret = xGetVS(&sc_pb);
+ break;
+
+ case LoopGet:
+ ret = xLoopGet(operand, &sc_pb);
+ break;
+
+ case GetFS:
+ ret = xGetFS(operand, &sc_pb);
+ break;
+
+ case GetI:
+ ret = xGetI(operand, &sc_pb);
+ break;
+
+ case GetC:
+ ret = xGetC(operand, &sc_pb);
+ break;
+
+ case PushI:
+ {
+ object *element;
+
+ element = newintobject((long)operand);
+ if (element == NULL) {
+ UnInit(self, &sc_pb);
+ return NULL;
+ }
+ ret = xPush(element, &sc_pb);
+ if (ret == 0)
+ DECREF(element);
+ }
+ break;
+
+ case Equal:
+ ret = xEqual(&sc_pb);
+ break;
+
+ default:
+ {
+ char errstr[256];
+
+ UnInit(self, &sc_pb);
+ sprintf(errstr, "Unknow stubcode %d", opcode);
+ err_setstr(RuntimeError, errstr);
+ return NULL;
+ }
+ }
+ if (ret != 0) {
+ UnInit(self, &sc_pb);
+ return NULL;
+ }
+ }
+ if (sc_pb.sp > 0) {
+ INCREF(sc_pb.stack[sc_pb.sp - 1]);
+ returnobject = sc_pb.stack[sc_pb.sp - 1];
+ } else {
+ INCREF(None);
+ returnobject = None;
+ }
+ UnInit(self, &sc_pb);
+ return returnobject;
+}
diff --git a/src/scdbg.c b/src/scdbg.c
new file mode 100644
index 0000000..4510896
--- /dev/null
+++ b/src/scdbg.c
@@ -0,0 +1,152 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+
+#include "sc_global.h"
+
+void xPrintNum(Num)
+TscOperand Num;
+{
+
+ printf(" %ld",(long)Num);
+}
+
+void xPrintFlags(Flags)
+TscOperand Flags;
+{
+long x;
+
+ x = (long)Flags;
+ x = x & 0x0000000F;
+ if (x == H_EXTRA) printf(" h_extra");
+ if (x == H_SIZE) printf(" h_size");
+ if (x == H_OFFSET) printf(" h_offset");
+ if (x == H_PORT) printf(" h_port");
+ if (x == H_PRIV) printf(" h_priv");
+ if (x == PSEUDOFIELD) printf(" h_port and h_priv");
+ x = (long)Flags;
+ if (x & NOSIGN) printf(" unsigned");
+ if (x & INT32) printf(" int32");
+}
+
+void xPrintCode(Opcode)
+TscOpcode Opcode;
+{
+
+ switch (Opcode) {
+
+ case BufSize: printf("BufSize");
+ break;
+
+ case Trans: printf("Trans");
+ break;
+
+ case TTupleS: printf("TTupleS");
+ break;
+
+ case Unpack: printf("Unpack");
+ break;
+
+ case AilWord: printf("AilWord");
+ break;
+
+ case ListS: printf("ListS");
+ break;
+
+ case StringS: printf("StringS");
+ break;
+
+ case PutFS: printf("PutFS");
+ break;
+
+ case TStringSeq: printf("TStringSeq");
+ break;
+
+ case TStringSlt: printf("TStringSlt");
+ break;
+
+ case PutVS: printf("PutVS");
+ break;
+
+ case TListSeq: printf("TListSeq");
+ break;
+
+ case TListSlt: printf("TListSlt");
+ break;
+
+ case LoopPut: printf("LoopPut");
+ break;
+
+ case EndLoop: printf("EndLoop");
+ break;
+
+ case PutI: printf("PutI");
+ break;
+
+ case PutC: printf("PutC");
+ break;
+
+ case Dup: printf("Dup");
+ break;
+
+ case Pop: printf("Pop");
+ break;
+
+ case Align: printf("Align");
+ break;
+
+ case Pack: printf("Pack");
+ break;
+
+ case GetVS: printf("GetVS");
+ break;
+
+ case LoopGet: printf("LoopGet");
+ break;
+
+ case GetFS: printf("GetFS");
+ break;
+
+ case GetI: printf("GetI");
+ break;
+
+ case GetC: printf("GetC");
+ break;
+
+ case PushI: printf("PushI");
+ break;
+
+ case MarshTC: printf("MarshTC");
+ break;
+
+ case UnMarshTC: printf("UnMarshTC");
+ break;
+
+ case Equal: printf("Equal");
+ break;
+
+ default: printf("Unknown opcode %04x",(int)Opcode);
+ break;
+ }
+}
diff --git a/src/sigtype.h b/src/sigtype.h
new file mode 100644
index 0000000..5cfd4b3
--- /dev/null
+++ b/src/sigtype.h
@@ -0,0 +1,51 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* The type of signal handlers is somewhat problematic.
+ This file encapsulates my knowledge about it:
+ - on the Mac (THINK C), it's int for 3.0, void for 4.0
+ - on other systems, it's usually void, except it's int on vax Ultrix.
+ Pass -DSIGTYPE=... to cc if you know better. */
+
+#ifndef SIGTYPE
+
+#ifdef THINK_C
+
+#ifdef THINK_C_3_0
+#define SIGTYPE int
+#else
+#define SIGTYPE void
+#endif
+
+#else /* !THINK_C */
+
+#if defined(vax) && !defined(AMOEBA)
+#define SIGTYPE int
+#else
+#define SIGTYPE void
+#endif
+
+#endif /* !THINK_C */
+
+#endif /* !SIGTYPE */
diff --git a/src/stdwinmodule.c b/src/stdwinmodule.c
new file mode 100644
index 0000000..75b1fc8
--- /dev/null
+++ b/src/stdwinmodule.c
@@ -0,0 +1,1697 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* Stdwin module */
+
+/* Stdwin itself is a module, not a separate object type.
+ Object types defined here:
+ wp: a window
+ dp: a drawing structure (only one can exist at a time)
+ mp: a menu
+ tp: a textedit block
+*/
+
+/* Rules for translating C stdwin function calls into Python stwin:
+ - All names drop their initial letter 'w'
+ - Functions with a window as first parameter are methods of window objects
+ - There is no equivalent for wclose(); just delete the window object
+ (all references to it!) (XXX maybe this is a bad idea)
+ - w.begindrawing() returns a drawing object
+ - There is no equivalent for wenddrawing(win); just delete the drawing
+ object (all references to it!) (XXX maybe this is a bad idea)
+ - Functions that may only be used inside wbegindrawing / wendddrawing
+ are methods of the drawing object; this includes the text measurement
+ functions (which however have doubles as module functions).
+ - Methods of the drawing object drop an initial 'draw' from their name
+ if they have it, e.g., wdrawline() --> d.line()
+ - The obvious type conversions: int --> intobject; string --> stringobject
+ - A text parameter followed by a length parameter is only a text (string)
+ parameter in Python
+ - A point or other pair of horizontal and vertical coordinates is always
+ a pair of integers in Python
+ - Two points forming a rectangle or endpoints of a line segment are a
+ pair of points in Python
+ - The arguments to d.elarc() are three points.
+ - The functions wgetclip() and wsetclip() are translated into
+ stdwin.getcutbuffer() and stdwin.setcutbuffer(); 'clip' is really
+ a bad word for what these functions do (clipping has a different
+ meaning in the drawing world), while cutbuffer is standard X jargon.
+ XXX This must change again in the light of changes to stdwin!
+ - For textedit, similar rules hold, but they are less strict.
+ XXX more?
+*/
+
+#include "allobjects.h"
+
+#include "modsupport.h"
+
+#include "stdwin.h"
+
+/* Window and menu object types declared here because of forward references */
+
+typedef struct {
+ OB_HEAD
+ object *w_title;
+ WINDOW *w_win;
+ object *w_attr; /* Attributes dictionary */
+} windowobject;
+
+extern typeobject Windowtype; /* Really static, forward */
+
+#define is_windowobject(wp) ((wp)->ob_type == &Windowtype)
+
+typedef struct {
+ OB_HEAD
+ MENU *m_menu;
+ int m_id;
+ object *m_attr; /* Attributes dictionary */
+} menuobject;
+
+extern typeobject Menutype; /* Really static, forward */
+
+#define is_menuobject(mp) ((mp)->ob_type == &Menutype)
+
+
+/* Strongly stdwin-specific argument handlers */
+
+static int
+getmousedetail(v, ep)
+ object *v;
+ EVENT *ep;
+{
+ if (v == NULL || !is_tupleobject(v) || gettuplesize(v) != 4)
+ return err_badarg();
+ return getintintarg(gettupleitem(v, 0),
+ &ep->u.where.h, &ep->u.where.v) &&
+ getintarg(gettupleitem(v, 1), &ep->u.where.clicks) &&
+ getintarg(gettupleitem(v, 2), &ep->u.where.button) &&
+ getintarg(gettupleitem(v, 3), &ep->u.where.mask);
+}
+
+static int
+getmenudetail(v, ep)
+ object *v;
+ EVENT *ep;
+{
+ object *mp;
+ if (v == NULL || !is_tupleobject(v) || gettuplesize(v) != 2)
+ return err_badarg();
+ mp = gettupleitem(v, 0);
+ if (mp == NULL || !is_menuobject(mp))
+ return err_badarg();
+ ep->u.m.id = ((menuobject *)mp) -> m_id;
+ return getintarg(gettupleitem(v, 1), &ep->u.m.item);
+}
+
+static int
+geteventarg(v, ep)
+ object *v;
+ EVENT *ep;
+{
+ object *wp, *detail;
+ int a[4];
+ if (v == NULL || !is_tupleobject(v) || gettuplesize(v) != 3)
+ return err_badarg();
+ if (!getintarg(gettupleitem(v, 0), &ep->type))
+ return 0;
+ wp = gettupleitem(v, 1);
+ if (wp == None)
+ ep->window = NULL;
+ else if (wp == NULL || !is_windowobject(wp))
+ return err_badarg();
+ else
+ ep->window = ((windowobject *)wp) -> w_win;
+ detail = gettupleitem(v, 2);
+ switch (ep->type) {
+ case WE_CHAR:
+ if (!is_stringobject(detail) || getstringsize(detail) != 1)
+ return err_badarg();
+ ep->u.character = getstringvalue(detail)[0];
+ return 1;
+ case WE_COMMAND:
+ return getintarg(detail, &ep->u.command);
+ case WE_DRAW:
+ if (!getrectarg(detail, a))
+ return 0;
+ ep->u.area.left = a[0];
+ ep->u.area.top = a[1];
+ ep->u.area.right = a[2];
+ ep->u.area.bottom = a[3];
+ return 1;
+ case WE_MOUSE_DOWN:
+ case WE_MOUSE_UP:
+ case WE_MOUSE_MOVE:
+ return getmousedetail(detail, ep);
+ case WE_MENU:
+ return getmenudetail(detail, ep);
+ default:
+ return 1;
+ }
+}
+
+
+/* Return construction tools */
+
+static object *
+makepoint(a, b)
+ int a, b;
+{
+ object *v;
+ object *w;
+ if ((v = newtupleobject(2)) == NULL)
+ return NULL;
+ if ((w = newintobject((long)a)) == NULL ||
+ settupleitem(v, 0, w) != 0 ||
+ (w = newintobject((long)b)) == NULL ||
+ settupleitem(v, 1, w) != 0) {
+ DECREF(v);
+ return NULL;
+ }
+ return v;
+}
+
+static object *
+makerect(a, b, c, d)
+ int a, b, c, d;
+{
+ object *v;
+ object *w;
+ if ((v = newtupleobject(2)) == NULL)
+ return NULL;
+ if ((w = makepoint(a, b)) == NULL ||
+ settupleitem(v, 0, w) != 0 ||
+ (w = makepoint(c, d)) == NULL ||
+ settupleitem(v, 1, w) != 0) {
+ DECREF(v);
+ return NULL;
+ }
+ return v;
+}
+
+static object *
+makemouse(hor, ver, clicks, button, mask)
+ int hor, ver, clicks, button, mask;
+{
+ object *v;
+ object *w;
+ if ((v = newtupleobject(4)) == NULL)
+ return NULL;
+ if ((w = makepoint(hor, ver)) == NULL ||
+ settupleitem(v, 0, w) != 0 ||
+ (w = newintobject((long)clicks)) == NULL ||
+ settupleitem(v, 1, w) != 0 ||
+ (w = newintobject((long)button)) == NULL ||
+ settupleitem(v, 2, w) != 0 ||
+ (w = newintobject((long)mask)) == NULL ||
+ settupleitem(v, 3, w) != 0) {
+ DECREF(v);
+ return NULL;
+ }
+ return v;
+}
+
+static object *
+makemenu(mp, item)
+ object *mp;
+ int item;
+{
+ object *v;
+ object *w;
+ if ((v = newtupleobject(2)) == NULL)
+ return NULL;
+ INCREF(mp);
+ if (settupleitem(v, 0, mp) != 0 ||
+ (w = newintobject((long)item)) == NULL ||
+ settupleitem(v, 1, w) != 0) {
+ DECREF(v);
+ return NULL;
+ }
+ return v;
+}
+
+
+/* Drawing objects */
+
+typedef struct {
+ OB_HEAD
+ windowobject *d_ref;
+} drawingobject;
+
+static drawingobject *Drawing; /* Set to current drawing object, or NULL */
+
+/* Drawing methods */
+
+static void
+drawing_dealloc(dp)
+ drawingobject *dp;
+{
+ wenddrawing(dp->d_ref->w_win);
+ Drawing = NULL;
+ DECREF(dp->d_ref);
+ free((char *)dp);
+}
+
+static object *
+drawing_generic(dp, args, func)
+ drawingobject *dp;
+ object *args;
+ void (*func) FPROTO((int, int, int, int));
+{
+ int a[4];
+ if (!getrectarg(args, a))
+ return NULL;
+ (*func)(a[0], a[1], a[2], a[3]);
+ INCREF(None);
+ return None;
+}
+
+static object *
+drawing_line(dp, args)
+ drawingobject *dp;
+ object *args;
+{
+ drawing_generic(dp, args, wdrawline);
+}
+
+static object *
+drawing_xorline(dp, args)
+ drawingobject *dp;
+ object *args;
+{
+ drawing_generic(dp, args, wxorline);
+}
+
+static object *
+drawing_circle(dp, args)
+ drawingobject *dp;
+ object *args;
+{
+ int a[3];
+ if (!getpointintarg(args, a))
+ return NULL;
+ wdrawcircle(a[0], a[1], a[2]);
+ INCREF(None);
+ return None;
+}
+
+static object *
+drawing_elarc(dp, args)
+ drawingobject *dp;
+ object *args;
+{
+ int a[6];
+ if (!get3pointarg(args, a))
+ return NULL;
+ wdrawelarc(a[0], a[1], a[2], a[3], a[4], a[5]);
+ INCREF(None);
+ return None;
+}
+
+static object *
+drawing_box(dp, args)
+ drawingobject *dp;
+ object *args;
+{
+ drawing_generic(dp, args, wdrawbox);
+}
+
+static object *
+drawing_erase(dp, args)
+ drawingobject *dp;
+ object *args;
+{
+ drawing_generic(dp, args, werase);
+}
+
+static object *
+drawing_paint(dp, args)
+ drawingobject *dp;
+ object *args;
+{
+ drawing_generic(dp, args, wpaint);
+}
+
+static object *
+drawing_invert(dp, args)
+ drawingobject *dp;
+ object *args;
+{
+ drawing_generic(dp, args, winvert);
+}
+
+static object *
+drawing_cliprect(dp, args)
+ drawingobject *dp;
+ object *args;
+{
+ drawing_generic(dp, args, wcliprect);
+}
+
+static object *
+drawing_noclip(dp, args)
+ drawingobject *dp;
+ object *args;
+{
+ if (!getnoarg(args))
+ return NULL;
+ wnoclip();
+ INCREF(None);
+ return None;
+}
+
+static object *
+drawing_shade(dp, args)
+ drawingobject *dp;
+ object *args;
+{
+ int a[5];
+ if (!getrectintarg(args, a))
+ return NULL;
+ wshade(a[0], a[1], a[2], a[3], a[4]);
+ INCREF(None);
+ return None;
+}
+
+static object *
+drawing_text(dp, args)
+ drawingobject *dp;
+ object *args;
+{
+ int a[2];
+ object *s;
+ if (!getpointstrarg(args, a, &s))
+ return NULL;
+ wdrawtext(a[0], a[1], getstringvalue(s), (int)getstringsize(s));
+ INCREF(None);
+ return None;
+}
+
+/* The following four are also used as stdwin functions */
+
+static object *
+drawing_lineheight(dp, args)
+ drawingobject *dp;
+ object *args;
+{
+ if (!getnoarg(args))
+ return NULL;
+ return newintobject((long)wlineheight());
+}
+
+static object *
+drawing_baseline(dp, args)
+ drawingobject *dp;
+ object *args;
+{
+ if (!getnoarg(args))
+ return NULL;
+ return newintobject((long)wbaseline());
+}
+
+static object *
+drawing_textwidth(dp, args)
+ drawingobject *dp;
+ object *args;
+{
+ object *s;
+ if (!getstrarg(args, &s))
+ return NULL;
+ return newintobject(
+ (long)wtextwidth(getstringvalue(s), (int)getstringsize(s)));
+}
+
+static object *
+drawing_textbreak(dp, args)
+ drawingobject *dp;
+ object *args;
+{
+ object *s;
+ int a;
+ if (!getstrintarg(args, &s, &a))
+ return NULL;
+ return newintobject(
+ (long)wtextbreak(getstringvalue(s), (int)getstringsize(s), a));
+}
+
+static struct methodlist drawing_methods[] = {
+ {"box", drawing_box},
+ {"circle", drawing_circle},
+ {"cliprect", drawing_cliprect},
+ {"elarc", drawing_elarc},
+ {"erase", drawing_erase},
+ {"invert", drawing_invert},
+ {"line", drawing_line},
+ {"noclip", drawing_noclip},
+ {"paint", drawing_paint},
+ {"shade", drawing_shade},
+ {"text", drawing_text},
+ {"xorline", drawing_xorline},
+
+ /* Text measuring methods: */
+ {"baseline", drawing_baseline},
+ {"lineheight", drawing_lineheight},
+ {"textbreak", drawing_textbreak},
+ {"textwidth", drawing_textwidth},
+ {NULL, NULL} /* sentinel */
+};
+
+static object *
+drawing_getattr(wp, name)
+ drawingobject *wp;
+ char *name;
+{
+ return findmethod(drawing_methods, (object *)wp, name);
+}
+
+static typeobject Drawingtype = {
+ OB_HEAD_INIT(&Typetype)
+ 0, /*ob_size*/
+ "drawing", /*tp_name*/
+ sizeof(drawingobject), /*tp_size*/
+ 0, /*tp_itemsize*/
+ /* methods */
+ drawing_dealloc, /*tp_dealloc*/
+ 0, /*tp_print*/
+ drawing_getattr, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+};
+
+
+/* Text(edit) objects */
+
+typedef struct {
+ OB_HEAD
+ TEXTEDIT *t_text;
+ windowobject *t_ref;
+ object *t_attr; /* Attributes dictionary */
+} textobject;
+
+extern typeobject Texttype; /* Really static, forward */
+
+static textobject *
+newtextobject(wp, left, top, right, bottom)
+ windowobject *wp;
+ int left, top, right, bottom;
+{
+ textobject *tp;
+ tp = NEWOBJ(textobject, &Texttype);
+ if (tp == NULL)
+ return NULL;
+ tp->t_attr = NULL;
+ INCREF(wp);
+ tp->t_ref = wp;
+ tp->t_text = tecreate(wp->w_win, left, top, right, bottom);
+ if (tp->t_text == NULL) {
+ DECREF(tp);
+ return (textobject *) err_nomem();
+ }
+ return tp;
+}
+
+/* Text(edit) methods */
+
+static void
+text_dealloc(tp)
+ textobject *tp;
+{
+ if (tp->t_text != NULL)
+ tefree(tp->t_text);
+ if (tp->t_attr != NULL)
+ DECREF(tp->t_attr);
+ DECREF(tp->t_ref);
+ DEL(tp);
+}
+
+static object *
+text_arrow(self, args)
+ textobject *self;
+ object *args;
+{
+ int code;
+ if (!getintarg(args, &code))
+ return NULL;
+ tearrow(self->t_text, code);
+ INCREF(None);
+ return None;
+}
+
+static object *
+text_draw(self, args)
+ textobject *self;
+ object *args;
+{
+ register TEXTEDIT *tp = self->t_text;
+ int a[4];
+ int left, top, right, bottom;
+ if (!getrectarg(args, a))
+ return NULL;
+ if (Drawing != NULL) {
+ err_setstr(RuntimeError, "not drawing");
+ return NULL;
+ }
+ /* Clip to text area and ignore if area is empty */
+ left = tegetleft(tp);
+ top = tegettop(tp);
+ right = tegetright(tp);
+ bottom = tegetbottom(tp);
+ if (a[0] < left) a[0] = left;
+ if (a[1] < top) a[1] = top;
+ if (a[2] > right) a[2] = right;
+ if (a[3] > bottom) a[3] = bottom;
+ if (a[0] < a[2] && a[1] < a[3]) {
+ /* Hide/show focus around draw call; these are undocumented,
+ but required here to get the highlighting correct.
+ The call to werase is also required for this reason.
+ Finally, this forces us to require (above) that we are NOT
+ already drawing. */
+ tehidefocus(tp);
+ wbegindrawing(self->t_ref->w_win);
+ werase(a[0], a[1], a[2], a[3]);
+ tedrawnew(tp, a[0], a[1], a[2], a[3]);
+ wenddrawing(self->t_ref->w_win);
+ teshowfocus(tp);
+ }
+ INCREF(None);
+ return None;
+}
+
+static object *
+text_event(self, args)
+ textobject *self;
+ object *args;
+{
+ register TEXTEDIT *tp = self->t_text;
+ EVENT e;
+ if (!geteventarg(args, &e))
+ return NULL;
+ if (e.type == WE_MOUSE_DOWN) {
+ /* Cheat at the margins */
+ int width, height;
+ wgetdocsize(e.window, &width, &height);
+ if (e.u.where.h < 0 && tegetleft(tp) == 0)
+ e.u.where.h = 0;
+ else if (e.u.where.h > width && tegetright(tp) == width)
+ e.u.where.h = width;
+ if (e.u.where.v < 0 && tegettop(tp) == 0)
+ e.u.where.v = 0;
+ else if (e.u.where.v > height && tegetright(tp) == height)
+ e.u.where.v = height;
+ }
+ return newintobject((long) teevent(tp, &e));
+}
+
+static object *
+text_getfocus(self, args)
+ textobject *self;
+ object *args;
+{
+ if (!getnoarg(args))
+ return NULL;
+ return makepoint(tegetfoc1(self->t_text), tegetfoc2(self->t_text));
+}
+
+static object *
+text_getfocustext(self, args)
+ textobject *self;
+ object *args;
+{
+ int f1, f2;
+ char *text;
+ if (!getnoarg(args))
+ return NULL;
+ f1 = tegetfoc1(self->t_text);
+ f2 = tegetfoc2(self->t_text);
+ text = tegettext(self->t_text);
+ return newsizedstringobject(text + f1, f2-f1);
+}
+
+static object *
+text_getrect(self, args)
+ textobject *self;
+ object *args;
+{
+ if (!getnoarg(args))
+ return NULL;
+ return makerect(tegetleft(self->t_text),
+ tegettop(self->t_text),
+ tegetright(self->t_text),
+ tegetbottom(self->t_text));
+}
+
+static object *
+text_gettext(self, args)
+ textobject *self;
+ object *args;
+{
+ if (!getnoarg(args))
+ return NULL;
+ return newsizedstringobject(tegettext(self->t_text),
+ tegetlen(self->t_text));
+}
+
+static object *
+text_move(self, args)
+ textobject *self;
+ object *args;
+{
+ int a[4];
+ if (!getrectarg(args, a))
+ return NULL;
+ temovenew(self->t_text, a[0], a[1], a[2], a[3]);
+ INCREF(None);
+ return None;
+}
+
+static object *
+text_setfocus(self, args)
+ textobject *self;
+ object *args;
+{
+ int a[2];
+ if (!getpointarg(args, a))
+ return NULL;
+ tesetfocus(self->t_text, a[0], a[1]);
+ INCREF(None);
+ return None;
+}
+
+static object *
+text_replace(self, args)
+ textobject *self;
+ object *args;
+{
+ object *text;
+ if (!getstrarg(args, &text))
+ return NULL;
+ tereplace(self->t_text, getstringvalue(text));
+ INCREF(None);
+ return None;
+}
+
+static struct methodlist text_methods[] = {
+ "arrow", text_arrow,
+ "draw", text_draw,
+ "event", text_event,
+ "getfocus", text_getfocus,
+ "getfocustext", text_getfocustext,
+ "getrect", text_getrect,
+ "gettext", text_gettext,
+ "move", text_move,
+ "replace", text_replace,
+ "setfocus", text_setfocus,
+ {NULL, NULL} /* sentinel */
+};
+
+static object *
+text_getattr(tp, name)
+ textobject *tp;
+ char *name;
+{
+ if (tp->t_attr != NULL) {
+ object *v = dictlookup(tp->t_attr, name);
+ if (v != NULL) {
+ INCREF(v);
+ return v;
+ }
+ }
+ return findmethod(text_methods, (object *)tp, name);
+}
+
+static int
+text_setattr(tp, name, v)
+ textobject *tp;
+ char *name;
+ object *v;
+{
+ if (tp->t_attr == NULL) {
+ tp->t_attr = newdictobject();
+ if (tp->t_attr == NULL)
+ return -1;
+ }
+ if (v == NULL)
+ return dictremove(tp->t_attr, name);
+ else
+ return dictinsert(tp->t_attr, name, v);
+}
+
+static typeobject Texttype = {
+ OB_HEAD_INIT(&Typetype)
+ 0, /*ob_size*/
+ "textedit", /*tp_name*/
+ sizeof(textobject), /*tp_size*/
+ 0, /*tp_itemsize*/
+ /* methods */
+ text_dealloc, /*tp_dealloc*/
+ 0, /*tp_print*/
+ text_getattr, /*tp_getattr*/
+ text_setattr, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+};
+
+
+/* Menu objects */
+
+#define IDOFFSET 10 /* Menu IDs we use start here */
+#define MAXNMENU 20 /* Max #menus we allow */
+static menuobject *menulist[MAXNMENU];
+
+static menuobject *
+newmenuobject(title)
+ object *title;
+{
+ int id;
+ MENU *menu;
+ menuobject *mp;
+ for (id = 0; id < MAXNMENU; id++) {
+ if (menulist[id] == NULL)
+ break;
+ }
+ if (id >= MAXNMENU)
+ return (menuobject *) err_nomem();
+ menu = wmenucreate(id + IDOFFSET, getstringvalue(title));
+ if (menu == NULL)
+ return (menuobject *) err_nomem();
+ mp = NEWOBJ(menuobject, &Menutype);
+ if (mp != NULL) {
+ mp->m_menu = menu;
+ mp->m_id = id + IDOFFSET;
+ mp->m_attr = NULL;
+ menulist[id] = mp;
+ }
+ else
+ wmenudelete(menu);
+ return mp;
+}
+
+/* Menu methods */
+
+static void
+menu_dealloc(mp)
+ menuobject *mp;
+{
+
+ int id = mp->m_id - IDOFFSET;
+ if (id >= 0 && id < MAXNMENU && menulist[id] == mp) {
+ menulist[id] = NULL;
+ }
+ wmenudelete(mp->m_menu);
+ if (mp->m_attr != NULL)
+ DECREF(mp->m_attr);
+ DEL(mp);
+}
+
+static object *
+menu_additem(self, args)
+ menuobject *self;
+ object *args;
+{
+ object *text;
+ int shortcut;
+ if (is_tupleobject(args)) {
+ object *v;
+ if (!getstrstrarg(args, &text, &v))
+ return NULL;
+ if (getstringsize(v) != 1) {
+ err_badarg();
+ return NULL;
+ }
+ shortcut = *getstringvalue(v) & 0xff;
+ }
+ else {
+ if (!getstrarg(args, &text))
+ return NULL;
+ shortcut = -1;
+ }
+ wmenuadditem(self->m_menu, getstringvalue(text), shortcut);
+ INCREF(None);
+ return None;
+}
+
+static object *
+menu_setitem(self, args)
+ menuobject *self;
+ object *args;
+{
+ int index;
+ object *text;
+ if (!getintstrarg(args, &index, &text))
+ return NULL;
+ wmenusetitem(self->m_menu, index, getstringvalue(text));
+ INCREF(None);
+ return None;
+}
+
+static object *
+menu_enable(self, args)
+ menuobject *self;
+ object *args;
+{
+ int index;
+ int flag;
+ if (!getintintarg(args, &index, &flag))
+ return NULL;
+ wmenuenable(self->m_menu, index, flag);
+ INCREF(None);
+ return None;
+}
+
+static object *
+menu_check(self, args)
+ menuobject *self;
+ object *args;
+{
+ int index;
+ int flag;
+ if (!getintintarg(args, &index, &flag))
+ return NULL;
+ wmenucheck(self->m_menu, index, flag);
+ INCREF(None);
+ return None;
+}
+
+static struct methodlist menu_methods[] = {
+ "additem", menu_additem,
+ "setitem", menu_setitem,
+ "enable", menu_enable,
+ "check", menu_check,
+ {NULL, NULL} /* sentinel */
+};
+
+static object *
+menu_getattr(mp, name)
+ menuobject *mp;
+ char *name;
+{
+ if (mp->m_attr != NULL) {
+ object *v = dictlookup(mp->m_attr, name);
+ if (v != NULL) {
+ INCREF(v);
+ return v;
+ }
+ }
+ return findmethod(menu_methods, (object *)mp, name);
+}
+
+static int
+menu_setattr(mp, name, v)
+ menuobject *mp;
+ char *name;
+ object *v;
+{
+ if (mp->m_attr == NULL) {
+ mp->m_attr = newdictobject();
+ if (mp->m_attr == NULL)
+ return -1;
+ }
+ if (v == NULL)
+ return dictremove(mp->m_attr, name);
+ else
+ return dictinsert(mp->m_attr, name, v);
+}
+
+static typeobject Menutype = {
+ OB_HEAD_INIT(&Typetype)
+ 0, /*ob_size*/
+ "menu", /*tp_name*/
+ sizeof(menuobject), /*tp_size*/
+ 0, /*tp_itemsize*/
+ /* methods */
+ menu_dealloc, /*tp_dealloc*/
+ 0, /*tp_print*/
+ menu_getattr, /*tp_getattr*/
+ menu_setattr, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+};
+
+
+/* Windows */
+
+#define MAXNWIN 50
+static windowobject *windowlist[MAXNWIN];
+
+/* Window methods */
+
+static void
+window_dealloc(wp)
+ windowobject *wp;
+{
+ if (wp->w_win != NULL) {
+ int tag = wgettag(wp->w_win);
+ if (tag >= 0 && tag < MAXNWIN)
+ windowlist[tag] = NULL;
+ else
+ fprintf(stderr, "XXX help! tag %d in window_dealloc\n",
+ tag);
+ wclose(wp->w_win);
+ }
+ DECREF(wp->w_title);
+ if (wp->w_attr != NULL)
+ DECREF(wp->w_attr);
+ free((char *)wp);
+}
+
+static void
+window_print(wp, fp, flags)
+ windowobject *wp;
+ FILE *fp;
+ int flags;
+{
+ fprintf(fp, "<window titled '%s'>", getstringvalue(wp->w_title));
+}
+
+static object *
+window_begindrawing(wp, args)
+ windowobject *wp;
+ object *args;
+{
+ drawingobject *dp;
+ if (!getnoarg(args))
+ return NULL;
+ if (Drawing != NULL) {
+ err_setstr(RuntimeError, "already drawing");
+ return NULL;
+ }
+ dp = NEWOBJ(drawingobject, &Drawingtype);
+ if (dp == NULL)
+ return NULL;
+ Drawing = dp;
+ INCREF(wp);
+ dp->d_ref = wp;
+ wbegindrawing(wp->w_win);
+ return (object *)dp;
+}
+
+static object *
+window_change(wp, args)
+ windowobject *wp;
+ object *args;
+{
+ int a[4];
+ if (!getrectarg(args, a))
+ return NULL;
+ wchange(wp->w_win, a[0], a[1], a[2], a[3]);
+ INCREF(None);
+ return None;
+}
+
+static object *
+window_gettitle(wp, args)
+ windowobject *wp;
+ object *args;
+{
+ if (!getnoarg(args))
+ return NULL;
+ INCREF(wp->w_title);
+ return wp->w_title;
+}
+
+static object *
+window_getwinsize(wp, args)
+ windowobject *wp;
+ object *args;
+{
+ int width, height;
+ if (!getnoarg(args))
+ return NULL;
+ wgetwinsize(wp->w_win, &width, &height);
+ return makepoint(width, height);
+}
+
+static object *
+window_getdocsize(wp, args)
+ windowobject *wp;
+ object *args;
+{
+ int width, height;
+ if (!getnoarg(args))
+ return NULL;
+ wgetdocsize(wp->w_win, &width, &height);
+ return makepoint(width, height);
+}
+
+static object *
+window_getorigin(wp, args)
+ windowobject *wp;
+ object *args;
+{
+ int width, height;
+ if (!getnoarg(args))
+ return NULL;
+ wgetorigin(wp->w_win, &width, &height);
+ return makepoint(width, height);
+}
+
+static object *
+window_scroll(wp, args)
+ windowobject *wp;
+ object *args;
+{
+ int a[6];
+ if (!getrectpointarg(args, a))
+ return NULL;
+ wscroll(wp->w_win, a[0], a[1], a[2], a[3], a[4], a[5]);
+ INCREF(None);
+ return None;
+}
+
+static object *
+window_setdocsize(wp, args)
+ windowobject *wp;
+ object *args;
+{
+ int a[2];
+ if (!getpointarg(args, a))
+ return NULL;
+ wsetdocsize(wp->w_win, a[0], a[1]);
+ INCREF(None);
+ return None;
+}
+
+static object *
+window_setorigin(wp, args)
+ windowobject *wp;
+ object *args;
+{
+ int a[2];
+ if (!getpointarg(args, a))
+ return NULL;
+ wsetorigin(wp->w_win, a[0], a[1]);
+ INCREF(None);
+ return None;
+}
+
+static object *
+window_settitle(wp, args)
+ windowobject *wp;
+ object *args;
+{
+ object *title;
+ if (!getstrarg(args, &title))
+ return NULL;
+ DECREF(wp->w_title);
+ INCREF(title);
+ wp->w_title = title;
+ wsettitle(wp->w_win, getstringvalue(title));
+ INCREF(None);
+ return None;
+}
+
+static object *
+window_show(wp, args)
+ windowobject *wp;
+ object *args;
+{
+ int a[4];
+ if (!getrectarg(args, a))
+ return NULL;
+ wshow(wp->w_win, a[0], a[1], a[2], a[3]);
+ INCREF(None);
+ return None;
+}
+
+static object *
+window_settimer(wp, args)
+ windowobject *wp;
+ object *args;
+{
+ int a;
+ if (!getintarg(args, &a))
+ return NULL;
+ wsettimer(wp->w_win, a);
+ INCREF(None);
+ return None;
+}
+
+static object *
+window_menucreate(self, args)
+ windowobject *self;
+ object *args;
+{
+ menuobject *mp;
+ object *title;
+ if (!getstrarg(args, &title))
+ return NULL;
+ wmenusetdeflocal(1);
+ mp = newmenuobject(title);
+ if (mp == NULL)
+ return NULL;
+ wmenuattach(self->w_win, mp->m_menu);
+ return (object *)mp;
+}
+
+static object *
+window_textcreate(self, args)
+ windowobject *self;
+ object *args;
+{
+ textobject *tp;
+ int a[4];
+ if (!getrectarg(args, a))
+ return NULL;
+ return (object *)
+ newtextobject(self, a[0], a[1], a[2], a[3]);
+}
+
+static object *
+window_setselection(self, args)
+ windowobject *self;
+ object *args;
+{
+ int sel;
+ object *str;
+ int ok;
+ if (!getintstrarg(args, &sel, &str))
+ return NULL;
+ ok = wsetselection(self->w_win, sel,
+ getstringvalue(str), (int)getstringsize(str));
+ return newintobject(ok);
+}
+
+static object *
+window_setwincursor(self, args)
+ windowobject *self;
+ object *args;
+{
+ object *str;
+ CURSOR *c;
+ if (!getstrarg(args, &str))
+ return NULL;
+ c = wfetchcursor(getstringvalue(str));
+ if (c == NULL) {
+ err_setstr(RuntimeError, "no such cursor");
+ return NULL;
+ }
+ wsetwincursor(self->w_win, c);
+ INCREF(None);
+ return None;
+}
+
+static struct methodlist window_methods[] = {
+ {"begindrawing",window_begindrawing},
+ {"change", window_change},
+ {"getdocsize", window_getdocsize},
+ {"getorigin", window_getorigin},
+ {"gettitle", window_gettitle},
+ {"getwinsize", window_getwinsize},
+ {"menucreate", window_menucreate},
+ {"scroll", window_scroll},
+ {"setwincursor",window_setwincursor},
+ {"setdocsize", window_setdocsize},
+ {"setorigin", window_setorigin},
+ {"setselection",window_setselection},
+ {"settimer", window_settimer},
+ {"settitle", window_settitle},
+ {"show", window_show},
+ {"textcreate", window_textcreate},
+ {NULL, NULL} /* sentinel */
+};
+
+static object *
+window_getattr(wp, name)
+ windowobject *wp;
+ char *name;
+{
+ if (wp->w_attr != NULL) {
+ object *v = dictlookup(wp->w_attr, name);
+ if (v != NULL) {
+ INCREF(v);
+ return v;
+ }
+ }
+ return findmethod(window_methods, (object *)wp, name);
+}
+
+static int
+window_setattr(wp, name, v)
+ windowobject *wp;
+ char *name;
+ object *v;
+{
+ if (wp->w_attr == NULL) {
+ wp->w_attr = newdictobject();
+ if (wp->w_attr == NULL)
+ return -1;
+ }
+ if (v == NULL)
+ return dictremove(wp->w_attr, name);
+ else
+ return dictinsert(wp->w_attr, name, v);
+}
+
+static typeobject Windowtype = {
+ OB_HEAD_INIT(&Typetype)
+ 0, /*ob_size*/
+ "window", /*tp_name*/
+ sizeof(windowobject), /*tp_size*/
+ 0, /*tp_itemsize*/
+ /* methods */
+ window_dealloc, /*tp_dealloc*/
+ window_print, /*tp_print*/
+ window_getattr, /*tp_getattr*/
+ window_setattr, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+};
+
+/* Stdwin methods */
+
+static object *
+stdwin_open(sw, args)
+ object *sw;
+ object *args;
+{
+ int tag;
+ object *title;
+ windowobject *wp;
+ if (!getstrarg(args, &title))
+ return NULL;
+ for (tag = 0; tag < MAXNWIN; tag++) {
+ if (windowlist[tag] == NULL)
+ break;
+ }
+ if (tag >= MAXNWIN)
+ return err_nomem();
+ wp = NEWOBJ(windowobject, &Windowtype);
+ if (wp == NULL)
+ return NULL;
+ INCREF(title);
+ wp->w_title = title;
+ wp->w_win = wopen(getstringvalue(title), (void (*)()) NULL);
+ wp->w_attr = NULL;
+ if (wp->w_win == NULL) {
+ DECREF(wp);
+ return NULL;
+ }
+ windowlist[tag] = wp;
+ wsettag(wp->w_win, tag);
+ return (object *)wp;
+}
+
+static object *
+stdwin_get_poll_event(poll, args)
+ int poll;
+ object *args;
+{
+ EVENT e;
+ object *v, *w;
+ if (!getnoarg(args))
+ return NULL;
+ if (Drawing != NULL) {
+ err_setstr(RuntimeError, "cannot getevent() while drawing");
+ return NULL;
+ }
+/* again: */
+ if (poll) {
+ if (!wpollevent(&e)) {
+ INCREF(None);
+ return None;
+ }
+ }
+ else
+ wgetevent(&e);
+ if (e.type == WE_COMMAND && e.u.command == WC_CANCEL) {
+ /* Turn keyboard interrupts into exceptions */
+ err_set(KeyboardInterrupt);
+ return NULL;
+ }
+/*
+ if (e.window == NULL && (e.type == WE_COMMAND || e.type == WE_CHAR))
+ goto again;
+*/
+ if (e.type == WE_COMMAND && e.u.command == WC_CLOSE) {
+ /* Turn WC_CLOSE commands into WE_CLOSE events */
+ e.type = WE_CLOSE;
+ }
+ v = newtupleobject(3);
+ if (v == NULL)
+ return NULL;
+ if ((w = newintobject((long)e.type)) == NULL) {
+ DECREF(v);
+ return NULL;
+ }
+ settupleitem(v, 0, w);
+ if (e.window == NULL)
+ w = None;
+ else {
+ int tag = wgettag(e.window);
+ if (tag < 0 || tag >= MAXNWIN || windowlist[tag] == NULL)
+ w = None;
+ else
+ w = (object *)windowlist[tag];
+#ifdef sgi
+ /* XXX Trap for unexplained weird bug */
+ if ((long)w == (long)0x80000001) {
+ err_setstr(SystemError,
+ "bad pointer in stdwin.getevent()");
+ return NULL;
+ }
+#endif
+ }
+ INCREF(w);
+ settupleitem(v, 1, w);
+ switch (e.type) {
+ case WE_CHAR:
+ {
+ char c[1];
+ c[0] = e.u.character;
+ w = newsizedstringobject(c, 1);
+ }
+ break;
+ case WE_COMMAND:
+ w = newintobject((long)e.u.command);
+ break;
+ case WE_DRAW:
+ w = makerect(e.u.area.left, e.u.area.top,
+ e.u.area.right, e.u.area.bottom);
+ break;
+ case WE_MOUSE_DOWN:
+ case WE_MOUSE_MOVE:
+ case WE_MOUSE_UP:
+ w = makemouse(e.u.where.h, e.u.where.v,
+ e.u.where.clicks,
+ e.u.where.button,
+ e.u.where.mask);
+ break;
+ case WE_MENU:
+ if (e.u.m.id >= IDOFFSET && e.u.m.id < IDOFFSET+MAXNMENU &&
+ menulist[e.u.m.id - IDOFFSET] != NULL)
+ w = (object *)menulist[e.u.m.id - IDOFFSET];
+ else
+ w = None;
+ w = makemenu(w, e.u.m.item);
+ break;
+ case WE_LOST_SEL:
+ w = newintobject((long)e.u.sel);
+ break;
+ default:
+ w = None;
+ INCREF(w);
+ break;
+ }
+ if (w == NULL) {
+ DECREF(v);
+ return NULL;
+ }
+ settupleitem(v, 2, w);
+ return v;
+}
+
+static object *
+stdwin_getevent(sw, args)
+ object *sw;
+ object *args;
+{
+ return stdwin_get_poll_event(0, args);
+}
+
+static object *
+stdwin_pollevent(sw, args)
+ object *sw;
+ object *args;
+{
+ return stdwin_get_poll_event(1, args);
+}
+
+static object *
+stdwin_setdefwinpos(sw, args)
+ object *sw;
+ object *args;
+{
+ int a[2];
+ if (!getpointarg(args, a))
+ return NULL;
+ wsetdefwinpos(a[0], a[1]);
+ INCREF(None);
+ return None;
+}
+
+static object *
+stdwin_setdefwinsize(sw, args)
+ object *sw;
+ object *args;
+{
+ int a[2];
+ if (!getpointarg(args, a))
+ return NULL;
+ wsetdefwinsize(a[0], a[1]);
+ INCREF(None);
+ return None;
+}
+
+static object *
+stdwin_getdefwinpos(wp, args)
+ windowobject *wp;
+ object *args;
+{
+ int h, v;
+ if (!getnoarg(args))
+ return NULL;
+ wgetdefwinpos(&h, &v);
+ return makepoint(h, v);
+}
+
+static object *
+stdwin_getdefwinsize(wp, args)
+ windowobject *wp;
+ object *args;
+{
+ int width, height;
+ if (!getnoarg(args))
+ return NULL;
+ wgetdefwinsize(&width, &height);
+ return makepoint(width, height);
+}
+
+static object *
+stdwin_menucreate(self, args)
+ object *self;
+ object *args;
+{
+ object *title;
+ if (!getstrarg(args, &title))
+ return NULL;
+ wmenusetdeflocal(0);
+ return (object *)newmenuobject(title);
+}
+
+static object *
+stdwin_askfile(self, args)
+ object *self;
+ object *args;
+{
+ object *prompt, *dflt;
+ int new, ret;
+ char buf[256];
+ if (!getstrstrintarg(args, &prompt, &dflt, &new))
+ return NULL;
+ strncpy(buf, getstringvalue(dflt), sizeof buf);
+ buf[sizeof buf - 1] = '\0';
+ ret = waskfile(getstringvalue(prompt), buf, sizeof buf, new);
+ if (!ret) {
+ err_set(KeyboardInterrupt);
+ return NULL;
+ }
+ return newstringobject(buf);
+}
+
+static object *
+stdwin_askync(self, args)
+ object *self;
+ object *args;
+{
+ object *prompt;
+ int new, ret;
+ if (!getstrintarg(args, &prompt, &new))
+ return NULL;
+ ret = waskync(getstringvalue(prompt), new);
+ if (ret < 0) {
+ err_set(KeyboardInterrupt);
+ return NULL;
+ }
+ return newintobject((long)ret);
+}
+
+static object *
+stdwin_askstr(self, args)
+ object *self;
+ object *args;
+{
+ object *prompt, *dflt;
+ int ret;
+ char buf[256];
+ if (!getstrstrarg(args, &prompt, &dflt))
+ return NULL;
+ strncpy(buf, getstringvalue(dflt), sizeof buf);
+ buf[sizeof buf - 1] = '\0';
+ ret = waskstr(getstringvalue(prompt), buf, sizeof buf);
+ if (!ret) {
+ err_set(KeyboardInterrupt);
+ return NULL;
+ }
+ return newstringobject(buf);
+}
+
+static object *
+stdwin_message(self, args)
+ object *self;
+ object *args;
+{
+ object *msg;
+ if (!getstrarg(args, &msg))
+ return NULL;
+ wmessage(getstringvalue(msg));
+ INCREF(None);
+ return None;
+}
+
+static object *
+stdwin_fleep(self, args)
+ object *self;
+ object *args;
+{
+ if (!getnoarg(args))
+ return NULL;
+ wfleep();
+ INCREF(None);
+ return None;
+}
+
+static object *
+stdwin_setcutbuffer(self, args)
+ object *self;
+ object *args;
+{
+ int i;
+ object *str;
+ if (!getintstrarg(args, &i, &str))
+ return NULL;
+ wsetcutbuffer(i, getstringvalue(str), getstringsize(str));
+ INCREF(None);
+ return None;
+}
+
+static object *
+stdwin_getcutbuffer(self, args)
+ object *self;
+ object *args;
+{
+ int i;
+ char *str;
+ int len;
+ if (!getintarg(args, &i))
+ return NULL;
+ str = wgetcutbuffer(i, &len);
+ if (str == NULL) {
+ str = "";
+ len = 0;
+ }
+ return newsizedstringobject(str, len);
+}
+
+static object *
+stdwin_rotatecutbuffers(self, args)
+ object *self;
+ object *args;
+{
+ int i;
+ if (!getintarg(args, &i))
+ return NULL;
+ wrotatecutbuffers(i);
+ INCREF(None);
+ return None;
+}
+
+static object *
+stdwin_getselection(self, args)
+ object *self;
+ object *args;
+{
+ int sel;
+ char *data;
+ int len;
+ if (!getintarg(args, &sel))
+ return NULL;
+ data = wgetselection(sel, &len);
+ if (data == NULL) {
+ data = "";
+ len = 0;
+ }
+ return newsizedstringobject(data, len);
+}
+
+static object *
+stdwin_resetselection(self, args)
+ object *self;
+ object *args;
+{
+ int sel;
+ if (!getintarg(args, &sel))
+ return NULL;
+ wresetselection(sel);
+ INCREF(None);
+ return None;
+}
+
+static struct methodlist stdwin_methods[] = {
+ {"askfile", stdwin_askfile},
+ {"askstr", stdwin_askstr},
+ {"askync", stdwin_askync},
+ {"fleep", stdwin_fleep},
+ {"getselection", stdwin_getselection},
+ {"getcutbuffer", stdwin_getcutbuffer},
+ {"getdefwinpos", stdwin_getdefwinpos},
+ {"getdefwinsize", stdwin_getdefwinsize},
+ {"getevent", stdwin_getevent},
+ {"menucreate", stdwin_menucreate},
+ {"message", stdwin_message},
+ {"open", stdwin_open},
+ {"pollevent", stdwin_pollevent},
+ {"resetselection", stdwin_resetselection},
+ {"rotatecutbuffers", stdwin_rotatecutbuffers},
+ {"setcutbuffer", stdwin_setcutbuffer},
+ {"setdefwinpos", stdwin_setdefwinpos},
+ {"setdefwinsize", stdwin_setdefwinsize},
+
+ /* Text measuring methods borrow code from drawing objects: */
+ {"baseline", drawing_baseline},
+ {"lineheight", drawing_lineheight},
+ {"textbreak", drawing_textbreak},
+ {"textwidth", drawing_textwidth},
+ {NULL, NULL} /* sentinel */
+};
+
+void
+initstdwin()
+{
+ static int inited;
+ if (!inited) {
+ winit();
+ inited = 1;
+ }
+ initmodule("stdwin", stdwin_methods);
+}
diff --git a/src/stdwinobject.h b/src/stdwinobject.h
new file mode 100644
index 0000000..a6d20b8
--- /dev/null
+++ b/src/stdwinobject.h
@@ -0,0 +1,31 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* Stdwin object interface */
+
+extern typeobject Stdwintype;
+
+#define is_stdwinobject(op) ((op)->ob_type == &Stdwintype)
+
+extern object *newstdwinobject PROTO((void));
diff --git a/src/strdup.c b/src/strdup.c
new file mode 100644
index 0000000..e39796d
--- /dev/null
+++ b/src/strdup.c
@@ -0,0 +1,39 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+#include "PROTO.h"
+#include "malloc.h"
+#include "string.h"
+
+char *
+strdup(str)
+ const char *str;
+{
+ if (str != NULL) {
+ register char *copy = NEW(char, strlen(str) + 1);
+ if (copy != NULL)
+ return strcpy(copy, str);
+ }
+ return NULL;
+}
diff --git a/src/strerror.c b/src/strerror.c
new file mode 100644
index 0000000..b2d9da9
--- /dev/null
+++ b/src/strerror.c
@@ -0,0 +1,47 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* PD implementation of strerror() for systems that don't have it.
+ Author: Guido van Rossum, CWI Amsterdam, Oct. 1990, <[email protected]>. */
+
+#include <stdio.h>
+
+extern int sys_nerr;
+extern char *sys_errlist[];
+
+char *
+strerror(err)
+ int err;
+{
+ static char buf[20];
+ if (err >= 0 && err < sys_nerr)
+ return sys_errlist[err];
+ sprintf(buf, "Unknown errno %d", err);
+ return buf;
+}
+
+#ifdef THINK_C
+int sys_nerr = 0;
+char *sys_errlist[1] = 0;
+#endif
diff --git a/src/stringobject.c b/src/stringobject.c
new file mode 100644
index 0000000..d27243f
--- /dev/null
+++ b/src/stringobject.c
@@ -0,0 +1,347 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* String object implementation */
+
+#include "allobjects.h"
+
+object *
+newsizedstringobject(str, size)
+ char *str;
+ int size;
+{
+ register stringobject *op = (stringobject *)
+ malloc(sizeof(stringobject) + size * sizeof(char));
+ if (op == NULL)
+ return err_nomem();
+ NEWREF(op);
+ op->ob_type = &Stringtype;
+ op->ob_size = size;
+ if (str != NULL)
+ memcpy(op->ob_sval, str, size);
+ op->ob_sval[size] = '\0';
+ return (object *) op;
+}
+
+object *
+newstringobject(str)
+ char *str;
+{
+ register unsigned int size = strlen(str);
+ register stringobject *op = (stringobject *)
+ malloc(sizeof(stringobject) + size * sizeof(char));
+ if (op == NULL)
+ return err_nomem();
+ NEWREF(op);
+ op->ob_type = &Stringtype;
+ op->ob_size = size;
+ strcpy(op->ob_sval, str);
+ return (object *) op;
+}
+
+unsigned int
+getstringsize(op)
+ register object *op;
+{
+ if (!is_stringobject(op)) {
+ err_badcall();
+ return -1;
+ }
+ return ((stringobject *)op) -> ob_size;
+}
+
+/*const*/ char *
+getstringvalue(op)
+ register object *op;
+{
+ if (!is_stringobject(op)) {
+ err_badcall();
+ return NULL;
+ }
+ return ((stringobject *)op) -> ob_sval;
+}
+
+/* Methods */
+
+static void
+stringprint(op, fp, flags)
+ stringobject *op;
+ FILE *fp;
+ int flags;
+{
+ int i;
+ char c;
+ if (flags & PRINT_RAW) {
+ fwrite(op->ob_sval, 1, (int) op->ob_size, fp);
+ return;
+ }
+ fprintf(fp, "'");
+ for (i = 0; i < op->ob_size; i++) {
+ c = op->ob_sval[i];
+ if (c == '\'' || c == '\\')
+ fprintf(fp, "\\%c", c);
+ else if (c < ' ' || c >= 0177)
+ fprintf(fp, "\\%03o", c&0377);
+ else
+ putc(c, fp);
+ }
+ fprintf(fp, "'");
+}
+
+static object *
+stringrepr(op)
+ register stringobject *op;
+{
+ /* XXX overflow? */
+ int newsize = 2 + 4 * op->ob_size * sizeof(char);
+ object *v = newsizedstringobject((char *)NULL, newsize);
+ if (v == NULL) {
+ return err_nomem();
+ }
+ else {
+ register int i;
+ register char c;
+ register char *p;
+ NEWREF(v);
+ v->ob_type = &Stringtype;
+ ((stringobject *)v)->ob_size = newsize;
+ p = ((stringobject *)v)->ob_sval;
+ *p++ = '\'';
+ for (i = 0; i < op->ob_size; i++) {
+ c = op->ob_sval[i];
+ if (c == '\'' || c == '\\')
+ *p++ = '\\', *p++ = c;
+ else if (c < ' ' || c >= 0177) {
+ sprintf(p, "\\%03o", c&0377);
+ while (*p != '\0')
+ p++;
+
+ }
+ else
+ *p++ = c;
+ }
+ *p++ = '\'';
+ *p = '\0';
+ resizestring(&v, (int) (p - ((stringobject *)v)->ob_sval));
+ return v;
+ }
+}
+
+static int
+stringlength(a)
+ stringobject *a;
+{
+ return a->ob_size;
+}
+
+static object *
+stringconcat(a, bb)
+ register stringobject *a;
+ register object *bb;
+{
+ register unsigned int size;
+ register stringobject *op;
+ if (!is_stringobject(bb)) {
+ err_badarg();
+ return NULL;
+ }
+#define b ((stringobject *)bb)
+ /* Optimize cases with empty left or right operand */
+ if (a->ob_size == 0) {
+ INCREF(bb);
+ return bb;
+ }
+ if (b->ob_size == 0) {
+ INCREF(a);
+ return (object *)a;
+ }
+ size = a->ob_size + b->ob_size;
+ op = (stringobject *)
+ malloc(sizeof(stringobject) + size * sizeof(char));
+ if (op == NULL)
+ return err_nomem();
+ NEWREF(op);
+ op->ob_type = &Stringtype;
+ op->ob_size = size;
+ memcpy(op->ob_sval, a->ob_sval, (int) a->ob_size);
+ memcpy(op->ob_sval + a->ob_size, b->ob_sval, (int) b->ob_size);
+ op->ob_sval[size] = '\0';
+ return (object *) op;
+#undef b
+}
+
+static object *
+stringrepeat(a, n)
+ register stringobject *a;
+ register int n;
+{
+ register int i;
+ register unsigned int size;
+ register stringobject *op;
+ if (n < 0)
+ n = 0;
+ size = a->ob_size * n;
+ if (size == a->ob_size) {
+ INCREF(a);
+ return (object *)a;
+ }
+ op = (stringobject *)
+ malloc(sizeof(stringobject) + size * sizeof(char));
+ if (op == NULL)
+ return err_nomem();
+ NEWREF(op);
+ op->ob_type = &Stringtype;
+ op->ob_size = size;
+ for (i = 0; i < size; i += a->ob_size)
+ memcpy(op->ob_sval+i, a->ob_sval, (int) a->ob_size);
+ op->ob_sval[size] = '\0';
+ return (object *) op;
+}
+
+/* String slice a[i:j] consists of characters a[i] ... a[j-1] */
+
+static object *
+stringslice(a, i, j)
+ register stringobject *a;
+ register int i, j; /* May be negative! */
+{
+ if (i < 0)
+ i = 0;
+ if (j < 0)
+ j = 0; /* Avoid signed/unsigned bug in next line */
+ if (j > a->ob_size)
+ j = a->ob_size;
+ if (i == 0 && j == a->ob_size) { /* It's the same as a */
+ INCREF(a);
+ return (object *)a;
+ }
+ if (j < i)
+ j = i;
+ return newsizedstringobject(a->ob_sval + i, (int) (j-i));
+}
+
+static object *
+stringitem(a, i)
+ stringobject *a;
+ register int i;
+{
+ if (i < 0 || i >= a->ob_size) {
+ err_setstr(IndexError, "string index out of range");
+ return NULL;
+ }
+ return stringslice(a, i, i+1);
+}
+
+static int
+stringcompare(a, b)
+ stringobject *a, *b;
+{
+ int len_a = a->ob_size, len_b = b->ob_size;
+ int min_len = (len_a < len_b) ? len_a : len_b;
+ int cmp = memcmp(a->ob_sval, b->ob_sval, min_len);
+ if (cmp != 0)
+ return cmp;
+ return (len_a < len_b) ? -1 : (len_a > len_b) ? 1 : 0;
+}
+
+static sequence_methods string_as_sequence = {
+ stringlength, /*tp_length*/
+ stringconcat, /*tp_concat*/
+ stringrepeat, /*tp_repeat*/
+ stringitem, /*tp_item*/
+ stringslice, /*tp_slice*/
+ 0, /*tp_ass_item*/
+ 0, /*tp_ass_slice*/
+};
+
+typeobject Stringtype = {
+ OB_HEAD_INIT(&Typetype)
+ 0,
+ "string",
+ sizeof(stringobject),
+ sizeof(char),
+ free, /*tp_dealloc*/
+ stringprint, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ stringcompare, /*tp_compare*/
+ stringrepr, /*tp_repr*/
+ 0, /*tp_as_number*/
+ &string_as_sequence, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+};
+
+void
+joinstring(pv, w)
+ register object **pv;
+ register object *w;
+{
+ register object *v;
+ if (*pv == NULL || w == NULL || !is_stringobject(*pv))
+ return;
+ v = stringconcat((stringobject *) *pv, w);
+ DECREF(*pv);
+ *pv = v;
+}
+
+/* The following function breaks the notion that strings are immutable:
+ it changes the size of a string. We get away with this only if there
+ is only one module referencing the object. You can also think of it
+ as creating a new string object and destroying the old one, only
+ more efficiently. In any case, don't use this if the string may
+ already be known to some other part of the code... */
+
+int
+resizestring(pv, newsize)
+ object **pv;
+ int newsize;
+{
+ register object *v;
+ register stringobject *sv;
+ v = *pv;
+ if (!is_stringobject(v) || v->ob_refcnt != 1) {
+ *pv = 0;
+ DECREF(v);
+ err_badcall();
+ return -1;
+ }
+ /* XXX UNREF/NEWREF interface should be more symmetrical */
+#ifdef REF_DEBUG
+ --ref_total;
+#endif
+ UNREF(v);
+ *pv = (object *)
+ realloc((char *)v,
+ sizeof(stringobject) + newsize * sizeof(char));
+ if (*pv == NULL) {
+ DEL(v);
+ err_nomem();
+ return -1;
+ }
+ NEWREF(*pv);
+ sv = (stringobject *) *pv;
+ sv->ob_size = newsize;
+ sv->ob_sval[newsize] = '\0';
+ return 0;
+}
diff --git a/src/stringobject.h b/src/stringobject.h
new file mode 100644
index 0000000..17e0367
--- /dev/null
+++ b/src/stringobject.h
@@ -0,0 +1,63 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* String object interface */
+
+/*
+123456789-123456789-123456789-123456789-123456789-123456789-123456789-12
+
+Type stringobject represents a character string. An extra zero byte is
+reserved at the end to ensure it is zero-terminated, but a size is
+present so strings with null bytes in them can be represented. This
+is an immutable object type.
+
+There are functions to create new string objects, to test
+an object for string-ness, and to get the
+string value. The latter function returns a null pointer
+if the object is not of the proper type.
+There is a variant that takes an explicit size as well as a
+variant that assumes a zero-terminated string. Note that none of the
+functions should be applied to nil objects.
+*/
+
+/* NB The type is revealed here only because it is used in dictobject.c */
+
+typedef struct {
+ OB_VARHEAD
+ char ob_sval[1];
+} stringobject;
+
+extern typeobject Stringtype;
+
+#define is_stringobject(op) ((op)->ob_type == &Stringtype)
+
+extern object *newsizedstringobject PROTO((char *, int));
+extern object *newstringobject PROTO((char *));
+extern unsigned int getstringsize PROTO((object *));
+extern char *getstringvalue PROTO((object *));
+extern void joinstring PROTO((object **, object *));
+extern int resizestring PROTO((object **, int));
+
+/* Macro, trading safety for speed */
+#define GETSTRINGVALUE(op) ((op)->ob_sval)
diff --git a/src/strtol.c b/src/strtol.c
new file mode 100644
index 0000000..cdf9b92
--- /dev/null
+++ b/src/strtol.c
@@ -0,0 +1,122 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/*
+** strtol
+** This is a general purpose routine for converting
+** an ascii string to an integer in an arbitrary base.
+** Leading white space is ignored, if 'base' is zero
+** it looks for a leading 0, 0x or 0X to tell which
+** base. If these are absent it defaults to 10.
+** Base must be between 0 and 36.
+** If 'ptr' is non-NULL it will contain a pointer to
+** the end of the scan.
+** Errors due to bad pointers will probably result in
+** exceptions - we don't check for them.
+*/
+
+#include "ctype.h"
+
+long
+strtol(str, ptr, base)
+register char * str;
+char ** ptr;
+int base;
+{
+ register long result; /* return value of the function */
+ register int c; /* current input character */
+ int minus; /* true if a leading minus was found */
+
+ result = 0;
+ minus = 0;
+
+/* catch silly bases */
+ if (base < 0 || base > 36)
+ {
+ if (ptr)
+ *ptr = str;
+ return result;
+ }
+
+/* skip leading white space */
+ while (*str && isspace(*str))
+ str++;
+
+/* check for optional leading minus sign */
+ if (*str == '-')
+ {
+ minus = 1;
+ str++;
+ }
+
+/* check for leading 0 or 0x for auto-base or base 16 */
+ switch (base)
+ {
+ case 0: /* look for leading 0, 0x or 0X */
+ if (*str == '0')
+ {
+ str++;
+ if (*str == 'x' || *str == 'X')
+ {
+ str++;
+ base = 16;
+ }
+ else
+ base = 8;
+ }
+ else
+ base = 10;
+ break;
+
+ case 16: /* skip leading 0x or 0X */
+ if (*str == '0' && (*(str+1) == 'x' || *(str+1) == 'X'))
+ str += 2;
+ break;
+ }
+
+/* do the conversion */
+ while (c = *str)
+ {
+ if (isdigit(c) && c - '0' < base)
+ c -= '0';
+ else
+ {
+ if (isupper(c))
+ c = tolower(c);
+ if (c >= 'a' && c <= 'z')
+ c -= 'a' - 10;
+ else /* non-"digit" character */
+ break;
+ if (c >= base) /* non-"digit" character */
+ break;
+ }
+ result = result * base + c;
+ str++;
+ }
+
+/* set pointer to point to the last character scanned */
+ if (ptr)
+ *ptr = str;
+ return minus ? -result : result;
+}
diff --git a/src/structmember.c b/src/structmember.c
new file mode 100644
index 0000000..c87a3c7
--- /dev/null
+++ b/src/structmember.c
@@ -0,0 +1,158 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* Map C struct members to Python object attributes */
+
+#include "allobjects.h"
+
+#include "structmember.h"
+
+object *
+getmember(addr, mlist, name)
+ char *addr;
+ struct memberlist *mlist;
+ char *name;
+{
+ struct memberlist *l;
+
+ for (l = mlist; l->name != NULL; l++) {
+ if (strcmp(l->name, name) == 0) {
+ object *v;
+ addr += l->offset;
+ switch (l->type) {
+ case T_SHORT:
+ v = newintobject((long) *(short*)addr);
+ break;
+ case T_INT:
+ v = newintobject((long) *(int*)addr);
+ break;
+ case T_LONG:
+ v = newintobject(*(long*)addr);
+ break;
+ case T_FLOAT:
+ v = newfloatobject((double)*(float*)addr);
+ break;
+ case T_DOUBLE:
+ v = newfloatobject(*(double*)addr);
+ break;
+ case T_STRING:
+ if (*(char**)addr == NULL) {
+ INCREF(None);
+ v = None;
+ }
+ else
+ v = newstringobject(*(char**)addr);
+ break;
+ case T_OBJECT:
+ v = *(object **)addr;
+ if (v == NULL)
+ v = None;
+ INCREF(v);
+ break;
+ default:
+ err_setstr(SystemError, "bad memberlist type");
+ v = NULL;
+ }
+ return v;
+ }
+ }
+
+ err_setstr(NameError, name);
+ return NULL;
+}
+
+int
+setmember(addr, mlist, name, v)
+ char *addr;
+ struct memberlist *mlist;
+ char *name;
+ object *v;
+{
+ struct memberlist *l;
+
+ for (l = mlist; l->name != NULL; l++) {
+ if (strcmp(l->name, name) == 0) {
+ if (l->readonly || l->type == T_STRING) {
+ err_setstr(RuntimeError, "readonly attribute");
+ return -1;
+ }
+ addr += l->offset;
+ switch (l->type) {
+ case T_SHORT:
+ if (!is_intobject(v)) {
+ err_badarg();
+ return -1;
+ }
+ *(short*)addr = getintvalue(v);
+ break;
+ case T_INT:
+ if (!is_intobject(v)) {
+ err_badarg();
+ return -1;
+ }
+ *(int*)addr = getintvalue(v);
+ break;
+ case T_LONG:
+ if (!is_intobject(v)) {
+ err_badarg();
+ return -1;
+ }
+ *(long*)addr = getintvalue(v);
+ break;
+ case T_FLOAT:
+ if (is_intobject(v))
+ *(float*)addr = getintvalue(v);
+ else if (is_floatobject(v))
+ *(float*)addr = getfloatvalue(v);
+ else {
+ err_badarg();
+ return -1;
+ }
+ break;
+ case T_DOUBLE:
+ if (is_intobject(v))
+ *(double*)addr = getintvalue(v);
+ else if (is_floatobject(v))
+ *(double*)addr = getfloatvalue(v);
+ else {
+ err_badarg();
+ return -1;
+ }
+ break;
+ case T_OBJECT:
+ XDECREF(*(object **)addr);
+ XINCREF(v);
+ *(object **)addr = v;
+ break;
+ default:
+ err_setstr(SystemError, "bad memberlist type");
+ return -1;
+ }
+ return 0;
+ }
+ }
+
+ err_setstr(NameError, name);
+ return -1;
+}
diff --git a/src/structmember.h b/src/structmember.h
new file mode 100644
index 0000000..93d2a2e
--- /dev/null
+++ b/src/structmember.h
@@ -0,0 +1,64 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* Interface to map C struct members to Python object attributes */
+
+/* The offsetof() macro calculates the offset of a structure member
+ in its structure. Unfortunately this cannot be written down
+ portably, hence it is provided by a Standard C header file.
+ For pre-Standard C compilers, here is a version that usually works
+ (but watch out!): */
+
+#ifndef offsetof
+#define offsetof(type, member) ( (int) & ((type*)0) -> member )
+#endif
+
+/* An array of memberlist structures defines the name, type and offset
+ of selected members of a C structure. These can be read by
+ getmember() and set by setmember() (except if their READONLY flag
+ is set). The array must be terminated with an entry whose name
+ pointer is NULL. */
+
+struct memberlist {
+ char *name;
+ int type;
+ int offset;
+ int readonly;
+};
+
+/* Types */
+#define T_SHORT 0
+#define T_INT 1
+#define T_LONG 2
+#define T_FLOAT 3
+#define T_DOUBLE 4
+#define T_STRING 5
+#define T_OBJECT 6
+
+/* Readonly flag */
+#define READONLY 1
+#define RO READONLY /* Shorthand */
+
+object *getmember PROTO((char *, struct memberlist *, char *));
+int setmember PROTO((char *, struct memberlist *, char *, object *));
diff --git a/src/stubcode.h b/src/stubcode.h
new file mode 100644
index 0000000..6e76c23
--- /dev/null
+++ b/src/stubcode.h
@@ -0,0 +1,28 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+
+#define CAP 0
+#define STUBC 1
+#define NAME 2
diff --git a/src/sysmodule.c b/src/sysmodule.c
new file mode 100644
index 0000000..6b3b576
--- /dev/null
+++ b/src/sysmodule.c
@@ -0,0 +1,214 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* System module */
+
+/*
+Various bits of information used by the interpreter are collected in
+module 'sys'.
+Function member:
+- exit(sts): call (C, POSIX) exit(sts)
+Data members:
+- stdin, stdout, stderr: standard file objects
+- modules: the table of modules (dictionary)
+- path: module search path (list of strings)
+- argv: script arguments (list of strings)
+- ps1, ps2: optional primary and secondary prompts (strings)
+*/
+
+#include "allobjects.h"
+
+#include "sysmodule.h"
+#include "import.h"
+#include "modsupport.h"
+
+/* Define delimiter used in $PYTHONPATH */
+
+#ifdef THINK_C
+#define DELIM ' '
+#endif
+
+#ifndef DELIM
+#define DELIM ':'
+#endif
+
+static object *sysdict;
+
+object *
+sysget(name)
+ char *name;
+{
+ return dictlookup(sysdict, name);
+}
+
+FILE *
+sysgetfile(name, def)
+ char *name;
+ FILE *def;
+{
+ FILE *fp = NULL;
+ object *v = sysget(name);
+ if (v != NULL)
+ fp = getfilefile(v);
+ if (fp == NULL)
+ fp = def;
+ return fp;
+}
+
+int
+sysset(name, v)
+ char *name;
+ object *v;
+{
+ if (v == NULL)
+ return dictremove(sysdict, name);
+ else
+ return dictinsert(sysdict, name, v);
+}
+
+static object *
+sys_exit(self, args)
+ object *self;
+ object *args;
+{
+ int sts;
+ if (!getintarg(args, &sts))
+ return NULL;
+ goaway(sts);
+ exit(sts); /* Just in case */
+ /* NOTREACHED */
+}
+
+static struct methodlist sys_methods[] = {
+ {"exit", sys_exit},
+ {NULL, NULL} /* sentinel */
+};
+
+static object *sysin, *sysout, *syserr;
+
+void
+initsys()
+{
+ object *m = initmodule("sys", sys_methods);
+ sysdict = getmoduledict(m);
+ INCREF(sysdict);
+ /* NB keep an extra ref to the std files to avoid closing them
+ when the user deletes them */
+ /* XXX File objects should have a "don't close" flag instead */
+ sysin = newopenfileobject(stdin, "<stdin>", "r");
+ sysout = newopenfileobject(stdout, "<stdout>", "w");
+ syserr = newopenfileobject(stderr, "<stderr>", "w");
+ if (err_occurred())
+ fatal("can't create sys.std* file objects");
+ dictinsert(sysdict, "stdin", sysin);
+ dictinsert(sysdict, "stdout", sysout);
+ dictinsert(sysdict, "stderr", syserr);
+ dictinsert(sysdict, "modules", get_modules());
+ if (err_occurred())
+ fatal("can't insert sys.* objects in sys dict");
+}
+
+static object *
+makepathobject(path, delim)
+ char *path;
+ int delim;
+{
+ int i, n;
+ char *p;
+ object *v, *w;
+
+ n = 1;
+ p = path;
+ while ((p = strchr(p, delim)) != NULL) {
+ n++;
+ p++;
+ }
+ v = newlistobject(n);
+ if (v == NULL)
+ return NULL;
+ for (i = 0; ; i++) {
+ p = strchr(path, delim);
+ if (p == NULL)
+ p = strchr(path, '\0'); /* End of string */
+ w = newsizedstringobject(path, (int) (p - path));
+ if (w == NULL) {
+ DECREF(v);
+ return NULL;
+ }
+ setlistitem(v, i, w);
+ if (*p == '\0')
+ break;
+ path = p+1;
+ }
+ return v;
+}
+
+void
+setpythonpath(path)
+ char *path;
+{
+ object *v;
+ if ((v = makepathobject(path, DELIM)) == NULL)
+ fatal("can't create sys.path");
+ if (sysset("path", v) != 0)
+ fatal("can't assign sys.path");
+ DECREF(v);
+}
+
+static object *
+makeargvobject(argc, argv)
+ int argc;
+ char **argv;
+{
+ object *av;
+ if (argc < 0 || argv == NULL)
+ argc = 0;
+ av = newlistobject(argc);
+ if (av != NULL) {
+ int i;
+ for (i = 0; i < argc; i++) {
+ object *v = newstringobject(argv[i]);
+ if (v == NULL) {
+ DECREF(av);
+ av = NULL;
+ break;
+ }
+ setlistitem(av, i, v);
+ }
+ }
+ return av;
+}
+
+void
+setpythonargv(argc, argv)
+ int argc;
+ char **argv;
+{
+ object *av = makeargvobject(argc, argv);
+ if (av == NULL)
+ fatal("no mem for sys.argv");
+ if (sysset("argv", av) != 0)
+ fatal("can't assign sys.argv");
+ DECREF(av);
+}
diff --git a/src/sysmodule.h b/src/sysmodule.h
new file mode 100644
index 0000000..eed1944
--- /dev/null
+++ b/src/sysmodule.h
@@ -0,0 +1,30 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* System module interface */
+
+object *sysget PROTO((char *));
+int sysset PROTO((char *, object *));
+FILE *sysgetfile PROTO((char *, FILE *));
+void initsys PROTO((void));
diff --git a/src/timemodule.c b/src/timemodule.c
new file mode 100644
index 0000000..dcaedbd
--- /dev/null
+++ b/src/timemodule.c
@@ -0,0 +1,229 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* Time module */
+
+#include "allobjects.h"
+
+#include "modsupport.h"
+
+#include "sigtype.h"
+
+#include <signal.h>
+#include <setjmp.h>
+
+#ifdef __STDC__
+#include <time.h>
+#else /* !__STDC__ */
+typedef unsigned long time_t;
+extern time_t time();
+#endif /* !__STDC__ */
+
+
+/* Time methods */
+
+static object *
+time_time(self, args)
+ object *self;
+ object *args;
+{
+ long secs;
+ if (!getnoarg(args))
+ return NULL;
+ secs = time((time_t *)NULL);
+ return newintobject(secs);
+}
+
+static jmp_buf sleep_intr;
+
+static void
+sleep_catcher(sig)
+ int sig;
+{
+ longjmp(sleep_intr, 1);
+}
+
+static object *
+time_sleep(self, args)
+ object *self;
+ object *args;
+{
+ int secs;
+ SIGTYPE (*sigsave)();
+ if (!getintarg(args, &secs))
+ return NULL;
+ if (setjmp(sleep_intr)) {
+ signal(SIGINT, sigsave);
+ err_set(KeyboardInterrupt);
+ return NULL;
+ }
+ sigsave = signal(SIGINT, SIG_IGN);
+ if (sigsave != (SIGTYPE (*)()) SIG_IGN)
+ signal(SIGINT, sleep_catcher);
+ sleep(secs);
+ signal(SIGINT, sigsave);
+ INCREF(None);
+ return None;
+}
+
+#ifdef THINK_C
+#define DO_MILLI
+#endif /* THINK_C */
+
+#ifdef AMOEBA
+#define DO_MILLI
+extern long sys_milli();
+#define millitimer sys_milli
+#endif /* AMOEBA */
+
+#ifdef BSD_TIME
+#define DO_MILLI
+#endif /* BSD_TIME */
+
+#ifdef DO_MILLI
+
+static object *
+time_millisleep(self, args)
+ object *self;
+ object *args;
+{
+ long msecs;
+ SIGTYPE (*sigsave)();
+ if (!getlongarg(args, &msecs))
+ return NULL;
+ if (setjmp(sleep_intr)) {
+ signal(SIGINT, sigsave);
+ err_set(KeyboardInterrupt);
+ return NULL;
+ }
+ sigsave = signal(SIGINT, SIG_IGN);
+ if (sigsave != (SIGTYPE (*)()) SIG_IGN)
+ signal(SIGINT, sleep_catcher);
+ millisleep(msecs);
+ signal(SIGINT, sigsave);
+ INCREF(None);
+ return None;
+}
+
+static object *
+time_millitimer(self, args)
+ object *self;
+ object *args;
+{
+ long msecs;
+ extern long millitimer();
+ if (!getnoarg(args))
+ return NULL;
+ msecs = millitimer();
+ return newintobject(msecs);
+}
+
+#endif /* DO_MILLI */
+
+
+static struct methodlist time_methods[] = {
+#ifdef DO_MILLI
+ {"millisleep", time_millisleep},
+ {"millitimer", time_millitimer},
+#endif /* DO_MILLI */
+ {"sleep", time_sleep},
+ {"time", time_time},
+ {NULL, NULL} /* sentinel */
+};
+
+
+void
+inittime()
+{
+ initmodule("time", time_methods);
+}
+
+
+#ifdef THINK_C
+
+#define MacTicks (* (long *)0x16A)
+
+static
+sleep(msecs)
+ int msecs;
+{
+ register long deadline;
+
+ deadline = MacTicks + msecs * 60;
+ while (MacTicks < deadline) {
+ if (intrcheck())
+ sleep_catcher(SIGINT);
+ }
+}
+
+static
+millisleep(msecs)
+ long msecs;
+{
+ register long deadline;
+
+ deadline = MacTicks + msecs * 3 / 50; /* msecs * 60 / 1000 */
+ while (MacTicks < deadline) {
+ if (intrcheck())
+ sleep_catcher(SIGINT);
+ }
+}
+
+static long
+millitimer()
+{
+ return MacTicks * 50 / 3; /* MacTicks * 1000 / 60 */
+}
+
+#endif /* THINK_C */
+
+
+#ifdef BSD_TIME
+
+#include <sys/types.h>
+#include <sys/time.h>
+
+static long
+millitimer()
+{
+ struct timeval t;
+ struct timezone tz;
+ if (gettimeofday(&t, &tz) != 0)
+ return -1;
+ return t.tv_sec*1000 + t.tv_usec/1000;
+
+}
+
+static
+millisleep(msecs)
+ long msecs;
+{
+ struct timeval t;
+ t.tv_sec = msecs/1000;
+ t.tv_usec = (msecs%1000)*1000;
+ (void) select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t);
+}
+
+#endif /* BSD_TIME */
+
diff --git a/src/token.h b/src/token.h
new file mode 100644
index 0000000..79f0ed0
--- /dev/null
+++ b/src/token.h
@@ -0,0 +1,69 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* Token types */
+
+#define ENDMARKER 0
+#define NAME 1
+#define NUMBER 2
+#define STRING 3
+#define NEWLINE 4
+#define INDENT 5
+#define DEDENT 6
+#define LPAR 7
+#define RPAR 8
+#define LSQB 9
+#define RSQB 10
+#define COLON 11
+#define COMMA 12
+#define SEMI 13
+#define PLUS 14
+#define MINUS 15
+#define STAR 16
+#define SLASH 17
+#define VBAR 18
+#define AMPER 19
+#define LESS 20
+#define GREATER 21
+#define EQUAL 22
+#define DOT 23
+#define PERCENT 24
+#define BACKQUOTE 25
+#define LBRACE 26
+#define RBRACE 27
+#define OP 28
+#define ERRORTOKEN 29
+#define N_TOKENS 30
+
+/* Special definitions for cooperation with parser */
+
+#define NT_OFFSET 256
+
+#define ISTERMINAL(x) ((x) < NT_OFFSET)
+#define ISNONTERMINAL(x) ((x) >= NT_OFFSET)
+#define ISEOF(x) ((x) == ENDMARKER)
+
+
+extern char *tok_name[]; /* Token names */
+extern int tok_1char PROTO((int));
diff --git a/src/tokenizer.c b/src/tokenizer.c
new file mode 100644
index 0000000..231123f
--- /dev/null
+++ b/src/tokenizer.c
@@ -0,0 +1,523 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* Tokenizer implementation */
+
+/* XXX This is rather old, should be restructured perhaps */
+/* XXX Need a better interface to report errors than writing to stderr */
+/* XXX Should use editor resource to fetch true tab size on Macintosh */
+
+#include "pgenheaders.h"
+
+#include <ctype.h>
+#include "string.h"
+
+#include "fgetsintr.h"
+#include "tokenizer.h"
+#include "errcode.h"
+
+#ifdef THINK_C
+#define TABSIZE 4
+#endif
+
+#ifndef TABSIZE
+#define TABSIZE 8
+#endif
+
+/* Forward */
+static struct tok_state *tok_new PROTO((void));
+static int tok_nextc PROTO((struct tok_state *tok));
+static void tok_backup PROTO((struct tok_state *tok, int c));
+
+/* Token names */
+
+char *tok_name[] = {
+ "ENDMARKER",
+ "NAME",
+ "NUMBER",
+ "STRING",
+ "NEWLINE",
+ "INDENT",
+ "DEDENT",
+ "LPAR",
+ "RPAR",
+ "LSQB",
+ "RSQB",
+ "COLON",
+ "COMMA",
+ "SEMI",
+ "PLUS",
+ "MINUS",
+ "STAR",
+ "SLASH",
+ "VBAR",
+ "AMPER",
+ "LESS",
+ "GREATER",
+ "EQUAL",
+ "DOT",
+ "PERCENT",
+ "BACKQUOTE",
+ "LBRACE",
+ "RBRACE",
+ "OP",
+ "<ERRORTOKEN>",
+ "<N_TOKENS>"
+};
+
+
+/* Create and initialize a new tok_state structure */
+
+static struct tok_state *
+tok_new()
+{
+ struct tok_state *tok = NEW(struct tok_state, 1);
+ if (tok == NULL)
+ return NULL;
+ tok->buf = tok->cur = tok->end = tok->inp = NULL;
+ tok->done = E_OK;
+ tok->fp = NULL;
+ tok->tabsize = TABSIZE;
+ tok->indent = 0;
+ tok->indstack[0] = 0;
+ tok->atbol = 1;
+ tok->pendin = 0;
+ tok->prompt = tok->nextprompt = NULL;
+ tok->lineno = 0;
+ return tok;
+}
+
+
+/* Set up tokenizer for string */
+
+struct tok_state *
+tok_setups(str)
+ char *str;
+{
+ struct tok_state *tok = tok_new();
+ if (tok == NULL)
+ return NULL;
+ tok->buf = tok->cur = str;
+ tok->end = tok->inp = strchr(str, '\0');
+ return tok;
+}
+
+
+/* Set up tokenizer for string */
+
+struct tok_state *
+tok_setupf(fp, ps1, ps2)
+ FILE *fp;
+ char *ps1, *ps2;
+{
+ struct tok_state *tok = tok_new();
+ if (tok == NULL)
+ return NULL;
+ if ((tok->buf = NEW(char, BUFSIZ)) == NULL) {
+ DEL(tok);
+ return NULL;
+ }
+ tok->cur = tok->inp = tok->buf;
+ tok->end = tok->buf + BUFSIZ;
+ tok->fp = fp;
+ tok->prompt = ps1;
+ tok->nextprompt = ps2;
+ return tok;
+}
+
+
+/* Free a tok_state structure */
+
+void
+tok_free(tok)
+ struct tok_state *tok;
+{
+ /* XXX really need a separate flag to say 'my buffer' */
+ if (tok->fp != NULL && tok->buf != NULL)
+ DEL(tok->buf);
+ DEL(tok);
+}
+
+
+/* Get next char, updating state; error code goes into tok->done */
+
+static int
+tok_nextc(tok)
+ register struct tok_state *tok;
+{
+ if (tok->done != E_OK)
+ return EOF;
+
+ for (;;) {
+ if (tok->cur < tok->inp)
+ return *tok->cur++;
+ if (tok->fp == NULL) {
+ tok->done = E_EOF;
+ return EOF;
+ }
+ if (tok->inp > tok->buf && tok->inp[-1] == '\n')
+ tok->inp = tok->buf;
+ if (tok->inp == tok->end) {
+ int n = tok->end - tok->buf;
+ char *new = tok->buf;
+ RESIZE(new, char, n+n);
+ if (new == NULL) {
+ fprintf(stderr, "tokenizer out of mem\n");
+ tok->done = E_NOMEM;
+ return EOF;
+ }
+ tok->buf = new;
+ tok->inp = tok->buf + n;
+ tok->end = tok->inp + n;
+ }
+#ifdef USE_READLINE
+ if (tok->prompt != NULL) {
+ extern char *readline PROTO((char *prompt));
+ static int been_here;
+ if (!been_here) {
+ /* Force rebind of TAB to insert-tab */
+ extern int rl_insert();
+ rl_bind_key('\t', rl_insert);
+ been_here++;
+ }
+ if (tok->buf != NULL)
+ free(tok->buf);
+ tok->buf = readline(tok->prompt);
+ (void) intrcheck(); /* Clear pending interrupt */
+ if (tok->nextprompt != NULL)
+ tok->prompt = tok->nextprompt;
+ /* XXX different semantics w/o readline()! */
+ if (tok->buf == NULL) {
+ tok->done = E_EOF;
+ }
+ else {
+ unsigned int n = strlen(tok->buf);
+ if (n > 0)
+ add_history(tok->buf);
+ /* Append the '\n' that readline()
+ doesn't give us, for the tokenizer... */
+ tok->buf = realloc(tok->buf, n+2);
+ if (tok->buf == NULL)
+ tok->done = E_NOMEM;
+ else {
+ tok->end = tok->buf + n;
+ *tok->end++ = '\n';
+ *tok->end = '\0';
+ tok->inp = tok->end;
+ tok->cur = tok->buf;
+ }
+ }
+ }
+ else
+#endif
+ {
+ tok->cur = tok->inp;
+ if (tok->prompt != NULL && tok->inp == tok->buf) {
+ fprintf(stderr, "%s", tok->prompt);
+ tok->prompt = tok->nextprompt;
+ }
+ tok->done = fgets_intr(tok->inp,
+ (int)(tok->end - tok->inp), tok->fp);
+ }
+ if (tok->done != E_OK) {
+ if (tok->prompt != NULL)
+ fprintf(stderr, "\n");
+ return EOF;
+ }
+ tok->inp = strchr(tok->inp, '\0');
+ }
+}
+
+
+/* Back-up one character */
+
+static void
+tok_backup(tok, c)
+ register struct tok_state *tok;
+ register int c;
+{
+ if (c != EOF) {
+ if (--tok->cur < tok->buf) {
+ fprintf(stderr, "tok_backup: begin of buffer\n");
+ abort();
+ }
+ if (*tok->cur != c)
+ *tok->cur = c;
+ }
+}
+
+
+/* Return the token corresponding to a single character */
+
+int
+tok_1char(c)
+ int c;
+{
+ switch (c) {
+ case '(': return LPAR;
+ case ')': return RPAR;
+ case '[': return LSQB;
+ case ']': return RSQB;
+ case ':': return COLON;
+ case ',': return COMMA;
+ case ';': return SEMI;
+ case '+': return PLUS;
+ case '-': return MINUS;
+ case '*': return STAR;
+ case '/': return SLASH;
+ case '|': return VBAR;
+ case '&': return AMPER;
+ case '<': return LESS;
+ case '>': return GREATER;
+ case '=': return EQUAL;
+ case '.': return DOT;
+ case '%': return PERCENT;
+ case '`': return BACKQUOTE;
+ case '{': return LBRACE;
+ case '}': return RBRACE;
+ default: return OP;
+ }
+}
+
+
+/* Get next token, after space stripping etc. */
+
+int
+tok_get(tok, p_start, p_end)
+ register struct tok_state *tok; /* In/out: tokenizer state */
+ char **p_start, **p_end; /* Out: point to start/end of token */
+{
+ register int c;
+
+ /* Get indentation level */
+ if (tok->atbol) {
+ register int col = 0;
+ tok->atbol = 0;
+ tok->lineno++;
+ for (;;) {
+ c = tok_nextc(tok);
+ if (c == ' ')
+ col++;
+ else if (c == '\t')
+ col = (col/tok->tabsize + 1) * tok->tabsize;
+ else
+ break;
+ }
+ tok_backup(tok, c);
+ if (col == tok->indstack[tok->indent]) {
+ /* No change */
+ }
+ else if (col > tok->indstack[tok->indent]) {
+ /* Indent -- always one */
+ if (tok->indent+1 >= MAXINDENT) {
+ fprintf(stderr, "excessive indent\n");
+ tok->done = E_TOKEN;
+ return ERRORTOKEN;
+ }
+ tok->pendin++;
+ tok->indstack[++tok->indent] = col;
+ }
+ else /* col < tok->indstack[tok->indent] */ {
+ /* Dedent -- any number, must be consistent */
+ while (tok->indent > 0 &&
+ col < tok->indstack[tok->indent]) {
+ tok->indent--;
+ tok->pendin--;
+ }
+ if (col != tok->indstack[tok->indent]) {
+ fprintf(stderr, "inconsistent dedent\n");
+ tok->done = E_TOKEN;
+ return ERRORTOKEN;
+ }
+ }
+ }
+
+ *p_start = *p_end = tok->cur;
+
+ /* Return pending indents/dedents */
+ if (tok->pendin != 0) {
+ if (tok->pendin < 0) {
+ tok->pendin++;
+ return DEDENT;
+ }
+ else {
+ tok->pendin--;
+ return INDENT;
+ }
+ }
+
+ again:
+ /* Skip spaces */
+ do {
+ c = tok_nextc(tok);
+ } while (c == ' ' || c == '\t');
+
+ /* Set start of current token */
+ *p_start = tok->cur - 1;
+
+ /* Skip comment */
+ if (c == '#') {
+ /* Hack to allow overriding the tabsize in the file.
+ This is also recognized by vi, when it occurs near the
+ beginning or end of the file. (Will vi never die...?) */
+ int x;
+ /* XXX The case to (unsigned char *) is needed by THINK C 3.0 */
+ if (sscanf(/*(unsigned char *)*/tok->cur,
+ " vi:set tabsize=%d:", &x) == 1 &&
+ x >= 1 && x <= 40) {
+ fprintf(stderr, "# vi:set tabsize=%d:\n", x);
+ tok->tabsize = x;
+ }
+ do {
+ c = tok_nextc(tok);
+ } while (c != EOF && c != '\n');
+ }
+
+ /* Check for EOF and errors now */
+ if (c == EOF)
+ return tok->done == E_EOF ? ENDMARKER : ERRORTOKEN;
+
+ /* Identifier (most frequent token!) */
+ if (isalpha(c) || c == '_') {
+ do {
+ c = tok_nextc(tok);
+ } while (isalnum(c) || c == '_');
+ tok_backup(tok, c);
+ *p_end = tok->cur;
+ return NAME;
+ }
+
+ /* Newline */
+ if (c == '\n') {
+ tok->atbol = 1;
+ *p_end = tok->cur - 1; /* Leave '\n' out of the string */
+ return NEWLINE;
+ }
+
+ /* Number */
+ if (isdigit(c)) {
+ if (c == '0') {
+ /* Hex or octal */
+ c = tok_nextc(tok);
+ if (c == '.')
+ goto fraction;
+ if (c == 'x' || c == 'X') {
+ /* Hex */
+ do {
+ c = tok_nextc(tok);
+ } while (isxdigit(c));
+ }
+ else {
+ /* Octal; c is first char of it */
+ /* There's no 'isoctdigit' macro, sigh */
+ while ('0' <= c && c < '8') {
+ c = tok_nextc(tok);
+ }
+ }
+ }
+ else {
+ /* Decimal */
+ do {
+ c = tok_nextc(tok);
+ } while (isdigit(c));
+ /* Accept floating point numbers.
+ XXX This accepts incomplete things like 12e or 1e+;
+ worry about that at run-time.
+ XXX Doesn't accept numbers starting with a dot */
+ if (c == '.') {
+ fraction:
+ /* Fraction */
+ do {
+ c = tok_nextc(tok);
+ } while (isdigit(c));
+ }
+ if (c == 'e' || c == 'E') {
+ /* Exponent part */
+ c = tok_nextc(tok);
+ if (c == '+' || c == '-')
+ c = tok_nextc(tok);
+ while (isdigit(c)) {
+ c = tok_nextc(tok);
+ }
+ }
+ }
+ tok_backup(tok, c);
+ *p_end = tok->cur;
+ return NUMBER;
+ }
+
+ /* String */
+ if (c == '\'') {
+ for (;;) {
+ c = tok_nextc(tok);
+ if (c == '\n' || c == EOF) {
+ tok->done = E_TOKEN;
+ return ERRORTOKEN;
+ }
+ if (c == '\\') {
+ c = tok_nextc(tok);
+ *p_end = tok->cur;
+ if (c == '\n' || c == EOF) {
+ tok->done = E_TOKEN;
+ return ERRORTOKEN;
+ }
+ continue;
+ }
+ if (c == '\'')
+ break;
+ }
+ *p_end = tok->cur;
+ return STRING;
+ }
+
+ /* Line continuation */
+ if (c == '\\') {
+ c = tok_nextc(tok);
+ if (c != '\n') {
+ tok->done = E_TOKEN;
+ return ERRORTOKEN;
+ }
+ tok->lineno++;
+ goto again; /* Read next line */
+ }
+
+ /* Punctuation character */
+ *p_end = tok->cur;
+ return tok_1char(c);
+}
+
+
+#ifdef DEBUG
+
+void
+tok_dump(type, start, end)
+ int type;
+ char *start, *end;
+{
+ printf("%s", tok_name[type]);
+ if (type == NAME || type == NUMBER || type == STRING || type == OP)
+ printf("(%.*s)", (int)(end - start), start);
+}
+
+#endif
diff --git a/src/tokenizer.h b/src/tokenizer.h
new file mode 100644
index 0000000..aec5ef3
--- /dev/null
+++ b/src/tokenizer.h
@@ -0,0 +1,53 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* Tokenizer interface */
+
+#include "token.h" /* For token types */
+
+#define MAXINDENT 100 /* Max indentation level */
+
+/* Tokenizer state */
+struct tok_state {
+ /* Input state; buf <= cur <= inp <= end */
+ /* NB an entire token must fit in the buffer */
+ char *buf; /* Input buffer */
+ char *cur; /* Next character in buffer */
+ char *inp; /* End of data in buffer */
+ char *end; /* End of input buffer */
+ int done; /* 0 normally, 1 at EOF, -1 after error */
+ FILE *fp; /* Rest of input; NULL if tokenizing a string */
+ int tabsize; /* Tab spacing */
+ int indent; /* Current indentation index */
+ int indstack[MAXINDENT]; /* Stack of indents */
+ int atbol; /* Nonzero if at begin of new line */
+ int pendin; /* Pending indents (if > 0) or dedents (if < 0) */
+ char *prompt, *nextprompt; /* For interactive prompting */
+ int lineno; /* Current line number */
+};
+
+extern struct tok_state *tok_setups PROTO((char *));
+extern struct tok_state *tok_setupf PROTO((FILE *, char *ps1, char *ps2));
+extern void tok_free PROTO((struct tok_state *));
+extern int tok_get PROTO((struct tok_state *, char **, char **));
diff --git a/src/traceback.c b/src/traceback.c
new file mode 100644
index 0000000..7d40ca5
--- /dev/null
+++ b/src/traceback.c
@@ -0,0 +1,217 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* Traceback implementation */
+
+#include "allobjects.h"
+
+#include "compile.h"
+#include "frameobject.h"
+#include "traceback.h"
+#include "structmember.h"
+
+typedef struct _tracebackobject {
+ OB_HEAD
+ struct _tracebackobject *tb_next;
+ frameobject *tb_frame;
+ int tb_lasti;
+ int tb_lineno;
+} tracebackobject;
+
+#define OFF(x) offsetof(tracebackobject, x)
+
+static struct memberlist tb_memberlist[] = {
+ {"tb_next", T_OBJECT, OFF(tb_next)},
+ {"tb_frame", T_OBJECT, OFF(tb_frame)},
+ {"tb_lasti", T_INT, OFF(tb_lasti)},
+ {"tb_lineno", T_INT, OFF(tb_lineno)},
+ {NULL} /* Sentinel */
+};
+
+static object *
+tb_getattr(tb, name)
+ tracebackobject *tb;
+ char *name;
+{
+ return getmember((char *)tb, tb_memberlist, name);
+}
+
+static void
+tb_dealloc(tb)
+ tracebackobject *tb;
+{
+ XDECREF(tb->tb_next);
+ XDECREF(tb->tb_frame);
+ DEL(tb);
+}
+
+static typeobject Tracebacktype = {
+ OB_HEAD_INIT(&Typetype)
+ 0,
+ "traceback",
+ sizeof(tracebackobject),
+ 0,
+ tb_dealloc, /*tp_dealloc*/
+ 0, /*tp_print*/
+ tb_getattr, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+};
+
+#define is_tracebackobject(v) ((v)->ob_type == &Tracebacktype)
+
+static tracebackobject *
+newtracebackobject(next, frame, lasti, lineno)
+ tracebackobject *next;
+ frameobject *frame;
+ int lasti, lineno;
+{
+ tracebackobject *tb;
+ if ((next != NULL && !is_tracebackobject(next)) ||
+ frame == NULL || !is_frameobject(frame)) {
+ err_badcall();
+ return NULL;
+ }
+ tb = NEWOBJ(tracebackobject, &Tracebacktype);
+ if (tb != NULL) {
+ XINCREF(next);
+ tb->tb_next = next;
+ XINCREF(frame);
+ tb->tb_frame = frame;
+ tb->tb_lasti = lasti;
+ tb->tb_lineno = lineno;
+ }
+ return tb;
+}
+
+static tracebackobject *tb_current = NULL;
+
+int
+tb_here(frame, lasti, lineno)
+ frameobject *frame;
+ int lasti;
+ int lineno;
+{
+ tracebackobject *tb;
+ tb = newtracebackobject(tb_current, frame, lasti, lineno);
+ if (tb == NULL)
+ return -1;
+ XDECREF(tb_current);
+ tb_current = tb;
+ return 0;
+}
+
+object *
+tb_fetch()
+{
+ object *v;
+ v = (object *)tb_current;
+ tb_current = NULL;
+ return v;
+}
+
+int
+tb_store(v)
+ object *v;
+{
+ if (v != NULL && !is_tracebackobject(v)) {
+ err_badcall();
+ return -1;
+ }
+ XDECREF(tb_current);
+ XINCREF(v);
+ tb_current = (tracebackobject *)v;
+ return 0;
+}
+
+static void
+tb_displayline(fp, filename, lineno)
+ FILE *fp;
+ char *filename;
+ int lineno;
+{
+ FILE *xfp;
+ char buf[1000];
+ int i;
+ if (filename[0] == '<' && filename[strlen(filename)-1] == '>')
+ return;
+ xfp = fopen(filename, "r");
+ if (xfp == NULL) {
+ fprintf(fp, " (cannot open \"%s\")\n", filename);
+ return;
+ }
+ for (i = 0; i < lineno; i++) {
+ if (fgets(buf, sizeof buf, xfp) == NULL)
+ break;
+ }
+ if (i == lineno) {
+ char *p = buf;
+ while (*p == ' ' || *p == '\t')
+ p++;
+ fprintf(fp, " %s", p);
+ if (strchr(p, '\n') == NULL)
+ fprintf(fp, "\n");
+ }
+ fclose(xfp);
+}
+
+static void
+tb_printinternal(tb, fp)
+ tracebackobject *tb;
+ FILE *fp;
+{
+ while (tb != NULL) {
+ if (intrcheck()) {
+ fprintf(fp, "[interrupted]\n");
+ break;
+ }
+ fprintf(fp, " File \"");
+ printobject(tb->tb_frame->f_code->co_filename, fp, PRINT_RAW);
+ fprintf(fp, "\", line %d\n", tb->tb_lineno);
+ tb_displayline(fp,
+ getstringvalue(tb->tb_frame->f_code->co_filename),
+ tb->tb_lineno);
+ tb = tb->tb_next;
+ }
+}
+
+int
+tb_print(v, fp)
+ object *v;
+ FILE *fp;
+{
+ if (v == NULL)
+ return 0;
+ if (!is_tracebackobject(v)) {
+ err_badcall();
+ return -1;
+ }
+ sysset("last_traceback", v);
+ tb_printinternal((tracebackobject *)v, fp);
+ return 0;
+}
diff --git a/src/traceback.h b/src/traceback.h
new file mode 100644
index 0000000..2127a33
--- /dev/null
+++ b/src/traceback.h
@@ -0,0 +1,30 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* Traceback interface */
+
+int tb_here PROTO((struct _frame *, int, int));
+object *tb_fetch PROTO((void));
+int tb_store PROTO((object *));
+int tb_print PROTO((object *, FILE *));
diff --git a/src/tupleobject.c b/src/tupleobject.c
new file mode 100644
index 0000000..5ea1e11
--- /dev/null
+++ b/src/tupleobject.c
@@ -0,0 +1,287 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* Tuple object implementation */
+
+#include "allobjects.h"
+
+object *
+newtupleobject(size)
+ register int size;
+{
+ register int i;
+ register tupleobject *op;
+ if (size < 0) {
+ err_badcall();
+ return NULL;
+ }
+ op = (tupleobject *)
+ malloc(sizeof(tupleobject) + size * sizeof(object *));
+ if (op == NULL)
+ return err_nomem();
+ NEWREF(op);
+ op->ob_type = &Tupletype;
+ op->ob_size = size;
+ for (i = 0; i < size; i++)
+ op->ob_item[i] = NULL;
+ return (object *) op;
+}
+
+int
+gettuplesize(op)
+ register object *op;
+{
+ if (!is_tupleobject(op)) {
+ err_badcall();
+ return -1;
+ }
+ else
+ return ((tupleobject *)op)->ob_size;
+}
+
+object *
+gettupleitem(op, i)
+ register object *op;
+ register int i;
+{
+ if (!is_tupleobject(op)) {
+ err_badcall();
+ return NULL;
+ }
+ if (i < 0 || i >= ((tupleobject *)op) -> ob_size) {
+ err_setstr(IndexError, "tuple index out of range");
+ return NULL;
+ }
+ return ((tupleobject *)op) -> ob_item[i];
+}
+
+int
+settupleitem(op, i, newitem)
+ register object *op;
+ register int i;
+ register object *newitem;
+{
+ register object *olditem;
+ if (!is_tupleobject(op)) {
+ if (newitem != NULL)
+ DECREF(newitem);
+ err_badcall();
+ return -1;
+ }
+ if (i < 0 || i >= ((tupleobject *)op) -> ob_size) {
+ if (newitem != NULL)
+ DECREF(newitem);
+ err_setstr(IndexError, "tuple assignment index out of range");
+ return -1;
+ }
+ olditem = ((tupleobject *)op) -> ob_item[i];
+ ((tupleobject *)op) -> ob_item[i] = newitem;
+ if (olditem != NULL)
+ DECREF(olditem);
+ return 0;
+}
+
+/* Methods */
+
+static void
+tupledealloc(op)
+ register tupleobject *op;
+{
+ register int i;
+ for (i = 0; i < op->ob_size; i++) {
+ if (op->ob_item[i] != NULL)
+ DECREF(op->ob_item[i]);
+ }
+ free((ANY *)op);
+}
+
+static void
+tupleprint(op, fp, flags)
+ tupleobject *op;
+ FILE *fp;
+ int flags;
+{
+ int i;
+ fprintf(fp, "(");
+ for (i = 0; i < op->ob_size && !StopPrint; i++) {
+ if (i > 0) {
+ fprintf(fp, ", ");
+ }
+ printobject(op->ob_item[i], fp, flags);
+ }
+ if (op->ob_size == 1)
+ fprintf(fp, ",");
+ fprintf(fp, ")");
+}
+
+object *
+tuplerepr(v)
+ tupleobject *v;
+{
+ object *s, *t, *comma;
+ int i;
+ s = newstringobject("(");
+ comma = newstringobject(", ");
+ for (i = 0; i < v->ob_size && s != NULL; i++) {
+ if (i > 0)
+ joinstring(&s, comma);
+ t = reprobject(v->ob_item[i]);
+ joinstring(&s, t);
+ if (t != NULL)
+ DECREF(t);
+ }
+ DECREF(comma);
+ if (v->ob_size == 1) {
+ t = newstringobject(",");
+ joinstring(&s, t);
+ DECREF(t);
+ }
+ t = newstringobject(")");
+ joinstring(&s, t);
+ DECREF(t);
+ return s;
+}
+
+static int
+tuplecompare(v, w)
+ register tupleobject *v, *w;
+{
+ register int len =
+ (v->ob_size < w->ob_size) ? v->ob_size : w->ob_size;
+ register int i;
+ for (i = 0; i < len; i++) {
+ int cmp = cmpobject(v->ob_item[i], w->ob_item[i]);
+ if (cmp != 0)
+ return cmp;
+ }
+ return v->ob_size - w->ob_size;
+}
+
+static int
+tuplelength(a)
+ tupleobject *a;
+{
+ return a->ob_size;
+}
+
+static object *
+tupleitem(a, i)
+ register tupleobject *a;
+ register int i;
+{
+ if (i < 0 || i >= a->ob_size) {
+ err_setstr(IndexError, "tuple index out of range");
+ return NULL;
+ }
+ INCREF(a->ob_item[i]);
+ return a->ob_item[i];
+}
+
+static object *
+tupleslice(a, ilow, ihigh)
+ register tupleobject *a;
+ register int ilow, ihigh;
+{
+ register tupleobject *np;
+ register int i;
+ if (ilow < 0)
+ ilow = 0;
+ if (ihigh > a->ob_size)
+ ihigh = a->ob_size;
+ if (ihigh < ilow)
+ ihigh = ilow;
+ if (ilow == 0 && ihigh == a->ob_size) {
+ /* XXX can only do this if tuples are immutable! */
+ INCREF(a);
+ return (object *)a;
+ }
+ np = (tupleobject *)newtupleobject(ihigh - ilow);
+ if (np == NULL)
+ return NULL;
+ for (i = ilow; i < ihigh; i++) {
+ object *v = a->ob_item[i];
+ INCREF(v);
+ np->ob_item[i - ilow] = v;
+ }
+ return (object *)np;
+}
+
+static object *
+tupleconcat(a, bb)
+ register tupleobject *a;
+ register object *bb;
+{
+ register int size;
+ register int i;
+ tupleobject *np;
+ if (!is_tupleobject(bb)) {
+ err_badarg();
+ return NULL;
+ }
+#define b ((tupleobject *)bb)
+ size = a->ob_size + b->ob_size;
+ np = (tupleobject *) newtupleobject(size);
+ if (np == NULL) {
+ return err_nomem();
+ }
+ for (i = 0; i < a->ob_size; i++) {
+ object *v = a->ob_item[i];
+ INCREF(v);
+ np->ob_item[i] = v;
+ }
+ for (i = 0; i < b->ob_size; i++) {
+ object *v = b->ob_item[i];
+ INCREF(v);
+ np->ob_item[i + a->ob_size] = v;
+ }
+ return (object *)np;
+#undef b
+}
+
+static sequence_methods tuple_as_sequence = {
+ tuplelength, /*sq_length*/
+ tupleconcat, /*sq_concat*/
+ 0, /*sq_repeat*/
+ tupleitem, /*sq_item*/
+ tupleslice, /*sq_slice*/
+ 0, /*sq_ass_item*/
+ 0, /*sq_ass_slice*/
+};
+
+typeobject Tupletype = {
+ OB_HEAD_INIT(&Typetype)
+ 0,
+ "tuple",
+ sizeof(tupleobject) - sizeof(object *),
+ sizeof(object *),
+ tupledealloc, /*tp_dealloc*/
+ tupleprint, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ tuplecompare, /*tp_compare*/
+ tuplerepr, /*tp_repr*/
+ 0, /*tp_as_number*/
+ &tuple_as_sequence, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+};
diff --git a/src/tupleobject.h b/src/tupleobject.h
new file mode 100644
index 0000000..293da22
--- /dev/null
+++ b/src/tupleobject.h
@@ -0,0 +1,56 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* Tuple object interface */
+
+/*
+123456789-123456789-123456789-123456789-123456789-123456789-123456789-12
+
+Another generally useful object type is an tuple of object pointers.
+This is a mutable type: the tuple items can be changed (but not their
+number). Out-of-range indices or non-tuple objects are ignored.
+
+*** WARNING *** settupleitem does not increment the new item's reference
+count, but does decrement the reference count of the item it replaces,
+if not nil. It does *decrement* the reference count if it is *not*
+inserted in the tuple. Similarly, gettupleitem does not increment the
+returned item's reference count.
+*/
+
+typedef struct {
+ OB_VARHEAD
+ object *ob_item[1];
+} tupleobject;
+
+extern typeobject Tupletype;
+
+#define is_tupleobject(op) ((op)->ob_type == &Tupletype)
+
+extern object *newtupleobject PROTO((int size));
+extern int gettuplesize PROTO((object *));
+extern object *gettupleitem PROTO((object *, int));
+extern int settupleitem PROTO((object *, int, object *));
+
+/* Macro, trading safety for speed */
+#define GETTUPLEITEM(op, i) ((op)->ob_item[i])
diff --git a/src/typeobject.c b/src/typeobject.c
new file mode 100644
index 0000000..39ed7c7
--- /dev/null
+++ b/src/typeobject.c
@@ -0,0 +1,61 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* Type object implementation */
+
+#include "allobjects.h"
+
+/* Type object implementation */
+
+static void
+type_print(v, fp, flags)
+ typeobject *v;
+ FILE *fp;
+ int flags;
+{
+ fprintf(fp, "<type '%s'>", v->tp_name);
+}
+
+static object *
+type_repr(v)
+ typeobject *v;
+{
+ char buf[100];
+ sprintf(buf, "<type '%.80s'>", v->tp_name);
+ return newstringobject(buf);
+}
+
+typeobject Typetype = {
+ OB_HEAD_INIT(&Typetype)
+ 0, /* Number of items for varobject */
+ "type", /* Name of this type */
+ sizeof(typeobject), /* Basic object size */
+ 0, /* Item size for varobject */
+ 0, /*tp_dealloc*/
+ type_print, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ type_repr, /*tp_repr*/
+};
diff --git a/src/xxobject.c b/src/xxobject.c
new file mode 100644
index 0000000..52be44b
--- /dev/null
+++ b/src/xxobject.c
@@ -0,0 +1,131 @@
+/***********************************************************
+Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* Use this file as a template to start implementing a new object type.
+ If your objects will be called foobar, start by copying this file to
+ foobarobject.c, changing all occurrences of xx to foobar and all
+ occurrences of Xx by Foobar. You will probably want to delete all
+ references to 'x_attr' and add your own types of attributes
+ instead. Maybe you want to name your local variables other than
+ 'xp'. If your object type is needed in other files, you'll have to
+ create a file "foobarobject.h"; see intobject.h for an example. */
+
+
+/* Xx objects */
+
+#include "allobjects.h"
+
+typedef struct {
+ OB_HEAD
+ object *x_attr; /* Attributes dictionary */
+} xxobject;
+
+extern typeobject Xxtype; /* Really static, forward */
+
+#define is_xxobject(v) ((v)->ob_type == &Xxtype)
+
+static xxobject *
+newxxobject(arg)
+ object *arg;
+{
+ xxobject *xp;
+ xp = NEWOBJ(xxobject, &Xxtype);
+ if (xp == NULL)
+ return NULL;
+ xp->x_attr = NULL;
+ return xp;
+}
+
+/* Xx methods */
+
+static void
+xx_dealloc(xp)
+ xxobject *xp;
+{
+ XDECREF(xp->x_attr);
+ DEL(xp);
+}
+
+static object *
+xx_demo(self, args)
+ xxobject *self;
+ object *args;
+{
+ if (!getnoarg(args))
+ return NULL;
+ INCREF(None);
+ return None;
+}
+
+static struct methodlist xx_methods[] = {
+ "demo", xx_demo,
+ {NULL, NULL} /* sentinel */
+};
+
+static object *
+xx_getattr(xp, name)
+ xxobject *xp;
+ char *name;
+{
+ if (xp->x_attr != NULL) {
+ object *v = dictlookup(xp->x_attr, name);
+ if (v != NULL) {
+ INCREF(v);
+ return v;
+ }
+ }
+ return findmethod(xx_methods, (object *)xp, name);
+}
+
+static int
+xx_setattr(xp, name, v)
+ xxobject *xp;
+ char *name;
+ object *v;
+{
+ if (xp->x_attr == NULL) {
+ xp->x_attr = newdictobject();
+ if (xp->x_attr == NULL)
+ return -1;
+ }
+ if (v == NULL)
+ return dictremove(xp->x_attr, name);
+ else
+ return dictinsert(xp->x_attr, name, v);
+}
+
+static typeobject Xxtype = {
+ OB_HEAD_INIT(&Typetype)
+ 0, /*ob_size*/
+ "xx", /*tp_name*/
+ sizeof(xxobject), /*tp_size*/
+ 0, /*tp_itemsize*/
+ /* methods */
+ xx_dealloc, /*tp_dealloc*/
+ 0, /*tp_print*/
+ xx_getattr, /*tp_getattr*/
+ xx_setattr, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+};