Python 0.9.1 part 15/21

Guido van Rossum guido at cwi.nl
Wed Feb 20 04:42:25 AEST 1991


: This is a shell archive.
: Extract with 'sh this_file'.
:
: Extract part 01 first since it makes all directories
echo 'Start of pack.out, part 15 out of 21:'
if test -s 'demo/sgi/gl/kites.py'
then echo '*** I will not over-write existing file demo/sgi/gl/kites.py'
else
echo 'x - demo/sgi/gl/kites.py'
sed 's/^X//' > 'demo/sgi/gl/kites.py' << 'EOF'
X#! /ufs/guido/bin/sgi/python
X
X# *** This only works correctly on a 24 bit-plane machine. ***
X#
X# A simple Python program that tests the some parts of the
X# GL library. It shows the speed that can be obtained when
X# doing simple graphics.
X#
X# The bottleneck in this program is NOT Python but the graphics
X# engine; i.e Python can feed the graphics pipeline fast enough
X# on the 4D/25G.
X#
X# This program show 3 kites flying around the screen. It uses
X#
X# 	* bgnpolygon, endpolygon
X# 	* v3, n3
X# 	* lmdef, lmbind
X#
X# Usage :
X# 
X# 	ESC 	-> exit program
X# 	MOUSE3 	-> freeze toggle
X# 	MOUSE2 	-> one step (use this in freeze state)
X
Xfrom GL import *
Xfrom gl import *
Ximport DEVICE
Xfrom math import *
X
X#
X# viewobj : sets the rotation, translation and scaling
X# set appropiate material, call drawobject()
X#
Xdef viewobj (r, s, t, mat) :
X	pushmatrix()
X	rot (r * 10.0, 'X')
X	rot (r * 10.0, 'Y')
X	rot (r * 10.0, 'Z')
X	scale (s[0], s[1], s[2])
X	translate (t[0], t[1], t[2])
X	lmbind(MATERIAL, mat)
X	drawobject()
X	popmatrix()
X
X#
X# makeobj : the contructor of the object
X#
Xdef mkobj () :
X	v0 = (-5.0 ,0.0, 0.0)
X	v1 = (0.0 ,5.0, 0.0)
X	v2 = (5.0 ,0.0, 0.0)
X	v3 = (0.0 ,2.0, 0.0)
X	n0 = (sqrt(2.0)/2.0, sqrt(2.0)/2.0, 0.0)
X	vn = ((v0, n0), (v1, n0), (v2, n0), (v3, n0))
X	#
X	return vn
X
X#
X# the object itself as an array of vertices and normals
X#
Xkite = mkobj ()
X
X#
X# drawobject : draw a triangle. with bgnpolygon
X#
Xdef drawobject () :
X	#
X	bgnpolygon()
X	vnarray (kite)
X	endpolygon()
X
X#
X# identity matrix
X#
Xidmat=[1.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,1.0]
X
X#
X# the rgb-value of light-blue 
X#
XLightBlue = (43,169,255)
X
X#
X# the different materials.
X#
Xm1=[SPECULAR,0.0,0.0,0.6,DIFFUSE,0.0,0.0,0.8,SHININESS,20.0,LMNULL]
Xm2=[SPECULAR,0.8,0.0,0.1,DIFFUSE,0.8,0.0,0.3,SHININESS,120.0,LMNULL]
Xm3=[SPECULAR,0.0,1.0,0.0,DIFFUSE,0.0,0.6,0.0,SHININESS,120.0,LMNULL]
X
X#
X# lightsources
X#
Xlight1 = [LCOLOR,1.0,1.0,1.0,POSITION,15.0,15.0,0.0,1.0,LMNULL]
Xlight2 = [LCOLOR,1.0,1.0,1.0,POSITION,-15.0,15.0,0.0,1.0,LMNULL]
X
X#
X# the lightmodel
X#
Xmodel = [AMBIENT,0.2,0.2,0.2,LMNULL]
X
X#
X# initgl : opens the window, configures the pipeline to 2buf and zbuf,
X# sets the viewing, defines and binds the materials
X#
Xdef initgl () :
X	#
X	# open window
X	#
X	foreground ()
X	keepaspect (1, 1)
X	prefposition (100, 500, 100, 500)
X	w = winopen ('PYTHON lights')
X	keepaspect (1, 1)
X	winconstraints()
X	#
X	# configure pipeline (zbuf, 2buf, GOURAUD and RGBmode)
X	#
X	zbuffer (1)
X	doublebuffer ()
X	shademodel (GOURAUD)
X	RGBmode ()
X	gconfig ()
X	#
X	# define and bind materials (set perspective BEFORE loadmat !)
X	#
X	mmode(MVIEWING)
X	perspective (900, 1.0, 1.0, 20.0)
X	loadmatrix(idmat)
X	lmdef(DEFMATERIAL, 1, m1)
X	lmdef(DEFMATERIAL, 2, m2)
X	lmdef(DEFMATERIAL, 3, m3)
X	lmdef(DEFLIGHT, 1, light1)
X	lmdef(DEFLIGHT, 2, light2)
X	lmdef(DEFLMODEL, 1, model)
X	lmbind(LIGHT0,1)
X	lmbind(LIGHT1,2)
X	lmbind(LMODEL,1)
X	#
X	# set viewing
X	#
X	lookat (0.0, 0.0, 10.0, 0.0, 0.0, 0.0, 0)
X	#
X	# ask for the REDRAW and ESCKEY events
X	#
X	qdevice(DEVICE.MOUSE3)
X	qdevice(DEVICE.MOUSE2)
X	qdevice(DEVICE.REDRAW)
X	qdevice(DEVICE.ESCKEY)
X
X#
X# GoForIT : use 2buf to redraw the object 2n times. index i is used as 
X# the (smoothly changing) rotation angle
X#
Xdef GoForIt(i) :
X	freeze = 1
X	while 1 :
X		if freeze <> 0 :
X			i = i + 1
X		#
X		# clear z-buffer and clear background to light-blue
X		#
X		zclear()
X		c3i (LightBlue)
X		clear()
X		#
X		# draw the 3 traiangles scaled above each other.
X		#
X		viewobj(float(i),[1.0,1.0,1.0],[1.0,1.0,1.0],1)
X		viewobj(float(i),[0.75,0.75,0.75],[0.0,2.0,2.0],2)
X		viewobj(float(i),[0.5,0.5,0.5],[0.0,4.0,4.0],3)
X		#
X		swapbuffers()
X		#
X		if qtest() <> 0 :
X			dev, val = qread()
X			if dev = DEVICE.ESCKEY :
X				break
X			elif dev = DEVICE.REDRAW :
X				reshapeviewport ()
X			elif dev = DEVICE.MOUSE3 and val <> 0 :
X				freeze = 1 - freeze
X			elif dev = DEVICE.MOUSE2 and val <> 0 :
X				i = i + 1
X
X
X# the main program
X#
Xdef main () :
X	initgl ()
X	GoForIt (0)
X
X#
X# exec main
X#
Xmain  ()
EOF
chmod +x 'demo/sgi/gl/kites.py'
fi
if test -s 'demo/sgi/gl_panel/nurbs/nurbs.s'
then echo '*** I will not over-write existing file demo/sgi/gl_panel/nurbs/nurbs.s'
else
echo 'x - demo/sgi/gl_panel/nurbs/nurbs.s'
sed 's/^X//' > 'demo/sgi/gl_panel/nurbs/nurbs.s' << 'EOF'
X;;; This file was automatically generated by the panel editor.
X;;; If you read it into gnu emacs, it will automagically format itself.
X
X(panel (prop help creator:user-panel-help)
X(prop user-panel #t)
X(label "NURB controls")
X(x 815)
X(y 22)
X(al (pnl_toggle_button (name "trim")
X(prop help creator:user-act-help)
X(label "trim on/off")
X(x 4)
X(y 4.5)
X(w 0.45)
X(h 0.4)
X(downfunc move-then-resize)
X)
X(pnl_toggle_button (name "motion")
X(prop help creator:user-act-help)
X(label "motion on/off")
X(y 1)
X(downfunc move-then-resize)
X)
X(pnl_toggle_button (name "xyzaxis")
X(prop help creator:user-act-help)
X(label "xyz-axis")
X(y 3)
X(downfunc move-then-resize)
X)
X(pnl_toggle_button (name "trimpnts")
X(prop help creator:user-act-help)
X(label "trimming pnts")
X(y 3.5)
X(downfunc move-then-resize)
X)
X(pnl_toggle_button (name "cntlpnts")
X(prop help creator:user-act-help)
X(label "control pnts")
X(y 4)
X(downfunc move-then-resize)
X)
X(pnl_toggle_button (name "nurb")
X(prop help creator:user-act-help)
X(label "nurb")
X(y 4.5)
X(val 1)
X(downfunc move-then-resize)
X)
X(pnl_button (name "quit")
X(prop help creator:user-act-help)
X(label "quit")
X(x 4)
X(y 1)
X(labeltype 1)
X(downfunc move-then-resize)
X)
X(pnl_label (prop help creator:user-act-help)
X(label "TRIMMING")
X(x 4)
X(y 5)
X(downfunc move-then-resize)
X)
X(pnl_label (prop help creator:user-act-help)
X(label "MOTION")
X(y 1.5)
X(downfunc move-then-resize)
X)
X(pnl_label (prop help creator:user-act-help)
X(label "VISIBILITY")
X(y 5)
X(downfunc move-then-resize)
X)
X)
X)
X;;; Local Variables:
X;;; mode: scheme
X;;; eval: (save-excursion (goto-char (point-min)) (kill-line 3))
X;;; eval: (save-excursion (goto-char (point-min)) (replace-regexp "[ \n]*)" ")"))
X;;; eval: (indent-region (point-min) (point-max) nil)
X;;; eval: (progn (kill-line -3) (delete-backward-char 1) (save-buffer))
X;;; End:
EOF
fi
if test -s 'lib/Sliders.py'
then echo '*** I will not over-write existing file lib/Sliders.py'
else
echo 'x - lib/Sliders.py'
sed 's/^X//' > 'lib/Sliders.py' << 'EOF'
X# Module 'Sliders'
X
X
Ximport stdwin
Xfrom stdwinevents import *
Ximport rect
Xfrom Buttons import *
Xfrom HVSplit import HSplit
X
X
X# Field indices in event detail
X#
X_HV = 0
X_CLICKS = 1
X_BUTTON = 2
X_MASK = 3
X
X
X# DragSlider is the simplest possible slider.
X# It looks like a button but dragging the mouse left or right
X# changes the controlled value.
X# It does not support any of the triggers or hooks defined by Buttons,
X# but defines its own setval_trigger and setval_hook.
X#
Xclass DragSliderReactivity() = BaseReactivity():
X	#
X	def mouse_down(self, detail):
X		h, v = hv = detail[_HV]
X		if self.enabled and self.mousetest(hv):
X			self.anchor = h
X			self.oldval = self.val
X			self.active = 1
X	#
X	def mouse_move(self, detail):
X		if self.active:
X			h, v = detail[_HV]
X			self.setval(self.oldval + (h - self.anchor))
X	#
X	def mouse_up(self, detail):
X		if self.active:
X			h, v = detail[_HV]
X			self.setval(self.oldval + (h - self.anchor))
X			self.active = 0
X	#
X
Xclass DragSliderAppearance() = ButtonAppearance():
X	#
X	# INVARIANTS maintained by the setval method:
X	#
X	#	self.min <= self.val <= self.max
X	#	self.text = self.pretext + `self.val` + self.postext
X	#
X	# (Notice that unlike Python ranges, the end point belongs
X	# to the range.)
X	#
X	def init_appearance(self):
X		ButtonAppearance.init_appearance(self)
X		self.min = 0
X		self.val = 0
X		self.max = 100
X		self.hook = 0
X		self.pretext = self.postext = ''
X		self.recalctext()
X	#
X	# The 'get*' and 'set*' methods belong to the generic slider interface
X	#
X	def getval(self): return self.val
X	#
X	def sethook(self, hook):
X		self.hook = hook
X	#
X	def setminvalmax(self, (min, val, max)):
X		self.min = min
X		self.max = max
X		self.setval(val)
X	#
X	def settexts(self, (pretext, postext)):
X		self.pretext = pretext
X		self.postext = postext
X		self.recalctext()
X	#
X	def setval(self, val):
X		val = min(self.max, max(self.min, val))
X		if val <> self.val:
X			self.val = val
X			self.recalctext()
X			self.trigger()
X	#
X	def trigger(self):
X		if self.hook:
X			self.hook(self)
X	#
X	def recalctext(self):
X		self.settext(self.pretext + `self.val` + self.postext)
X	#
X
Xclass DragSlider() = DragSliderReactivity(), DragSliderAppearance(), Define():
X	def definetext(self, (parent, text)):
X		raise RuntimeError, 'DragSlider.definetext() not supported'
X
X
X# Auxiliary class for PushButton incorporated in ComplexSlider
X#
Xclass _StepButton() = PushButton():
X	def define(self, parent):
X		self = PushButton.define(self, parent)
X		self.step = 0
X		return self
X	def setstep(self, step):
X		self.step = step
X	def definetextstep(self, (parent, text, step)):
X		self = self.definetext(parent, text)
X		self.setstep(step)
X		return self
X	def init_reactivity(self):
X		PushButton.init_reactivity(self)
X		self.parent.need_timer(self)
X	def step_trigger(self):
X		self.parent.setval(self.parent.getval() + self.step)
X	def down_trigger(self):
X		self.step_trigger()
X		self.parent.settimer(5)
X	def timer(self):
X		if self.hilited:
X			self.step_trigger()
X		if self.active:
X			self.parent.settimer(1)
X
X
X# A complex slider is an HSplit initialized to three buttons:
X# one to step down, a dragslider, and one to step up.
X#
Xclass ComplexSlider() = HSplit():
X	#
X	# Override Slider define() method
X	#
X	def define(self, parent):
X		self = self.create(parent) # HSplit
X		#
X		self.downbutton = _StepButton().definetextstep(self, '-', -1)
X		self.dragbutton = DragSlider().define(self)
X		self.upbutton = _StepButton().definetextstep(self, '+', 1)
X		#
X		return self
X	#
X	# Override HSplit methods
X	#
X	def minsize(self, m):
X		w1, h1 = self.downbutton.minsize(m)
X		w2, h2 = self.dragbutton.minsize(m)
X		w3, h3 = self.upbutton.minsize(m)
X		height = max(h1, h2, h3)
X		w1 = max(w1, height)
X		w3 = max(w3, height)
X		return w1+w2+w3, height
X	#
X	def setbounds(self, bounds):
X		(left, top), (right, bottom) = self.bounds = bounds
X		size = bottom - top
X		self.downbutton.setbounds((left, top), (left+size, bottom))
X		self.dragbutton.setbounds((left+size, top), \
X						(right-size, bottom))
X		self.upbutton.setbounds((right-size, top), (right, bottom))
X	#
X	# Pass other Slider methods on to dragbutton
X	#
X	def getval(self): return self.dragbutton.getval()
X	def sethook(self, hook): self.dragbutton.sethook(hook)
X	def setminvalmax(self, args): self.dragbutton.setminvalmax(args)
X	def settexts(self, args): self.dragbutton.settexts(args)
X	def setval(self, val): self.dragbutton.setval(val)
X	def enable(self, flag):
X		self.downbutton.enable(flag)
X		self.dragbutton.enable(flag)
X		self.upbutton.enable(flag)
EOF
fi
if test -s 'lib/clock.py'
then echo '*** I will not over-write existing file lib/clock.py'
else
echo 'x - lib/clock.py'
sed 's/^X//' > 'lib/clock.py' << 'EOF'
X# 'klok' -- A simple alarm clock
X
X# The alarm can be set at 5 minute intervals on a 12 hour basis.
X# It is controlled with the mouse:
X# - Click and drag around the circle to set the alarm.
X# - Click far outside the circle to clear the alarm.
X# - Click near the center to set the alarm at the last time set.
X# The alarm time is indicated by a small triangle just outside the circle,
X# and also by a digital time at the bottom.
X# The indicators disappear when the alarm is not set.
X# When the alarm goes off, it beeps every minute for five minutes,
X# and the clock turns into inverse video.
X# Click or activate the window to turn the ringing off.
X
Ximport stdwin
Xfrom stdwinevents import WE_MOUSE_DOWN, WE_MOUSE_MOVE, WE_MOUSE_UP, \
X	WE_TIMER, WE_DRAW, WE_SIZE, WE_CLOSE, WE_ACTIVATE
Ximport time
Xfrom math import sin, cos, atan2, pi, sqrt
X
XDEFWIDTH, DEFHEIGHT = 200, 200
X
Xmouse_events = (WE_MOUSE_DOWN, WE_MOUSE_MOVE, WE_MOUSE_UP)
Xorigin = 0, 0
Xfaraway = 2000, 2000
Xeverywhere = origin, faraway
X
Xclass struct(): pass	# A class to declare featureless objects
X
XG = struct()		# Global variables (most set in setdimensions())
XG.tzdiff = 5*3600	# THINK computes UCT from local time assuming EST!
X
XA = struct()		# Globals used by the alarm
XA.set = 1		# True when alarm is set
XA.time = 11*60 + 40	# Time when alarm must go off
XA.ring = 0		# True when alarm is ringing
X
Xdef main():
X	try:
X		realmain()
X	except KeyboardInterrupt:
X		print 'KeyboardInterrupt'
X	finally:
X		G.w = 0
X
Xdef realmain():
X	setdimensions(DEFWIDTH, DEFHEIGHT)
X	stdwin.setdefwinsize(G.farcorner)
X	G.w = stdwin.open('klok')
X	settimer()
X	while 1:
X		type, window, detail = stdwin.getevent()
X		if type = WE_DRAW:
X			drawproc(detail)
X		elif type = WE_TIMER:
X			settimer()
X			drawproc(everywhere)
X		elif type in mouse_events:
X			mouseclick(type, detail)
X		elif type = WE_ACTIVATE:
X			if A.ring:
X				# Turn the ringing off
X				A.ring = 0
X				G.w.begindrawing().invert(G.mainarea)
X		elif type = WE_SIZE:
X			G.w.change(everywhere)
X			width, height = G.w.getwinsize()
X			height = height - stdwin.lineheight()
X			setdimensions(width, height)
X		elif type = WE_CLOSE:
X			break
X
Xdef setdimensions(width, height):
X	if width < height: size = width
X	else: size = height
X	halfwidth = width/2
X	halfheight = height/2
X	G.center = halfwidth, halfheight
X	G.radius = size*45/100
X	G.width = width
X	G.height = height
X	G.corner = width, height
X	G.mainarea = origin, G.corner
X	G.lineheight = stdwin.lineheight()
X	G.farcorner = width, height + G.lineheight
X	G.statusarea = (0, height), G.farcorner
X	G.fullarea = origin, G.farcorner
X
Xdef settimer():
X	now = getlocaltime()
X	G.times = calctime(now)
X	delay = 61 - now % 60
X	G.w.settimer(10 * delay)
X	minutes = (now/60) % 720
X	if A.ring:
X		# Is it time to stop the alarm ringing?
X		since = (minutes - A.time + 720) % 720
X		if since >= 5:
X			# Stop it now
X			A.ring = 0
X		else:
X			# Ring again, once every minute
X			stdwin.fleep()
X	elif A.set and minutes = A.time:
X		# Start the alarm ringing
X		A.ring = 1
X		stdwin.fleep()
X
Xdef drawproc(area):
X	hours, minutes, seconds = G.times
X	d = G.w.begindrawing()
X	d.cliprect(area)
X	d.erase(everywhere)
X	d.circle(G.center, G.radius)
X	d.line(G.center, calcpoint(hours*30 + minutes/2, 0.6))
X	d.line(G.center, calcpoint(minutes*6, 1.0))
X	str = dd(hours) + ':' + dd(minutes)
X	p = (G.width - d.textwidth(str))/2, G.height * 3 / 4
X	d.text(p, str)
X	if A.set:
X		drawalarm(d)
X		drawalarmtime(d)
X	if A.ring:
X		d.invert(G.mainarea)
X
Xdef mouseclick(type, detail):
X	d = G.w.begindrawing()
X	if A.ring:
X		# First turn the ringing off
X		A.ring = 0
X		d.invert(G.mainarea)
X	h, v = detail[0]
X	ch, cv = G.center
X	x, y = h-ch, cv-v
X	dist = sqrt(x*x + y*y) / float(G.radius)
X	if dist > 1.2:
X		if A.set:
X			drawalarm(d)
X			erasealarmtime(d)
X			A.set = 0
X	elif dist < 0.8:
X		if not A.set:
X			A.set = 1
X			drawalarm(d)
X			drawalarmtime(d)
X	else:
X		# Convert to half-degrees (range 0..720)
X		alpha = atan2(y, x)
X		hdeg = alpha*360.0/pi
X		hdeg = 180.0 - hdeg
X		hdeg = (hdeg + 720.0) % 720.0
X		atime = 5*int(hdeg/5.0 + 0.5)
X		if atime <> A.time or not A.set:
X			if A.set:
X				drawalarm(d)
X				erasealarmtime(d)
X			A.set = 1
X			A.time = atime
X			drawalarm(d)
X			drawalarmtime(d)
X
Xdef drawalarm(d):
X	p1 = calcpoint(float(A.time)/2.0, 1.02)
X	p2 = calcpoint(float(A.time)/2.0 - 4.0, 1.1)
X	p3 = calcpoint(float(A.time)/2.0 + 4.0, 1.1)
X	d.xorline(p1, p2)
X	d.xorline(p2, p3)
X	d.xorline(p3, p1)
X
Xdef erasealarmtime(d):
X	d.erase(G.statusarea)
X
Xdef drawalarmtime(d):
X	# A.time is in the range 0..720 with origin at 12 o'clock
X	# Convert to hours (0..12) and minutes (12*(0..60))
X	hh = A.time/60
X	mm = A.time%60
X	str = 'Alarm@' + dd(hh) + ':' + dd(mm)
X	p1 = (G.width - d.textwidth(str))/2, G.height
X	d.text(p1, str)
X
Xdef calctime(now):
X	seconds = now % 60
X	minutes = (now/60) % 60
X	hours = (now/3600) % 12
X	return hours, minutes, seconds
X
Xdef calcpoint(degrees, size):
X	alpha = pi/2.0 - float(degrees) * pi/180.0
X	x, y = cos(alpha), sin(alpha)
X	h, v = G.center
X	r = float(G.radius)
X	return h + int(x*size*r), v - int(y*size*r)
X
Xdef dd(n):
X	s = `n`
X	return '0'*(2-len(s)) + s
X
Xdef getlocaltime():
X	return time.time() - G.tzdiff
X
X#main()
EOF
fi
if test -s 'lib/dircmp.py'
then echo '*** I will not over-write existing file lib/dircmp.py'
else
echo 'x - lib/dircmp.py'
sed 's/^X//' > 'lib/dircmp.py' << 'EOF'
X# Module 'dirmp'
X#
X# Defines a class to build directory diff tools on.
X
Ximport posix
X
Ximport path
X
Ximport dircache
Ximport cmpcache
Ximport statcache
Xfrom stat import *
X
X# Directory comparison class.
X#
Xclass dircmp():
X	#
X	def new(dd, (a, b)): # Initialize
X		dd.a = a
X		dd.b = b
X		# Properties that caller may change before callingdd. run():
X		dd.hide = ['.', '..'] # Names never to be shown
X		dd.ignore = ['RCS', 'tags'] # Names ignored in comparison
X		#
X		return dd
X	#
X	def run(dd): # Compare everything except common subdirectories
X		dd.a_list = filter(dircache.listdir(dd.a), dd.hide)
X		dd.b_list = filter(dircache.listdir(dd.b), dd.hide)
X		dd.a_list.sort()
X		dd.b_list.sort()
X		dd.phase1()
X		dd.phase2()
X		dd.phase3()
X	#
X	def phase1(dd): # Compute common names
X		dd.a_only = []
X		dd.common = []
X		for x in dd.a_list:
X			if x in dd.b_list:
X				dd.common.append(x)
X			else:
X				dd.a_only.append(x)
X		#
X		dd.b_only = []
X		for x in dd.b_list:
X			if x not in dd.common:
X				dd.b_only.append(x)
X	#
X	def phase2(dd): # Distinguish files, directories, funnies
X		dd.common_dirs = []
X		dd.common_files = []
X		dd.common_funny = []
X		#
X		for x in dd.common:
X			a_path = path.cat(dd.a, x)
X			b_path = path.cat(dd.b, x)
X			#
X			ok = 1
X			try:
X				a_stat = statcache.stat(a_path)
X			except posix.error, why:
X				# print 'Can\'t stat', a_path, ':', why[1]
X				ok = 0
X			try:
X				b_stat = statcache.stat(b_path)
X			except posix.error, why:
X				# print 'Can\'t stat', b_path, ':', why[1]
X				ok = 0
X			#
X			if ok:
X				a_type = S_IFMT(a_stat[ST_MODE])
X				b_type = S_IFMT(b_stat[ST_MODE])
X				if a_type <> b_type:
X					dd.common_funny.append(x)
X				elif S_ISDIR(a_type):
X					dd.common_dirs.append(x)
X				elif S_ISREG(a_type):
X					dd.common_files.append(x)
X				else:
X					dd.common_funny.append(x)
X			else:
X				dd.common_funny.append(x)
X	#
X	def phase3(dd): # Find out differences between common files
X		xx = cmpfiles(dd.a, dd.b, dd.common_files)
X		dd.same_files, dd.diff_files, dd.funny_files = xx
X	#
X	def phase4(dd): # Find out differences between common subdirectories
X		# A new dircmp object is created for each common subdirectory,
X		# these are stored in a dictionary indexed by filename.
X		# The hide and ignore properties are inherited from the parent
X		dd.subdirs = {}
X		for x in dd.common_dirs:
X			a_x = path.cat(dd.a, x)
X			b_x = path.cat(dd.b, x)
X			dd.subdirs[x] = newdd = dircmp().new(a_x, b_x)
X			newdd.hide = dd.hide
X			newdd.ignore = dd.ignore
X			newdd.run()
X	#
X	def phase4_closure(dd): # Recursively call phase4() on subdirectories
X		dd.phase4()
X		for x in dd.subdirs.keys():
X			dd.subdirs[x].phase4_closure()
X	#
X	def report(dd): # Print a report on the differences between a and b
X		# Assume that phases 1 to 3 have been executed
X		# Output format is purposely lousy
X		print 'diff', dd.a, dd.b
X		if dd.a_only:
X			print 'Only in', dd.a, ':', dd.a_only
X		if dd.b_only:
X			print 'Only in', dd.b, ':', dd.b_only
X		if dd.same_files:
X			print 'Identical files :', dd.same_files
X		if dd.diff_files:
X			print 'Differing files :', dd.diff_files
X		if dd.funny_files:
X			print 'Trouble with common files :', dd.funny_files
X		if dd.common_dirs:
X			print 'Common subdirectories :', dd.common_dirs
X		if dd.common_funny:
X			print 'Common funny cases :', dd.common_funny
X	#
X	def report_closure(dd): # Print reports on dd and on subdirs
X		# If phase 4 hasn't been done, no subdir reports are printed
X		dd.report()
X		try:
X			x = dd.subdirs
X		except NameError:
X			return # No subdirectories computed
X		for x in dd.subdirs.keys():
X			print
X			dd.subdirs[x].report_closure()
X	#
X	def report_phase4_closure(dd): # Report and do phase 4 recursively
X		dd.report()
X		dd.phase4()
X		for x in dd.subdirs.keys():
X			print
X			dd.subdirs[x].report_phase4_closure()
X
X
X# Compare common files in two directories.
X# Return:
X#	- files that compare equal
X#	- files that compare different
X#	- funny cases (can't stat etc.)
X#
Xdef cmpfiles(a, b, common):
X	res = ([], [], [])
X	for x in common:
X		res[cmp(path.cat(a, x), path.cat(b, x))].append(x)
X	return res
X
X
X# Compare two files.
X# Return:
X#	0 for equal
X#	1 for different
X#	2 for funny cases (can't stat, etc.)
X#
Xdef cmp(a, b):
X	try:
X		if cmpcache.cmp(a, b): return 0
X		return 1
X	except posix.error:
X		return 2
X
X
X# Remove a list item.
X# NB: This modifies the list argument.
X#
Xdef remove(list, item):
X	for i in range(len(list)):
X		if list[i] = item:
X			del list[i]
X			break
X
X
X# Return a copy with items that occur in skip removed.
X#
Xdef filter(list, skip):
X	result = []
X	for item in list:
X		if item not in skip: result.append(item)
X	return result
X
X
X# Demonstration and testing.
X#
Xdef demo():
X	import sys
X	import getopt
X	options, args = getopt.getopt(sys.argv[1:], 'r')
X	if len(args) <> 2: raise getopt.error, 'need exactly two args'
X	dd = dircmp().new(args[0], args[1])
X	dd.run()
X	if ('-r', '') in options:
X		dd.report_phase4_closure()
X	else:
X		dd.report()
X
X# demo()
EOF
fi
if test -s 'lib/dis.py'
then echo '*** I will not over-write existing file lib/dis.py'
else
echo 'x - lib/dis.py'
sed 's/^X//' > 'lib/dis.py' << 'EOF'
X# Disassembler
X
Ximport sys
Ximport string
X
Xdef dis():
X	tb = sys.last_traceback
X	while tb.tb_next: tb = tb.tb_next
X	distb(tb)
X
Xdef distb(tb):
X	disassemble(tb.tb_frame.f_code, tb.tb_lasti)
X
Xdef disco(co):
X	disassemble(co, -1)
X
Xdef disassemble(co, lasti):
X	code = co.co_code
X	labels = findlabels(code)
X	n = len(code)
X	i = 0
X	while i < n:
X		c = code[i]
X		op = ord(c)
X		if op = SET_LINENO and i > 0: print # Extra blank line
X		if i = lasti: print '-->',
X		else: print '   ',
X		if i in labels: print '>>',
X		else: print '  ',
X		print string.rjust(`i`, 4),
X		print string.ljust(opname[op], 15),
X		i = i+1
X		if op >= HAVE_ARGUMENT:
X			oparg = ord(code[i]) + ord(code[i+1])*256
X			i = i+2
X			print string.rjust(`oparg`, 5),
X			if op in hasconst:
X				print '(' + `co.co_consts[oparg]` + ')',
X			elif op in hasname:
X				print '(' + co.co_names[oparg] + ')',
X			elif op in hasjrel:
X				print '(to ' + `i + oparg` + ')',
X		print
X
Xdef findlabels(code):
X	labels = []
X	n = len(code)
X	i = 0
X	while i < n:
X		c = code[i]
X		op = ord(c)
X		i = i+1
X		if op >= HAVE_ARGUMENT:
X			oparg = ord(code[i]) + ord(code[i+1])*256
X			i = i+2
X			label = -1
X			if op in hasjrel:
X				label = i+oparg
X			elif op in hasjabs:
X				label = oparg
X			if label >= 0:
X				if label not in labels:
X					labels.append(label)
X	return labels
X
Xhasconst = []
Xhasname = []
Xhasjrel = []
Xhasjabs = []
X
Xopname = range(256)
Xfor op in opname: opname[op] = '<' + `op` + '>'
X
Xdef def_op(name, op):
X	opname[op] = name
X
Xdef name_op(name, op):
X	opname[op] = name
X	hasname.append(op)
X
Xdef jrel_op(name, op):
X	opname[op] = name
X	hasjrel.append(op)
X
Xdef jabs_op(name, op):
X	opname[op] = name
X	hasjabs.append(op)
X
X# Instruction opcodes for compiled code
X
Xdef_op('STOP_CODE', 0)
Xdef_op('POP_TOP', 1)
Xdef_op('ROT_TWO', 2)
Xdef_op('ROT_THREE', 3)
Xdef_op('DUP_TOP', 4)
X
Xdef_op('UNARY_POSITIVE', 10)
Xdef_op('UNARY_NEGATIVE', 11)
Xdef_op('UNARY_NOT', 12)
Xdef_op('UNARY_CONVERT', 13)
Xdef_op('UNARY_CALL', 14)
X
Xdef_op('BINARY_MULTIPLY', 20)
Xdef_op('BINARY_DIVIDE', 21)
Xdef_op('BINARY_MODULO', 22)
Xdef_op('BINARY_ADD', 23)
Xdef_op('BINARY_SUBTRACT', 24)
Xdef_op('BINARY_SUBSCR', 25)
Xdef_op('BINARY_CALL', 26)
X
Xdef_op('SLICE+0', 30)
Xdef_op('SLICE+1', 31)
Xdef_op('SLICE+2', 32)
Xdef_op('SLICE+3', 33)
X
Xdef_op('STORE_SLICE+0', 40)
Xdef_op('STORE_SLICE+1', 41)
Xdef_op('STORE_SLICE+2', 42)
Xdef_op('STORE_SLICE+3', 43)
X
Xdef_op('DELETE_SLICE+0', 50)
Xdef_op('DELETE_SLICE+1', 51)
Xdef_op('DELETE_SLICE+2', 52)
Xdef_op('DELETE_SLICE+3', 53)
X
Xdef_op('STORE_SUBSCR', 60)
Xdef_op('DELETE_SUBSCR', 61)
X
Xdef_op('PRINT_EXPR', 70)
Xdef_op('PRINT_ITEM', 71)
Xdef_op('PRINT_NEWLINE', 72)
X
Xdef_op('BREAK_LOOP', 80)
Xdef_op('RAISE_EXCEPTION', 81)
Xdef_op('LOAD_LOCALS', 82)
Xdef_op('RETURN_VALUE', 83)
Xdef_op('REQUIRE_ARGS', 84)
Xdef_op('REFUSE_ARGS', 85)
Xdef_op('BUILD_FUNCTION', 86)
Xdef_op('POP_BLOCK', 87)
Xdef_op('END_FINALLY', 88)
Xdef_op('BUILD_CLASS', 89)
X
XHAVE_ARGUMENT = 90		# Opcodes from here have an argument: 
X
Xname_op('STORE_NAME', 90)	# Index in name list 
Xname_op('DELETE_NAME', 91)	# "" 
Xdef_op('UNPACK_TUPLE', 92)	# Number of tuple items 
Xdef_op('UNPACK_LIST', 93)	# Number of list items 
X# unused:		94
Xname_op('STORE_ATTR', 95)	# Index in name list 
Xname_op('DELETE_ATTR', 96)	# "" 
X
Xdef_op('LOAD_CONST', 100)	# Index in const list 
Xhasconst.append(100)
Xname_op('LOAD_NAME', 101)	# Index in name list 
Xdef_op('BUILD_TUPLE', 102)	# Number of tuple items 
Xdef_op('BUILD_LIST', 103)	# Number of list items 
Xdef_op('BUILD_MAP', 104)	# Always zero for now 
Xname_op('LOAD_ATTR', 105)	# Index in name list 
Xdef_op('COMPARE_OP', 106)	# Comparison operator 
Xname_op('IMPORT_NAME', 107)	# Index in name list 
Xname_op('IMPORT_FROM', 108)	# Index in name list 
X
Xjrel_op('JUMP_FORWARD', 110)	# Number of bytes to skip 
Xjrel_op('JUMP_IF_FALSE', 111)	# "" 
Xjrel_op('JUMP_IF_TRUE', 112)	# "" 
Xjabs_op('JUMP_ABSOLUTE', 113)	# Target byte offset from beginning of code 
Xjrel_op('FOR_LOOP', 114)	# Number of bytes to skip 
X
Xjrel_op('SETUP_LOOP', 120)	# Distance to target address
Xjrel_op('SETUP_EXCEPT', 121)	# ""
Xjrel_op('SETUP_FINALLY', 122)	# ""
X
Xdef_op('SET_LINENO', 127)	# Current line number
XSET_LINENO = 127
EOF
fi
if test -s 'lib/lambda.py'
then echo '*** I will not over-write existing file lib/lambda.py'
else
echo 'x - lib/lambda.py'
sed 's/^X//' > 'lib/lambda.py' << 'EOF'
X# A bit of Lambda Calculus illustrated in Python.
X#
X# This does not use Python's built-in 'eval' or 'exec' functions!
X
X
X# Currying
X#
X# From a function with 2 args, f(x, y), and a value for the 1st arg,
X# we can create a new function with one argument fx(y) = f(x, y).
X# This is called "Currying" (after the idea's inventor, a Mr. Curry).
X#
X# To implement this we create a class member, of which fx is a method;
X# f and x are stored as data attributes of the member.
X
Xclass _CurryClass():
X	def new(self, (f, x)):
X		self.f = f
X		self.x = x
X		return self
X	def fx(self, y):
X		return self.f(self.x, y)
X
Xdef CURRY(f, x):
X	# NB: f is not "simple": it has 2 arguments
X	return _CurryClass().new(f, x).fx
X
X
X# Numbers in Lambda Calculus
X#
X# In the lambda calculus, natural numbers are represented by
X# higher-order functions Ntimes(f, x) that yield f applied N
X# times to x, e.g., Twice(f, x) = f(f(x)).
X# As far as I understand, there is no difference in real lambda
X# calculus between
X#	lambda f x : f(f(x))
X# and
X#	lambda f : f o f	# 'o' means function composition
X# but in Python we have to write the first as Twice(f, x) and
X# the second as twice(f).
X
Xdef Never(f, x): return x
Xdef Once(f, x): return f(x)
Xdef Twice(f, x): return f(f(x))
Xdef Thrice(f, x): return f(f(f(x)))
Xdef Fourfold(f, x): return f(f(f(f(x))))
X# (etc.)
X
Xdef never(f): return CURRY(Never, f)
Xdef once(f): return CURRY(Once, f)
Xdef twice(f): return CURRY(Twice, f)
Xdef thrice(f): return CURRY(Thrice, f)
Xdef fourfold(f): return CURRY(Fourfold, f)
X# (etc.)
X
X
X# NB: actually 'ntimes' is less concrete than 'Ntimes', as
X# 'ntimes' returns a function, while 'Ntimes' returns a value
X# similar to what f(x) returns.  'Ntimes' can be derived
X# from 'ntimes', as follows:
X#	def Ntimes(f, x): return ntimes(f)(x)
X# but this doesn't help us since 'ntimes' can only be defined
X# using Ntimes (or a trick like the one used by CURRY).
X
X
X# Arithmetic in Lambda Calculus
X#
X# We can perform simple arithmetic on the un-curried versions, e.g.,
X#	Successor(Twice)	= Thrice	(2+1)
X#	Sum(Thrice, Twice)	= Fivefold	(3+2)
X#	Product(Thrice, Twice)	= Sixfold	(3*2)
X#	Power(Thrice, Twice)	= Ninefold	(3**2)
X#
X# First we define versions that need f and x arguments.
X# They have funny argument forms so the final functions can
X# use CURRY, which only works on functions of exactly 2 arguments.
X
Xdef SUCCESSOR(Ntimes, (f, x)): return f(Ntimes(f, x))
Xdef SUCCESSOR(Ntimes, (f, x)): return Ntimes(f, f(x))	# Same effect
Xdef SUM(Ntimes, (Mtimes, (f, x))): return Ntimes(f, Mtimes(f, x))
Xdef PRODUCT(Ntimes, (Mtimes, (f, x))): return Ntimes(CURRY(Mtimes, f), x)
Xdef POWER(Ntimes, (Mtimes, (f, x))):
X	return Mtimes(CURRY(CURRY, Ntimes), f)(x)
X
Xdef Successor(Ntimes): return CURRY(SUCCESSOR, Ntimes)
Xdef Sum(Ntimes, Mtimes): return CURRY(CURRY(SUM, Ntimes), Mtimes)
Xdef Product(Ntimes, Mtimes): return CURRY(CURRY(PRODUCT, Ntimes), Mtimes)
Xdef Power(Ntimes, Mtimes): return CURRY(CURRY(POWER, Ntimes), Mtimes)
X
X
X# Sorry, I don't have a clue on how to do subtraction or division...
X
X
X# References
X#
X# All I know about lambda calculus is from Roger Penrose's
X# The Emperor's New Mind, Chapter 2.
X
X
X# P.S.: Here is a Lambda function in Python.
X# It uses 'exec' and expects two strings to describe the arguments
X# and the function expression.  Example:
X#	lambda('x', 'x+1')
X# defines the successor function.
X
Xdef lambda(args, expr):
X	if '\n' in args or '\n' in expr:
X		raise RuntimeError, 'lambda: no cheating!'
X	stmt = 'def func(' + args + '): return ' + expr + '\n'
X	print 'lambda:', stmt,
X	exec(stmt)
X	return func
X
X
X# P.P.S.S.: Here is a way to construct Ntimes and ntimes directly.
X# Example:
X#	GenericNtimes(4)
X# is equivalent to Fourfold.
X
Xclass _GenericNtimesClass():
X	def new(self, n):
X		self.n = n
X		return self
X	def Ntimes(self, (f, x)):
X		n = self.n
X		while n > 0: x, n = f(x), n-1
X		return x
X
Xdef GenericNtimes(n):
X	return _GenericNtimesClass().new(n).Ntimes
X
X
X# To construct any 'ntimes' function from the corresponding 'Ntimes',
X# we use a trick as used by CURRY.  For example,
X#	Ntimes2ntimes(Fourfold)
X# yields a function equivalent to fourfold.
X
Xclass _Ntimes2ntimesClass():
X	def new(self, Ntimes):
X		self.Ntimes = Ntimes
X		return self
X	def ntimes(self, f):
X		return CURRY(self.Ntimes, f)
X
Xdef Ntimes2ntimes(Ntimes): return _Ntimes2ntimesClass().new(Ntimes).ntimes
X
X
X# This allows us to construct generic 'ntimes' functions.  Example:
X#	generic_ntimes(3)
X# is the same as thrice.
X
Xdef generic_ntimes(n): return Ntimes2ntimes(GenericNtimes(n))
EOF
fi
if test -s 'lib/tb.py'
then echo '*** I will not over-write existing file lib/tb.py'
else
echo 'x - lib/tb.py'
sed 's/^X//' > 'lib/tb.py' << 'EOF'
X# Print tracebacks, with a dump of local variables.
X# Also an interactive stack trace browser.
X
Ximport sys
Xtry:
X	import mac
X	os = mac
Xexcept NameError:
X	import posix
X	os = posix
Xfrom stat import *
Ximport string
X
Xdef br(): browser(sys.last_traceback)
X
Xdef tb(): printtb(sys.last_traceback)
X
Xdef browser(tb):
X	if not tb:
X		print 'No traceback.'
X		return
X	tblist = []
X	while tb:
X		tblist.append(tb)
X		tb = tb.tb_next
X	ptr = len(tblist)-1
X	tb = tblist[ptr]
X	while 1:
X		if tb <> tblist[ptr]:
X			tb = tblist[ptr]
X			print `ptr` + ':',
X			printtbheader(tb)
X		try:
X			line = raw_input('TB: ')
X		except KeyboardInterrupt:
X			print '\n[Interrupted]'
X			break
X		except EOFError:
X			print '\n[EOF]'
X			break
X		cmd = string.strip(line)
X		if cmd:
X			if cmd = 'quit':
X				break
X			elif cmd = 'list':
X				browserlist(tb)
X			elif cmd = 'up':
X				if ptr-1 >= 0: ptr = ptr-1
X				else: print 'Bottom of stack.'
X			elif cmd = 'down':
X				if ptr+1 < len(tblist): ptr = ptr+1
X				else: print 'Top of stack.'
X			elif cmd = 'locals':
X				printsymbols(tb.tb_frame.f_locals)
X			elif cmd = 'globals':
X				printsymbols(tb.tb_frame.f_globals)
X			elif cmd in ('?', 'help'):
X				browserhelp()
X			else:
X				browserexec(tb, cmd)
X
Xdef browserlist(tb):
X	filename = tb.tb_frame.f_code.co_filename
X	lineno = tb.tb_lineno
X	last = lineno
X	first = max(1, last-10)
X	for i in range(first, last+1):
X		if i = lineno: prefix = '***' + string.rjust(`i`, 4) + ':'
X		else: prefix = string.rjust(`i`, 7) + ':'
X		line = readfileline(filename, i)
X		if line[-1:] = '\n': line = line[:-1]
X		print prefix + line
X
Xdef browserexec(tb, cmd):
X	locals = tb.tb_frame.f_locals
X	globals = tb.tb_frame.f_globals
X	try:
X		exec(cmd+'\n', globals, locals)
X	except:
X		print '*** Exception:',
X		print sys.exc_type,
X		if sys.exc_value <> None:
X			print ':', sys.exc_value,
X		print
X		print 'Type help to get help.'
X
Xdef browserhelp():
X	print
X	print '    This is the traceback browser.  Commands are:'
X	print '        up      : move one level up in the call stack'
X	print '        down    : move one level down in the call stack'
X	print '        locals  : print all local variables at this level'
X	print '        globals : print all global variables at this level'
X	print '        list    : list source code around the failure'
X	print '        help    : print help (what you are reading now)'
X	print '        quit    : back to command interpreter'
X	print '    Typing any other 1-line statement will execute it'
X	print '    using the current level\'s symbol tables'
X	print
X
Xdef printtb(tb):
X	while tb:
X		print1tb(tb)
X		tb = tb.tb_next
X
Xdef print1tb(tb):
X	printtbheader(tb)
X	if tb.tb_frame.f_locals is not tb.tb_frame.f_globals:
X		printsymbols(tb.tb_frame.f_locals)
X
Xdef printtbheader(tb):
X	filename = tb.tb_frame.f_code.co_filename
X	lineno = tb.tb_lineno
X	info = '"' + filename + '"(' + `lineno` + ')'
X	line = readfileline(filename, lineno)
X	if line:
X		info = info + ': ' + string.strip(line)
X	print info
X
Xdef printsymbols(d):
X	keys = d.keys()
X	keys.sort()
X	for name in keys:
X		print '  ' + string.ljust(name, 12) + ':',
X		printobject(d[name], 4)
X		print
X
Xdef printobject(v, maxlevel):
X	if v = None:
X		print 'None',
X	elif type(v) in (type(0), type(0.0)):
X		print v,
X	elif type(v) = type(''):
X		if len(v) > 20:
X			print `v[:17] + '...'`,
X		else:
X			print `v`,
X	elif type(v) = type(()):
X		print '(',
X		printlist(v, maxlevel)
X		print ')',
X	elif type(v) = type([]):
X		print '[',
X		printlist(v, maxlevel)
X		print ']',
X	elif type(v) = type({}):
X		print '{',
X		printdict(v, maxlevel)
X		print '}',
X	else:
X		print v,
X
Xdef printlist(v, maxlevel):
X	n = len(v)
X	if n = 0: return
X	if maxlevel <= 0:
X		print '...',
X		return
X	for i in range(min(6, n)):
X		printobject(v[i], maxlevel-1)
X		if i+1 < n: print ',',
X	if n > 6: print '...',
X
Xdef printdict(v, maxlevel):
X	keys = v.keys()
X	n = len(keys)
X	if n = 0: return
X	if maxlevel <= 0:
X		print '...',
X		return
X	keys.sort()
X	for i in range(min(6, n)):
X		key = keys[i]
X		print `key` + ':',
X		printobject(v[key], maxlevel-1)
X		if i+1 < n: print ',',
X	if n > 6: print '...',
X
X_filecache = {}
X
Xdef readfileline(filename, lineno):
X	try:
X		stat = os.stat(filename)
X	except os.error, msg:
X		print 'Cannot stat', filename, '--', msg
X		return ''
X	cache_ok = 0
X	if _filecache.has_key(filename):
X		cached_stat, lines = _filecache[filename]
X		if stat[ST_SIZE] = cached_stat[ST_SIZE] and \
X				stat[ST_MTIME] = cached_stat[ST_MTIME]:
X			cache_ok = 1
X		else:
X			print 'Stale cache entry for', filename
X			del _filecache[filename]
X	if not cache_ok:
X		lines = readfilelines(filename)
X		if not lines:
X			return ''
X		_filecache[filename] = stat, lines
X	if 0 <= lineno-1 < len(lines):
X		return lines[lineno-1]
X	else:
X		print 'Line number out of range, last line is', len(lines)
X		return ''
X
Xdef readfilelines(filename):
X	try:
X		fp = open(filename, 'r')
X	except:
X		print 'Cannot open', filename
X		return []
X	lines = []
X	while 1:
X		line = fp.readline()
X		if not line: break
X		lines.append(line)
X	if not lines:
X		print 'Empty file', filename
X	return lines
EOF
fi
if test -s 'src/errors.c'
then echo '*** I will not over-write existing file src/errors.c'
else
echo 'x - src/errors.c'
sed 's/^X//' > 'src/errors.c' << 'EOF'
X/***********************************************************
XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
XNetherlands.
X
X                        All Rights Reserved
X
XPermission to use, copy, modify, and distribute this software and its 
Xdocumentation for any purpose and without fee is hereby granted, 
Xprovided that the above copyright notice appear in all copies and that
Xboth that copyright notice and this permission notice appear in 
Xsupporting documentation, and that the names of Stichting Mathematisch
XCentrum or CWI not be used in advertising or publicity pertaining to
Xdistribution of the software without specific, written prior permission.
X
XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
X
X******************************************************************/
X
X/* Error handling -- see also run.c */
X
X/* New error handling interface.
X
X   The following problem exists (existed): methods of built-in modules
X   are called with 'self' and 'args' arguments, but without a context
X   argument, so they have no way to raise a specific exception.
X   The same is true for the object implementations: no context argument.
X   The old convention was to set 'errno' and to return NULL.
X   The caller (usually call_function() in eval.c) detects the NULL
X   return value and then calls puterrno(ctx) to turn the errno value
X   into a true exception.  Problems with this approach are:
X   - it used standard errno values to indicate Python-specific errors,
X     but this means that when such an error code is reported by a system
X     call (e.g., in module posix), the user gets a confusing message
X   - errno is a global variable, which makes extensions to a multi-
X     threading environment difficult; e.g., in IRIX, multi-threaded
X     programs must use the function oserror() instead of looking in errno
X   - there is no portable way to add new error numbers for specic
X     situations -- the value space for errno is reserved to the OS, yet
X     the way to turn module-specific errors into a module-specific
X     exception requires module-specific values for errno
X   - there is no way to add a more situation-specific message to an
X     error.
X  
X  The new interface solves all these problems.  To return an error, a
X  built-in function calls err_set(exception), err_setval(exception,
X  value) or err_setstr(exception, string), and returns NULL.  These
X  functions save the value for later use by puterrno().  To adapt this
X  scheme to a multi-threaded environment, only the implementation of
X  err_setval() has to be changed.
X*/
X
X#include "allobjects.h"
X
X#include <errno.h>
X#ifndef errno
Xextern int errno;
X#endif
X
X#include "errcode.h"
X
Xextern char *strerror PROTO((int));
X
X/* Last exception stored by err_setval() */
X
Xstatic object *last_exception;
Xstatic object *last_exc_val;
X
Xvoid
Xerr_setval(exception, value)
X	object *exception;
X	object *value;
X{
X	XDECREF(last_exception);
X	XINCREF(exception);
X	last_exception = exception;
X	
X	XDECREF(last_exc_val);
X	XINCREF(value);
X	last_exc_val = value;
X}
X
Xvoid
Xerr_set(exception)
X	object *exception;
X{
X	err_setval(exception, (object *)NULL);
X}
X
Xvoid
Xerr_setstr(exception, string)
X	object *exception;
X	char *string;
X{
X	object *value = newstringobject(string);
X	err_setval(exception, value);
X	XDECREF(value);
X}
X
Xint
Xerr_occurred()
X{
X	return last_exception != NULL;
X}
X
Xvoid
Xerr_get(p_exc, p_val)
X	object **p_exc;
X	object **p_val;
X{
X	*p_exc = last_exception;
X	last_exception = NULL;
X	*p_val = last_exc_val;
X	last_exc_val = NULL;
X}
X
Xvoid
Xerr_clear()
X{
X	XDECREF(last_exception);
X	last_exception = NULL;
X	XDECREF(last_exc_val);
X	last_exc_val = NULL;
X}
X
X/* Convenience functions to set a type error exception and return 0 */
X
Xint
Xerr_badarg()
X{
X	err_setstr(TypeError, "illegal argument type for built-in operation");
X	return 0;
X}
X
Xobject *
Xerr_nomem()
X{
X	err_set(MemoryError);
X	return NULL;
X}
X
Xobject *
Xerr_errno(exc)
X	object *exc;
X{
X	object *v = newtupleobject(2);
X	if (v != NULL) {
X		settupleitem(v, 0, newintobject((long)errno));
X		settupleitem(v, 1, newstringobject(strerror(errno)));
X	}
X	err_setval(exc, v);
X	XDECREF(v);
X	return NULL;
X}
X
Xvoid
Xerr_badcall()
X{
X	err_setstr(SystemError, "bad argument to internal function");
X}
X
X/* Set the error appropriate to the given input error code (see errcode.h) */
X
Xvoid
Xerr_input(err)
X	int err;
X{
X	switch (err) {
X	case E_DONE:
X	case E_OK:
X		break;
X	case E_SYNTAX:
X		err_setstr(RuntimeError, "syntax error");
X		break;
X	case E_TOKEN:
X		err_setstr(RuntimeError, "illegal token");
X		break;
X	case E_INTR:
X		err_set(KeyboardInterrupt);
X		break;
X	case E_NOMEM:
X		err_nomem();
X		break;
X	case E_EOF:
X		err_set(EOFError);
X		break;
X	default:
X		err_setstr(RuntimeError, "unknown input error");
X		break;
X	}
X}
EOF
fi
if test -s 'src/mathmodule.c'
then echo '*** I will not over-write existing file src/mathmodule.c'
else
echo 'x - src/mathmodule.c'
sed 's/^X//' > 'src/mathmodule.c' << 'EOF'
X/***********************************************************
XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
XNetherlands.
X
X                        All Rights Reserved
X
XPermission to use, copy, modify, and distribute this software and its 
Xdocumentation for any purpose and without fee is hereby granted, 
Xprovided that the above copyright notice appear in all copies and that
Xboth that copyright notice and this permission notice appear in 
Xsupporting documentation, and that the names of Stichting Mathematisch
XCentrum or CWI not be used in advertising or publicity pertaining to
Xdistribution of the software without specific, written prior permission.
X
XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
X
X******************************************************************/
X
X/* Math module -- standard C math library functions, pi and e */
X
X#include "allobjects.h"
X
X#include <errno.h>
X#ifndef errno
Xextern int errno;
X#endif
X
X#include "modsupport.h"
X
X#include <math.h>
X
Xstatic int
Xgetdoublearg(args, px)
X	register object *args;
X	double *px;
X{
X	if (args == NULL)
X		return err_badarg();
X	if (is_floatobject(args)) {
X		*px = getfloatvalue(args);
X		return 1;
X	}
X	if (is_intobject(args)) {
X		*px = getintvalue(args);
X		return 1;
X	}
X	return err_badarg();
X}
X
Xstatic int
Xget2doublearg(args, px, py)
X	register object *args;
X	double *px, *py;
X{
X	if (args == NULL || !is_tupleobject(args) || gettuplesize(args) != 2)
X		return err_badarg();
X	return getdoublearg(gettupleitem(args, 0), px) &&
X		getdoublearg(gettupleitem(args, 1), py);
X}
X
Xstatic object *
Xmath_1(args, func)
X	object *args;
X	double (*func) FPROTO((double));
X{
X	double x;
X	if (!getdoublearg(args, &x))
X		return NULL;
X	errno = 0;
X	x = (*func)(x);
X	if (errno != 0)
X		return NULL;
X	else
X		return newfloatobject(x);
X}
X
Xstatic object *
Xmath_2(args, func)
X	object *args;
X	double (*func) FPROTO((double, double));
X{
X	double x, y;
X	if (!get2doublearg(args, &x, &y))
X		return NULL;
X	errno = 0;
X	x = (*func)(x, y);
X	if (errno != 0)
X		return NULL;
X	else
X		return newfloatobject(x);
X}
X
X#define FUNC1(stubname, func) \
X	static object * stubname(self, args) object *self, *args; { \
X		return math_1(args, func); \
X	}
X
X#define FUNC2(stubname, func) \
X	static object * stubname(self, args) object *self, *args; { \
X		return math_2(args, func); \
X	}
X
XFUNC1(math_acos, acos)
XFUNC1(math_asin, asin)
XFUNC1(math_atan, atan)
XFUNC2(math_atan2, atan2)
XFUNC1(math_ceil, ceil)
XFUNC1(math_cos, cos)
XFUNC1(math_cosh, cosh)
XFUNC1(math_exp, exp)
XFUNC1(math_fabs, fabs)
XFUNC1(math_floor, floor)
X#if 0
X/* XXX This one is not in the Amoeba library yet, so what the heck... */
XFUNC2(math_fmod, fmod)
X#endif
XFUNC1(math_log, log)
XFUNC1(math_log10, log10)
XFUNC2(math_pow, pow)
XFUNC1(math_sin, sin)
XFUNC1(math_sinh, sinh)
XFUNC1(math_sqrt, sqrt)
XFUNC1(math_tan, tan)
XFUNC1(math_tanh, tanh)
X
X#if 0
X/* What about these? */
Xdouble	frexp(double x, int *i);
Xdouble	ldexp(double x, int n);
Xdouble	modf(double x, double *i);
X#endif
X
Xstatic struct methodlist math_methods[] = {
X	{"acos", math_acos},
X	{"asin", math_asin},
X	{"atan", math_atan},
X	{"atan2", math_atan2},
X	{"ceil", math_ceil},
X	{"cos", math_cos},
X	{"cosh", math_cosh},
X	{"exp", math_exp},
X	{"fabs", math_fabs},
X	{"floor", math_floor},
X#if 0
X	{"fmod", math_fmod},
X	{"frexp", math_freqp},
X	{"ldexp", math_ldexp},
X#endif
X	{"log", math_log},
X	{"log10", math_log10},
X#if 0
X	{"modf", math_modf},
X#endif
X	{"pow", math_pow},
X	{"sin", math_sin},
X	{"sinh", math_sinh},
X	{"sqrt", math_sqrt},
X	{"tan", math_tan},
X	{"tanh", math_tanh},
X	{NULL,		NULL}		/* sentinel */
X};
X
Xvoid
Xinitmath()
X{
X	object *m, *d, *v;
X	
X	m = initmodule("math", math_methods);
X	d = getmoduledict(m);
X	dictinsert(d, "pi", v = newfloatobject(atan(1.0) * 4.0));
X	DECREF(v);
X	dictinsert(d, "e", v = newfloatobject(exp(1.0)));
X	DECREF(v);
X}
EOF
fi
if test -s 'src/sysmodule.c'
then echo '*** I will not over-write existing file src/sysmodule.c'
else
echo 'x - src/sysmodule.c'
sed 's/^X//' > 'src/sysmodule.c' << 'EOF'
X/***********************************************************
XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
XNetherlands.
X
X                        All Rights Reserved
X
XPermission to use, copy, modify, and distribute this software and its 
Xdocumentation for any purpose and without fee is hereby granted, 
Xprovided that the above copyright notice appear in all copies and that
Xboth that copyright notice and this permission notice appear in 
Xsupporting documentation, and that the names of Stichting Mathematisch
XCentrum or CWI not be used in advertising or publicity pertaining to
Xdistribution of the software without specific, written prior permission.
X
XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
X
X******************************************************************/
X
X/* System module */
X
X/*
XVarious bits of information used by the interpreter are collected in
Xmodule 'sys'.
XFunction member:
X- exit(sts): call (C, POSIX) exit(sts)
XData members:
X- stdin, stdout, stderr: standard file objects
X- modules: the table of modules (dictionary)
X- path: module search path (list of strings)
X- argv: script arguments (list of strings)
X- ps1, ps2: optional primary and secondary prompts (strings)
X*/
X
X#include "allobjects.h"
X
X#include "sysmodule.h"
X#include "import.h"
X#include "modsupport.h"
X
X/* Define delimiter used in $PYTHONPATH */
X
X#ifdef THINK_C
X#define DELIM ' '
X#endif
X
X#ifndef DELIM
X#define DELIM ':'
X#endif
X
Xstatic object *sysdict;
X
Xobject *
Xsysget(name)
X	char *name;
X{
X	return dictlookup(sysdict, name);
X}
X
XFILE *
Xsysgetfile(name, def)
X	char *name;
X	FILE *def;
X{
X	FILE *fp = NULL;
X	object *v = sysget(name);
X	if (v != NULL)
X		fp = getfilefile(v);
X	if (fp == NULL)
X		fp = def;
X	return fp;
X}
X
Xint
Xsysset(name, v)
X	char *name;
X	object *v;
X{
X	if (v == NULL)
X		return dictremove(sysdict, name);
X	else
X		return dictinsert(sysdict, name, v);
X}
X
Xstatic object *
Xsys_exit(self, args)
X	object *self;
X	object *args;
X{
X	int sts;
X	if (!getintarg(args, &sts))
X		return NULL;
X	goaway(sts);
X	exit(sts); /* Just in case */
X	/* NOTREACHED */
X}
X
Xstatic struct methodlist sys_methods[] = {
X	{"exit",	sys_exit},
X	{NULL,		NULL}		/* sentinel */
X};
X
Xstatic object *sysin, *sysout, *syserr;
X
Xvoid
Xinitsys()
X{
X	object *m = initmodule("sys", sys_methods);
X	sysdict = getmoduledict(m);
X	INCREF(sysdict);
X	/* NB keep an extra ref to the std files to avoid closing them
X	   when the user deletes them */
X	/* XXX File objects should have a "don't close" flag instead */
X	sysin = newopenfileobject(stdin, "<stdin>", "r");
X	sysout = newopenfileobject(stdout, "<stdout>", "w");
X	syserr = newopenfileobject(stderr, "<stderr>", "w");
X	if (err_occurred())
X		fatal("can't create sys.std* file objects");
X	dictinsert(sysdict, "stdin", sysin);
X	dictinsert(sysdict, "stdout", sysout);
X	dictinsert(sysdict, "stderr", syserr);
X	dictinsert(sysdict, "modules", get_modules());
X	if (err_occurred())
X		fatal("can't insert sys.* objects in sys dict");
X}
X
Xstatic object *
Xmakepathobject(path, delim)
X	char *path;
X	int delim;
X{
X	int i, n;
X	char *p;
X	object *v, *w;
X	
X	n = 1;
X	p = path;
X	while ((p = strchr(p, delim)) != NULL) {
X		n++;
X		p++;
X	}
X	v = newlistobject(n);
X	if (v == NULL)
X		return NULL;
X	for (i = 0; ; i++) {
X		p = strchr(path, delim);
X		if (p == NULL)
X			p = strchr(path, '\0'); /* End of string */
X		w = newsizedstringobject(path, (int) (p - path));
X		if (w == NULL) {
X			DECREF(v);
X			return NULL;
X		}
X		setlistitem(v, i, w);
X		if (*p == '\0')
X			break;
X		path = p+1;
X	}
X	return v;
X}
X
Xvoid
Xsetpythonpath(path)
X	char *path;
X{
X	object *v;
X	if ((v = makepathobject(path, DELIM)) == NULL)
X		fatal("can't create sys.path");
X	if (sysset("path", v) != 0)
X		fatal("can't assign sys.path");
X	DECREF(v);
X}
X
Xstatic object *
Xmakeargvobject(argc, argv)
X	int argc;
X	char **argv;
X{
X	object *av;
X	if (argc < 0 || argv == NULL)
X		argc = 0;
X	av = newlistobject(argc);
X	if (av != NULL) {
X		int i;
X		for (i = 0; i < argc; i++) {
X			object *v = newstringobject(argv[i]);
X			if (v == NULL) {
X				DECREF(av);
X				av = NULL;
X				break;
X			}
X			setlistitem(av, i, v);
X		}
X	}
X	return av;
X}
X
Xvoid
Xsetpythonargv(argc, argv)
X	int argc;
X	char **argv;
X{
X	object *av = makeargvobject(argc, argv);
X	if (av == NULL)
X		fatal("no mem for sys.argv");
X	if (sysset("argv", av) != 0)
X		fatal("can't assign sys.argv");
X	DECREF(av);
X}
EOF
fi
if test -s 'src/timemodule.c'
then echo '*** I will not over-write existing file src/timemodule.c'
else
echo 'x - src/timemodule.c'
sed 's/^X//' > 'src/timemodule.c' << 'EOF'
X/***********************************************************
XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
XNetherlands.
X
X                        All Rights Reserved
X
XPermission to use, copy, modify, and distribute this software and its 
Xdocumentation for any purpose and without fee is hereby granted, 
Xprovided that the above copyright notice appear in all copies and that
Xboth that copyright notice and this permission notice appear in 
Xsupporting documentation, and that the names of Stichting Mathematisch
XCentrum or CWI not be used in advertising or publicity pertaining to
Xdistribution of the software without specific, written prior permission.
X
XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
X
X******************************************************************/
X
X/* Time module */
X
X#include "allobjects.h"
X
X#include "modsupport.h"
X
X#include "sigtype.h"
X
X#include <signal.h>
X#include <setjmp.h>
X
X#ifdef __STDC__
X#include <time.h>
X#else /* !__STDC__ */
Xtypedef unsigned long time_t;
Xextern time_t time();
X#endif /* !__STDC__ */
X
X
X/* Time methods */
X
Xstatic object *
Xtime_time(self, args)
X	object *self;
X	object *args;
X{
X	long secs;
X	if (!getnoarg(args))
X		return NULL;
X	secs = time((time_t *)NULL);
X	return newintobject(secs);
X}
X
Xstatic jmp_buf sleep_intr;
X
Xstatic void
Xsleep_catcher(sig)
X	int sig;
X{
X	longjmp(sleep_intr, 1);
X}
X
Xstatic object *
Xtime_sleep(self, args)
X	object *self;
X	object *args;
X{
X	int secs;
X	SIGTYPE (*sigsave)();
X	if (!getintarg(args, &secs))
X		return NULL;
X	if (setjmp(sleep_intr)) {
X		signal(SIGINT, sigsave);
X		err_set(KeyboardInterrupt);
X		return NULL;
X	}
X	sigsave = signal(SIGINT, SIG_IGN);
X	if (sigsave != (SIGTYPE (*)()) SIG_IGN)
X		signal(SIGINT, sleep_catcher);
X	sleep(secs);
X	signal(SIGINT, sigsave);
X	INCREF(None);
X	return None;
X}
X
X#ifdef THINK_C
X#define DO_MILLI
X#endif /* THINK_C */
X
X#ifdef AMOEBA
X#define DO_MILLI
Xextern long sys_milli();
X#define millitimer sys_milli
X#endif /* AMOEBA */
X
X#ifdef BSD_TIME
X#define DO_MILLI
X#endif /* BSD_TIME */
X
X#ifdef DO_MILLI
X
Xstatic object *
Xtime_millisleep(self, args)
X	object *self;
X	object *args;
X{
X	long msecs;
X	SIGTYPE (*sigsave)();
X	if (!getlongarg(args, &msecs))
X		return NULL;
X	if (setjmp(sleep_intr)) {
X		signal(SIGINT, sigsave);
X		err_set(KeyboardInterrupt);
X		return NULL;
X	}
X	sigsave = signal(SIGINT, SIG_IGN);
X	if (sigsave != (SIGTYPE (*)()) SIG_IGN)
X		signal(SIGINT, sleep_catcher);
X	millisleep(msecs);
X	signal(SIGINT, sigsave);
X	INCREF(None);
X	return None;
X}
X
Xstatic object *
Xtime_millitimer(self, args)
X	object *self;
X	object *args;
X{
X	long msecs;
X	extern long millitimer();
X	if (!getnoarg(args))
X		return NULL;
X	msecs = millitimer();
X	return newintobject(msecs);
X}
X
X#endif /* DO_MILLI */
X
X
Xstatic struct methodlist time_methods[] = {
X#ifdef DO_MILLI
X	{"millisleep",	time_millisleep},
X	{"millitimer",	time_millitimer},
X#endif /* DO_MILLI */
X	{"sleep",	time_sleep},
X	{"time",	time_time},
X	{NULL,		NULL}		/* sentinel */
X};
X
X
Xvoid
Xinittime()
X{
X	initmodule("time", time_methods);
X}
X
X
X#ifdef THINK_C
X
X#define MacTicks	(* (long *)0x16A)
X
Xstatic
Xsleep(msecs)
X	int msecs;
X{
X	register long deadline;
X	
X	deadline = MacTicks + msecs * 60;
X	while (MacTicks < deadline) {
X		if (intrcheck())
X			sleep_catcher(SIGINT);
X	}
X}
X
Xstatic
Xmillisleep(msecs)
X	long msecs;
X{
X	register long deadline;
X	
X	deadline = MacTicks + msecs * 3 / 50; /* msecs * 60 / 1000 */
X	while (MacTicks < deadline) {
X		if (intrcheck())
X			sleep_catcher(SIGINT);
X	}
X}
X
Xstatic long
Xmillitimer()
X{
X	return MacTicks * 50 / 3; /* MacTicks * 1000 / 60 */
X}
X
X#endif /* THINK_C */
X
X
X#ifdef BSD_TIME
X
X#include <sys/types.h>
X#include <sys/time.h>
X
Xstatic long
Xmillitimer()
X{
X	struct timeval t;
X	struct timezone tz;
X	if (gettimeofday(&t, &tz) != 0)
X		return -1;
X	return t.tv_sec*1000 + t.tv_usec/1000;
X	
X}
X
Xstatic
Xmillisleep(msecs)
X	long msecs;
X{
X	struct timeval t;
X	t.tv_sec = msecs/1000;
X	t.tv_usec = (msecs%1000)*1000;
X	(void) select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t);
X}
X
X#endif /* BSD_TIME */
X
EOF
fi
if test -s 'src/traceback.c'
then echo '*** I will not over-write existing file src/traceback.c'
else
echo 'x - src/traceback.c'
sed 's/^X//' > 'src/traceback.c' << 'EOF'
X/***********************************************************
XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
XNetherlands.
X
X                        All Rights Reserved
X
XPermission to use, copy, modify, and distribute this software and its 
Xdocumentation for any purpose and without fee is hereby granted, 
Xprovided that the above copyright notice appear in all copies and that
Xboth that copyright notice and this permission notice appear in 
Xsupporting documentation, and that the names of Stichting Mathematisch
XCentrum or CWI not be used in advertising or publicity pertaining to
Xdistribution of the software without specific, written prior permission.
X
XSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
XTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
XFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
XFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
XWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
XACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
XOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
X
X******************************************************************/
X
X/* Traceback implementation */
X
X#include "allobjects.h"
X
X#include "compile.h"
X#include "frameobject.h"
X#include "traceback.h"
X#include "structmember.h"
X
Xtypedef struct _tracebackobject {
X	OB_HEAD
X	struct _tracebackobject *tb_next;
X	frameobject *tb_frame;
X	int tb_lasti;
X	int tb_lineno;
X} tracebackobject;
X
X#define OFF(x) offsetof(tracebackobject, x)
X
Xstatic struct memberlist tb_memberlist[] = {
X	{"tb_next",	T_OBJECT,	OFF(tb_next)},
X	{"tb_frame",	T_OBJECT,	OFF(tb_frame)},
X	{"tb_lasti",	T_INT,		OFF(tb_lasti)},
X	{"tb_lineno",	T_INT,		OFF(tb_lineno)},
X	{NULL}	/* Sentinel */
X};
X
Xstatic object *
Xtb_getattr(tb, name)
X	tracebackobject *tb;
X	char *name;
X{
X	return getmember((char *)tb, tb_memberlist, name);
X}
X
Xstatic void
Xtb_dealloc(tb)
X	tracebackobject *tb;
X{
X	XDECREF(tb->tb_next);
X	XDECREF(tb->tb_frame);
X	DEL(tb);
X}
X
Xstatic typeobject Tracebacktype = {
X	OB_HEAD_INIT(&Typetype)
X	0,
X	"traceback",
X	sizeof(tracebackobject),
X	0,
X	tb_dealloc,	/*tp_dealloc*/
X	0,		/*tp_print*/
X	tb_getattr,	/*tp_getattr*/
X	0,		/*tp_setattr*/
X	0,		/*tp_compare*/
X	0,		/*tp_repr*/
X	0,		/*tp_as_number*/
X	0,		/*tp_as_sequence*/
X	0,		/*tp_as_mapping*/
X};
X
X#define is_tracebackobject(v) ((v)->ob_type == &Tracebacktype)
X
Xstatic tracebackobject *
Xnewtracebackobject(next, frame, lasti, lineno)
X	tracebackobject *next;
X	frameobject *frame;
X	int lasti, lineno;
X{
X	tracebackobject *tb;
X	if ((next != NULL && !is_tracebackobject(next)) ||
X			frame == NULL || !is_frameobject(frame)) {
X		err_badcall();
X		return NULL;
X	}
X	tb = NEWOBJ(tracebackobject, &Tracebacktype);
X	if (tb != NULL) {
X		XINCREF(next);
X		tb->tb_next = next;
X		XINCREF(frame);
X		tb->tb_frame = frame;
X		tb->tb_lasti = lasti;
X		tb->tb_lineno = lineno;
X	}
X	return tb;
X}
X
Xstatic tracebackobject *tb_current = NULL;
X
Xint
Xtb_here(frame, lasti, lineno)
X	frameobject *frame;
X	int lasti;
X	int lineno;
X{
X	tracebackobject *tb;
X	tb = newtracebackobject(tb_current, frame, lasti, lineno);
X	if (tb == NULL)
X		return -1;
X	XDECREF(tb_current);
X	tb_current = tb;
X	return 0;
X}
X
Xobject *
Xtb_fetch()
X{
X	object *v;
X	v = (object *)tb_current;
X	tb_current = NULL;
X	return v;
X}
X
Xint
Xtb_store(v)
X	object *v;
X{
X	if (v != NULL && !is_tracebackobject(v)) {
X		err_badcall();
X		return -1;
X	}
X	XDECREF(tb_current);
X	XINCREF(v);
X	tb_current = (tracebackobject *)v;
X	return 0;
X}
X
Xstatic void
Xtb_displayline(fp, filename, lineno)
X	FILE *fp;
X	char *filename;
X	int lineno;
X{
X	FILE *xfp;
X	char buf[1000];
X	int i;
X	if (filename[0] == '<' && filename[strlen(filename)-1] == '>')
X		return;
X	xfp = fopen(filename, "r");
X	if (xfp == NULL) {
X		fprintf(fp, "    (cannot open \"%s\")\n", filename);
X		return;
X	}
X	for (i = 0; i < lineno; i++) {
X		if (fgets(buf, sizeof buf, xfp) == NULL)
X			break;
X	}
X	if (i == lineno) {
X		char *p = buf;
X		while (*p == ' ' || *p == '\t')
X			p++;
X		fprintf(fp, "    %s", p);
X		if (strchr(p, '\n') == NULL)
X			fprintf(fp, "\n");
X	}
X	fclose(xfp);
X}
X
Xstatic void
Xtb_printinternal(tb, fp)
X	tracebackobject *tb;
X	FILE *fp;
X{
X	while (tb != NULL) {
X		if (intrcheck()) {
X			fprintf(fp, "[interrupted]\n");
X			break;
X		}
X		fprintf(fp, "  File \"");
X		printobject(tb->tb_frame->f_code->co_filename, fp, PRINT_RAW);
X		fprintf(fp, "\", line %d\n", tb->tb_lineno);
X		tb_displayline(fp,
X		     getstringvalue(tb->tb_frame->f_code->co_filename),
X							tb->tb_lineno);
X		tb = tb->tb_next;
X	}
X}
X
Xint
Xtb_print(v, fp)
X	object *v;
X	FILE *fp;
X{
X	if (v == NULL)
X		return 0;
X	if (!is_tracebackobject(v)) {
X		err_badcall();
X		return -1;
X	}
X	sysset("last_traceback", v);
X	tb_printinternal((tracebackobject *)v, fp);
X	return 0;
X}
EOF
fi
echo 'Part 15 out of 21 of pack.out complete.'
exit 0



More information about the Alt.sources mailing list