diff options
Diffstat (limited to 'shar/python-0.9.1-10-21.shar')
| -rw-r--r-- | shar/python-0.9.1-10-21.shar | 2508 |
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 |
