home *** CD-ROM | disk | FTP | other *** search
- From: guido@cwi.nl (Guido van Rossum)
- Newsgroups: alt.sources
- Subject: Python 0.9.1 part 07/21
- Message-ID: <2969@charon.cwi.nl>
- Date: 19 Feb 91 17:41:43 GMT
-
- : 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
-