aboutsummaryrefslogtreecommitdiff
path: root/shar/python-0.9.1-10-21.shar
diff options
context:
space:
mode:
Diffstat (limited to 'shar/python-0.9.1-10-21.shar')
-rw-r--r--shar/python-0.9.1-10-21.shar2508
1 files changed, 2508 insertions, 0 deletions
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