diff options
| author | Skip Montanaro <[email protected]> | 2021-02-16 14:40:46 -0600 |
|---|---|---|
| committer | Skip Montanaro <[email protected]> | 2021-02-16 14:40:46 -0600 |
| commit | a19a216bc60160c162e616145ef091dd18ce4e61 (patch) | |
| tree | fa4bdff21f9b04a125c84a2bfab8a1c738359e15 /shar/python-0.9.1-07-21.shar | |
| download | python-0.9.1-patched-QoL-a19a216bc60160c162e616145ef091dd18ce4e61.tar.xz python-0.9.1-patched-QoL-a19a216bc60160c162e616145ef091dd18ce4e61.zip | |
Python 0.9.1 as posted in alt.sources
Diffstat (limited to 'shar/python-0.9.1-07-21.shar')
| -rw-r--r-- | shar/python-0.9.1-07-21.shar | 2518 |
1 files changed, 2518 insertions, 0 deletions
diff --git a/shar/python-0.9.1-07-21.shar b/shar/python-0.9.1-07-21.shar new file mode 100644 index 0000000..e242423 --- /dev/null +++ b/shar/python-0.9.1-07-21.shar @@ -0,0 +1,2518 @@ +: This is a shell archive. +: Extract with 'sh this_file'. +: +: Extract part 01 first since it makes all directories +echo 'Start of pack.out, part 07 out of 21:' +if test -s 'demo/sgi/gl/mclock.py' +then echo '*** I will not over-write existing file demo/sgi/gl/mclock.py' +else +echo 'x - demo/sgi/gl/mclock.py' +sed 's/^X//' > 'demo/sgi/gl/mclock.py' << 'EOF' +X#! /ufs/guido/bin/sgi/python +X +X############################################################################# +X# NOTA BENE: Before installing, fix TZDIFF to reflect your local time zone! # +X############################################################################# +X +X# "M Clock" +X# +X# An implementation in software of an original design by Rob Juda. +X# Clock implementation: Guido van Rossum. +X# Alarm and Gong features: Sape Mullender. +X# +X# XXX TO DO: +X# find out local time zone difference automatically +X# add a date indicator +X# allow multiple alarms +X# allow the menu to change more parameters +X +Ximport sys +X +Xfrom gl import * +Xfrom GL import * +Xfrom DEVICE import * +Ximport time +Ximport getopt +Ximport string +Ximport path +Xfrom math import pi +Ximport math +Ximport posix +X +XFULLC = 3600 # Full circle in 1/10-ths of a degree +XMIDN = 900 # Angle of the 12 o'clock position +XR, G, B = 0, 1, 2 # Indices of colors in RGB list +X +XHOUR = 3600 # Number of seconds per hour +XMINUTE = 60 # Number of seconds per minute +X +Xclass struct(): pass # Class to define featureless structures +XGl = struct() # Object to hold writable global variables +X +X# Default constants (used in multiple places) +X +XSCREENBG = 127, 156, 191 +XNPARTS = 9 +XTITLE = 'M Clock' +XTZDIFF = -1*HOUR # <--- change this to reflect your local time zone +X +X# Default parameters +X +XGl.foreground = 0 # If set, run in the foreground +XGl.fullscreen = 0 # If set, run on full screen +XGl.tzdiff = TZDIFF # Seconds west of Greenwich (winter time) +XGl.nparts = NPARTS # Number of parts each circle is divided in (>= 2) +XGl.debug = 0 # If set, print debug output +XGl.doublebuffer = 1 # If set, use double buffering +XGl.update = 0 # Update interval; seconds hand is suppressed if > 1 +XGl.colorsubset = 0 # If set, display only a subset of the colors +XGl.cyan = 0 # If set, display cyan overlay (big hand) +XGl.magenta = 0 # If set, display magenta overlay (little hand) +XGl.yellow = 0 # If set, display yellow overlay (fixed background) +XGl.black = 0 # If set, display black overlay (hands) +XGl.colormap = 0 # If set, use colormap mode instead of RGB mode +XGl.warnings = 0 # If set, print warnings +XGl.title = '- - ' # Window title (default set later) +XGl.border = 1 # If set, use a window border (and title) +XGl.bg = 0, 0, 0 # Background color R, G, B value +XGl.iconic = 0 # Set in iconic state +XGl.fg = 255, 0, 0 # Alarm background RGB (either normal or alarm) +XGl.ox,Gl.oy = 0,0 # Window origin +XGl.cx,Gl.cy = 0,0 # Window size +XGl.alarm_set = 0 # Alarm on or off +XGl.alarm_on = 0 # Alarm is ringing +XGl.alarm_time = 0 # Alarm time in seconds after midnight +XGl.alarm_hours = 0 # Alarm hour setting, 24 hour clock +XGl.alarm_minutes = 0 # Alarm minutes setting +XGl.alarm_rgb = 0,0,0 # Alarm display RGB colors +XGl.alarm_cmd = '' # Command to execute when alarm goes off +XGl.mouse2down = 0 # Mouse button state +XGl.mouse3down = 0 # Mouse button state +XGl.gong_cmd = '' # Command to execute when chimes go off +XGl.gong_int = 3600 # Gong interval +XGl.indices = R, G, B # Colors (permuted when alarm is on) +X +Xdef main(): +X # +X sys.stdout = sys.stderr # All output is errors/warnings etc. +X # +X try: +X args = getoptions() +X except string.atoi_error, value: +X usage(string.atoi_error, value) +X except getopt.error, msg: +X usage(getopt.error, msg) +X # +X if args: +X realtime = 0 +X hours = string.atoi(args[0]) +X minutes = seconds = 0 +X if args[1:]: minutes = string.atoi(args[1]) +X if args[2:]: seconds = string.atoi(args[2]) +X localtime = ((hours*60)+minutes)*60+seconds +X else: +X realtime = 1 +X # +X if Gl.title = '- - ': +X if realtime: +X Gl.title = TITLE +X else: +X title = '' +X for arg in args: title = title + ' ' + arg +X Gl.title = title[1:] +X del title +X # +X wid = makewindow() +X Gl.ox,Gl.oy = getorigin() +X Gl.cx,Gl.cy = getsize() +X initmenu() +X clearall() +X # +X if not Gl.update: +X Gl.update = 60 +X # +X if Gl.update <= 1: +X Gl.timernoise = 6 +X else: +X Gl.timernoise = 60 +X noise(TIMER0, Gl.timernoise) +X # +X qdevice(WINSHUT) +X qdevice(WINQUIT) +X qdevice(ESCKEY) +X if realtime: +X qdevice(TIMER0) +X qdevice(REDRAW) +X qdevice(WINFREEZE) +X qdevice(WINTHAW) +X qdevice(MENUBUTTON) # MOUSE1 +X qdevice(MOUSE3) # Left button +X qdevice(MOUSE2) # Middle button +X unqdevice(INPUTCHANGE) +X # +X lasttime = 0 +X Gl.change = 1 +X while 1: +X if realtime: +X localtime = time.time() - Gl.tzdiff +X if Gl.alarm_set: +X if localtime%(24*HOUR) = Gl.alarm_time: +X # Ring the alarm! +X if Gl.debug: +X print 'Rrrringg!' +X Gl.alarm_on = 1 +X if Gl.alarm_cmd <> '': +X d = posix.system(Gl.alarm_cmd+' '+`Gl.alarm_time/3600`+' '+`(Gl.alarm_time/60)%60` + ' &') +X Gl.change = 1 +X clearall() +X if Gl.alarm_on: +X if (localtime - Gl.alarm_time) % (24*HOUR) > 300: +X # More than 5 minutes away from alarm +X Gl.alarm_on = 0 +X if Gl.debug: +X print 'Alarm turned off' +X Gl.change = 1 +X clearall() +X Gl.indices = R, G, B +X else: +X if localtime % 2 = 0: +X # Permute color indices +X Gl.indices = Gl.indices[2:] + Gl.indices[:2] +X Gl.change = 1 +X if Gl.gong_cmd <> '' and localtime%Gl.gong_int = 0: +X d = posix.system(Gl.gong_cmd+' '+`(localtime/3600)%24`+' '+`(localtime/60)%60` + ' &') +X if localtime/Gl.update <> lasttime/Gl.update: +X if Gl.debug: print 'new time' +X Gl.change = 1 +X if Gl.change: +X if Gl.debug: print 'drawing' +X doit(localtime) +X lasttime = localtime +X Gl.change = 0 +X dev, data = qread() +X if Gl.debug and dev <> TIMER0: +X print dev, data +X if dev = TIMER0: +X if Gl.debug > 1: +X print dev, data +X elif dev = MOUSE3: +X mousex = getvaluator(MOUSEX) +X mousey = getvaluator(MOUSEY) +X if mouseclick(3, data, mousex, mousey): +X Gl.change = 1 +X elif dev = MOUSE2: +X mousex = getvaluator(MOUSEX) +X mousey = getvaluator(MOUSEY) +X if mouseclick(2, data, mousex, mousey): +X Gl.change = 1 +X elif dev = MOUSEX: +X mousex = data +X if Gl.mouse2down: +X mouse2track(mousex, mousey) +X if Gl.mouse3down: +X mouse3track(mousex, mousey) +X elif dev = MOUSEY: +X mousey = data +X if Gl.mouse2down: +X mouse2track(mousex, mousey) +X if Gl.mouse3down: +X mouse3track(mousex, mousey) +X elif dev = REDRAW or dev = REDRAWICONIC: +X if Gl.debug: +X if dev = REDRAW: print 'REDRAW' +X else: print 'REDRAWICONIC' +X reshapeviewport() +X Gl.ox,Gl.oy = getorigin() +X Gl.cx,Gl.cy = getsize() +X Gl.change = 1 +X clearall() +X elif dev = MENUBUTTON: +X if Gl.debug: print 'MENUBUTTON' +X handlemenu() +X elif dev = WINFREEZE: +X if Gl.debug: print 'WINFREEZE' +X Gl.iconic = 1 +X noise(TIMER0, 60*60) # Redraw every 60 seconds only +X elif dev = WINTHAW: +X if Gl.debug: print 'WINTHAW' +X Gl.iconic = 0 +X noise(TIMER0, Gl.timernoise) +X Gl.change = 1 +X elif dev = ESCKEY or dev = WINSHUT or dev = WINQUIT: +X if Gl.debug: print 'Exit' +X sys.exit(0) +X +Xdef getoptions(): +X optlist, args = getopt.getopt(sys.argv[1:], 'A:a:B:bc:dFfG:g:n:sT:t:u:wCMYK') +X for optname, optarg in optlist: +X if optname = '-A': +X Gl.fg = eval(optarg) # Should be (r,g,b) +X elif optname = '-a': +X Gl.alarm_cmd = optarg +X elif optname = '-B': +X Gl.bg = eval(optarg) # Should be (r,g,b) +X elif optname = '-b': +X Gl.border = 0 +X elif optname = '-c': +X Gl.colormap = string.atoi(optarg) +X elif optname = '-d': +X Gl.debug = Gl.debug + 1 +X Gl.warnings = 1 +X elif optname = '-F': +X Gl.foreground = 1 +X elif optname = '-f': +X Gl.fullscreen = 1 +X elif optname = '-G': +X Gl.gong_int = 60*string.atoi(optarg) +X elif optname = '-g': +X Gl.gong_cmd = optarg +X elif optname = '-n': +X Gl.nparts = string.atoi(optarg) +X elif optname = '-s': +X Gl.doublebuffer = 0 +X elif optname = '-T': +X Gl.title = optarg +X elif optname = '-t': +X Gl.tzdiff = string.atoi(optarg) +X elif optname = '-u': +X Gl.update = string.atoi(optarg) +X elif optname = '-w': +X Gl.warnings = 1 +X elif optname = '-C': +X Gl.cyan = Gl.colorsubset = 1 +X elif optname = '-M': +X Gl.magenta = Gl.colorsubset = 1 +X elif optname = '-Y': +X Gl.yellow = Gl.colorsubset = 1 +X elif optname = '-K': +X Gl.black = Gl.colorsubset = 1 +X else: +X print 'Unsupported option', optname +X return args +X +Xdef usage(exc, msg): +X if sys.argv: +X progname = path.basename(sys.argv[0]) +X else: +X progname = 'mclock' +X # +X print progname + ':', +X if exc = string.atoi_error: +X print 'non-numeric argument:', +X print msg +X # +X print 'usage:', progname, '[options] [hh [mm [ss]]]' +X # +X print '-A r,g,b : alarm background red,green,blue [255,0,0]' +X print '-a cmd : shell command executed when alarm goes off' +X print '-B r,g,b : background red,green,blue [0,0,0]' +X print ' (-B SCREENBG uses the default screen background)' +X print '-b : suppress window border and title' +X print '-c cmapid : select explicit colormap' +X print '-d : more debug output (implies -F, -w)' +X print '-F : run in foreground' +X print '-f : use full screen' +X print '-G intrvl : interval between chimes in minutes [60]' +X print '-g cmd : shell command executed when chimes go off' +X print '-s : single buffer mode' +X print '-w : print various warnings' +X print '-n nparts : number of parts [' + `NPARTS` + ']' +X print '-T title : alternate window title [\'' + TITLE + '\']' +X print '-t tzdiff : time zone difference [' + `TZDIFF` + ']' +X print '-u update : update interval [60]' +X print '-CMYK : Cyan, Magenta, Yellow or blacK overlay only' +X print 'if hh [mm [ss]] is specified, display that time statically' +X print 'on machines with < 12 bitplanes, -c and -s are forced on' +X # +X sys.exit(2) +X +Xdef doit(localtime): +X hands = makehands(localtime) +X list = makelist(hands) +X render(list, hands) +X +Xdef makehands(localtime): +X localtime = localtime % (12*HOUR) +X seconds_hand = MIDN + FULLC - (localtime*60) % FULLC +X big_hand = (MIDN + FULLC - (localtime%HOUR)) % FULLC +X little_hand = (MIDN + FULLC - ((localtime/12) % HOUR)) % FULLC +X return little_hand, big_hand, seconds_hand +X +Xdef makelist(little_hand, big_hand, seconds_hand): +X total = [] +X if Gl.cyan or not Gl.colorsubset: +X total = total + makesublist(big_hand, Gl.indices[0]) +X if Gl.magenta or not Gl.colorsubset: +X total = total + makesublist(little_hand, Gl.indices[1]) +X if Gl.yellow or not Gl.colorsubset: +X total = total + makesublist(MIDN, Gl.indices[2]) +X total.sort() +X return total +X +Xdef makesublist(first, icolor): +X list = [] +X alpha = FULLC/Gl.nparts +X a = first - alpha/2 +X for i in range(Gl.nparts): +X angle = (a + i*alpha + FULLC) % FULLC +X value = 255*(Gl.nparts-1-i)/(Gl.nparts-1) +X list.append(angle, icolor, value) +X list.sort() +X a, icolor, value = list[0] +X if a <> 0: +X a, icolor, value = list[len(list)-1] +X t = 0, icolor, value +X list.insert(0, t) +X return list +X +Xdef rgb_fg(): +X return Gl.fg +X # Obsolete code: +X if Gl.alarm_on: +X return Gl.bg +X else: +X return Gl.fg +X +Xdef rgb_bg(): +X return Gl.bg +X # Obsolete code: +X if Gl.alarm_on: +X return Gl.fg +X else: +X return Gl.bg +X +Xdef clearall(): +X Gl.c3i(rgb_bg()) +X clear() +X if Gl.doublebuffer: +X swapbuffers() +X clear() +X +Xdef draw_alarm(color): +X frontbuffer(TRUE) +X Gl.c3i(color) +X pushmatrix() +X rotate(-((Gl.alarm_time/12)%3600), 'z') +X bgnpolygon() +X v2f( 0.00,1.00) +X v2f( 0.04,1.05) +X v2f(-0.04,1.05) +X endpolygon() +X popmatrix() +X # +X pushmatrix() +X rotate(-((Gl.alarm_time)%3600), 'z') +X bgnpolygon() +X v2f( 0.00,1.05) +X v2f( 0.07,1.10) +X v2f(-0.07,1.10) +X endpolygon() +X popmatrix() +X # +X cmov2(-1.06, -1.06) +X charstr(string.rjust(`Gl.alarm_time/3600`,2)) +X charstr(':') +X charstr(string.zfill((Gl.alarm_time/60)%60,2)) +X frontbuffer(FALSE) +X +Xdef render(list, (little_hand, big_hand, seconds_hand)): +X # +X if Gl.colormap: +X resetindex() +X # +X if not list: +X Gl.c3i(255, 255, 255) # White +X circf(0.0, 0.0, 1.0) +X else: +X list.append(3600, 0, 255) # Sentinel +X # +X rgb = [255, 255, 255] +X a_prev = 0 +X for a, icolor, value in list: +X if a <> a_prev: +X [r, g, b] = rgb +X if Gl.debug > 1: +X print rgb, a_prev, a +X Gl.c3i(r, g, b) +X arcf(0.0, 0.0, 1.0, a_prev, a) +X rgb[icolor] = value +X a_prev = a +X # +X if Gl.black or not Gl.colorsubset: +X # +X # Draw the hands -- in black +X # +X Gl.c3i(0, 0, 0) +X # +X if Gl.update = 1 and not Gl.iconic: +X # Seconds hand is only drawn if we update every second +X pushmatrix() +X rotate(seconds_hand, 'z') +X bgnline() +X v2f(0.0, 0.0) +X v2f(1.0, 0.0) +X endline() +X popmatrix() +X # +X pushmatrix() +X rotate(big_hand, 'z') +X rectf(0.0, -0.01, 0.97, 0.01) +X circf(0.0, 0.0, 0.01) +X circf(0.97, 0.0, 0.01) +X popmatrix() +X # +X pushmatrix() +X rotate(little_hand, 'z') +X rectf(0.04, -0.02, 0.63, 0.02) +X circf(0.04, 0.0, 0.02) +X circf(0.63, 0.0, 0.02) +X popmatrix() +X # +X # Draw the alarm time, if set or being set +X # +X if Gl.alarm_set: +X draw_alarm(rgb_fg()) +X # +X if Gl.doublebuffer: swapbuffers() +X +Xdef makewindow(): +X # +X if Gl.debug or Gl.foreground: +X foreground() +X # +X if Gl.fullscreen: +X # XXX Should find out true screen size using getgdesc() +X prefposition(0, 1279, 0, 1023) +X else: +X keepaspect(1, 1) +X minsize(64, 64) +X # +X if not Gl.border: +X noborder() +X wid = winopen(Gl.title) +X # +X if not Gl.fullscreen: +X keepaspect(1, 1) +X minsize(10, 10) +X maxsize(2000, 2000) +X iconsize(66, 66) +X winconstraints() +X # +X nplanes = getplanes() +X nmaps = getgdesc(GD_NMMAPS) +X if Gl.warnings: +X print nplanes, 'color planes,', nmaps, 'color maps' +X # +X if nplanes < 12 or Gl.colormap: +X if not Gl.colormap: +X Gl.colormap = nmaps - 1 +X if Gl.warnings: +X print 'not enough color planes available', +X print 'for RGB mode; forcing colormap mode' +X print 'using color map number', Gl.colormap +X if not Gl.colorsubset: +X needed = 3 +X else: +X needed = Gl.cyan + Gl.magenta + Gl.yellow +X needed = needed*Gl.nparts +X if Gl.bg <> (0, 0, 0): +X needed = needed+1 +X if Gl.fg <> (0, 0, 0): +X needed = needed+1 +X if Gl.doublebuffer: +X if needed > available(nplanes/2): +X Gl.doublebuffer = 0 +X if Gl.warnings: +X print 'not enough colors available', +X print 'for double buffer mode;', +X print 'forcing single buffer mode' +X else: +X nplanes = nplanes/2 +X if needed > available(nplanes): +X # Do this warning always +X print 'still not enough colors available;', +X print 'parts will be left white' +X print '(needed', needed, 'but have only', +X print available(nplanes), 'colors available)' +X # +X if Gl.doublebuffer: +X doublebuffer() +X gconfig() +X # +X if Gl.colormap: +X Gl.c3i = pseudo_c3i +X fixcolormap() +X else: +X Gl.c3i = c3i +X RGBmode() +X gconfig() +X # +X if Gl.fullscreen: +X # XXX Should find out true screen size using getgdesc() +X ortho2(-1.1*1.280, 1.1*1.280, -1.1*1.024, 1.1*1.024) +X else: +X ortho2(-1.1, 1.1, -1.1, 1.1) +X # +X return wid +X +Xdef available(nplanes): +X return pow(2, nplanes) - 1 # Reserve one pixel for black +X +Xdef fixcolormap(): +X multimap() +X gconfig() +X nplanes = getplanes() +X if Gl.warnings: +X print 'multimap mode has', nplanes, 'color planes' +X imap = Gl.colormap +X Gl.startindex = pow(2, nplanes) - 1 +X Gl.stopindex = 1 +X setmap(imap) +X mapcolor(0, 0, 0, 0) # Fixed entry for black +X if Gl.bg <> (0, 0, 0): +X r, g, b = Gl.bg +X mapcolor(1, r, g, b) # Fixed entry for Gl.bg +X Gl.stopindex = 2 +X if Gl.fg <> (0, 0, 0): +X r, g, b = Gl.fg +X mapcolor(2, r, g, b) # Fixed entry for Gl.fg +X Gl.stopindex = 3 +X Gl.overflow_seen = 0 +X resetindex() +X +Xdef resetindex(): +X Gl.index = Gl.startindex +X +Xr0g0b0 = (0, 0, 0) +X +Xdef pseudo_c3i(rgb): +X if rgb = r0g0b0: +X index = 0 +X elif rgb = Gl.bg: +X index = 1 +X elif rgb = Gl.fg: +X index = 2 +X else: +X index = definecolor(rgb) +X color(index) +X +Xdef definecolor(rgb): +X index = Gl.index +X if index < Gl.stopindex: +X if Gl.debug: print 'definecolor hard case', rgb +X # First see if we already have this one... +X for index in range(Gl.stopindex, Gl.startindex+1): +X if rgb = getmcolor(index): +X if Gl.debug: print 'return', index +X return index +X # Don't clobber reserverd colormap entries +X if not Gl.overflow_seen: +X # Shouldn't happen any more, hence no Gl.warnings test +X print 'mclock: out of colormap entries' +X Gl.overflow_seen = 1 +X return Gl.stopindex +X r, g, b = rgb +X if Gl.debug > 1: print 'mapcolor', (index, r, g, b) +X mapcolor(index, r, g, b) +X Gl.index = index - 1 +X return index +X +X# Compute n**i +Xdef pow(n, i): +X x = 1 +X for j in range(i): x = x*n +X return x +X +Xdef mouseclick(mouse, updown, x, y): +X if updown = 1: +X # mouse button came down, start tracking +X if Gl.debug: +X print 'mouse', mouse, 'down at', x, y +X if mouse = 2: +X Gl.mouse2down = 1 +X mouse2track(x, y) +X elif mouse = 3: +X Gl.mouse3down = 1 +X mouse3track(x, y) +X else: +X print 'fatal error' +X qdevice(MOUSEX) +X qdevice(MOUSEY) +X return 0 +X else: +X # mouse button came up, stop tracking +X if Gl.debug: +X print 'mouse', mouse, 'up at', x, y +X unqdevice(MOUSEX) +X unqdevice(MOUSEY) +X if mouse = 2: +X mouse2track(x, y) +X Gl.mouse2down = 0 +X elif mouse = 3: +X mouse3track(x, y) +X Gl.mouse3down = 0 +X else: +X print 'fatal error' +X Gl.alarm_set = 1 +X return 1 +X +Xdef mouse3track(x, y): +X # first compute polar coordinates from x and y +X cx, cy = Gl.ox + Gl.cx/2, Gl.oy + Gl.cy/2 +X x, y = x - cx, y - cy +X if (x, y) = (0, 0): return # would cause an exception +X minutes = int(30.5 + 30.0*math.atan2(float(-x), float(-y))/pi) +X if minutes = 60: minutes = 0 +X a,b = Gl.alarm_minutes/15, minutes/15 +X if (a,b) = (0,3): +X # Moved backward through 12 o'clock: +X Gl.alarm_hours = Gl.alarm_hours - 1 +X if Gl.alarm_hours < 0: Gl.alarm_hours = Gl.alarm_hours + 24 +X if (a,b) = (3,0): +X # Moved forward through 12 o'clock: +X Gl.alarm_hours = Gl.alarm_hours + 1 +X if Gl.alarm_hours >= 24: Gl.alarm_hours = Gl.alarm_hours - 24 +X Gl.alarm_minutes = minutes +X seconds = Gl.alarm_hours * HOUR + Gl.alarm_minutes * MINUTE +X if seconds <> Gl.alarm_time: +X draw_alarm(rgb_bg()) +X Gl.alarm_time = seconds +X draw_alarm(rgb_fg()) +X +Xdef mouse2track(x, y): +X # first compute polar coordinates from x and y +X cx, cy = Gl.ox + Gl.cx/2, Gl.oy + Gl.cy/2 +X x, y = x - cx, y - cy +X if (x, y) = (0, 0): return # would cause an exception +X hours = int(6.5 - float(Gl.alarm_minutes)/60.0 + 6.0*math.atan2(float(-x), float(-y))/pi) +X if hours = 12: hours = 0 +X if (Gl.alarm_hours,hours) = (0,11): +X # Moved backward through midnight: +X Gl.alarm_hours = 23 +X elif (Gl.alarm_hours,hours) = (12,11): +X # Moved backward through noon: +X Gl.alarm_hours = 11 +X elif (Gl.alarm_hours,hours) = (11,0): +X # Moved forward through noon: +X Gl.alarm_hours = 12 +X elif (Gl.alarm_hours,hours) = (23,0): +X # Moved forward through midnight: +X Gl.alarm_hours = 0 +X elif Gl.alarm_hours < 12: +X Gl.alarm_hours = hours +X else: +X Gl.alarm_hours = hours + 12 +X seconds = Gl.alarm_hours * HOUR + Gl.alarm_minutes * MINUTE +X if seconds <> Gl.alarm_time: +X draw_alarm(rgb_bg()) +X Gl.alarm_time = seconds +X draw_alarm(rgb_fg()) +X +Xdef initmenu(): +X Gl.pup = pup = newpup() +X addtopup(pup, 'M Clock%t|Alarm On/Off|Seconds Hand On/Off|Quit', 0) +X +Xdef handlemenu(): +X item = dopup(Gl.pup) +X if item = 1: +X # Toggle alarm +X if Gl.alarm_set: +X Gl.alarm_set = 0 +X Gl.alarm_on = 0 +X else: +X Gl.alarm_set = 1 +X Gl.change = 1 +X clearall() +X elif item = 2: +X # Toggle Seconds Hand +X if Gl.update = 1: +X Gl.update = 60 +X Gl.timernoise = 60 +X else: +X Gl.update = 1 +X Gl.timernoise = 6 +X Gl.change = 1 +X elif item = 3: +X if Gl.debug: print 'Exit' +X sys.exit(0) +X +Xmain() +EOF +chmod +x 'demo/sgi/gl/mclock.py' +fi +if test -s 'src/ceval.c' +then echo '*** I will not over-write existing file src/ceval.c' +else +echo 'x - src/ceval.c' +sed 's/^X//' > 'src/ceval.c' << 'EOF' +X/*********************************************************** +XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The +XNetherlands. +X +X All Rights Reserved +X +XPermission to use, copy, modify, and distribute this software and its +Xdocumentation for any purpose and without fee is hereby granted, +Xprovided that the above copyright notice appear in all copies and that +Xboth that copyright notice and this permission notice appear in +Xsupporting documentation, and that the names of Stichting Mathematisch +XCentrum or CWI not be used in advertising or publicity pertaining to +Xdistribution of the software without specific, written prior permission. +X +XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO +XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE +XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +X +X******************************************************************/ +X +X/* Execute compiled code */ +X +X#include "allobjects.h" +X +X#include "import.h" +X#include "sysmodule.h" +X#include "compile.h" +X#include "frameobject.h" +X#include "ceval.h" +X#include "opcode.h" +X#include "bltinmodule.h" +X#include "traceback.h" +X +X#ifndef NDEBUG +X#define TRACE +X#endif +X +X#ifdef TRACE +Xstatic int +Xprtrace(v, str) +X object *v; +X char *str; +X{ +X printf("%s ", str); +X printobject(v, stdout, 0); +X printf("\n"); +X} +X#endif +X +Xstatic frameobject *current_frame; +X +Xobject * +Xgetlocals() +X{ +X if (current_frame == NULL) +X return NULL; +X else +X return current_frame->f_locals; +X} +X +Xobject * +Xgetglobals() +X{ +X if (current_frame == NULL) +X return NULL; +X else +X return current_frame->f_globals; +X} +X +Xvoid +Xprinttraceback(fp) +X FILE *fp; +X{ +X object *v = tb_fetch(); +X if (v != NULL) { +X fprintf(fp, "Stack backtrace (innermost last):\n"); +X tb_print(v, fp); +X DECREF(v); +X } +X} +X +X +X/* XXX Mixing "print ...," and direct file I/O on stdin/stdout +X XXX has some bad consequences. The needspace flag should +X XXX really be part of the file object. */ +X +Xstatic int needspace; +X +Xvoid +Xflushline() +X{ +X FILE *fp = sysgetfile("stdout", stdout); +X if (needspace) { +X fprintf(fp, "\n"); +X needspace = 0; +X } +X} +X +X +X/* Test a value used as condition, e.g., in a for or if statement */ +X +Xstatic int +Xtestbool(v) +X object *v; +X{ +X if (is_intobject(v)) +X return getintvalue(v) != 0; +X if (is_floatobject(v)) +X return getfloatvalue(v) != 0.0; +X if (v->ob_type->tp_as_sequence != NULL) +X return (*v->ob_type->tp_as_sequence->sq_length)(v) != 0; +X if (v->ob_type->tp_as_mapping != NULL) +X return (*v->ob_type->tp_as_mapping->mp_length)(v) != 0; +X if (v == None) +X return 0; +X /* All other objects are 'true' */ +X return 1; +X} +X +Xstatic object * +Xadd(v, w) +X object *v, *w; +X{ +X if (v->ob_type->tp_as_number != NULL) +X v = (*v->ob_type->tp_as_number->nb_add)(v, w); +X else if (v->ob_type->tp_as_sequence != NULL) +X v = (*v->ob_type->tp_as_sequence->sq_concat)(v, w); +X else { +X err_setstr(TypeError, "+ not supported by operands"); +X return NULL; +X } +X return v; +X} +X +Xstatic object * +Xsub(v, w) +X object *v, *w; +X{ +X if (v->ob_type->tp_as_number != NULL) +X return (*v->ob_type->tp_as_number->nb_subtract)(v, w); +X err_setstr(TypeError, "bad operand type(s) for -"); +X return NULL; +X} +X +Xstatic object * +Xmul(v, w) +X object *v, *w; +X{ +X typeobject *tp; +X if (is_intobject(v) && w->ob_type->tp_as_sequence != NULL) { +X /* int*sequence -- swap v and w */ +X object *tmp = v; +X v = w; +X w = tmp; +X } +X tp = v->ob_type; +X if (tp->tp_as_number != NULL) +X return (*tp->tp_as_number->nb_multiply)(v, w); +X if (tp->tp_as_sequence != NULL) { +X if (!is_intobject(w)) { +X err_setstr(TypeError, +X "can't multiply sequence with non-int"); +X return NULL; +X } +X if (tp->tp_as_sequence->sq_repeat == NULL) { +X err_setstr(TypeError, "sequence does not support *"); +X return NULL; +X } +X return (*tp->tp_as_sequence->sq_repeat) +X (v, (int)getintvalue(w)); +X } +X err_setstr(TypeError, "bad operand type(s) for *"); +X return NULL; +X} +X +Xstatic object * +Xdivide(v, w) +X object *v, *w; +X{ +X if (v->ob_type->tp_as_number != NULL) +X return (*v->ob_type->tp_as_number->nb_divide)(v, w); +X err_setstr(TypeError, "bad operand type(s) for /"); +X return NULL; +X} +X +Xstatic object * +Xrem(v, w) +X object *v, *w; +X{ +X if (v->ob_type->tp_as_number != NULL) +X return (*v->ob_type->tp_as_number->nb_remainder)(v, w); +X err_setstr(TypeError, "bad operand type(s) for %"); +X return NULL; +X} +X +Xstatic object * +Xneg(v) +X object *v; +X{ +X if (v->ob_type->tp_as_number != NULL) +X return (*v->ob_type->tp_as_number->nb_negative)(v); +X err_setstr(TypeError, "bad operand type(s) for unary -"); +X return NULL; +X} +X +Xstatic object * +Xpos(v) +X object *v; +X{ +X if (v->ob_type->tp_as_number != NULL) +X return (*v->ob_type->tp_as_number->nb_positive)(v); +X err_setstr(TypeError, "bad operand type(s) for unary +"); +X return NULL; +X} +X +Xstatic object * +Xnot(v) +X object *v; +X{ +X int outcome = testbool(v); +X object *w = outcome == 0 ? True : False; +X INCREF(w); +X return w; +X} +X +Xstatic object * +Xcall_builtin(func, arg) +X object *func; +X object *arg; +X{ +X if (is_methodobject(func)) { +X method meth = getmethod(func); +X object *self = getself(func); +X return (*meth)(self, arg); +X } +X if (is_classobject(func)) { +X if (arg != NULL) { +X err_setstr(TypeError, +X "classobject() allows no arguments"); +X return NULL; +X } +X return newclassmemberobject(func); +X } +X err_setstr(TypeError, "call of non-function"); +X return NULL; +X} +X +Xstatic object * +Xcall_function(func, arg) +X object *func; +X object *arg; +X{ +X object *newarg = NULL; +X object *newlocals, *newglobals; +X object *co, *v; +X +X if (is_classmethodobject(func)) { +X object *self = classmethodgetself(func); +X func = classmethodgetfunc(func); +X if (arg == NULL) { +X arg = self; +X } +X else { +X newarg = newtupleobject(2); +X if (newarg == NULL) +X return NULL; +X INCREF(self); +X INCREF(arg); +X settupleitem(newarg, 0, self); +X settupleitem(newarg, 1, arg); +X arg = newarg; +X } +X } +X else { +X if (!is_funcobject(func)) { +X err_setstr(TypeError, "call of non-function"); +X return NULL; +X } +X } +X +X co = getfunccode(func); +X if (co == NULL) { +X XDECREF(newarg); +X return NULL; +X } +X if (!is_codeobject(co)) { +X fprintf(stderr, "XXX Bad code\n"); +X abort(); +X } +X newlocals = newdictobject(); +X if (newlocals == NULL) { +X XDECREF(newarg); +X return NULL; +X } +X +X newglobals = getfuncglobals(func); +X INCREF(newglobals); +X +X v = eval_code((codeobject *)co, newglobals, newlocals, arg); +X +X DECREF(newlocals); +X DECREF(newglobals); +X +X XDECREF(newarg); +X +X return v; +X} +X +Xstatic object * +Xapply_subscript(v, w) +X object *v, *w; +X{ +X typeobject *tp = v->ob_type; +X if (tp->tp_as_sequence == NULL && tp->tp_as_mapping == NULL) { +X err_setstr(TypeError, "unsubscriptable object"); +X return NULL; +X } +X if (tp->tp_as_sequence != NULL) { +X int i; +X if (!is_intobject(w)) { +X err_setstr(TypeError, "sequence subscript not int"); +X return NULL; +X } +X i = getintvalue(w); +X return (*tp->tp_as_sequence->sq_item)(v, i); +X } +X return (*tp->tp_as_mapping->mp_subscript)(v, w); +X} +X +Xstatic object * +Xloop_subscript(v, w) +X object *v, *w; +X{ +X sequence_methods *sq = v->ob_type->tp_as_sequence; +X int i, n; +X if (sq == NULL) { +X err_setstr(TypeError, "loop over non-sequence"); +X return NULL; +X } +X i = getintvalue(w); +X n = (*sq->sq_length)(v); +X if (i >= n) +X return NULL; /* End of loop */ +X return (*sq->sq_item)(v, i); +X} +X +Xstatic int +Xslice_index(v, isize, pi) +X object *v; +X int isize; +X int *pi; +X{ +X if (v != NULL) { +X if (!is_intobject(v)) { +X err_setstr(TypeError, "slice index must be int"); +X return -1; +X } +X *pi = getintvalue(v); +X if (*pi < 0) +X *pi += isize; +X } +X return 0; +X} +X +Xstatic object * +Xapply_slice(u, v, w) /* return u[v:w] */ +X object *u, *v, *w; +X{ +X typeobject *tp = u->ob_type; +X int ilow, ihigh, isize; +X if (tp->tp_as_sequence == NULL) { +X err_setstr(TypeError, "only sequences can be sliced"); +X return NULL; +X } +X ilow = 0; +X isize = ihigh = (*tp->tp_as_sequence->sq_length)(u); +X if (slice_index(v, isize, &ilow) != 0) +X return NULL; +X if (slice_index(w, isize, &ihigh) != 0) +X return NULL; +X return (*tp->tp_as_sequence->sq_slice)(u, ilow, ihigh); +X} +X +Xstatic int +Xassign_subscript(w, key, v) /* w[key] = v */ +X object *w; +X object *key; +X object *v; +X{ +X typeobject *tp = w->ob_type; +X sequence_methods *sq; +X mapping_methods *mp; +X int (*func)(); +X if ((sq = tp->tp_as_sequence) != NULL && +X (func = sq->sq_ass_item) != NULL) { +X if (!is_intobject(key)) { +X err_setstr(TypeError, +X "sequence subscript must be integer"); +X return -1; +X } +X else +X return (*func)(w, (int)getintvalue(key), v); +X } +X else if ((mp = tp->tp_as_mapping) != NULL && +X (func = mp->mp_ass_subscript) != NULL) { +X return (*func)(w, key, v); +X } +X else { +X err_setstr(TypeError, +X "can't assign to this subscripted object"); +X return -1; +X } +X} +X +Xstatic int +Xassign_slice(u, v, w, x) /* u[v:w] = x */ +X object *u, *v, *w, *x; +X{ +X sequence_methods *sq = u->ob_type->tp_as_sequence; +X int ilow, ihigh, isize; +X if (sq == NULL) { +X err_setstr(TypeError, "assign to slice of non-sequence"); +X return -1; +X } +X if (sq == NULL || sq->sq_ass_slice == NULL) { +X err_setstr(TypeError, "unassignable slice"); +X return -1; +X } +X ilow = 0; +X isize = ihigh = (*sq->sq_length)(u); +X if (slice_index(v, isize, &ilow) != 0) +X return -1; +X if (slice_index(w, isize, &ihigh) != 0) +X return -1; +X return (*sq->sq_ass_slice)(u, ilow, ihigh, x); +X} +X +Xstatic int +Xcmp_exception(err, v) +X object *err, *v; +X{ +X if (is_tupleobject(v)) { +X int i, n; +X n = gettuplesize(v); +X for (i = 0; i < n; i++) { +X if (err == gettupleitem(v, i)) +X return 1; +X } +X return 0; +X } +X return err == v; +X} +X +Xstatic int +Xcmp_member(v, w) +X object *v, *w; +X{ +X int i, n, cmp; +X object *x; +X sequence_methods *sq; +X /* Special case for char in string */ +X if (is_stringobject(w)) { +X register char *s, *end; +X register char c; +X if (!is_stringobject(v) || getstringsize(v) != 1) { +X err_setstr(TypeError, +X "string member test needs char left operand"); +X return -1; +X } +X c = getstringvalue(v)[0]; +X s = getstringvalue(w); +X end = s + getstringsize(w); +X while (s < end) { +X if (c == *s++) +X return 1; +X } +X return 0; +X } +X sq = w->ob_type->tp_as_sequence; +X if (sq == NULL) { +X err_setstr(TypeError, +X "'in' or 'not in' needs sequence right argument"); +X return -1; +X } +X n = (*sq->sq_length)(w); +X for (i = 0; i < n; i++) { +X x = (*sq->sq_item)(w, i); +X cmp = cmpobject(v, x); +X XDECREF(x); +X if (cmp == 0) +X return 1; +X } +X return 0; +X} +X +Xstatic object * +Xcmp_outcome(op, v, w) +X enum cmp_op op; +X register object *v; +X register object *w; +X{ +X register int cmp; +X register int res = 0; +X switch (op) { +X case IS: +X case IS_NOT: +X res = (v == w); +X if (op == IS_NOT) +X res = !res; +X break; +X case IN: +X case NOT_IN: +X res = cmp_member(v, w); +X if (res < 0) +X return NULL; +X if (op == NOT_IN) +X res = !res; +X break; +X case EXC_MATCH: +X res = cmp_exception(v, w); +X break; +X default: +X cmp = cmpobject(v, w); +X switch (op) { +X case LT: res = cmp < 0; break; +X case LE: res = cmp <= 0; break; +X case EQ: res = cmp == 0; break; +X case NE: res = cmp != 0; break; +X case GT: res = cmp > 0; break; +X case GE: res = cmp >= 0; break; +X /* XXX no default? (res is initialized to 0 though) */ +X } +X } +X v = res ? True : False; +X INCREF(v); +X return v; +X} +X +Xstatic int +Ximport_from(locals, v, name) +X object *locals; +X object *v; +X char *name; +X{ +X object *w, *x; +X w = getmoduledict(v); +X if (name[0] == '*') { +X int i; +X int n = getdictsize(w); +X for (i = 0; i < n; i++) { +X name = getdictkey(w, i); +X if (name == NULL || name[0] == '_') +X continue; +X x = dictlookup(w, name); +X if (x == NULL) { +X /* XXX can't happen? */ +X err_setstr(NameError, name); +X return -1; +X } +X if (dictinsert(locals, name, x) != 0) +X return -1; +X } +X return 0; +X } +X else { +X x = dictlookup(w, name); +X if (x == NULL) { +X err_setstr(NameError, name); +X return -1; +X } +X else +X return dictinsert(locals, name, x); +X } +X} +X +Xstatic object * +Xbuild_class(v, w) +X object *v; /* None or tuple containing base classes */ +X object *w; /* dictionary */ +X{ +X if (is_tupleobject(v)) { +X int i; +X for (i = gettuplesize(v); --i >= 0; ) { +X object *x = gettupleitem(v, i); +X if (!is_classobject(x)) { +X err_setstr(TypeError, +X "base is not a class object"); +X return NULL; +X } +X } +X } +X else { +X v = NULL; +X } +X if (!is_dictobject(w)) { +X err_setstr(SystemError, "build_class with non-dictionary"); +X return NULL; +X } +X return newclassobject(v, w); +X} +X +X +X/* Status code for main loop (reason for stack unwind) */ +X +Xenum why_code { +X WHY_NOT, /* No error */ +X WHY_EXCEPTION, /* Exception occurred */ +X WHY_RERAISE, /* Exception re-raised by 'finally' */ +X WHY_RETURN, /* 'return' statement */ +X WHY_BREAK /* 'break' statement */ +X}; +X +X/* Interpreter main loop */ +X +Xobject * +Xeval_code(co, globals, locals, arg) +X codeobject *co; +X object *globals; +X object *locals; +X object *arg; +X{ +X register unsigned char *next_instr; +X register int opcode; /* Current opcode */ +X register int oparg; /* Current opcode argument, if any */ +X register object **stack_pointer; +X register enum why_code why; /* Reason for block stack unwind */ +X register int err; /* Error status -- nonzero if error */ +X register object *x; /* Result object -- NULL if error */ +X register object *v; /* Temporary objects popped off stack */ +X register object *w; +X register object *u; +X register object *t; +X register frameobject *f; /* Current frame */ +X int lineno; /* Current line number */ +X object *retval; /* Return value iff why == WHY_RETURN */ +X char *name; /* Name used by some instructions */ +X FILE *fp; /* Used by print operations */ +X#ifdef TRACE +X int trace = dictlookup(globals, "__trace__") != NULL; +X#endif +X +X/* Code access macros */ +X +X#define GETCONST(i) Getconst(f, i) +X#define GETNAME(i) Getname(f, i) +X#define FIRST_INSTR() (GETUSTRINGVALUE(f->f_code->co_code)) +X#define INSTR_OFFSET() (next_instr - FIRST_INSTR()) +X#define NEXTOP() (*next_instr++) +X#define NEXTARG() (next_instr += 2, (next_instr[-1]<<8) + next_instr[-2]) +X#define JUMPTO(x) (next_instr = FIRST_INSTR() + (x)) +X#define JUMPBY(x) (next_instr += (x)) +X +X/* Stack manipulation macros */ +X +X#define STACK_LEVEL() (stack_pointer - f->f_valuestack) +X#define EMPTY() (STACK_LEVEL() == 0) +X#define TOP() (stack_pointer[-1]) +X#define BASIC_PUSH(v) (*stack_pointer++ = (v)) +X#define BASIC_POP() (*--stack_pointer) +X +X#ifdef TRACE +X#define PUSH(v) (BASIC_PUSH(v), trace && prtrace(TOP(), "push")) +X#define POP() (trace && prtrace(TOP(), "pop"), BASIC_POP()) +X#else +X#define PUSH(v) BASIC_PUSH(v) +X#define POP() BASIC_POP() +X#endif +X +X f = newframeobject( +X current_frame, /*back*/ +X co, /*code*/ +X globals, /*globals*/ +X locals, /*locals*/ +X 50, /*nvalues*/ +X 20); /*nblocks*/ +X if (f == NULL) +X return NULL; +X +X current_frame = f; +X +X next_instr = GETUSTRINGVALUE(f->f_code->co_code); +X +X stack_pointer = f->f_valuestack; +X +X if (arg != NULL) { +X INCREF(arg); +X PUSH(arg); +X } +X +X why = WHY_NOT; +X err = 0; +X x = None; /* Not a reference, just anything non-NULL */ +X lineno = -1; +X +X for (;;) { +X static ticker; +X +X /* Do periodic things */ +X +X if (--ticker < 0) { +X ticker = 100; +X if (intrcheck()) { +X err_set(KeyboardInterrupt); +X why = WHY_EXCEPTION; +X tb_here(f, INSTR_OFFSET(), lineno); +X break; +X } +X } +X +X /* Extract opcode and argument */ +X +X opcode = NEXTOP(); +X if (HAS_ARG(opcode)) +X oparg = NEXTARG(); +X +X#ifdef TRACE +X /* Instruction tracing */ +X +X if (trace) { +X if (HAS_ARG(opcode)) { +X printf("%d: %d, %d\n", +X (int) (INSTR_OFFSET() - 3), +X opcode, oparg); +X } +X else { +X printf("%d: %d\n", +X (int) (INSTR_OFFSET() - 1), opcode); +X } +X } +X#endif +X +X /* Main switch on opcode */ +X +X switch (opcode) { +X +X /* BEWARE! +X It is essential that any operation that fails sets either +X x to NULL, err to nonzero, or why to anything but WHY_NOT, +X and that no operation that succeeds does this! */ +X +X /* case STOP_CODE: this is an error! */ +X +X case POP_TOP: +X v = POP(); +X DECREF(v); +X break; +X +X case ROT_TWO: +X v = POP(); +X w = POP(); +X PUSH(v); +X PUSH(w); +X break; +X +X case ROT_THREE: +X v = POP(); +X w = POP(); +X x = POP(); +X PUSH(v); +X PUSH(x); +X PUSH(w); +X break; +X +X case DUP_TOP: +X v = TOP(); +X INCREF(v); +X PUSH(v); +X break; +X +X case UNARY_POSITIVE: +X v = POP(); +X x = pos(v); +X DECREF(v); +X PUSH(x); +X break; +X +X case UNARY_NEGATIVE: +X v = POP(); +X x = neg(v); +X DECREF(v); +X PUSH(x); +X break; +X +X case UNARY_NOT: +X v = POP(); +X x = not(v); +X DECREF(v); +X PUSH(x); +X break; +X +X case UNARY_CONVERT: +X v = POP(); +X x = reprobject(v); +X DECREF(v); +X PUSH(x); +X break; +X +X case UNARY_CALL: +X v = POP(); +X if (is_classmethodobject(v) || is_funcobject(v)) +X x = call_function(v, (object *)NULL); +X else +X x = call_builtin(v, (object *)NULL); +X DECREF(v); +X PUSH(x); +X break; +X +X case BINARY_MULTIPLY: +X w = POP(); +X v = POP(); +X x = mul(v, w); +X DECREF(v); +X DECREF(w); +X PUSH(x); +X break; +X +X case BINARY_DIVIDE: +X w = POP(); +X v = POP(); +X x = divide(v, w); +X DECREF(v); +X DECREF(w); +X PUSH(x); +X break; +X +X case BINARY_MODULO: +X w = POP(); +X v = POP(); +X x = rem(v, w); +X DECREF(v); +X DECREF(w); +X PUSH(x); +X break; +X +X case BINARY_ADD: +X w = POP(); +X v = POP(); +X x = add(v, w); +X DECREF(v); +X DECREF(w); +X PUSH(x); +X break; +X +X case BINARY_SUBTRACT: +X w = POP(); +X v = POP(); +X x = sub(v, w); +X DECREF(v); +X DECREF(w); +X PUSH(x); +X break; +X +X case BINARY_SUBSCR: +X w = POP(); +X v = POP(); +X x = apply_subscript(v, w); +X DECREF(v); +X DECREF(w); +X PUSH(x); +X break; +X +X case BINARY_CALL: +X w = POP(); +X v = POP(); +X if (is_classmethodobject(v) || is_funcobject(v)) +X x = call_function(v, w); +X else +X x = call_builtin(v, w); +X DECREF(v); +X DECREF(w); +X PUSH(x); +X break; +X +X case SLICE+0: +X case SLICE+1: +X case SLICE+2: +X case SLICE+3: +X if ((opcode-SLICE) & 2) +X w = POP(); +X else +X w = NULL; +X if ((opcode-SLICE) & 1) +X v = POP(); +X else +X v = NULL; +X u = POP(); +X x = apply_slice(u, v, w); +X DECREF(u); +X XDECREF(v); +X XDECREF(w); +X PUSH(x); +X break; +X +X case STORE_SLICE+0: +X case STORE_SLICE+1: +X case STORE_SLICE+2: +X case STORE_SLICE+3: +X if ((opcode-STORE_SLICE) & 2) +X w = POP(); +X else +X w = NULL; +X if ((opcode-STORE_SLICE) & 1) +X v = POP(); +X else +X v = NULL; +X u = POP(); +X t = POP(); +X err = assign_slice(u, v, w, t); /* u[v:w] = t */ +X DECREF(t); +X DECREF(u); +X XDECREF(v); +X XDECREF(w); +X break; +X +X case DELETE_SLICE+0: +X case DELETE_SLICE+1: +X case DELETE_SLICE+2: +X case DELETE_SLICE+3: +X if ((opcode-DELETE_SLICE) & 2) +X w = POP(); +X else +X w = NULL; +X if ((opcode-DELETE_SLICE) & 1) +X v = POP(); +X else +X v = NULL; +X u = POP(); +X err = assign_slice(u, v, w, (object *)NULL); +X /* del u[v:w] */ +X DECREF(u); +X XDECREF(v); +X XDECREF(w); +X break; +X +X case STORE_SUBSCR: +X w = POP(); +X v = POP(); +X u = POP(); +X /* v[w] = u */ +X err = assign_subscript(v, w, u); +X DECREF(u); +X DECREF(v); +X DECREF(w); +X break; +X +X case DELETE_SUBSCR: +X w = POP(); +X v = POP(); +X /* del v[w] */ +X err = assign_subscript(v, w, (object *)NULL); +X DECREF(v); +X DECREF(w); +X break; +X +X case PRINT_EXPR: +X v = POP(); +X fp = sysgetfile("stdout", stdout); +X /* Print value except if procedure result */ +X if (v != None) { +X flushline(); +X printobject(v, fp, 0); +X fprintf(fp, "\n"); +X } +X DECREF(v); +X break; +X +X case PRINT_ITEM: +X v = POP(); +X fp = sysgetfile("stdout", stdout); +X if (needspace) +X fprintf(fp, " "); +X if (is_stringobject(v)) { +X char *s = getstringvalue(v); +X int len = getstringsize(v); +X fwrite(s, 1, len, fp); +X if (len > 0 && s[len-1] == '\n') +X needspace = 0; +X else +X needspace = 1; +X } +X else { +X printobject(v, fp, 0); +X needspace = 1; +X } +X DECREF(v); +X break; +X +X case PRINT_NEWLINE: +X fp = sysgetfile("stdout", stdout); +X fprintf(fp, "\n"); +X needspace = 0; +X break; +X +X case BREAK_LOOP: +X why = WHY_BREAK; +X break; +X +X case RAISE_EXCEPTION: +X v = POP(); +X w = POP(); +X if (!is_stringobject(w)) +X err_setstr(TypeError, +X "exceptions must be strings"); +X else +X err_setval(w, v); +X DECREF(v); +X DECREF(w); +X why = WHY_EXCEPTION; +X break; +X +X case LOAD_LOCALS: +X v = f->f_locals; +X INCREF(v); +X PUSH(v); +X break; +X +X case RETURN_VALUE: +X retval = POP(); +X why = WHY_RETURN; +X break; +X +X case REQUIRE_ARGS: +X if (EMPTY()) { +X err_setstr(TypeError, +X "function expects argument(s)"); +X why = WHY_EXCEPTION; +X } +X break; +X +X case REFUSE_ARGS: +X if (!EMPTY()) { +X err_setstr(TypeError, +X "function expects no argument(s)"); +X why = WHY_EXCEPTION; +X } +X break; +X +X case BUILD_FUNCTION: +X v = POP(); +X x = newfuncobject(v, f->f_globals); +X DECREF(v); +X PUSH(x); +X break; +X +X case POP_BLOCK: +X { +X block *b = pop_block(f); +X while (STACK_LEVEL() > b->b_level) { +X v = POP(); +X DECREF(v); +X } +X } +X break; +X +X case END_FINALLY: +X v = POP(); +X if (is_intobject(v)) { +X why = (enum why_code) getintvalue(v); +X if (why == WHY_RETURN) +X retval = POP(); +X } +X else if (is_stringobject(v)) { +X w = POP(); +X err_setval(v, w); +X DECREF(w); +X w = POP(); +X tb_store(w); +X DECREF(w); +X why = WHY_RERAISE; +X } +X else if (v != None) { +X err_setstr(SystemError, +X "'finally' pops bad exception"); +X why = WHY_EXCEPTION; +X } +X DECREF(v); +X break; +X +X case BUILD_CLASS: +X w = POP(); +X v = POP(); +X x = build_class(v, w); +X PUSH(x); +X DECREF(v); +X DECREF(w); +X break; +X +X case STORE_NAME: +X name = GETNAME(oparg); +X v = POP(); +X err = dictinsert(f->f_locals, name, v); +X DECREF(v); +X break; +X +X case DELETE_NAME: +X name = GETNAME(oparg); +X if ((err = dictremove(f->f_locals, name)) != 0) +X err_setstr(NameError, name); +X break; +X +X case UNPACK_TUPLE: +X v = POP(); +X if (!is_tupleobject(v)) { +X err_setstr(TypeError, "unpack non-tuple"); +X why = WHY_EXCEPTION; +X } +X else if (gettuplesize(v) != oparg) { +X err_setstr(RuntimeError, +X "unpack tuple of wrong size"); +X why = WHY_EXCEPTION; +X } +X else { +X for (; --oparg >= 0; ) { +X w = gettupleitem(v, oparg); +X INCREF(w); +X PUSH(w); +X } +X } +X DECREF(v); +X break; +X +X case UNPACK_LIST: +X v = POP(); +X if (!is_listobject(v)) { +X err_setstr(TypeError, "unpack non-list"); +X why = WHY_EXCEPTION; +X } +X else if (getlistsize(v) != oparg) { +X err_setstr(RuntimeError, +X "unpack list of wrong size"); +X why = WHY_EXCEPTION; +X } +X else { +X for (; --oparg >= 0; ) { +X w = getlistitem(v, oparg); +X INCREF(w); +X PUSH(w); +X } +X } +X DECREF(v); +X break; +X +X case STORE_ATTR: +X name = GETNAME(oparg); +X v = POP(); +X u = POP(); +X err = setattr(v, name, u); /* v.name = u */ +X DECREF(v); +X DECREF(u); +X break; +X +X case DELETE_ATTR: +X name = GETNAME(oparg); +X v = POP(); +X err = setattr(v, name, (object *)NULL); +X /* del v.name */ +X DECREF(v); +X break; +X +X case LOAD_CONST: +X x = GETCONST(oparg); +X INCREF(x); +X PUSH(x); +X break; +X +X case LOAD_NAME: +X name = GETNAME(oparg); +X x = dictlookup(f->f_locals, name); +X if (x == NULL) { +X x = dictlookup(f->f_globals, name); +X if (x == NULL) +X x = getbuiltin(name); +X } +X if (x == NULL) +X err_setstr(NameError, name); +X else +X INCREF(x); +X PUSH(x); +X break; +X +X case BUILD_TUPLE: +X x = newtupleobject(oparg); +X if (x != NULL) { +X for (; --oparg >= 0;) { +X w = POP(); +X err = settupleitem(x, oparg, w); +X if (err != 0) +X break; +X } +X PUSH(x); +X } +X break; +X +X case BUILD_LIST: +X x = newlistobject(oparg); +X if (x != NULL) { +X for (; --oparg >= 0;) { +X w = POP(); +X err = setlistitem(x, oparg, w); +X if (err != 0) +X break; +X } +X PUSH(x); +X } +X break; +X +X case BUILD_MAP: +X x = newdictobject(); +X PUSH(x); +X break; +X +X case LOAD_ATTR: +X name = GETNAME(oparg); +X v = POP(); +X x = getattr(v, name); +X DECREF(v); +X PUSH(x); +X break; +X +X case COMPARE_OP: +X w = POP(); +X v = POP(); +X x = cmp_outcome((enum cmp_op)oparg, v, w); +X DECREF(v); +X DECREF(w); +X PUSH(x); +X break; +X +X case IMPORT_NAME: +X name = GETNAME(oparg); +X x = import_module(name); +X XINCREF(x); +X PUSH(x); +X break; +X +X case IMPORT_FROM: +X name = GETNAME(oparg); +X v = TOP(); +X err = import_from(f->f_locals, v, name); +X break; +X +X case JUMP_FORWARD: +X JUMPBY(oparg); +X break; +X +X case JUMP_IF_FALSE: +X if (!testbool(TOP())) +X JUMPBY(oparg); +X break; +X +X case JUMP_IF_TRUE: +X if (testbool(TOP())) +X JUMPBY(oparg); +X break; +X +X case JUMP_ABSOLUTE: +X JUMPTO(oparg); +X break; +X +X case FOR_LOOP: +X /* for v in s: ... +X On entry: stack contains s, i. +X On exit: stack contains s, i+1, s[i]; +X but if loop exhausted: +X s, i are popped, and we jump */ +X w = POP(); /* Loop index */ +X v = POP(); /* Sequence object */ +X u = loop_subscript(v, w); +X if (u != NULL) { +X PUSH(v); +X x = newintobject(getintvalue(w)+1); +X PUSH(x); +X DECREF(w); +X PUSH(u); +X } +X else { +X DECREF(v); +X DECREF(w); +X /* A NULL can mean "s exhausted" +X but also an error: */ +X if (err_occurred()) +X why = WHY_EXCEPTION; +X else +X JUMPBY(oparg); +X } +X break; +X +X case SETUP_LOOP: +X case SETUP_EXCEPT: +X case SETUP_FINALLY: +X setup_block(f, opcode, INSTR_OFFSET() + oparg, +X STACK_LEVEL()); +X break; +X +X case SET_LINENO: +X#ifdef TRACE +X if (trace) +X printf("--- Line %d ---\n", oparg); +X#endif +X lineno = oparg; +X break; +X +X default: +X fprintf(stderr, +X "XXX lineno: %d, opcode: %d\n", +X lineno, opcode); +X err_setstr(SystemError, "eval_code: unknown opcode"); +X why = WHY_EXCEPTION; +X break; +X +X } /* switch */ +X +X +X /* Quickly continue if no error occurred */ +X +X if (why == WHY_NOT) { +X if (err == 0 && x != NULL) +X continue; /* Normal, fast path */ +X why = WHY_EXCEPTION; +X x = None; +X err = 0; +X } +X +X#ifndef NDEBUG +X /* Double-check exception status */ +X +X if (why == WHY_EXCEPTION || why == WHY_RERAISE) { +X if (!err_occurred()) { +X fprintf(stderr, "XXX ghost error\n"); +X err_setstr(SystemError, "ghost error"); +X why = WHY_EXCEPTION; +X } +X } +X else { +X if (err_occurred()) { +X fprintf(stderr, "XXX undetected error\n"); +X why = WHY_EXCEPTION; +X } +X } +X#endif +X +X /* Log traceback info if this is a real exception */ +X +X if (why == WHY_EXCEPTION) { +X int lasti = INSTR_OFFSET() - 1; +X if (HAS_ARG(opcode)) +X lasti -= 2; +X tb_here(f, lasti, lineno); +X } +X +X /* For the rest, treat WHY_RERAISE as WHY_EXCEPTION */ +X +X if (why == WHY_RERAISE) +X why = WHY_EXCEPTION; +X +X /* Unwind stacks if a (pseudo) exception occurred */ +X +X while (why != WHY_NOT && f->f_iblock > 0) { +X block *b = pop_block(f); +X while (STACK_LEVEL() > b->b_level) { +X v = POP(); +X XDECREF(v); +X } +X if (b->b_type == SETUP_LOOP && why == WHY_BREAK) { +X why = WHY_NOT; +X JUMPTO(b->b_handler); +X break; +X } +X if (b->b_type == SETUP_FINALLY || +X b->b_type == SETUP_EXCEPT && +X why == WHY_EXCEPTION) { +X if (why == WHY_EXCEPTION) { +X object *exc, *val; +X err_get(&exc, &val); +X if (val == NULL) { +X val = None; +X INCREF(val); +X } +X v = tb_fetch(); +X /* Make the raw exception data +X available to the handler, +X so a program can emulate the +X Python main loop. Don't do +X this for 'finally'. */ +X if (b->b_type == SETUP_EXCEPT) { +X#if 0 /* Oops, this breaks too many things */ +X sysset("exc_traceback", v); +X#endif +X sysset("exc_value", val); +X sysset("exc_type", exc); +X err_clear(); +X } +X PUSH(v); +X PUSH(val); +X PUSH(exc); +X } +X else { +X if (why == WHY_RETURN) +X PUSH(retval); +X v = newintobject((long)why); +X PUSH(v); +X } +X why = WHY_NOT; +X JUMPTO(b->b_handler); +X break; +X } +X } /* unwind stack */ +X +X /* End the loop if we still have an error (or return) */ +X +X if (why != WHY_NOT) +X break; +X +X } /* main loop */ +X +X /* Pop remaining stack entries */ +X +X while (!EMPTY()) { +X v = POP(); +X XDECREF(v); +X } +X +X /* Restore previous frame and release the current one */ +X +X current_frame = f->f_back; +X DECREF(f); +X +X if (why == WHY_RETURN) +X return retval; +X else +X return NULL; +X} +EOF +fi +if test -s 'src/object.h' +then echo '*** I will not over-write existing file src/object.h' +else +echo 'x - src/object.h' +sed 's/^X//' > 'src/object.h' << 'EOF' +X/*********************************************************** +XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The +XNetherlands. +X +X All Rights Reserved +X +XPermission to use, copy, modify, and distribute this software and its +Xdocumentation for any purpose and without fee is hereby granted, +Xprovided that the above copyright notice appear in all copies and that +Xboth that copyright notice and this permission notice appear in +Xsupporting documentation, and that the names of Stichting Mathematisch +XCentrum or CWI not be used in advertising or publicity pertaining to +Xdistribution of the software without specific, written prior permission. +X +XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO +XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE +XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +X +X******************************************************************/ +X +X#define NDEBUG +X/* Object and type object interface */ +X +X/* +X123456789-123456789-123456789-123456789-123456789-123456789-123456789-12 +X +XObjects are structures allocated on the heap. Special rules apply to +Xthe use of objects to ensure they are properly garbage-collected. +XObjects are never allocated statically or on the stack; they must be +Xaccessed through special macros and functions only. (Type objects are +Xexceptions to the first rule; the standard types are represented by +Xstatically initialized type objects.) +X +XAn object has a 'reference count' that is increased or decreased when a +Xpointer to the object is copied or deleted; when the reference count +Xreaches zero there are no references to the object left and it can be +Xremoved from the heap. +X +XAn object has a 'type' that determines what it represents and what kind +Xof data it contains. An object's type is fixed when it is created. +XTypes themselves are represented as objects; an object contains a +Xpointer to the corresponding type object. The type itself has a type +Xpointer pointing to the object representing the type 'type', which +Xcontains a pointer to itself!). +X +XObjects do not float around in memory; once allocated an object keeps +Xthe same size and address. Objects that must hold variable-size data +Xcan contain pointers to variable-size parts of the object. Not all +Xobjects of the same type have the same size; but the size cannot change +Xafter allocation. (These restrictions are made so a reference to an +Xobject can be simply a pointer -- moving an object would require +Xupdating all the pointers, and changing an object's size would require +Xmoving it if there was another object right next to it.) +X +XObjects are always accessed through pointers of the type 'object *'. +XThe type 'object' is a structure that only contains the reference count +Xand the type pointer. The actual memory allocated for an object +Xcontains other data that can only be accessed after casting the pointer +Xto a pointer to a longer structure type. This longer type must start +Xwith the reference count and type fields; the macro OB_HEAD should be +Xused for this (to accomodate for future changes). The implementation +Xof a particular object type can cast the object pointer to the proper +Xtype and back. +X +XA standard interface exists for objects that contain an array of items +Xwhose size is determined when the object is allocated. +X +X123456789-123456789-123456789-123456789-123456789-123456789-123456789-12 +X*/ +X +X#ifndef NDEBUG +X +X/* Turn on heavy reference debugging */ +X#define TRACE_REFS +X +X/* Turn on reference counting */ +X#define REF_DEBUG +X +X#endif /* NDEBUG */ +X +X#ifdef TRACE_REFS +X#define OB_HEAD \ +X struct _object *_ob_next, *_ob_prev; \ +X int ob_refcnt; \ +X struct _typeobject *ob_type; +X#define OB_HEAD_INIT(type) 0, 0, 1, type, +X#else +X#define OB_HEAD \ +X unsigned int ob_refcnt; \ +X struct _typeobject *ob_type; +X#define OB_HEAD_INIT(type) 1, type, +X#endif +X +X#define OB_VARHEAD \ +X OB_HEAD \ +X unsigned int ob_size; /* Number of items in variable part */ +X +Xtypedef struct _object { +X OB_HEAD +X} object; +X +Xtypedef struct { +X OB_VARHEAD +X} varobject; +X +X +X/* +X123456789-123456789-123456789-123456789-123456789-123456789-123456789-12 +X +XType objects contain a string containing the type name (to help somewhat +Xin debugging), the allocation parameters (see newobj() and newvarobj()), +Xand methods for accessing objects of the type. Methods are optional,a +Xnil pointer meaning that particular kind of access is not available for +Xthis type. The DECREF() macro uses the tp_dealloc method without +Xchecking for a nil pointer; it should always be implemented except if +Xthe implementation can guarantee that the reference count will never +Xreach zero (e.g., for type objects). +X +XNB: the methods for certain type groups are now contained in separate +Xmethod blocks. +X*/ +X +Xtypedef struct { +X object *(*nb_add) FPROTO((object *, object *)); +X object *(*nb_subtract) FPROTO((object *, object *)); +X object *(*nb_multiply) FPROTO((object *, object *)); +X object *(*nb_divide) FPROTO((object *, object *)); +X object *(*nb_remainder) FPROTO((object *, object *)); +X object *(*nb_power) FPROTO((object *, object *)); +X object *(*nb_negative) FPROTO((object *)); +X object *(*nb_positive) FPROTO((object *)); +X} number_methods; +X +Xtypedef struct { +X int (*sq_length) FPROTO((object *)); +X object *(*sq_concat) FPROTO((object *, object *)); +X object *(*sq_repeat) FPROTO((object *, int)); +X object *(*sq_item) FPROTO((object *, int)); +X object *(*sq_slice) FPROTO((object *, int, int)); +X int (*sq_ass_item) FPROTO((object *, int, object *)); +X int (*sq_ass_slice) FPROTO((object *, int, int, object *)); +X} sequence_methods; +X +Xtypedef struct { +X int (*mp_length) FPROTO((object *)); +X object *(*mp_subscript) FPROTO((object *, object *)); +X int (*mp_ass_subscript) FPROTO((object *, object *, object *)); +X} mapping_methods; +X +Xtypedef struct _typeobject { +X OB_VARHEAD +X char *tp_name; /* For printing */ +X unsigned int tp_basicsize, tp_itemsize; /* For allocation */ +X +X /* Methods to implement standard operations */ +X +X void (*tp_dealloc) FPROTO((object *)); +X void (*tp_print) FPROTO((object *, FILE *, int)); +X object *(*tp_getattr) FPROTO((object *, char *)); +X int (*tp_setattr) FPROTO((object *, char *, object *)); +X int (*tp_compare) FPROTO((object *, object *)); +X object *(*tp_repr) FPROTO((object *)); +X +X /* Method suites for standard classes */ +X +X number_methods *tp_as_number; +X sequence_methods *tp_as_sequence; +X mapping_methods *tp_as_mapping; +X} typeobject; +X +Xextern typeobject Typetype; /* The type of type objects */ +X +X#define is_typeobject(op) ((op)->ob_type == &Typetype) +X +X/* Generic operations on objects */ +Xextern void printobject PROTO((object *, FILE *, int)); +Xextern object * reprobject PROTO((object *)); +Xextern int cmpobject PROTO((object *, object *)); +Xextern object *getattr PROTO((object *, char *)); +Xextern int setattr PROTO((object *, char *, object *)); +X +X/* Flag bits for printing: */ +X#define PRINT_RAW 1 /* No string quotes etc. */ +X +X/* +X123456789-123456789-123456789-123456789-123456789-123456789-123456789-12 +X +XThe macros INCREF(op) and DECREF(op) are used to increment or decrement +Xreference counts. DECREF calls the object's deallocator function; for +Xobjects that don't contain references to other objects or heap memory +Xthis can be the standard function free(). Both macros can be used +Xwhereever a void expression is allowed. The argument shouldn't be a +XNIL pointer. The macro NEWREF(op) is used only to initialize reference +Xcounts to 1; it is defined here for convenience. +X +XWe assume that the reference count field can never overflow; this can +Xbe proven when the size of the field is the same as the pointer size +Xbut even with a 16-bit reference count field it is pretty unlikely so +Xwe ignore the possibility. (If you are paranoid, make it a long.) +X +XType objects should never be deallocated; the type pointer in an object +Xis not considered to be a reference to the type object, to save +Xcomplications in the deallocation function. (This is actually a +Xdecision that's up to the implementer of each new type so if you want, +Xyou can count such references to the type object.) +X +X*** WARNING*** The DECREF macro must have a side-effect-free argument +Xsince it may evaluate its argument multiple times. (The alternative +Xwould be to mace it a proper function or assign it to a global temporary +Xvariable first, both of which are slower; and in a multi-threaded +Xenvironment the global variable trick is not safe.) +X*/ +X +X#ifdef TRACE_REFS +X#ifndef REF_DEBUG +X#define REF_DEBUG +X#endif +X#endif +X +X#ifndef TRACE_REFS +X#define DELREF(op) (*(op)->ob_type->tp_dealloc)((object *)(op)) +X#define UNREF(op) /*empty*/ +X#endif +X +X#ifdef REF_DEBUG +Xextern long ref_total; +X#ifndef TRACE_REFS +X#define NEWREF(op) (ref_total++, (op)->ob_refcnt = 1) +X#endif +X#define INCREF(op) (ref_total++, (op)->ob_refcnt++) +X#define DECREF(op) \ +X if (--ref_total, --(op)->ob_refcnt > 0) \ +X ; \ +X else \ +X DELREF(op) +X#else +X#define NEWREF(op) ((op)->ob_refcnt = 1) +X#define INCREF(op) ((op)->ob_refcnt++) +X#define DECREF(op) \ +X if (--(op)->ob_refcnt > 0) \ +X ; \ +X else \ +X DELREF(op) +X#endif +X +X/* Macros to use in case the object pointer may be NULL: */ +X +X#define XINCREF(op) if ((op) == NULL) ; else INCREF(op) +X#define XDECREF(op) if ((op) == NULL) ; else DECREF(op) +X +X/* Definition of NULL, so you don't have to include <stdio.h> */ +X +X#ifndef NULL +X#define NULL 0 +X#endif +X +X +X/* +XNoObject is an object of undefined type which can be used in contexts +Xwhere NULL (nil) is not suitable (since NULL often means 'error'). +X +XDon't forget to apply INCREF() when returning this value!!! +X*/ +X +Xextern object NoObject; /* Don't use this directly */ +X +X#define None (&NoObject) +X +X +X/* +X123456789-123456789-123456789-123456789-123456789-123456789-123456789-12 +X +XMore conventions +X================ +X +XArgument Checking +X----------------- +X +XFunctions that take objects as arguments normally don't check for nil +Xarguments, but they do check the type of the argument, and return an +Xerror if the function doesn't apply to the type. +X +XFailure Modes +X------------- +X +XFunctions may fail for a variety of reasons, including running out of +Xmemory. This is communicated to the caller in two ways: an error string +Xis set (see errors.h), and the function result differs: functions that +Xnormally return a pointer return NULL for failure, functions returning +Xan integer return -1 (which could be a legal return value too!), and +Xother functions return 0 for success and -1 for failure. +XCallers should always check for errors before using the result. +X +XReference Counts +X---------------- +X +XIt takes a while to get used to the proper usage of reference counts. +X +XFunctions that create an object set the reference count to 1; such new +Xobjects must be stored somewhere or destroyed again with DECREF(). +XFunctions that 'store' objects such as settupleitem() and dictinsert() +Xdon't increment the reference count of the object, since the most +Xfrequent use is to store a fresh object. Functions that 'retrieve' +Xobjects such as gettupleitem() and dictlookup() also don't increment +Xthe reference count, since most frequently the object is only looked at +Xquickly. Thus, to retrieve an object and store it again, the caller +Xmust call INCREF() explicitly. +X +XNOTE: functions that 'consume' a reference count like dictinsert() even +Xconsume the reference if the object wasn't stored, to simplify error +Xhandling. +X +XIt seems attractive to make other functions that take an object as +Xargument consume a reference count; however this may quickly get +Xconfusing (even the current practice is already confusing). Consider +Xit carefully, it may safe lots of calls to INCREF() and DECREF() at +Xtimes. +X +X123456789-123456789-123456789-123456789-123456789-123456789-123456789-12 +X*/ +EOF +fi +echo 'Part 07 out of 21 of pack.out complete.' +exit 0 |
