From a19a216bc60160c162e616145ef091dd18ce4e61 Mon Sep 17 00:00:00 2001 From: Skip Montanaro Date: Tue, 16 Feb 2021 14:40:46 -0600 Subject: Python 0.9.1 as posted in alt.sources --- shar/python-0.9.1-01-21.shar | 1952 ++++++++++++++++++++++++++++ shar/python-0.9.1-01.patch | 163 +++ shar/python-0.9.1-03-21.shar | 2944 ++++++++++++++++++++++++++++++++++++++++++ shar/python-0.9.1-04-21.shar | 2755 +++++++++++++++++++++++++++++++++++++++ shar/python-0.9.1-05-21.shar | 2528 ++++++++++++++++++++++++++++++++++++ shar/python-0.9.1-06-21.shar | 2510 +++++++++++++++++++++++++++++++++++ shar/python-0.9.1-07-21.shar | 2518 ++++++++++++++++++++++++++++++++++++ shar/python-0.9.1-08-21.shar | 2349 +++++++++++++++++++++++++++++++++ shar/python-0.9.1-09-21.shar | 2688 ++++++++++++++++++++++++++++++++++++++ shar/python-0.9.1-10-21.shar | 2508 +++++++++++++++++++++++++++++++++++ shar/python-0.9.1-11-21.shar | 2618 +++++++++++++++++++++++++++++++++++++ shar/python-0.9.1-12-21.shar | 2833 ++++++++++++++++++++++++++++++++++++++++ shar/python-0.9.1-13-21.shar | 2811 ++++++++++++++++++++++++++++++++++++++++ shar/python-0.9.1-14-21.shar | 2720 ++++++++++++++++++++++++++++++++++++++ shar/python-0.9.1-15-21.shar | 2539 ++++++++++++++++++++++++++++++++++++ shar/python-0.9.1-16-21.shar | 2495 +++++++++++++++++++++++++++++++++++ shar/python-0.9.1-17-21.shar | 2464 +++++++++++++++++++++++++++++++++++ shar/python-0.9.1-18-21.shar | 2268 ++++++++++++++++++++++++++++++++ shar/python-0.9.1-19-21.shar | 1997 ++++++++++++++++++++++++++++ shar/python-0.9.1-20-21.shar | 1941 ++++++++++++++++++++++++++++ shar/python-0.9.1-21-21.shar | 1675 ++++++++++++++++++++++++ 21 files changed, 49276 insertions(+) create mode 100644 shar/python-0.9.1-01-21.shar create mode 100644 shar/python-0.9.1-01.patch create mode 100644 shar/python-0.9.1-03-21.shar create mode 100644 shar/python-0.9.1-04-21.shar create mode 100644 shar/python-0.9.1-05-21.shar create mode 100644 shar/python-0.9.1-06-21.shar create mode 100644 shar/python-0.9.1-07-21.shar create mode 100644 shar/python-0.9.1-08-21.shar create mode 100644 shar/python-0.9.1-09-21.shar create mode 100644 shar/python-0.9.1-10-21.shar create mode 100644 shar/python-0.9.1-11-21.shar create mode 100644 shar/python-0.9.1-12-21.shar create mode 100644 shar/python-0.9.1-13-21.shar create mode 100644 shar/python-0.9.1-14-21.shar create mode 100644 shar/python-0.9.1-15-21.shar create mode 100644 shar/python-0.9.1-16-21.shar create mode 100644 shar/python-0.9.1-17-21.shar create mode 100644 shar/python-0.9.1-18-21.shar create mode 100644 shar/python-0.9.1-19-21.shar create mode 100644 shar/python-0.9.1-20-21.shar create mode 100644 shar/python-0.9.1-21-21.shar (limited to 'shar') diff --git a/shar/python-0.9.1-01-21.shar b/shar/python-0.9.1-01-21.shar new file mode 100644 index 0000000..75c124e --- /dev/null +++ b/shar/python-0.9.1-01-21.shar @@ -0,0 +1,1952 @@ +: This is a shell archive. +: Extract with 'sh this_file'. +: Extract this part first since it makes all directories +echo 'Start of pack.out, part 01 out of 21:' +echo -n 'Making directories ... ' +err="no" +test -d 'demo' || mkdir 'demo' || err="yes" +test -d 'demo/scripts' || mkdir 'demo/scripts' || err="yes" +test -d 'demo/sgi' || mkdir 'demo/sgi' || err="yes" +test -d 'demo/sgi/audio' || mkdir 'demo/sgi/audio' || err="yes" +test -d 'demo/sgi/audio_stdwin' || mkdir 'demo/sgi/audio_stdwin' || err="yes" +test -d 'demo/sgi/gl' || mkdir 'demo/sgi/gl' || err="yes" +test -d 'demo/sgi/gl_panel' || mkdir 'demo/sgi/gl_panel' || err="yes" +test -d 'demo/sgi/gl_panel/apanel' || mkdir 'demo/sgi/gl_panel/apanel' || err="yes" +test -d 'demo/sgi/gl_panel/flying' || mkdir 'demo/sgi/gl_panel/flying' || err="yes" +test -d 'demo/sgi/gl_panel/nurbs' || mkdir 'demo/sgi/gl_panel/nurbs' || err="yes" +test -d 'demo/sgi/gl_panel/twoview' || mkdir 'demo/sgi/gl_panel/twoview' || err="yes" +test -d 'demo/stdwin' || mkdir 'demo/stdwin' || err="yes" +test -d 'doc' || mkdir 'doc' || err="yes" +test -d 'lib' || mkdir 'lib' || err="yes" +test -d 'src' || mkdir 'src' || err="yes" +echo 'done' +if test "$err" = "yes" +then echo "didn't make it." +fi +if test -s 'README' +then echo '*** I will not over-write existing file README' +else +echo 'x - README' +sed 's/^X//' > 'README' << 'EOF' +XThis is Python, an extensible interpreted programming language that +Xcombines remarkable power with very clear syntax. +X +XThis is version 0.9 (the first beta release), patchlevel 1. +X +XPython can be used instead of shell, Awk or Perl scripts, to write +Xprototypes of real applications, or as an extension language of large +Xsystems, you name it. There are built-in modules that interface to +Xthe operating system and to various window systems: X11, the Mac +Xwindow system (you need STDWIN for these two), and Silicon Graphics' +XGL library. It runs on most modern versions of UNIX, on the Mac, and +XI wouldn't be surprised if it ran on MS-DOS unchanged. I developed it +Xmostly on an SGI IRIS workstation (using IRIX 3.1 and 3.2) and on the +XMac, but have tested it also on SunOS (4.1) and BSD 4.3 (tahoe). +X +XBuilding and installing Python is easy (but do read the Makefile). +XA UNIX style manual page and extensive documentation (in LaTeX format) +Xare provided. (In the beta release, the documentation is still under +Xdevelopment.) +X +XPlease try it out and send me your comments (on anything -- the +Xlanguage design, implementation, portability, installation, +Xdocumentation) and the modules you wrote for it, to make the first +Xreal release better. If you needed to hack the source to get it to +Xcompile and run on a particular machine, send me the fixes -- I'll try +Xto incorporate them into the next patch. If you can't get it to work +Xat all, send me a *detailed* description of the problem and I may look +Xinto it. +X +XIf you want to profit of the X11 or Mac window interface, you'll need +XSTDWIN. This is a portable window system interface by the same +Xauthor. The versions of STDWIN floating around on some archives are +Xnot sufficiently up-to-date for use with Python. I will distribute +Xthe latest and greatest STDWIN version at about the same time as Python. +X +XI am the author of Python: +X +X Guido van Rossum +X CWI, dept. CST +X Kruislaan 413 +X 1098 SJ Amsterdam +X The Netherlands +X +X E-mail: gu...@cwi.nl +X +XThe Python source is copyrighted, but you can freely use and copy it +Xas long as you don't change or remove the copyright: +X +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******************************************************************/ +EOF +fi +if test -s 'python.man' +then echo '*** I will not over-write existing file python.man' +else +echo 'x - python.man' +sed 's/^X//' > 'python.man' << 'EOF' +X.TH PYTHON "19 February 1991" +X.SH NAME +Xpython \(en an extensible interpreted programming language +X.SH SYNOPSIS +X.B python +X[ +X.I X11-options +X] [ +X.I script +X[ +X.I arguments +X] ] +X.SH DESCRIPTION +XPython is an extensible interpreted programming language that +Xcombines remarkable power with very clear syntax. +XFor an introduction to programming in Python you are referred to the +XPython Tutorial. +X.PP +XThe interpreter operates somewhat like the UNIX shell: when called with +Xstandard input connected to a tty device, it reads and executes commands +Xinteractively until an EOF is read; +Xwhen called with a file name argument or with a file as standard +Xinput, it reads and executes a +X.I script +Xfrom that file. +XIf available, the script name and additional arguments thereafter are +Xpassed to the script in the variable +X.I sys.argv , +Xwhich is a list of strings. +XIn interactive mode, the primary prompt is `>>>'; the second prompt +X(which appears when a command is not complete) is `...'. +X.SH FILES AND DIRECTORIES +X.IP /usr/local/lib/python +XThis might be the directory containing the library of standard modules. +X(Installation-dependent.) +X.SH ENVIRONMENT VARIABLES +X.IP PYTHONPATH +XSets the search path for module files. +XThe format is the same as the shell's $PATH: one or more directory +Xpathnames separated by colons. +XNon-existant directories are silently ignored. +XThe default search path is installation dependent, but always begins +Xwith `.', (for example, +X.I .:/usr/local/lib/python ). +X.SH SEE ALSO +XPython Tutorial +X.br +XPython Library Reference +X.SH AUTHOR +X.nf +XGuido van Rossum +XCWI, dept. CST +XKruislaan 413 +X1098 SJ Amsterdam +XThe Netherlands +X.PP +XE-mail: gu...@cwi.nl +X.fi +X.SH COPYRIGHT +XCopyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The +XNetherlands. +X.IP " " +XAll Rights Reserved +X.PP +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. +EOF +fi +if test -s 'demo/sgi/gl_panel/nurbs/nurbs.py' +then echo '*** I will not over-write existing file demo/sgi/gl_panel/nurbs/nurbs.py' +else +echo 'x - demo/sgi/gl_panel/nurbs/nurbs.py' +sed 's/^X//' > 'demo/sgi/gl_panel/nurbs/nurbs.py' << 'EOF' +X#! /ufs/guido/bin/sgi/python +X +X# Fancy NURBS demo. Require Z buffer and Panel Library. +X +Xfrom gl import * +Xfrom GL import * +Xfrom DEVICE import * +Xfrom nurbsdata import * +Ximport panel +X +X# +X# flags = trim_f, invis_f, cpvis_f, tpvis_f, axvis_f, freeze_f +X# +XTRIM = 0 +XVIS = 1 +XCPVIS = 2 +XTPVIS = 3 +XAXVIS = 4 +XFREEZE = 5 +Xflags = [0, 1, 0, 0, 0, 0] +X +Xdef draw_axis () : +X cpack (0x0) +X zero = (0.0, 0.0, 0.0) +X # +X one = (1.0, 0.0, 0.0) +X smallline (zero, one) +X cmov (1.0, 0.0, 0.0) +X charstr ('x') +X # +X one = (0.0, 1.0, 0.0) +X smallline (zero, one) +X cmov (0.0, 1.0, 0.0) +X charstr ('y') +X # +X one = (0.0, 0.0, 1.0) +X smallline (zero, one) +X cmov (0.0, 0.0, 1.0) +X charstr ('z') +X +XDELTA = 0.1 +X +Xdef cross (p) : +X p0 = [p[0], p[1], p[2]] +X p1 = [p[0], p[1], p[2]] +X for i in range (0, 3) : +X p0[i] = p0[i] + DELTA +X p1[i] = p1[i] - DELTA +X smallline (p0, p1) +X p0[i] = p0[i] - DELTA +X p1[i] = p1[i] + DELTA +X +Xdef smallline (p0, p1) : +X bgnline () +X v3f (p0) +X v3f (p1) +X endline () +X +Xdef draw_pts (pnts, color) : +X linewidth (2) +X cpack (color) +X for i in pnts : +X cross (i) +X +Xdef init_windows(): +X foreground() +X wid = winopen('nurbs') +X wintitle('NURBS Surface') +X doublebuffer() +X RGBmode() +X gconfig() +X lsetdepth(0x000, 0x7fffff) +X zbuffer( TRUE ) +X +Xdef init_view(): +X mmode(MPROJECTION) +X ortho( -5., 5., -5., 5., -5., 5. ) +X # +X mmode(MVIEWING) +X loadmatrix(idmat) +X # +X lmbind(MATERIAL, 1) +X +Xdef set_scene(flags): +X # +X lmbind(MATERIAL, 0) +X RGBcolor(150,150,150) +X lmbind(MATERIAL, 1) +X clear() +X zclear() +X # +X if not flags[FREEZE] : +X rotate( 100, 'y' ) +X rotate( 100, 'z' ) +X +Xdef draw_trim_surface(flags): +X pnts = ctlpoints +X if flags[VIS] : +X bgnsurface() +X nurbssurface(surfknots,surfknots,pnts,ORDER,ORDER,N_XYZ) +X if flags[TRIM]: +X bgntrim() +X nurbscurve(trimknots,trimpoints,ORDER-1,N_STW) +X endtrim() +X endsurface() +X # +X if flags[CPVIS] : +X for i in pnts : +X draw_pts (i, RED) +X # +X if flags[TPVIS] : +X tpts = trimpoints +X draw_pts (tpts, YELLOW) +X # +X if flags[AXVIS] : +X draw_axis () +X # +X swapbuffers() +X +Xdef make_lights(): +X lmdef(DEFLMODEL,1,[]) +X lmdef(DEFLIGHT,1,[]) +X # +X # define material #1 +X # +X a = [] +X a = a + [EMISSION, 0.0, 0.0, 0.0] +X a = a + [AMBIENT, 0.1, 0.1, 0.1] +X a = a + [DIFFUSE, 0.6, 0.3, 0.3] +X a = a + [SPECULAR, 0.0, 0.6, 0.0] +X a = a + [SHININESS, 2.0] +X a = a + [LMNULL] +X lmdef(DEFMATERIAL, 1, a) +X # +X # turn on lighting +X # +X lmbind(LIGHT0, 1) +X lmbind(LMODEL, 1) +X +Xdef main(): +X init_windows() +X make_lights() +X init_view() +X # +X panel.needredraw() +X panels = panel.defpanellist('nurbs.s') +X p = panels[0] +X # +X def cbtrim (a) : +X flags[TRIM:TRIM+1] = [int (a.val)] +X p.trim.upfunc = cbtrim +X # +X def cbquit (a) : +X import sys +X sys.exit (1) +X p.quit.upfunc = cbquit +X # +X def cbmotion (a) : +X flags[FREEZE:FREEZE+1] = [int (a.val)] +X p.motion.upfunc = cbmotion +X # +X def cbxyzaxis (a) : +X flags[AXVIS:AXVIS+1] = [int (a.val)] +X p.xyzaxis.upfunc = cbxyzaxis +X # +X def cbtrimpnts (a) : +X flags[TPVIS:TPVIS+1] = [int (a.val)] +X p.trimpnts.upfunc = cbtrimpnts +X # +X def cbcntlpnts (a) : +X flags[CPVIS:CPVIS+1] = [int (a.val)] +X p.cntlpnts.upfunc = cbcntlpnts +X # +X def cbnurb (a) : +X flags[VIS:VIS+1] = [int (a.val)] +X p.nurb.upfunc = cbnurb +X # +X set_scene(flags) +X setnurbsproperty( N_ERRORCHECKING, 1.0 ) +X setnurbsproperty( N_PIXEL_TOLERANCE, 50.0 ) +X draw_trim_surface(flags) +X # +X while 1: +X act = panel.dopanel() +X # +X wid = panel.userredraw () +X if wid : +X winset (wid) +X reshapeviewport() +X set_scene(flags) +X draw_trim_surface(flags) +X # +X set_scene(flags) +X draw_trim_surface(flags) +X +Xmain() +EOF +chmod +x 'demo/sgi/gl_panel/nurbs/nurbs.py' +fi +if test -s 'doc/tut.tex' +then echo '*** I will not over-write existing file doc/tut.tex' +else +echo 'x - doc/tut.tex' +sed 's/^X//' > 'doc/tut.tex' << 'EOF' +X% Format this file with latex. +X +X%\documentstyle[garamond,11pt,myformat]{article} +X\documentstyle[11pt,myformat]{article} +X +X\title{\bf +X Python Tutorial \\ +X (DRAFT) +X} +X +X\author{ +X Guido van Rossum \\ +X Dept. CST, CWI, Kruislaan 413 \\ +X 1098 SJ Amsterdam, The Netherlands \\ +X E-mail: {\tt gu...@cwi.nl} +X} +X +X\begin{document} +X +X\pagenumbering{roman} +X +X\maketitle +X +X\begin{abstract} +X +X\noindent +X\Python\ is a simple, yet powerful programming language that bridges the +Xgap between C and shell programming, and is thus ideally suited for rapid +Xprototyping. +XIts syntax is put together from constructs borrowed from a variety of other +Xlanguages; most prominent are influences from ABC, C, Modula-3 and Icon. +X +XThe \Python\ interpreter is easily extended with new functions and data +Xtypes implemented in C. +X\Python\ is also suitable as an extension language for highly +Xcustomizable C applications such as editors or window managers. +X +X\Python\ is available for various operating systems, amongst which +Xseveral flavors of \UNIX, Amoeba, and the Apple Macintosh O.S. +X +XThis tutorial introduces the reader informally to the basic concepts and +Xfeatures of the \Python\ language and system. +XIt helps to have a \Python\ interpreter handy for hands-on experience, +Xbut as the examples are self-contained, the tutorial can be read +Xoff-line as well. +X +XFor a description of standard objects and modules, see the Library +XReference document. +XThe Language Reference document (XXX not yet existing) +Xgives a more formal reference to the language. +X +X\end{abstract} +X +X\pagebreak +X +X\tableofcontents +X +X\pagebreak +X +X\pagenumbering{arabic} +X +X\section{Whetting Your Appetite} +X +XIf you ever wrote a large shell script, you probably know this feeling: +Xyou'd love to add yet another feature, but it's already so slow, and so +Xbig, and so complicated; or the feature involves a system call or other +Xfuncion that is only accessible from C \ldots +XUsually the problem at hand isn't serious enough to warrant rewriting +Xthe script in C; perhaps because the problem requires variable-length +Xstrings or other data types (like sorted lists of file names) that +Xare easy in the shell but lots of work to implement in C; or perhaps +Xjust because you're not sufficiently familiar with C. +X +XIn all such cases, \Python\ is just the language for you. +X\Python\ is simple to use, but it is a real programming language, offering +Xmuch more structure and support for large programs than the shell has. +XOn the other hand, it also offers much more error checking than C, and, +Xbeing a +X{\em very-high-level language}, +Xit has high-level data types built in, such as flexible arrays and +Xdictionaries that would cost you days to implement efficiently in C. +XBecause of its more general data types \Python\ is applicable to a +Xmuch larger problem domain than +X{\em Awk} +Xor even +X{\em Perl}, +Xyet most simple things are at least as easy in \Python\ as in those +Xlanguages. +X +X\Python\ allows you to split up your program in modules that can be reused +Xin other \Python\ programs. +XIt comes with a large collection of standard modules that you can use as +Xthe basis for your programs --- or as examples to start learning to +Xprogram in \Python. +XThere are also built-in modules that provide things like file I/O, +Xsystem calls, and even a generic interface to window systems (STDWIN). +X +X\Python\ is an interpreted language, which saves you considerable time +Xduring program development because no compilation and linking is +Xnecessary. +XThe interpreter can be used interactively, which makes it easy to +Xexperiment with features of the language, to write throw-away programs, +Xor to test functions during bottom-up program development. +XIt is also a handy desk calculator. +X +X\Python\ allows writing very compact and readable programs. +XPrograms written in \Python\ are typically much shorter than equivalent C +Xprograms: +XNo declarations are necessary (all type checking is +Xdynamic); statement grouping is done by indentation instead of begin/end +Xbrackets; and the high-level data types allow you to express complex +Xoperations in a single statement. +X +X\Python\ is +X{\em extensible}: +Xif you know how to program in C it is easy to add a new built-in module +Xto the interpreter, either to perform critical operations at maximum +Xspeed, or to link \Python\ programs to libraries that may be only available +Xin binary form (such as a vendor-specific graphics library). +XOnce you are really hooked, you can link the \Python\ interpreter into an +Xapplication written in C and use it as an extension or command language. +X +X\subsection{Where From Here} +X +XNow that you are all excited about \Python, you'll want to examine it in +Xsome more detail. +XSince the best introduction to a language is using it, you are invited +Xhere to do so. +X +XIn the next section, the mechanics of using the interpreter are +Xexplained. +XThis is rather mundane information, but essential for trying out the +Xexamples shown later. +XThe rest of the tutorial introduces various features of the \Python\ +Xlanguage and system though examples, beginning with simple expressions, +Xstatements and data types, through functions and modules, and finally +Xtouching upon advanced concepts like exceptions and classes. +X +X\section{Using the Python Interpreter} +X +XThe \Python\ interpreter is usually installed as +X{\tt /usr/local/python} +Xon those machines where it is available; putting +X{\tt /usr/local} +Xin your \UNIX\ shell's search path makes it possible to start it by +Xtyping the command +X\bcode\begin{verbatim} +Xpython +X\end{verbatim}\ecode +Xto the shell. +XSince the choice of the directory where the interpreter lives is an +Xinstallation option, other places instead of +X{\tt /usr/local} +Xare possible; check with your local \Python\ guru or system +Xadministrator.% +X\footnote{ +X At CWI, at the time of writing, the interpreter can be found in +X the following places: +X On the Amoeba Ultrix machines, use the standard path, +X {\tt /usr/local/python}. +X On the Sun file servers, use +X {\tt /ufs/guido/bin/}{\em arch}{\tt /python}, +X where {\em arch} can be {\tt sgi} or {\tt sun4}. +X On piring, use {\tt /userfs3/amoeba/bin/python}. +X (If you can't find a binary advertised here, get in touch with me.) +X} +X +XThe interpreter operates somewhat like the \UNIX\ shell: when called with +Xstandard input connected to a tty device, it reads and executes commands +Xinteractively; when called with a file name argument or with a file as +Xstandard input, it reads and executes a +X{\em script} +Xfrom that file.% +X\footnote{ +X There is a difference between ``{\tt python file}'' and +X ``{\tt python $<$file}''. In the latter case {\tt input()} and +X {\tt raw\_input()} are satisfied from {\em file}, which has +X already been read until the end by the parser, so they will read +X EOF immediately. In the former case (which is usually what +X you want) they are satisfied from whatever file or device is +X connected to standard input of the \Python\ interpreter. +X} +XIf available, the script name and additional arguments thereafter are +Xpassed to the script in the variable +X{\tt sys.argv}, +Xwhich is a list of strings. +X +XWhen standard input is a tty, the interpreter is said to be in +X{\em interactive\ mode}. +XIn this mode it prompts for the next command with the +X{\em primary\ prompt}, +Xusually three greater-than signs ({\tt >>>}); for continuation lines +Xit prompts with the +X{\em secondary\ prompt}, +Xby default three dots ({\tt ...}). +XTyping an EOF (Control-D) at the primary prompt causes the interpreter +Xto exit with a zero exit status. +X +XWhen an error occurs in interactive mode, the interpreter prints a +Xmessage and a stack trace and returns to the primary prompt; with input +Xfrom a file, it exits with a nonzero exit status. +X(Exceptions handled by an +X{\tt except} +Xclause in a +X{\tt try} +Xstatement are not errors in this context.) +XSome errors are unconditionally fatal and cause an exit with a nonzero +Xexit; this applies to internal inconsistencies and some cases of running +Xout of memory. +XAll error messages are written to the standard error stream; normal +Xoutput from the executed commands is written to standard output. +X +XTyping an interrupt (normally Control-C or DEL) to the primary or +Xsecondary prompt cancels the input and returns to the primary prompt. +XTyping an interrupt while a command is being executed raises the +X{\tt KeyboardInterrupt} +Xexception, which may be handled by a +X{\tt try} +Xstatement. +X +XWhen a module named +X{\tt foo} +Xis imported, the interpreter searches for a file named +X{\tt foo.py} +Xin a list of directories specified by the environment variable +X{\tt PYTHONPATH}. +XIt has the same syntax as the \UNIX\ shell variable +X{\tt PATH}, +Xi.e., a list of colon-separated directory names. +XWhen +X{\tt PYTHONPATH} +Xis not set, an installation-dependent default path is used, usually +X{\tt .:/usr/local/lib/python}.% +X\footnote{ +X Modules are really searched in the list of directories given by +X the variable {\tt sys.path} which is initialized from +X {\tt PYTHONPATH} or from the installation-dependent default. +X See the section on Standard Modules later. +X} +X +XOn BSD'ish \UNIX\ systems, \Python\ scripts can be made directly executable, +Xlike shell scripts, by putting the line +X\bcode\begin{verbatim} +X#! /usr/local/python +X\end{verbatim}\ecode +X(assuming that's the name of the interpreter) at the beginning of the +Xscript and giving the file an executable mode. +X(The +X{\tt \#!} +Xmust be the first two characters of the file.) +X +X\subsection{Interactive Input Editing and History Substitution} +X +XSome versions of the \Python\ interpreter support editing of the current +Xinput line and history substitution, similar to facilities found in the +XKorn shell and the GNU Bash shell. +XThis is implemented using the +X{\em GNU\ Readline} +Xlibrary, which supports Emacs-style and vi-style editing. +XThis library has its own documentation which I won't duplicate here; +Xhowever, the basics are easily explained. +X +XIf supported,% +X\footnote{ +X Perhaps the quickest check to see whether command line editing +X is supported is typing Control-P to the first \Python\ prompt +X you get. If it beeps, you have command line editing. +X If not, you can skip the rest of this section. +X} +Xinput line editing is active whenever the interpreter prints a primary +Xor secondary prompt. +XThe current line can be edited using the conventional Emacs control +Xcharacters. +XThe most important of these are: +XC-A (Control-A) moves the cursor to the beginning of the line, C-E to +Xthe end, C-B moves it one position to the left, C-F to the right. +XBackspace erases the character to the left of the cursor, C-D the +Xcharacter to its right. +XC-K kills (erases) the rest of the line to the right of the cursor, C-Y +Xyanks back the last killed string. +XC-underscore undoes the last change you made; it can be repeated for +Xcumulative effect. +X +XHistory substitution works as follows. +XAll non-empty input lines issued are saved in a history buffer, +Xand when a new prompt is given you are positioned on a new line at the +Xbottom of this buffer. +XC-P moves one line up (back) in the history buffer, C-N moves one down. +XAny line in the history buffer can be edited; an asterisk appears in +Xfront of the prompt to mark a line as modified. +XPressing the Return key passes the current line to the interpreter. +XC-R starts an incremental reverse search; C-S starts a forward search. +X +XThe key bindings and some other parameters of the Readline library can +Xbe customized by placing commands in an initialization file called +X{\tt \$HOME/.initrc}. +XKey bindings have the form +X\bcode\begin{verbatim} +Xkey-name: function-name +X\end{verbatim}\ecode +Xand options can be set with +X\bcode\begin{verbatim} +Xset option-name value +X\end{verbatim}\ecode +XExample: +X\bcode\begin{verbatim} +X# I prefer vi-style editing: +Xset editing-mode vi +X# Edit using a single line: +Xset horizontal-scroll-mode On +X# Rebind some keys: +XMeta-h: backward-kill-word +XControl-u: universal-argument +X\end{verbatim}\ecode +XNote that the default binding for TAB in \Python\ is to insert a TAB +Xinstead of Readline's default filename completion function. +XIf you insist, you can override this by putting +X\bcode\begin{verbatim} +XTAB: complete +X\end{verbatim}\ecode +Xin your +X{\tt \$HOME/.inputrc}. +X(Of course, this makes it hard to type indented continuation lines.) +X +XThis facility is an enormous step forward compared to previous versions of +Xthe interpreter; however, some wishes are left: +XIt would be nice if the proper indentation were suggested on +Xcontinuation lines (the parser knows if an indent token is required +Xnext). +XThe completion mechanism might use the interpreter's symbol table. +XA function to check (or even suggest) matching parentheses, quotes +Xetc. would also be useful. +X +X\section{An Informal Introduction to Python} +X +XIn the following examples, input and output are distinguished by the +Xpresence or absence of prompts ({\tt >>>} and {\tt ...}): to repeat the +Xexample, you must type everything after the prompt, when the prompt +Xappears; everything on lines that do not begin with a prompt is output +Xfrom the interpreter. +XNote that a secondary prompt on a line by itself in an example means you +Xmust type a blank line; this is used to end a multi-line command. +X +X\subsection{Using Python as a Calculator} +X +XLet's try some simple \Python\ commands. +XStart the interpreter and wait for the primary prompt, +X{\tt >>>}. +XThe interpreter acts as a simple calculator: you can type an expression +Xat it and it will write the value. +XExpression syntax is straightforward: the operators +X{\tt +}, +X{\tt -}, +X{\tt *} +Xand +X{\tt /} +Xwork just as in most other languages (e.g., Pascal or C); parentheses +Xcan be used for grouping. +XFor example: +X\bcode\begin{verbatim} +X>>> # This is a comment +X>>> 2+2 +X4 +X>>> +X>>> (50-5+5*6+25)/4 +X25 +X>>> # Division truncates towards zero: +X>>> 7/3 +X2 +X>>> +X\end{verbatim}\ecode +XAs in C, the equal sign ({\tt =}) is used to assign a value to a variable. +XThe value of an assignment is not written: +X\bcode\begin{verbatim} +X>>> width = 20 +X>>> height = 5*9 +X>>> width * height +X900 +X>>> +X\end{verbatim}\ecode +XThere is some support for floating point, but you can't mix floating +Xpoint and integral numbers in expression (yet): +X\bcode\begin{verbatim} +X>>> 10.0 / 3.3 +X3.0303030303 +X>>> +X\end{verbatim}\ecode +XBesides numbers, \Python\ can also manipulate strings, enclosed in single +Xquotes: +X\bcode\begin{verbatim} +X>>> 'foo bar' +X'foo bar' +X>>> 'doesn\'t' +X'doesn\'t' +X>>> +X\end{verbatim}\ecode +XStrings are written inside quotes and with quotes and other funny +Xcharacters escaped by backslashes, to show the precise value. +X(There is also a way to write strings without quotes and escapes.) +XStrings can be concatenated (glued together) with the +X{\tt +} +Xoperator, and repeated with~{\tt *}: +X\bcode\begin{verbatim} +X>>> word = 'Help' + 'A' +X>>> word +X'HelpA' +X>>> '<' + word*5 + '>' +X'' +X>>> +X\end{verbatim}\ecode +XStrings can be subscripted; as in C, the first character of a string has +Xsubscript 0. +XThere is no separate character type; a character is simply a string of +Xsize one. +XAs in Icon, substrings can be specified with the +X{\em slice} +Xnotation: two subscripts (indices) separated by a colon. +X\bcode\begin{verbatim} +X>>> word[4] +X'A' +X>>> word[0:2] +X'He' +X>>> word[2:4] +X'lp' +X>>> # Slice indices have useful defaults: +X>>> word[:2] # Take first two characters +X'He' +X>>> word[2:] # Drop first two characters +X'lpA' +X>>> # A useful invariant: s[:i] + s[i:] = s +X>>> word[:3] + word[3:] +X'HelpA' +X>>> +X\end{verbatim}\ecode +XDegenerate cases are handled gracefully: an index that is too large is +Xreplaced by the string size, an upper bound smaller than the lower bound +Xreturns an empty string. +X\bcode\begin{verbatim} +X>>> word[1:100] +X'elpA' +X>>> word[10:] +X'' +X>>> word[2:1] +X'' +X>>> +X\end{verbatim}\ecode +XSlice indices (but not simple subscripts) may be negative numbers, to +Xstart counting from the right. +XFor example: +X\bcode\begin{verbatim} +X>>> word[-2:] # Take last two characters +X'pA' +X>>> word[:-2] # Drop last two characters +X'Hel' +X>>> # But -0 does not count from the right! +X>>> word[-0:] # (since -0 equals 0) +X'HelpA' +X>>> +X\end{verbatim}\ecode +XThe best way to remember how slices work is to think of the indices as +Xpointing +X{\em between} +Xcharacters, with the left edge of the first character numbered 0. +XThen the right edge of the last character of a string of +X{\tt n} +Xcharacters has index +X{\tt n}, +Xfor example: +X\bcode\begin{verbatim} +X +---+---+---+---+---+ +X | H | e | l | p | A | +X +---+---+---+---+---+ +X 0 1 2 3 4 5 +X-5 -4 -3 -2 -1 +X\end{verbatim}\ecode +XThe first row of numbers gives the position of the indices 0...5 in the +Xstring; the second row gives the corresponding negative indices. +XFor nonnegative indices, the length of a slice is the difference of the +Xindices, if both are within bounds, +Xe.g., +Xthe length of +X{\tt word[1:3]} +Xis 3--1 = 2. +X +XFinally, the built-in function {\tt len()} computes the length of a +Xstring: +X\bcode\begin{verbatim} +X>>> s = 'supercalifragilisticexpialidocious' +X>>> len(s) +X34 +X>>> +X\end{verbatim}\ecode +X\Python\ knows a number of +X{\em compound} +Xdata types, used to group together other values. +XThe most versatile is the +X{\em list}, +Xwhich can be written as a list of comma-separated values between square +Xbrackets: +X\bcode\begin{verbatim} +X>>> a = ['foo', 'bar', 100, 1234] +X>>> a +X['foo', 'bar', 100, 1234] +X>>> +X\end{verbatim}\ecode +XAs for strings, list subscripts start at 0: +X\bcode\begin{verbatim} +X>>> a[0] +X'foo' +X>>> a[3] +X1234 +X>>> +X\end{verbatim}\ecode +XLists can be sliced and concatenated like strings: +X\bcode\begin{verbatim} +X>>> a[1:3] +X['bar', 100] +X>>> a[:2] + ['bletch', 2*2] +X['foo', 'bar', 'bletch', 4] +X>>> +X\end{verbatim}\ecode +XUnlike strings, which are +X{\em immutable}, +Xit is possible to change individual elements of a list: +X\bcode\begin{verbatim} +X>>> a +X['foo', 'bar', 100, 1234] +X>>> a[2] = a[2] + 23 +X>>> a +X['foo', 'bar', 123, 1234] +X>>> +X\end{verbatim}\ecode +XAssignment to slices is also possible, and this may even change the size +Xof the list: +X\bcode\begin{verbatim} +X>>> # Replace some items: +X>>> a[0:2] = [1, 12] +X>>> a +X[1, 12, 123, 1234] +X>>> # Remove some: +X>>> a[0:2] = [] +X>>> a +X[123, 1234] +X>>> # Insert some: +X>>> a[1:1] = ['bletch', 'xyzzy'] +X>>> a +X[123, 'bletch', 'xyzzy', 1234] +X>>> +X\end{verbatim}\ecode +XThe built-in function {\tt len()} also applies to lists: +X\bcode\begin{verbatim} +X>>> len(a) +X4 +X>>> +X\end{verbatim}\ecode +X +X\subsection{Tuples and Sequences} +X +XXXX To Be Done. +X +X\subsection{First Steps Towards Programming} +X +XOf course, we can use \Python\ for more complicated tasks than adding two +Xand two together. +XFor instance, we can write an initial subsequence of the +X{\em Fibonacci} +Xseries as follows: +X\bcode\begin{verbatim} +X>>> # Fibonacci series: +X>>> # the sum of two elements defines the next +X>>> a, b = 0, 1 +X>>> while b < 100: +X... print b +X... a, b = b, a+b +X... +X1 +X1 +X2 +X3 +X5 +X8 +X13 +X21 +X34 +X55 +X89 +X>>> +X\end{verbatim}\ecode +XThis example introduces several new features. +X\begin{itemize} +X\item +XThe first line contains a +X{\em multiple\ assignment}: +Xthe variables +X{\tt a} +Xand +X{\tt b} +Xsimultaneously get the new values 0 and 1. +XOn the last line this is used again, demonstrating that the expressions +Xon the right-hand side are all evaluated first before any of the +Xassignments take place. +X\item +XThe +X{\tt while} +Xloop executes as long as the condition (here: $b < 100$) remains true. +XIn \Python, as in C, any non-zero integer value is true; zero is false. +XThe condition may also be a string or list value, in fact any sequence; +Xanything with a non-zero length is true, empty sequences are false. +XThe test used in the example is a simple comparison. +XThe standard comparison operators are written as +X{\tt <}, +X{\tt >}, +X{\tt =}, +X{\tt <=}, +X{\tt >=} +Xand +X{\tt <>}.% +X\footnote{ +X The ambiguity of using {\tt =} +X for both assignment and equality is resolved by disallowing +X unparenthesized conditions at the right hand side of assignments. +X} +X\item +XThe +X{\em body} +Xof the loop is +X{\em indented}: indentation is \Python's way of grouping statements. +X\Python\ does not (yet!) provide an intelligent input line editing +Xfacility, so you have to type a tab or space(s) for each indented line. +XIn practice you will prepare more complicated input for \Python\ with a +Xtext editor; most text editors have an auto-indent facility. +XWhen a compound statement is entered interactively, it must be +Xfollowed by a blank line to indicate completion (since the parser +Xcannot guess when you have typed the last line). +X\item +XThe +X{\tt print} +Xstatement writes the value of the expression(s) it is given. +XIt differs from just writing the expression you want to write (as we did +Xearlier in the calculator examples) in the way it handles multiple +Xexpressions and strings. +XStrings are written without quotes and a space is inserted between +Xitems, so you can format things nicely, like this: +X\bcode\begin{verbatim} +X>>> i = 256*256 +X>>> print 'The value of i is', i +XThe value of i is 65536 +X>>> +X\end{verbatim}\ecode +XA trailing comma avoids the newline after the output: +X\bcode\begin{verbatim} +X>>> a, b = 0, 1 +X>>> while b < 1000: +X... print b, +X... a, b = b, a+b +X... +X1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 +X>>> +X\end{verbatim}\ecode +XNote that the interpreter inserts a newline before it prints the next +Xprompt if the last line was not completed. +X\end{itemize} +X +X\subsection{More Control Flow Tools} +X +XBesides the {\tt while} statement just introduced, \Python\ knows the +Xusual control flow statements known from other languages, with some +Xtwists. +X +X\subsubsection{If Statements} +X +XPerhaps the most well-known statement type is the {\tt if} statement. +XFor example: +X\bcode\begin{verbatim} +X>>> if x < 0: +X... x = 0 +X... print 'Negative changed to zero' +X... elif x = 0: +X... print 'Zero' +X... elif x = 1: +X... print 'Single' +X... else: +X... print 'More' +X... +X\end{verbatim}\ecode +XThere can be zero or more {\tt elif} parts, and the {\tt else} part is +Xoptional. +XThe keyword `{\tt elif}' is short for `{\tt else if}', and is useful to +Xavoid excessive indentation. +XAn {\tt if...elif...elif...} sequence is a substitute for the +X{\em switch} or {\em case} statements found in other languages. +X +X\subsubsection{For Statements} +X +XThe {\tt for} statement in \Python\ differs a bit from what you may be +Xused to in C or Pascal. +XRather than always iterating over an arithmetic progression of numbers +X(as Pascal), or leaving the user completely free in the iteration test +Xand step (as C), \Python's {\tt for} statement iterates over the items +Xof any sequence (e.g., a list or a string). +XFor example (no pun intended): +X\bcode\begin{verbatim} +X>>> # Measure some strings: +X>>> a = ['cat', 'window', 'defenestrate'] +X>>> for x in a: +X... print x, len(x) +X... +Xcat 3 +Xwindow 6 +Xdefenestrate 12 +X>>> +X\end{verbatim}\ecode +X +X\subsubsection{The {\tt range()} Function} +X +XIf you do need to iterate over a sequence of numbers, the built-in +Xfunction {\tt range()} comes in handy. +XIt generates lists containing arithmetic progressions, +Xe.g.: +X\bcode\begin{verbatim} +X>>> range(10) +X[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] +X>>> +X\end{verbatim}\ecode +XThe given end point is never part of the generated list; +X{\tt range(10)} generates a list of 10 values, +Xexactly the legal indices for items of a sequence of length 10. +XIt is possible to let the range start at another number, or to specify a +Xdifferent increment (even negative): +X\bcode\begin{verbatim} +X>>> range(5, 10) +X[5, 6, 7, 8, 9] +X>>> range(0, 10, 3) +X[0, 3, 6, 9] +X>>> range(-10, -100, -30) +X[-10, -40, -70] +X>>> +X\end{verbatim}\ecode +XTo iterate over the indices of a sequence, combine {\tt range()} +Xand {\tt len()} as follows: +X\bcode\begin{verbatim} +X>>> a = ['Mary', 'had', 'a', 'little', 'boy'] +X>>> for i in range(len(a)): +X... print i, a[i] +X... +X0 Mary +X1 had +X2 a +X3 little +X4 boy +X>>> +X\end{verbatim}\ecode +X +X\subsubsection{Break Statements and Else Clauses on Loops} +X +XThe {\tt break} statement breaks out of the smallest enclosing {\tt for} +Xor {\tt while} loop. +XLoop statements may have an {\tt else} clause; it is executed when the +Xloop terminates through exhaustion of the list (with {\tt for}) or when +Xthe condition becomes false (with {\tt while}) but not when the loop is +Xterminated by a {\tt break} statement. +XThis is exemplified by the following loop, which searches for a list +Xitem of value 0: +X\bcode\begin{verbatim} +X>>> for n in range(2, 10): +X... for x in range(2, n): +X... if n % x = 0: +X... print n, 'equals', x, '*', n/x +X... break +X... else: +X... print n, 'is a prime number' +X... +X2 is a prime number +X3 is a prime number +X4 equals 2 * 2 +X5 is a prime number +X6 equals 2 * 3 +X7 is a prime number +X8 equals 2 * 4 +X9 equals 3 * 3 +X>>> +X\end{verbatim}\ecode +X +X\subsubsection{Pass Statements} +X +XThe {\tt pass} statement does nothing. +XIt can be used when a statement is required syntactically but the +Xprogram requires no action. +XFor example: +X\bcode\begin{verbatim} +X>>> while 1: +X... pass # Busy-wait for keyboard interrupt +X... +X\end{verbatim}\ecode +X +X\subsubsection{Conditions Revisited} +X +XXXX To Be Done. +X +X\subsection{Defining Functions} +X +XWe can create a function that writes the Fibonacci series to an +Xarbitrary boundary: +X\bcode\begin{verbatim} +X>>> def fib(n): # write Fibonacci series up to n +X... a, b = 0, 1 +X... while b <= n: +X... print b, +X... a, b = b, a+b +X... +X>>> # Now call the function we just defined: +X>>> fib(2000) +X1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 +X>>> +X\end{verbatim}\ecode +XThe keyword +X{\tt def} +Xintroduces a function +X{\em definition}. +XIt must be followed by the function name and the parenthesized list of +Xformal parameters. +XThe statements that form the body of the function starts at the next +Xline, indented by a tab stop. +XThe +X{\em execution} +Xof a function introduces a new symbol table used for the local variables +Xof the function. +XMore precisely, all variable assignments in a function store the value +Xin the local symbol table; variable references first look in the local +Xsymbol table, then in the global symbol table, and then in the table of +Xbuilt-in names. +XThus, the global symbol table is +X{\em read-only} +Xwithin a function. +XThe actual parameters (arguments) to a function call are introduced in +Xthe local symbol table of the called function when it is called; +Xthus, arguments are passed using +X{\em call\ by\ value}.% +X\footnote{ +X Actually, {\em call by object reference} would be a better +X description, since if a mutable object is passed, the caller +X will see any changes the callee makes to it (e.g., items +X inserted into a list). +X} +XWhen a function calls another function, a new local symbol table is +Xcreated for that call. +X +XA function definition introduces the function name in the global symbol +Xtable. +XThe value has a type that is recognized by the interpreter as a +Xuser-defined function. +XThis value can be assigned to another name which can then also be used +Xas a function. +XThis serves as a general renaming mechanism: +X\bcode\begin{verbatim} +X>>> fib +X +X>>> f = fib +X>>> f(100) +X1 1 2 3 5 8 13 21 34 55 89 +X>>> +X\end{verbatim}\ecode +XYou might object that +X{\tt fib} +Xis not a function but a procedure. +XIn \Python, as in C, procedures are just functions that don't return a +Xvalue. +XIn fact, technically speaking, procedures do return a value, albeit a +Xrather boring one. +XThis value is called {\tt None} (it's a built-in name). +XWriting the value {\tt None} is normally suppressed by the interpreter +Xif it would be the only value written. +XYou can see it if you really want to: +X\bcode\begin{verbatim} +X>>> print fib(0) +XNone +X>>> +X\end{verbatim}\ecode +XIt is simple to write a function that returns a list of the numbers of +Xthe Fibonacci series, instead of printing it: +X\bcode\begin{verbatim} +X>>> def fib2(n): # return Fibonacci series up to n +X... result = [] +X... a, b = 0, 1 +X... while b <= n: +X... result.append(b) # see below +X... a, b = b, a+b +X... return result +X... +X>>> f100 = fib2(100) # call it +X>>> f100 # write the result +X[1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89] +X>>> +X\end{verbatim}\ecode +XThis example, as usual, demonstrates some new \Python\ features: +X\begin{itemize} +X\item +XThe +X{\tt return} +Xstatement returns with a value from a function. +X{\tt return} +Xwithout an expression argument is used to return from the middle of a +Xprocedure (falling off the end also returns from a proceduce). +X\item +XThe statement +X{\tt ret.append(b)} +Xcalls a +X{\em method} +Xof the list object +X{\tt ret}. +XA method is a function that `belongs' to an object and is named +X{\tt obj.methodname}, +Xwhere +X{\tt obj} +Xis some object (this may be an expression), and +X{\tt methodname} +Xis the name of a method that is defined by the object's type. +XDifferent types define different methods. +XMethods of different types may have the same name without causing +Xambiguity. +XSee the section on classes, later, to find out how you can define your +Xown object types and methods. +XThe method +X{\tt append} +Xshown in the example, is defined for list objects; it adds a new element +Xat the end of the list. +XIn this case it is equivalent to +X{\tt ret = ret + [b]}, +Xbut more efficient.% +X\footnote{ +X There is a subtle semantic difference if the object +X is referenced from more than one place. +X} +X\end{itemize} +XThe list object type has two more methods: +X\begin{description} +X\item[{\tt insert(i, x)}] +XInserts an item at a given position. +XThe first argument is the index of the element before which to insert, +Xso {\tt a.insert(0, x)} inserts at the front of the list, and +X{\tt a.insert(len(a), x)} is equivalent to {\tt a.append(x)}. +X\item[{\tt sort()}] +XSorts the elements of the list. +X\end{description} +XFor example: +X\bcode\begin{verbatim} +X>>> a = [10, 100, 1, 1000] +X>>> a.insert(2, -1) +X>>> a +X[10, 100, -1, 1, 1000] +X>>> a.sort() +X>>> a +X[-1, 1, 10, 100, 1000] +X>>> # Strings are sorted according to ASCII: +X>>> b = ['Mary', 'had', 'a', 'little', 'boy'] +X>>> b.sort() +X>>> b +X['Mary', 'a', 'boy', 'had', 'little'] +X>>> +X\end{verbatim}\ecode +X +X\subsection{Modules} +X +XIf you quit from the \Python\ interpreter and enter it again, the +Xdefinitions you have made (functions and variables) are lost. +XTherefore, if you want to write a somewhat longer program, you are +Xbetter off using a text editor to prepare the input for the interpreter +Xand run it with that file as input instead. +XThis is known as creating a +X{\em script}. +XAs your program gets longer, you may want to split it into several files +Xfor easier maintenance. +XYou may also want to use a handy function that you've written in several +Xprograms without copying its definition into each program. +XTo support this, \Python\ has a way to put definitions in a file and use +Xthem in a script or in an interactive instance of the interpreter. +XSuch a file is called a +X{\em module}; +Xdefinitions from a module can be +X{\em imported} +Xinto other modules or into the +X{\em main} +Xmodule (the collection of variables that you have access to in +Xa script and in calculator mode). +X +XA module is a file containing \Python\ definitions and statements. +XThe file name is the module name with the suffix +X{\tt .py} +Xappended. +XFor instance, use your favorite text editor to create a file called +X{\tt fibo.py} +Xin the current directory with the following contents: +X\bcode\begin{verbatim} +X# Fibonacci numbers module +X +Xdef fib(n): # write Fibonacci series up to n +X a, b = 0, 1 +X while b <= n: +X print b, +X a, b = b, a+b +X +Xdef fib2(n): # return Fibonacci series up to n +X ret = [] +X a, b = 0, 1 +X while b <= n: +X ret.append(b) +X a, b = b, a+b +X return ret +X\end{verbatim}\ecode +XNow enter the \Python\ interpreter and import this module with the +Xfollowing command: +X\bcode\begin{verbatim} +X>>> import fibo +X>>> +X\end{verbatim}\ecode +XThis does not enter the names of the functions defined in +X{\tt fibo} +Xdirectly in the symbol table; it only enters the module name +X{\tt fibo} +Xthere. +XUsing the module name you can access the functions: +X\bcode\begin{verbatim} +X>>> fibo.fib(1000) +X1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 +X>>> fibo.fib2(100) +X[1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89] +X>>> +X\end{verbatim}\ecode +XIf you intend to use a function often you can assign it to a local name: +X\bcode\begin{verbatim} +X>>> fib = fibo.fib +X>>> fib(500) +X1 1 2 3 5 8 13 21 34 55 89 144 233 377 +X>>> +X\end{verbatim}\ecode +X +X\subsubsection{More on Modules} +X +XA module can contain executable statements as well as function +Xdefinitions. +XThese statements are intended to initialize the module. +XThey are executed only the +X{\em first} +Xtime the module is imported somewhere.% +X\footnote{ +X In fact function definitions are also `statements' that are +X `executed'; the execution enters the function name in the +X module's global symbol table. +X} +X +XEach module has its own private symbol table, which is used as the +Xglobal symbol table by all functions defined in the module. +XThus, the author of a module can use global variables in the module +Xwithout worrying about accidental clashes with a user's global +Xvariables. +XOn the other hand, if you know what you are doing you can touch a +Xmodule's global variables with the same notation used to refer to its +Xfunctions, +X{\tt modname.itemname}. +X +XModules can import other modules. +XIt is customary but not required to place all +X{\tt import} +Xstatements at the beginning of a module (or script, for that matter). +XThe imported module names are placed in the importing module's global +Xsymbol table. +X +XThere is a variant of the +X{\tt import} +Xstatement that imports names from a module directly into the importing +Xmodule's symbol table. +XFor example: +X\bcode\begin{verbatim} +X>>> from fibo import fib, fib2 +X>>> fib(500) +X1 1 2 3 5 8 13 21 34 55 89 144 233 377 +X>>> +X\end{verbatim}\ecode +XThis does not introduce the module name from which the imports are taken +Xin the local symbol table (so in the example, {\tt fibo} is not +Xdefined). +X +XThere is even a variant to import all names that a module defines: +X\bcode\begin{verbatim} +X>>> from fibo import * +X>>> fib(500) +X1 1 2 3 5 8 13 21 34 55 89 144 233 377 +X>>> +X\end{verbatim}\ecode +XThis imports all names except those beginning with an underscore +X({\tt \_}). +X +X\subsubsection{Standard Modules} +X +X\Python\ comes with a library of standard modules, described in a separate +Xdocument (Python Library and Module Reference). +XSome modules are built into the interpreter; these provide access to +Xoperations that are not part of the core of the language but are +Xnevertheless built in, either for efficiency or to provide access to +Xoperating system primitives such as system calls. +XThe set of such modules is a configuration option; e.g., the +X{\tt amoeba} +Xmodule is only provided on systems that somehow support Amoeba +Xprimitives. +XOne particular module deserves some attention: +X{\tt sys}, +Xwhich is built into every \Python\ interpreter. +XThe variables +X{\tt sys.ps1} +Xand +X{\tt sys.ps2} +Xdefine the strings used as primary and secondary prompts: +X\bcode\begin{verbatim} +X>>> import sys +X>>> sys.ps1 +X'>>> ' +X>>> sys.ps2 +X'... ' +X>>> sys.ps1 = 'C> ' +XC> print 'Yuck!' +XYuck! +XC> +X\end{verbatim}\ecode +XThese two variables are only defined if the interpreter is in +Xinteractive mode. +X +XThe variable +X{\tt sys.path} +Xis a list of strings that determine the interpreter's search path for +Xmodules. +XIt is initialized to a default path taken from the environment variable +X{\tt PYTHONPATH}, +Xor from a built-in default if +X{\tt PYTHONPATH} +Xis not set. +XYou can modify it using standard list operations, e.g.: +X\bcode\begin{verbatim} +X>>> import sys +X>>> sys.path.append('/ufs/guido/lib/python') +X>>> +X\end{verbatim}\ecode +X +X\subsection{Errors and Exceptions} +X +XUntil now error messages haven't yet been mentioned, but if you have +Xtried out the examples you have probably seen some. +XThere are (at least) two distinguishable kinds of errors: +X{\em syntax\ errors} +Xand +X{\em exceptions}. +X +X\subsubsection{Syntax Errors} +X +XSyntax errors, also known as parsing errors, are perhaps the most common +Xkind of complaint you get while you are still learning \Python: +X\bcode\begin{verbatim} +X>>> while 1 print 'Hello world' +XParsing error: file , line 1: +Xwhile 1 print 'Hello world' +X ^ +XUnhandled exception: run-time error: syntax error +X>>> +X\end{verbatim}\ecode +XThe parser repeats the offending line and displays a little `arrow' +Xpointing at the earliest point in the line where the error was detected. +XThe error is caused by (or at least detected at) the token +X{\em preceding} +Xthe arrow: in the example, the error is detected at the keyword +X{\tt print}, since a colon ({\tt :}) is missing before it. +XFile name and line number are printed so you know where to look in case +Xthe input came from a script. +X +X\subsubsection{Exceptions} +X +XEven if a statement or expression is syntactically correct, it may cause +Xan error when an attempt is made to execute it: +X\bcode\small\begin{verbatim} +X>>> 10 * (1/0) +XUnhandled exception: run-time error: integer division by zero +XStack backtrace (innermost last): +X File "", line 1 +X>>> 4 + foo*3 +XUnhandled exception: undefined name: foo +XStack backtrace (innermost last): +X File "", line 1 +X>>> '2' + 2 +XUnhandled exception: type error: illegal argument type for built-in operation +XStack backtrace (innermost last): +X File "", line 1 +X>>> +X\end{verbatim}\ecode +XErrors detected during execution are called +X{\em exceptions} +Xand are not unconditionally fatal: you will soon learn how to handle +Xthem in \Python\ programs. +XMost exceptions are not handled by programs, however, and result +Xin error messages as shown here. +X +XThe first line of the error message indicates what happened. +XExceptions come in different types, and the type is printed as part of +Xthe message: the types in the example are +X{\tt run-time error}, +X{\tt undefined name} +Xand +X{\tt type error}. +XThe rest of the line is a detail whose interpretation depends on the +Xexception type. +X +XThe rest of the error message shows the context where the +Xexception happened. +XIn general it contains a stack backtrace listing source lines; however, +Xit will not display lines read from standard input. +X +XHere is a summary of the most common exceptions: +X\begin{itemize} +X\item +X{\em Run-time\ errors} +Xare generally caused by wrong data used by the program; this can be the +Xprogrammer's fault or caused by bad input. +XThe detail states the cause of the error in more detail. +X\item +X{\em Undefined\ name} +Xerrors are more serious: these are usually caused by misspelled +Xidentifiers.% +X\footnote{ +X The parser does not check whether names used in a program are at +X all defined elsewhere in the program, so such checks are +X postponed until run-time. The same holds for type checking. +X} +XThe detail is the offending identifier. +X\item +X{\em Type\ errors} +Xare also pretty serious: this is another case of using wrong data (or +Xbetter, using data the wrong way), but here the error can be glanced +Xfrom the object type(s) alone. +XThe detail shows in what context the error was detected. +X\end{itemize} +X +X\subsubsection{Handling Exceptions} +X +XIt is possible to write programs that handle selected exceptions. +XLook at the following example, which prints a table of inverses of +Xsome floating point numbers: +X\bcode\begin{verbatim} +X>>> numbers = [0.3333, 2.5, 0.0, 10.0] +X>>> for x in numbers: +X... print x, +X... try: +X... print 1.0 / x +X... except RuntimeError: +X... print '*** has no inverse ***' +X... +X0.3333 3.00030003 +X2.5 0.4 +X0 *** has no inverse *** +X10 0.1 +X>>> +X\end{verbatim}\ecode +XThe {\tt try} statement works as follows. +X\begin{itemize} +X\item +XFirst, the +X{\em try\ clause} +X(the statement(s) between the {\tt try} and {\tt except} keywords) is +Xexecuted. +X\item +XIf no exception occurs, the +X{\em except\ clause} +Xis skipped and execution of the {\tt try} statement is finished. +X\item +XIf an exception occurs during execution of the try clause, and its +Xtype matches the exception named after the {\tt except} keyword, the +Xrest of the try clause is skipped, the except clause is executed, and +Xthen execution continues after the {\tt try} statement. +X\item +XIf an exception occurs which does not match the exception named in the +Xexcept clause, it is passed on to outer try statements; if no handler is +Xfound, it is an +X{\em unhandled\ exception} +Xand execution stops with a message as shown above. +X\end{itemize} +XA {\tt try} statement may have more than one except clause, to specify +Xhandlers for different exceptions. +XAt most one handler will be executed. +XHandlers only handle exceptions that occur in the corresponding try +Xclause, not in other handlers of the same {\tt try} statement. +XAn except clause may name multiple exceptions as a parenthesized list, +Xe.g.: +X\bcode\begin{verbatim} +X... except (RuntimeError, TypeError, NameError): +X... pass +X\end{verbatim}\ecode +XThe last except clause may omit the exception name(s), to serve as a +Xwildcard. +XUse this with extreme caution! +X +XWhen an exception occurs, it may have an associated value, also known as +Xthe exceptions's +X{\em argument}. +XThe presence and type of the argument depend on the exception type. +XFor exception types which have an argument, the except clause may +Xspecify a variable after the exception name (or list) to receive the +Xargument's value, as follows: +X\bcode\begin{verbatim} +X>>> try: +X... foo() +X... except NameError, x: +X... print 'name', x, 'undefined' +X... +Xname foo undefined +X>>> +X\end{verbatim}\ecode +XIf an exception has an argument, it is printed as the third part +X(`detail') of the message for unhandled exceptions. +X +XStandard exception names are built-in identifiers (not reserved +Xkeywords). +XThese are in fact string objects whose +X{\em object\ identity} +X(not their value!) identifies the exceptions.% +X\footnote{ +X There should really be a separate exception type; it is pure +X laziness that exceptions are identified by strings, and this may +X be fixed in the future. +X} +XThe string is printed as the second part of the message for unhandled +Xexceptions. +XTheir names and values are: +X\bcode\begin{verbatim} +XEOFError 'end-of-file read' +XKeyboardInterrupt 'keyboard interrupt' +XMemoryError 'out of memory' * +XNameError 'undefined name' * +XRuntimeError 'run-time error' * +XSystemError 'system error' * +XTypeError 'type error' * +X\end{verbatim}\ecode +XThe meanings should be clear enough. +XThose exceptions with a {\tt *} in the third column have an argument. +X +XException handlers don't just handle exceptions if they occur +Ximmediately in the try clause, but also if they occur inside functions +Xthat are called (even indirectly) in the try clause. +XFor example: +X\bcode\begin{verbatim} +X>>> def this_fails(): +X... x = 1/0 +X... +X>>> try: +X... this_fails() +X... except RuntimeError, detail: +X... print 'Handling run-time error:', detail +X... +XHandling run-time error: domain error or zero division +X>>> +X\end{verbatim}\ecode +X +X\subsubsection{Raising Exceptions} +X +XThe {\tt raise} statement allows the programmer to force a specified +Xexception to occur. +XFor example: +X\bcode\begin{verbatim} +X>>> raise NameError, 'Hi There!' +XUnhandled exception: undefined name: Hi There! +XStack backtrace (innermost last): +X File "", line 1 +X>>> +X\end{verbatim}\ecode +XThe first argument to {\tt raise} names the exception to be raised. +XThe optional second argument specifies the exception's argument. +X +X\subsubsection{User-defined Exceptions} +X +XPrograms may name their own exceptions by assigning a string to a +Xvariable. +XFor example: +X\bcode\begin{verbatim} +X>>> my_exc = 'nobody likes me!' +X>>> try: +X... raise my_exc, 2*2 +X... except my_exc, val: +X... print 'My exception occured, value:', val +X... +XMy exception occured, value: 4 +X>>> raise my_exc, 1 +XUnhandled exception: nobody likes me!: 1 +XStack backtrace (innermost last): +X File "", line 7 +X>>> +X\end{verbatim}\ecode +XMany standard modules use this to report errors that may occur in +Xfunctions they define. +X +X\subsubsection{Defining Clean-up Actions} +X +XThe {\tt try} statement has another optional clause which is intended to +Xdefine clean-up actions that must be executed under all circumstances. +XFor example: +X\bcode\begin{verbatim} +X>>> try: +X... raise KeyboardInterrupt +X... finally: +X... print 'Goodbye, world!' +X... +XGoodbye, world! +XUnhandled exception: keyboard interrupt +XStack backtrace (innermost last): +X File "", line 2 +X>>> +X\end{verbatim}\ecode +XThe +X{\em finally\ clause} +Xmust follow the except clauses(s), if any. +XIt is executed whether or not an exception occurred. +XIf the exception is handled, the finally clause is executed after the +Xhandler (and even if another exception occurred in the handler). +XIt is also executed when the {\tt try} statement is left via a +X{\tt break} or {\tt return} statement. +X +X\subsection{Classes} +X +XClasses in \Python\ make it possible to play the game of encapsulation in a +Xsomewhat different way than it is played with modules. +XClasses are an advanced topic and are probably best skipped on the first +Xencounter with \Python. +X +X\subsubsection{Prologue} +X +X\Python's class mechanism is not particularly elegant, but quite powerful. +XIt is a mixture of the class mechanisms found in C++ and Modula-3. +XAs is true for modules, classes in \Python\ do not put an absolute barrier +Xbetween definition and user, but rather rely on the politeness of the +Xuser not to ``break into the definition.'' +XThe most important features of classes are retained with full power, +Xhowever: the class inheritance mechanism allows multiple base classes, +Xa derived class can override any method of its base class(es), a method +Xcan call the method of a base class with the same name. +XObjects can contain an arbitrary amount of private data. +X +XIn C++ terminology, all class members (including data members) are +X{\em public}, +Xand all member functions (methods) are +X{\em virtual}. +XThere are no special constructors or destructors. +XAs in Modula-3, there are no shorthands for referencing the object's +Xmembers from its methods: the method function is declared with an +Xexplicit first argument representing the object, which is provided +Ximplicitly by the call. +XAs in Smalltalk, classes themselves are objects, albeit in the wider +Xsense of the word: in \Python, all data types are objects. +XThis provides semantics for renaming or aliasing. +XBut, just like in C++ or Modula-3, the built-in types cannot be used as +Xbase classes for extension by the user. +XAlso, like Modula-3 but unlike C++, the built-in operators with special +Xsyntax (arithmetic operators, subscripting etc.) cannot be redefined for +Xclass members.% +X\footnote{ +X They can be redefined for new object types implemented in C in +X extensions to the interpreter, however. It would require only a +X naming convention and a relatively small change to the +X interpreter to allow operator overloading for classes, so +X perhaps someday... +X} +X +X\subsubsection{A Simple Example} +X +XConsider the following example, which defines a class {\tt Set} +Xrepresenting a (finite) mathematical set with operations to add and +Xremove elements, a membership test, and a request for the size of the +Xset. +X\bcode\begin{verbatim} +Xclass Set(): +X def new(self): +X self.elements = [] +X return self +X def add(self, e): +X if e not in self.elements: +X self.elements.append(e) +X def remove(self, e): +X if e in self.elements: +X for i in range(len(self.elements)): +X if self.elements[i] = e: +X del self.elements[i] +X break +X def is_element(self, e): +X return e in self.elements +X def size(self): +X return len(self.elements) +X\end{verbatim}\ecode +XNote that the class definition looks like a big compound statement, +Xwith all the function definitons indented repective to the +X{\tt class} +Xkeyword. +X +XLet's assume that this +X{\em class\ definition} +Xis the only contents of the module file +X{\tt SetClass.py}. +XWe can then use it in a \Python\ program as follows: +X\bcode\begin{verbatim} +X>>> from SetClass import Set +X>>> a = Set().new() # create a Set object +X>>> a.add(2) +X>>> a.add(3) +X>>> a.add(1) +X>>> a.add(1) +X>>> if a.is_element(3): print '3 is in the set' +X... +X3 is in the set +X>>> if not a.is_element(4): print '4 is not in the set' +X... +X4 is not in the set +X>>> print 'a has', a.size(), 'elements' +Xa has 3 elements +X>>> a.remove(1) +X>>> print 'now a has', a.size(), 'elements' +X>>> +Xnow a has 2 elements +X>>> +X\end{verbatim}\ecode +XFrom the example we learn in the first place that the functions defined +Xin the class (e.g., +X{\tt add}) +Xcan be called using the +X{\em member} +Xnotation for the object +X{\tt a}. +XThe member function is called with one less argument than it is defined: +Xthe object is implicitly passed as the first argument. +XThus, the call +X{\tt a.add(2)} +Xis equivalent to +X{\tt Set.add(a, 2)}. +X +XXXX This section is not complete yet! +X +X\section{XXX P.M.} +X +X\begin{itemize} +X\item The {\tt del} statement. +X\item The {\tt dir()} function. +X\item Tuples. +X\item Dictionaries. +X\item Objects and types in general. +X\item Backquotes. +X\item And/Or/Not. +X\end{itemize} +X +X\end{document} +EOF +fi +echo 'Part 01 out of 21 of pack.out complete.' +exit 0 diff --git a/shar/python-0.9.1-01.patch b/shar/python-0.9.1-01.patch new file mode 100644 index 0000000..b27b7f6 --- /dev/null +++ b/shar/python-0.9.1-01.patch @@ -0,0 +1,163 @@ +Here is official patch #1 for Python. It fixes an embarrassing bug in +patchlevel.h, fixes the testall.py module to work non-interactively, and +adds some comments and a fix to the Makefile. +IMPORTANT NOTE: Use "patch -p + +*** /usr/people/guido/python-dist/src/Makefile Tue Feb 19 13:42:10 1991 +--- src/Makefile Wed Feb 20 13:37:32 1991 +*************** +*** 65,74 **** +# Installation Options +# ==================== + +! # You may want to change PYTHONPATH to reflect where you install the +! # Python module library. + +! PYTHONPATH= .:/usr/local/lib/python:/ufs/guido/lib/python + + +# For "Pure" BSD Systems +--- 65,76 ---- +# Installation Options +# ==================== + +! # You may want to change DEFPYTHONPATH to reflect where you install the +! # Python module library. The default contains "../lib" so running +! # the interpreter from the source/build directory as distributed will +! # find the library (admittedly a hack). + +! DEFPYTHONPATH= .:/usr/local/lib/python:/ufs/guido/lib/python:../lib + + +# For "Pure" BSD Systems +*************** +*** 248,257 **** +# about 70K to the Python text size and about 260K to the unstripped +# binary size. +# +! # Note: the file 'glmodule.c' is created by a Python script. If you +! # lost the file and have no working Python interpreter, turn off the GL +! # and Panel options, rebuild the Python interpreter, use it to create +! # glmodule.c, and then turn the options back on. +# +# Uncomment the following block to use the GL option. + +--- 250,265 ---- +# about 70K to the Python text size and about 260K to the unstripped +# binary size. +# +! # NOTE WHEN BUILDING FOR THE FIRST TIME: +! # There is a circular dependency in the build process: you need to have +! # a working Python interpreter before you can build a Python interpreter +! # that incorporates the 'gl' module -- the source file 'glmodule.c' is +! # not distributed (it's about 140K!) and a Python script is used to +! # create it. Thus, you first have to build python without the the GL +! # and Panel options, then edit the Makefile to turn them (or at least GL) +! # on and rebuild. You may also have to set PYTHONPATH to point to +! # the place where the module library is for the generation script to +! # work. +# +# Uncomment the following block to use the GL option. + +*************** +*** 270,276 **** +# the standard module 'panel' to provide an interface to most features +# of the Panel Library. This option requires that you also turn on the +# GL option. It adds about 100K to the Python text size and about 160K +! # to the unstripped binary size. +# +# Uncomment and edit the following block to use the Panel option. +# - Edit the PANELDIR definition to point to the top-level directory +--- 278,286 ---- +# the standard module 'panel' to provide an interface to most features +# of the Panel Library. This option requires that you also turn on the +# GL option. It adds about 100K to the Python text size and about 160K +! # to the unstripped binary size. This requires Panel Library version 9.7 +! # (for lower versions you may have to remove some functionality -- send +! # me the patches if you bothered to do this). +# +# Uncomment and edit the following block to use the Panel option. +# - Edit the PANELDIR definition to point to the top-level directory +*************** +*** 335,341 **** +tupleobject.c typeobject.c + +CONFIGDEFS= $(STDW_USE) $(AM_USE) $(AUDIO_USE) $(GL_USE) $(PANEL_USE) \ +! '-DPYTHONPATH="$(PYTHONPATH)"' + +CONFIGINCLS= $(STDW_INCL) + +--- 345,351 ---- +tupleobject.c typeobject.c + +CONFIGDEFS= $(STDW_USE) $(AM_USE) $(AUDIO_USE) $(GL_USE) $(PANEL_USE) \ +! '-DPYTHONPATH="$(DEFPYTHONPATH)"' + +CONFIGINCLS= $(STDW_INCL) + +*************** +*** 480,486 **** +# The rules for doing so are given here. + +# Build "glmodule.c", the GL interface. +! # Ignore the messages emitted by the cgen script. +# Also ignore the warnings emitted while compiling glmodule.c; it works. + +glmodule.c: cstubs cgen +--- 490,499 ---- +# The rules for doing so are given here. + +# Build "glmodule.c", the GL interface. +! # See important note at "GL Option" above. +! # You may have to set and export PYTHONPATH for this to work. +! # Ignore the messages emitted by the cgen script as long as its exit +! # status is zero. +# Also ignore the warnings emitted while compiling glmodule.c; it works. + +glmodule.c: cstubs cgen +*** /usr/people/guido/python-dist/src/patchlevel.h Tue Feb 19 13:44:44 1991 +--- src/patchlevel.h Wed Feb 20 12:57:39 1991 +*************** +*** 1 **** +! 1 +--- 1 ---- +! #define PATCHLEVEL 1 +*** /usr/people/guido/python-dist/lib/testall.py Wed Dec 26 15:40:20 1990 +--- lib/testall.py Wed Feb 20 12:59:22 1991 +*************** +*** 122,128 **** +[4] +from math import * +[5] +! from sys import modules, ps1, ps2 +[6] + +### compound_stmt: if_stmt | while_stmt | for_stmt | try_stmt | funcdef | classdef +--- 122,128 ---- +[4] +from math import * +[5] +! from sys import modules, path +[6] + +### compound_stmt: if_stmt | while_stmt | for_stmt | try_stmt | funcdef | classdef +*************** +*** 213,219 **** +x = +1 +x = -1 +x = 1 +! c = sys.ps1[0] +x = time.time() +x = sys.modules['time'].time() +a = '01234' +--- 213,219 ---- +x = +1 +x = -1 +x = 1 +! c = sys.path[0] +x = time.time() +x = sys.modules['time'].time() +a = '01234' \ No newline at end of file diff --git a/shar/python-0.9.1-03-21.shar b/shar/python-0.9.1-03-21.shar new file mode 100644 index 0000000..b2f6af5 --- /dev/null +++ b/shar/python-0.9.1-03-21.shar @@ -0,0 +1,2944 @@ +: 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 03 out of 21:' +if test -s 'src/compile.c' +then echo '*** I will not over-write existing file src/compile.c' +else +echo 'x - src/compile.c' +sed 's/^X//' > 'src/compile.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/* Compile an expression node to intermediate code */ +X +X/* XXX TO DO: +X XXX Compute maximum needed stack sizes while compiling +X XXX Generate simple jump for break/return outside 'try...finally' +X XXX Include function name in code (and module names?) +X*/ +X +X#include "allobjects.h" +X +X#include "node.h" +X#include "token.h" +X#include "graminit.h" +X#include "compile.h" +X#include "opcode.h" +X#include "structmember.h" +X +X#include +X +X#define OFF(x) offsetof(codeobject, x) +X +Xstatic struct memberlist code_memberlist[] = { +X {"co_code", T_OBJECT, OFF(co_code)}, +X {"co_consts", T_OBJECT, OFF(co_consts)}, +X {"co_names", T_OBJECT, OFF(co_names)}, +X {"co_filename", T_OBJECT, OFF(co_filename)}, +X {NULL} /* Sentinel */ +X}; +X +Xstatic object * +Xcode_getattr(co, name) +X codeobject *co; +X char *name; +X{ +X return getmember((char *)co, code_memberlist, name); +X} +X +Xstatic void +Xcode_dealloc(co) +X codeobject *co; +X{ +X XDECREF(co->co_code); +X XDECREF(co->co_consts); +X XDECREF(co->co_names); +X XDECREF(co->co_filename); +X DEL(co); +X} +X +Xtypeobject Codetype = { +X OB_HEAD_INIT(&Typetype) +X 0, +X "code", +X sizeof(codeobject), +X 0, +X code_dealloc, /*tp_dealloc*/ +X 0, /*tp_print*/ +X code_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 +Xstatic codeobject *newcodeobject PROTO((object *, object *, object *, char *)); +X +Xstatic codeobject * +Xnewcodeobject(code, consts, names, filename) +X object *code; +X object *consts; +X object *names; +X char *filename; +X{ +X codeobject *co; +X int i; +X /* Check argument types */ +X if (code == NULL || !is_stringobject(code) || +X consts == NULL || !is_listobject(consts) || +X names == NULL || !is_listobject(names)) { +X err_badcall(); +X return NULL; +X } +X /* Make sure the list of names contains only strings */ +X for (i = getlistsize(names); --i >= 0; ) { +X object *v = getlistitem(names, i); +X if (v == NULL || !is_stringobject(v)) { +X err_badcall(); +X return NULL; +X } +X } +X co = NEWOBJ(codeobject, &Codetype); +X if (co != NULL) { +X INCREF(code); +X co->co_code = (stringobject *)code; +X INCREF(consts); +X co->co_consts = consts; +X INCREF(names); +X co->co_names = names; +X if ((co->co_filename = newstringobject(filename)) == NULL) { +X DECREF(co); +X co = NULL; +X } +X } +X return co; +X} +X +X +X/* Data structure used internally */ +Xstruct compiling { +X object *c_code; /* string */ +X object *c_consts; /* list of objects */ +X object *c_names; /* list of strings (names) */ +X int c_nexti; /* index into c_code */ +X int c_errors; /* counts errors occurred */ +X int c_infunction; /* set when compiling a function */ +X int c_loops; /* counts nested loops */ +X char *c_filename; /* filename of current node */ +X}; +X +X/* Prototypes */ +Xstatic int com_init PROTO((struct compiling *, char *)); +Xstatic void com_free PROTO((struct compiling *)); +Xstatic void com_done PROTO((struct compiling *)); +Xstatic void com_node PROTO((struct compiling *, struct _node *)); +Xstatic void com_addbyte PROTO((struct compiling *, int)); +Xstatic void com_addint PROTO((struct compiling *, int)); +Xstatic void com_addoparg PROTO((struct compiling *, int, int)); +Xstatic void com_addfwref PROTO((struct compiling *, int, int *)); +Xstatic void com_backpatch PROTO((struct compiling *, int)); +Xstatic int com_add PROTO((struct compiling *, object *, object *)); +Xstatic int com_addconst PROTO((struct compiling *, object *)); +Xstatic int com_addname PROTO((struct compiling *, object *)); +Xstatic void com_addopname PROTO((struct compiling *, int, node *)); +X +Xstatic int +Xcom_init(c, filename) +X struct compiling *c; +X char *filename; +X{ +X if ((c->c_code = newsizedstringobject((char *)NULL, 0)) == NULL) +X goto fail_3; +X if ((c->c_consts = newlistobject(0)) == NULL) +X goto fail_2; +X if ((c->c_names = newlistobject(0)) == NULL) +X goto fail_1; +X c->c_nexti = 0; +X c->c_errors = 0; +X c->c_infunction = 0; +X c->c_loops = 0; +X c->c_filename = filename; +X return 1; +X +X fail_1: +X DECREF(c->c_consts); +X fail_2: +X DECREF(c->c_code); +X fail_3: +X return 0; +X} +X +Xstatic void +Xcom_free(c) +X struct compiling *c; +X{ +X XDECREF(c->c_code); +X XDECREF(c->c_consts); +X XDECREF(c->c_names); +X} +X +Xstatic void +Xcom_done(c) +X struct compiling *c; +X{ +X if (c->c_code != NULL) +X resizestring(&c->c_code, c->c_nexti); +X} +X +Xstatic void +Xcom_addbyte(c, byte) +X struct compiling *c; +X int byte; +X{ +X int len; +X if (byte < 0 || byte > 255) { +X fprintf(stderr, "XXX compiling bad byte: %d\n", byte); +X abort(); +X err_setstr(SystemError, "com_addbyte: byte out of range"); +X c->c_errors++; +X } +X if (c->c_code == NULL) +X return; +X len = getstringsize(c->c_code); +X if (c->c_nexti >= len) { +X if (resizestring(&c->c_code, len+1000) != 0) { +X c->c_errors++; +X return; +X } +X } +X getstringvalue(c->c_code)[c->c_nexti++] = byte; +X} +X +Xstatic void +Xcom_addint(c, x) +X struct compiling *c; +X int x; +X{ +X com_addbyte(c, x & 0xff); +X com_addbyte(c, x >> 8); /* XXX x should be positive */ +X} +X +Xstatic void +Xcom_addoparg(c, op, arg) +X struct compiling *c; +X int op; +X int arg; +X{ +X com_addbyte(c, op); +X com_addint(c, arg); +X} +X +Xstatic void +Xcom_addfwref(c, op, p_anchor) +X struct compiling *c; +X int op; +X int *p_anchor; +X{ +X /* Compile a forward reference for backpatching */ +X int here; +X int anchor; +X com_addbyte(c, op); +X here = c->c_nexti; +X anchor = *p_anchor; +X *p_anchor = here; +X com_addint(c, anchor == 0 ? 0 : here - anchor); +X} +X +Xstatic void +Xcom_backpatch(c, anchor) +X struct compiling *c; +X int anchor; /* Must be nonzero */ +X{ +X unsigned char *code = (unsigned char *) getstringvalue(c->c_code); +X int target = c->c_nexti; +X int lastanchor = 0; +X int dist; +X int prev; +X for (;;) { +X /* Make the JUMP instruction at anchor point to target */ +X prev = code[anchor] + (code[anchor+1] << 8); +X dist = target - (anchor+2); +X code[anchor] = dist & 0xff; +X code[anchor+1] = dist >> 8; +X if (!prev) +X break; +X lastanchor = anchor; +X anchor -= prev; +X } +X} +X +X/* Handle constants and names uniformly */ +X +Xstatic int +Xcom_add(c, list, v) +X struct compiling *c; +X object *list; +X object *v; +X{ +X int n = getlistsize(list); +X int i; +X for (i = n; --i >= 0; ) { +X object *w = getlistitem(list, i); +X if (cmpobject(v, w) == 0) +X return i; +X } +X if (addlistitem(list, v) != 0) +X c->c_errors++; +X return n; +X} +X +Xstatic int +Xcom_addconst(c, v) +X struct compiling *c; +X object *v; +X{ +X return com_add(c, c->c_consts, v); +X} +X +Xstatic int +Xcom_addname(c, v) +X struct compiling *c; +X object *v; +X{ +X return com_add(c, c->c_names, v); +X} +X +Xstatic void +Xcom_addopname(c, op, n) +X struct compiling *c; +X int op; +X node *n; +X{ +X object *v; +X int i; +X char *name; +X if (TYPE(n) == STAR) +X name = "*"; +X else { +X REQ(n, NAME); +X name = STR(n); +X } +X if ((v = newstringobject(name)) == NULL) { +X c->c_errors++; +X i = 255; +X } +X else { +X i = com_addname(c, v); +X DECREF(v); +X } +X com_addoparg(c, op, i); +X} +X +Xstatic object * +Xparsenumber(s) +X char *s; +X{ +X extern long strtol(); +X extern double atof(); +X char *end = s; +X long x; +X x = strtol(s, &end, 0); +X if (*end == '\0') +X return newintobject(x); +X if (*end == '.' || *end == 'e' || *end == 'E') +X return newfloatobject(atof(s)); +X err_setstr(RuntimeError, "bad number syntax"); +X return NULL; +X} +X +Xstatic object * +Xparsestr(s) +X char *s; +X{ +X object *v; +X int len; +X char *buf; +X char *p; +X int c; +X if (*s != '\'') { +X err_badcall(); +X return NULL; +X } +X s++; +X len = strlen(s); +X if (s[--len] != '\'') { +X err_badcall(); +X return NULL; +X } +X if (strchr(s, '\\') == NULL) +X return newsizedstringobject(s, len); +X v = newsizedstringobject((char *)NULL, len); +X p = buf = getstringvalue(v); +X while (*s != '\0' && *s != '\'') { +X if (*s != '\\') { +X *p++ = *s++; +X continue; +X } +X s++; +X switch (*s++) { +X /* XXX This assumes ASCII! */ +X case '\\': *p++ = '\\'; break; +X case '\'': *p++ = '\''; break; +X case 'b': *p++ = '\b'; break; +X case 'f': *p++ = '\014'; break; /* FF */ +X case 't': *p++ = '\t'; break; +X case 'n': *p++ = '\n'; break; +X case 'r': *p++ = '\r'; break; +X case 'v': *p++ = '\013'; break; /* VT */ +X case 'E': *p++ = '\033'; break; /* ESC, not C */ +X case 'a': *p++ = '\007'; break; /* BEL, not classic C */ +X case '0': case '1': case '2': case '3': +X case '4': case '5': case '6': case '7': +X c = s[-1] - '0'; +X if ('0' <= *s && *s <= '7') { +X c = (c<<3) + *s++ - '0'; +X if ('0' <= *s && *s <= '7') +X c = (c<<3) + *s++ - '0'; +X } +X *p++ = c; +X break; +X case 'x': +X if (isxdigit(*s)) { +X sscanf(s, "%x", &c); +X *p++ = c; +X do { +X s++; +X } while (isxdigit(*s)); +X break; +X } +X /* FALLTHROUGH */ +X default: *p++ = '\\'; *p++ = s[-1]; break; +X } +X } +X resizestring(&v, (int)(p - buf)); +X return v; +X} +X +Xstatic void +Xcom_list_constructor(c, n) +X struct compiling *c; +X node *n; +X{ +X int len; +X int i; +X object *v, *w; +X if (TYPE(n) != testlist) +X REQ(n, exprlist); +X /* exprlist: expr (',' expr)* [',']; likewise for testlist */ +X len = (NCH(n) + 1) / 2; +X for (i = 0; i < NCH(n); i += 2) +X com_node(c, CHILD(n, i)); +X com_addoparg(c, BUILD_LIST, len); +X} +X +Xstatic void +Xcom_atom(c, n) +X struct compiling *c; +X node *n; +X{ +X node *ch; +X object *v; +X int i; +X REQ(n, atom); +X ch = CHILD(n, 0); +X switch (TYPE(ch)) { +X case LPAR: +X if (TYPE(CHILD(n, 1)) == RPAR) +X com_addoparg(c, BUILD_TUPLE, 0); +X else +X com_node(c, CHILD(n, 1)); +X break; +X case LSQB: +X if (TYPE(CHILD(n, 1)) == RSQB) +X com_addoparg(c, BUILD_LIST, 0); +X else +X com_list_constructor(c, CHILD(n, 1)); +X break; +X case LBRACE: +X com_addoparg(c, BUILD_MAP, 0); +X break; +X case BACKQUOTE: +X com_node(c, CHILD(n, 1)); +X com_addbyte(c, UNARY_CONVERT); +X break; +X case NUMBER: +X if ((v = parsenumber(STR(ch))) == NULL) { +X c->c_errors++; +X i = 255; +X } +X else { +X i = com_addconst(c, v); +X DECREF(v); +X } +X com_addoparg(c, LOAD_CONST, i); +X break; +X case STRING: +X if ((v = parsestr(STR(ch))) == NULL) { +X c->c_errors++; +X i = 255; +X } +X else { +X i = com_addconst(c, v); +X DECREF(v); +X } +X com_addoparg(c, LOAD_CONST, i); +X break; +X case NAME: +X com_addopname(c, LOAD_NAME, ch); +X break; +X default: +X fprintf(stderr, "node type %d\n", TYPE(ch)); +X err_setstr(SystemError, "com_atom: unexpected node type"); +X c->c_errors++; +X } +X} +X +Xstatic void +Xcom_slice(c, n, op) +X struct compiling *c; +X node *n; +X int op; +X{ +X if (NCH(n) == 1) { +X com_addbyte(c, op); +X } +X else if (NCH(n) == 2) { +X if (TYPE(CHILD(n, 0)) != COLON) { +X com_node(c, CHILD(n, 0)); +X com_addbyte(c, op+1); +X } +X else { +X com_node(c, CHILD(n, 1)); +X com_addbyte(c, op+2); +X } +X } +X else { +X com_node(c, CHILD(n, 0)); +X com_node(c, CHILD(n, 2)); +X com_addbyte(c, op+3); +X } +X} +X +Xstatic void +Xcom_apply_subscript(c, n) +X struct compiling *c; +X node *n; +X{ +X REQ(n, subscript); +X if (NCH(n) == 1 && TYPE(CHILD(n, 0)) != COLON) { +X /* It's a single subscript */ +X com_node(c, CHILD(n, 0)); +X com_addbyte(c, BINARY_SUBSCR); +X } +X else { +X /* It's a slice: [expr] ':' [expr] */ +X com_slice(c, n, SLICE); +X } +X} +X +Xstatic void +Xcom_call_function(c, n) +X struct compiling *c; +X node *n; /* EITHER testlist OR ')' */ +X{ +X if (TYPE(n) == RPAR) { +X com_addbyte(c, UNARY_CALL); +X } +X else { +X com_node(c, n); +X com_addbyte(c, BINARY_CALL); +X } +X} +X +Xstatic void +Xcom_select_member(c, n) +X struct compiling *c; +X node *n; +X{ +X com_addopname(c, LOAD_ATTR, n); +X} +X +Xstatic void +Xcom_apply_trailer(c, n) +X struct compiling *c; +X node *n; +X{ +X REQ(n, trailer); +X switch (TYPE(CHILD(n, 0))) { +X case LPAR: +X com_call_function(c, CHILD(n, 1)); +X break; +X case DOT: +X com_select_member(c, CHILD(n, 1)); +X break; +X case LSQB: +X com_apply_subscript(c, CHILD(n, 1)); +X break; +X default: +X err_setstr(SystemError, +X "com_apply_trailer: unknown trailer type"); +X c->c_errors++; +X } +X} +X +Xstatic void +Xcom_factor(c, n) +X struct compiling *c; +X node *n; +X{ +X int i; +X REQ(n, factor); +X if (TYPE(CHILD(n, 0)) == PLUS) { +X com_factor(c, CHILD(n, 1)); +X com_addbyte(c, UNARY_POSITIVE); +X } +X else if (TYPE(CHILD(n, 0)) == MINUS) { +X com_factor(c, CHILD(n, 1)); +X com_addbyte(c, UNARY_NEGATIVE); +X } +X else { +X com_atom(c, CHILD(n, 0)); +X for (i = 1; i < NCH(n); i++) +X com_apply_trailer(c, CHILD(n, i)); +X } +X} +X +Xstatic void +Xcom_term(c, n) +X struct compiling *c; +X node *n; +X{ +X int i; +X int op; +X REQ(n, term); +X com_factor(c, CHILD(n, 0)); +X for (i = 2; i < NCH(n); i += 2) { +X com_factor(c, CHILD(n, i)); +X switch (TYPE(CHILD(n, i-1))) { +X case STAR: +X op = BINARY_MULTIPLY; +X break; +X case SLASH: +X op = BINARY_DIVIDE; +X break; +X case PERCENT: +X op = BINARY_MODULO; +X break; +X default: +X err_setstr(SystemError, +X "com_term: term operator not *, / or %"); +X c->c_errors++; +X op = 255; +X } +X com_addbyte(c, op); +X } +X} +X +Xstatic void +Xcom_expr(c, n) +X struct compiling *c; +X node *n; +X{ +X int i; +X int op; +X REQ(n, expr); +X com_term(c, CHILD(n, 0)); +X for (i = 2; i < NCH(n); i += 2) { +X com_term(c, CHILD(n, i)); +X switch (TYPE(CHILD(n, i-1))) { +X case PLUS: +X op = BINARY_ADD; +X break; +X case MINUS: +X op = BINARY_SUBTRACT; +X break; +X default: +X err_setstr(SystemError, +X "com_expr: expr operator not + or -"); +X c->c_errors++; +X op = 255; +X } +X com_addbyte(c, op); +X } +X} +X +Xstatic enum cmp_op +Xcmp_type(n) +X node *n; +X{ +X REQ(n, comp_op); +X /* comp_op: '<' | '>' | '=' | '>' '=' | '<' '=' | '<' '>' +X | 'in' | 'not' 'in' | 'is' | 'is' not' */ +X if (NCH(n) == 1) { +X n = CHILD(n, 0); +X switch (TYPE(n)) { +X case LESS: return LT; +X case GREATER: return GT; +X case EQUAL: return EQ; +X case NAME: if (strcmp(STR(n), "in") == 0) return IN; +X if (strcmp(STR(n), "is") == 0) return IS; +X } +X } +X else if (NCH(n) == 2) { +X int t2 = TYPE(CHILD(n, 1)); +X switch (TYPE(CHILD(n, 0))) { +X case LESS: if (t2 == EQUAL) return LE; +X if (t2 == GREATER) return NE; +X break; +X case GREATER: if (t2 == EQUAL) return GE; +X break; +X case NAME: if (strcmp(STR(CHILD(n, 1)), "in") == 0) +X return NOT_IN; +X if (strcmp(STR(CHILD(n, 0)), "is") == 0) +X return IS_NOT; +X } +X } +X return BAD; +X} +X +Xstatic void +Xcom_comparison(c, n) +X struct compiling *c; +X node *n; +X{ +X int i; +X enum cmp_op op; +X int anchor; +X REQ(n, comparison); /* comparison: expr (comp_op expr)* */ +X com_expr(c, CHILD(n, 0)); +X if (NCH(n) == 1) +X return; +X +X /**************************************************************** +X The following code is generated for all but the last +X comparison in a chain: +X +X label: on stack: opcode: jump to: +X +X a +X a, b DUP_TOP +X a, b, b ROT_THREE +X b, a, b COMPARE_OP +X b, 0-or-1 JUMP_IF_FALSE L1 +X b, 1 POP_TOP +X b +X +X We are now ready to repeat this sequence for the next +X comparison in the chain. +X +X For the last we generate: +X +X b +X b, c COMPARE_OP +X 0-or-1 +X +X If there were any jumps to L1 (i.e., there was more than one +X comparison), we generate: +X +X 0-or-1 JUMP_FORWARD L2 +X L1: b, 0 ROT_TWO +X 0, b POP_TOP +X 0 +X L2: +X ****************************************************************/ +X +X anchor = 0; +X +X for (i = 2; i < NCH(n); i += 2) { +X com_expr(c, CHILD(n, i)); +X if (i+2 < NCH(n)) { +X com_addbyte(c, DUP_TOP); +X com_addbyte(c, ROT_THREE); +X } +X op = cmp_type(CHILD(n, i-1)); +X if (op == BAD) { +X err_setstr(SystemError, +X "com_comparison: unknown comparison op"); +X c->c_errors++; +X } +X com_addoparg(c, COMPARE_OP, op); +X if (i+2 < NCH(n)) { +X com_addfwref(c, JUMP_IF_FALSE, &anchor); +X com_addbyte(c, POP_TOP); +X } +X } +X +X if (anchor) { +X int anchor2 = 0; +X com_addfwref(c, JUMP_FORWARD, &anchor2); +X com_backpatch(c, anchor); +X com_addbyte(c, ROT_TWO); +X com_addbyte(c, POP_TOP); +X com_backpatch(c, anchor2); +X } +X} +X +Xstatic void +Xcom_not_test(c, n) +X struct compiling *c; +X node *n; +X{ +X REQ(n, not_test); /* 'not' not_test | comparison */ +X if (NCH(n) == 1) { +X com_comparison(c, CHILD(n, 0)); +X } +X else { +X com_not_test(c, CHILD(n, 1)); +X com_addbyte(c, UNARY_NOT); +X } +X} +X +Xstatic void +Xcom_and_test(c, n) +X struct compiling *c; +X node *n; +X{ +X int i; +X int anchor; +X REQ(n, and_test); /* not_test ('and' not_test)* */ +X anchor = 0; +X i = 0; +X for (;;) { +X com_not_test(c, CHILD(n, i)); +X if ((i += 2) >= NCH(n)) +X break; +X com_addfwref(c, JUMP_IF_FALSE, &anchor); +X com_addbyte(c, POP_TOP); +X } +X if (anchor) +X com_backpatch(c, anchor); +X} +X +Xstatic void +Xcom_test(c, n) +X struct compiling *c; +X node *n; +X{ +X int i; +X int anchor; +X REQ(n, test); /* and_test ('and' and_test)* */ +X anchor = 0; +X i = 0; +X for (;;) { +X com_and_test(c, CHILD(n, i)); +X if ((i += 2) >= NCH(n)) +X break; +X com_addfwref(c, JUMP_IF_TRUE, &anchor); +X com_addbyte(c, POP_TOP); +X } +X if (anchor) +X com_backpatch(c, anchor); +X} +X +Xstatic void +Xcom_list(c, n) +X struct compiling *c; +X node *n; +X{ +X /* exprlist: expr (',' expr)* [',']; likewise for testlist */ +X if (NCH(n) == 1) { +X com_node(c, CHILD(n, 0)); +X } +X else { +X int i; +X int len; +X len = (NCH(n) + 1) / 2; +X for (i = 0; i < NCH(n); i += 2) +X com_node(c, CHILD(n, i)); +X com_addoparg(c, BUILD_TUPLE, len); +X } +X} +X +X +X/* Begin of assignment compilation */ +X +Xstatic void com_assign_name PROTO((struct compiling *, node *, int)); +Xstatic void com_assign PROTO((struct compiling *, node *, int)); +X +Xstatic void +Xcom_assign_attr(c, n, assigning) +X struct compiling *c; +X node *n; +X int assigning; +X{ +X com_addopname(c, assigning ? STORE_ATTR : DELETE_ATTR, n); +X} +X +Xstatic void +Xcom_assign_slice(c, n, assigning) +X struct compiling *c; +X node *n; +X int assigning; +X{ +X com_slice(c, n, assigning ? STORE_SLICE : DELETE_SLICE); +X} +X +Xstatic void +Xcom_assign_subscript(c, n, assigning) +X struct compiling *c; +X node *n; +X int assigning; +X{ +X com_node(c, n); +X com_addbyte(c, assigning ? STORE_SUBSCR : DELETE_SUBSCR); +X} +X +Xstatic void +Xcom_assign_trailer(c, n, assigning) +X struct compiling *c; +X node *n; +X int assigning; +X{ +X char *name; +X REQ(n, trailer); +X switch (TYPE(CHILD(n, 0))) { +X case LPAR: /* '(' [exprlist] ')' */ +X err_setstr(TypeError, "can't assign to function call"); +X c->c_errors++; +X break; +X case DOT: /* '.' NAME */ +X com_assign_attr(c, CHILD(n, 1), assigning); +X break; +X case LSQB: /* '[' subscript ']' */ +X n = CHILD(n, 1); +X REQ(n, subscript); /* subscript: expr | [expr] ':' [expr] */ +X if (NCH(n) > 1 || TYPE(CHILD(n, 0)) == COLON) +X com_assign_slice(c, n, assigning); +X else +X com_assign_subscript(c, CHILD(n, 0), assigning); +X break; +X default: +X err_setstr(TypeError, "unknown trailer type"); +X c->c_errors++; +X } +X} +X +Xstatic void +Xcom_assign_tuple(c, n, assigning) +X struct compiling *c; +X node *n; +X int assigning; +X{ +X int i; +X if (TYPE(n) != testlist) +X REQ(n, exprlist); +X if (assigning) +X com_addoparg(c, UNPACK_TUPLE, (NCH(n)+1)/2); +X for (i = 0; i < NCH(n); i += 2) +X com_assign(c, CHILD(n, i), assigning); +X} +X +Xstatic void +Xcom_assign_list(c, n, assigning) +X struct compiling *c; +X node *n; +X int assigning; +X{ +X int i; +X if (assigning) +X com_addoparg(c, UNPACK_LIST, (NCH(n)+1)/2); +X for (i = 0; i < NCH(n); i += 2) +X com_assign(c, CHILD(n, i), assigning); +X} +X +Xstatic void +Xcom_assign_name(c, n, assigning) +X struct compiling *c; +X node *n; +X int assigning; +X{ +X REQ(n, NAME); +X com_addopname(c, assigning ? STORE_NAME : DELETE_NAME, n); +X} +X +Xstatic void +Xcom_assign(c, n, assigning) +X struct compiling *c; +X node *n; +X int assigning; +X{ +X /* Loop to avoid trivial recursion */ +X for (;;) { +X switch (TYPE(n)) { +X +X case exprlist: +X case testlist: +X if (NCH(n) > 1) { +X com_assign_tuple(c, n, assigning); +X return; +X } +X n = CHILD(n, 0); +X break; +X +X case test: +X case and_test: +X case not_test: +X if (NCH(n) > 1) { +X err_setstr(TypeError, +X "can't assign to operator"); +X c->c_errors++; +X return; +X } +X n = CHILD(n, 0); +X break; +X +X case comparison: +X if (NCH(n) > 1) { +X err_setstr(TypeError, +X "can't assign to operator"); +X c->c_errors++; +X return; +X } +X n = CHILD(n, 0); +X break; +X +X case expr: +X if (NCH(n) > 1) { +X err_setstr(TypeError, +X "can't assign to operator"); +X c->c_errors++; +X return; +X } +X n = CHILD(n, 0); +X break; +X +X case term: +X if (NCH(n) > 1) { +X err_setstr(TypeError, +X "can't assign to operator"); +X c->c_errors++; +X return; +X } +X n = CHILD(n, 0); +X break; +X +X case factor: /* ('+'|'-') factor | atom trailer* */ +X if (TYPE(CHILD(n, 0)) != atom) { /* '+' | '-' */ +X err_setstr(TypeError, +X "can't assign to operator"); +X c->c_errors++; +X return; +X } +X if (NCH(n) > 1) { /* trailer present */ +X int i; +X com_node(c, CHILD(n, 0)); +X for (i = 1; i+1 < NCH(n); i++) { +X com_apply_trailer(c, CHILD(n, i)); +X } /* NB i is still alive */ +X com_assign_trailer(c, +X CHILD(n, i), assigning); +X return; +X } +X n = CHILD(n, 0); +X break; +X +X case atom: +X switch (TYPE(CHILD(n, 0))) { +X case LPAR: +X n = CHILD(n, 1); +X if (TYPE(n) == RPAR) { +X /* XXX Should allow () = () ??? */ +X err_setstr(TypeError, +X "can't assign to ()"); +X c->c_errors++; +X return; +X } +X break; +X case LSQB: +X n = CHILD(n, 1); +X if (TYPE(n) == RSQB) { +X err_setstr(TypeError, +X "can't assign to []"); +X c->c_errors++; +X return; +X } +X com_assign_list(c, n, assigning); +X return; +X case NAME: +X com_assign_name(c, CHILD(n, 0), assigning); +X return; +X default: +X err_setstr(TypeError, +X "can't assign to constant"); +X c->c_errors++; +X return; +X } +X break; +X +X default: +X fprintf(stderr, "node type %d\n", TYPE(n)); +X err_setstr(SystemError, "com_assign: bad node"); +X c->c_errors++; +X return; +X +X } +X } +X} +X +Xstatic void +Xcom_expr_stmt(c, n) +X struct compiling *c; +X node *n; +X{ +X REQ(n, expr_stmt); /* exprlist ('=' exprlist)* NEWLINE */ +X com_node(c, CHILD(n, NCH(n)-2)); +X if (NCH(n) == 2) { +X com_addbyte(c, PRINT_EXPR); +X } +X else { +X int i; +X for (i = 0; i < NCH(n)-3; i+=2) { +X if (i+2 < NCH(n)-3) +X com_addbyte(c, DUP_TOP); +X com_assign(c, CHILD(n, i), 1/*assign*/); +X } +X } +X} +X +Xstatic void +Xcom_print_stmt(c, n) +X struct compiling *c; +X node *n; +X{ +X int i; +X REQ(n, print_stmt); /* 'print' (test ',')* [test] NEWLINE */ +X for (i = 1; i+1 < NCH(n); i += 2) { +X com_node(c, CHILD(n, i)); +X com_addbyte(c, PRINT_ITEM); +X } +X if (TYPE(CHILD(n, NCH(n)-2)) != COMMA) +X com_addbyte(c, PRINT_NEWLINE); +X /* XXX Alternatively, LOAD_CONST '\n' and then PRINT_ITEM */ +X} +X +Xstatic void +Xcom_return_stmt(c, n) +X struct compiling *c; +X node *n; +X{ +X REQ(n, return_stmt); /* 'return' [testlist] NEWLINE */ +X if (!c->c_infunction) { +X err_setstr(TypeError, "'return' outside function"); +X c->c_errors++; +X } +X if (NCH(n) == 2) +X com_addoparg(c, LOAD_CONST, com_addconst(c, None)); +X else +X com_node(c, CHILD(n, 1)); +X com_addbyte(c, RETURN_VALUE); +X} +X +Xstatic void +Xcom_raise_stmt(c, n) +X struct compiling *c; +X node *n; +X{ +X REQ(n, raise_stmt); /* 'raise' expr [',' expr] NEWLINE */ +X com_node(c, CHILD(n, 1)); +X if (NCH(n) > 3) +X com_node(c, CHILD(n, 3)); +X else +X com_addoparg(c, LOAD_CONST, com_addconst(c, None)); +X com_addbyte(c, RAISE_EXCEPTION); +X} +X +Xstatic void +Xcom_import_stmt(c, n) +X struct compiling *c; +X node *n; +X{ +X int i; +X REQ(n, import_stmt); +X /* 'import' NAME (',' NAME)* NEWLINE | +X 'from' NAME 'import' ('*' | NAME (',' NAME)*) NEWLINE */ +X if (STR(CHILD(n, 0))[0] == 'f') { +X /* 'from' NAME 'import' ... */ +X REQ(CHILD(n, 1), NAME); +X com_addopname(c, IMPORT_NAME, CHILD(n, 1)); +X for (i = 3; i < NCH(n); i += 2) +X com_addopname(c, IMPORT_FROM, CHILD(n, i)); +X com_addbyte(c, POP_TOP); +X } +X else { +X /* 'import' ... */ +X for (i = 1; i < NCH(n); i += 2) { +X com_addopname(c, IMPORT_NAME, CHILD(n, i)); +X com_addopname(c, STORE_NAME, CHILD(n, i)); +X } +X } +X} +X +Xstatic void +Xcom_if_stmt(c, n) +X struct compiling *c; +X node *n; +X{ +X int i; +X int anchor = 0; +X REQ(n, if_stmt); +X /*'if' test ':' suite ('elif' test ':' suite)* ['else' ':' suite] */ +X for (i = 0; i+3 < NCH(n); i+=4) { +X int a = 0; +X node *ch = CHILD(n, i+1); +X if (i > 0) +X com_addoparg(c, SET_LINENO, ch->n_lineno); +X com_node(c, CHILD(n, i+1)); +X com_addfwref(c, JUMP_IF_FALSE, &a); +X com_addbyte(c, POP_TOP); +X com_node(c, CHILD(n, i+3)); +X com_addfwref(c, JUMP_FORWARD, &anchor); +X com_backpatch(c, a); +X com_addbyte(c, POP_TOP); +X } +X if (i+2 < NCH(n)) +X com_node(c, CHILD(n, i+2)); +X com_backpatch(c, anchor); +X} +X +Xstatic void +Xcom_while_stmt(c, n) +X struct compiling *c; +X node *n; +X{ +X int break_anchor = 0; +X int anchor = 0; +X int begin; +X REQ(n, while_stmt); /* 'while' test ':' suite ['else' ':' suite] */ +X com_addfwref(c, SETUP_LOOP, &break_anchor); +X begin = c->c_nexti; +X com_addoparg(c, SET_LINENO, n->n_lineno); +X com_node(c, CHILD(n, 1)); +X com_addfwref(c, JUMP_IF_FALSE, &anchor); +X com_addbyte(c, POP_TOP); +X c->c_loops++; +X com_node(c, CHILD(n, 3)); +X c->c_loops--; +X com_addoparg(c, JUMP_ABSOLUTE, begin); +X com_backpatch(c, anchor); +X com_addbyte(c, POP_TOP); +X com_addbyte(c, POP_BLOCK); +X if (NCH(n) > 4) +X com_node(c, CHILD(n, 6)); +X com_backpatch(c, break_anchor); +X} +X +Xstatic void +Xcom_for_stmt(c, n) +X struct compiling *c; +X node *n; +X{ +X object *v; +X int break_anchor = 0; +X int anchor = 0; +X int begin; +X REQ(n, for_stmt); +X /* 'for' exprlist 'in' exprlist ':' suite ['else' ':' suite] */ +X com_addfwref(c, SETUP_LOOP, &break_anchor); +X com_node(c, CHILD(n, 3)); +X v = newintobject(0L); +X if (v == NULL) +X c->c_errors++; +X com_addoparg(c, LOAD_CONST, com_addconst(c, v)); +X XDECREF(v); +X begin = c->c_nexti; +X com_addoparg(c, SET_LINENO, n->n_lineno); +X com_addfwref(c, FOR_LOOP, &anchor); +X com_assign(c, CHILD(n, 1), 1/*assigning*/); +X c->c_loops++; +X com_node(c, CHILD(n, 5)); +X c->c_loops--; +X com_addoparg(c, JUMP_ABSOLUTE, begin); +X com_backpatch(c, anchor); +X com_addbyte(c, POP_BLOCK); +X if (NCH(n) > 8) +X com_node(c, CHILD(n, 8)); +X com_backpatch(c, break_anchor); +X} +X +X/* Although 'execpt' and 'finally' clauses can be combined +X syntactically, they are compiled separately. In fact, +X try: S +X except E1: S1 +X except E2: S2 +X ... +X finally: Sf +X is equivalent to +X try: +X try: S +X except E1: S1 +X except E2: S2 +X ... +X finally: Sf +X meaning that the 'finally' clause is entered even if things +X go wrong again in an exception handler. Note that this is +X not the case for exception handlers: at most one is entered. +X +X Code generated for "try: S finally: Sf" is as follows: +X +X SETUP_FINALLY L +X +X POP_BLOCK +X LOAD_CONST +X L: +X END_FINALLY +X +X The special instructions use the block stack. Each block +X stack entry contains the instruction that created it (here +X SETUP_FINALLY), the level of the value stack at the time the +X block stack entry was created, and a label (here L). +X +X SETUP_FINALLY: +X Pushes the current value stack level and the label +X onto the block stack. +X POP_BLOCK: +X Pops en entry from the block stack, and pops the value +X stack until its level is the same as indicated on the +X block stack. (The label is ignored.) +X END_FINALLY: +X Pops a variable number of entries from the *value* stack +X and re-raises the exception they specify. The number of +X entries popped depends on the (pseudo) exception type. +X +X The block stack is unwound when an exception is raised: +X when a SETUP_FINALLY entry is found, the exception is pushed +X onto the value stack (and the exception condition is cleared), +X and the interpreter jumps to the label gotten from the block +X stack. +X +X Code generated for "try: S except E1, V1: S1 except E2, V2: S2 ...": +X (The contents of the value stack is shown in [], with the top +X at the right; 'tb' is trace-back info, 'val' the exception's +X associated value, and 'exc' the exception.) +X +X Value stack Label Instruction Argument +X [] SETUP_EXCEPT L1 +X [] +X [] POP_BLOCK +X [] JUMP_FORWARD L0 +X +X [tb, val, exc] L1: DUP ) +X [tb, val, exc, exc] ) +X [tb, val, exc, exc, E1] COMPARE_OP EXC_MATCH ) only if E1 +X [tb, val, exc, 1-or-0] JUMP_IF_FALSE L2 ) +X [tb, val, exc, 1] POP ) +X [tb, val, exc] POP +X [tb, val] (or POP if no V1) +X [tb] POP +X [] +X JUMP_FORWARD L0 +X +X [tb, val, exc, 0] L2: POP +X [tb, val, exc] DUP +X .............................etc....................... +X +X [tb, val, exc, 0] Ln+1: POP +X [tb, val, exc] END_FINALLY # re-raise exception +X +X [] L0: +X +X Of course, parts are not generated if Vi or Ei is not present. +X*/ +X +Xstatic void +Xcom_try_stmt(c, n) +X struct compiling *c; +X node *n; +X{ +X int finally_anchor = 0; +X int except_anchor = 0; +X REQ(n, try_stmt); +X /* 'try' ':' suite (except_clause ':' suite)* ['finally' ':' suite] */ +X +X if (NCH(n) > 3 && TYPE(CHILD(n, NCH(n)-3)) != except_clause) { +X /* Have a 'finally' clause */ +X com_addfwref(c, SETUP_FINALLY, &finally_anchor); +X } +X if (NCH(n) > 3 && TYPE(CHILD(n, 3)) == except_clause) { +X /* Have an 'except' clause */ +X com_addfwref(c, SETUP_EXCEPT, &except_anchor); +X } +X com_node(c, CHILD(n, 2)); +X if (except_anchor) { +X int end_anchor = 0; +X int i; +X node *ch; +X com_addbyte(c, POP_BLOCK); +X com_addfwref(c, JUMP_FORWARD, &end_anchor); +X com_backpatch(c, except_anchor); +X for (i = 3; +X i < NCH(n) && TYPE(ch = CHILD(n, i)) == except_clause; +X i += 3) { +X /* except_clause: 'except' [expr [',' expr]] */ +X if (except_anchor == 0) { +X err_setstr(TypeError, +X "default 'except:' must be last"); +X c->c_errors++; +X break; +X } +X except_anchor = 0; +X com_addoparg(c, SET_LINENO, ch->n_lineno); +X if (NCH(ch) > 1) { +X com_addbyte(c, DUP_TOP); +X com_node(c, CHILD(ch, 1)); +X com_addoparg(c, COMPARE_OP, EXC_MATCH); +X com_addfwref(c, JUMP_IF_FALSE, &except_anchor); +X com_addbyte(c, POP_TOP); +X } +X com_addbyte(c, POP_TOP); +X if (NCH(ch) > 3) +X com_assign(c, CHILD(ch, 3), 1/*assigning*/); +X else +X com_addbyte(c, POP_TOP); +X com_addbyte(c, POP_TOP); +X com_node(c, CHILD(n, i+2)); +X com_addfwref(c, JUMP_FORWARD, &end_anchor); +X if (except_anchor) { +X com_backpatch(c, except_anchor); +X com_addbyte(c, POP_TOP); +X } +X } +X com_addbyte(c, END_FINALLY); +X com_backpatch(c, end_anchor); +X } +X if (finally_anchor) { +X node *ch; +X com_addbyte(c, POP_BLOCK); +X com_addoparg(c, LOAD_CONST, com_addconst(c, None)); +X com_backpatch(c, finally_anchor); +X ch = CHILD(n, NCH(n)-1); +X com_addoparg(c, SET_LINENO, ch->n_lineno); +X com_node(c, ch); +X com_addbyte(c, END_FINALLY); +X } +X} +X +Xstatic void +Xcom_suite(c, n) +X struct compiling *c; +X node *n; +X{ +X REQ(n, suite); +X /* simple_stmt | NEWLINE INDENT NEWLINE* (stmt NEWLINE*)+ DEDENT */ +X if (NCH(n) == 1) { +X com_node(c, CHILD(n, 0)); +X } +X else { +X int i; +X for (i = 0; i < NCH(n); i++) { +X node *ch = CHILD(n, i); +X if (TYPE(ch) == stmt) +X com_node(c, ch); +X } +X } +X} +X +Xstatic void +Xcom_funcdef(c, n) +X struct compiling *c; +X node *n; +X{ +X object *v; +X REQ(n, funcdef); /* funcdef: 'def' NAME parameters ':' suite */ +X v = (object *)compile(n, c->c_filename); +X if (v == NULL) +X c->c_errors++; +X else { +X int i = com_addconst(c, v); +X com_addoparg(c, LOAD_CONST, i); +X com_addbyte(c, BUILD_FUNCTION); +X com_addopname(c, STORE_NAME, CHILD(n, 1)); +X DECREF(v); +X } +X} +X +Xstatic void +Xcom_bases(c, n) +X struct compiling *c; +X node *n; +X{ +X int i, nbases; +X REQ(n, baselist); +X /* +X baselist: atom arguments (',' atom arguments)* +X arguments: '(' [testlist] ')' +X */ +X for (i = 0; i < NCH(n); i += 3) +X com_node(c, CHILD(n, i)); +X com_addoparg(c, BUILD_TUPLE, (NCH(n)+1) / 3); +X} +X +Xstatic void +Xcom_classdef(c, n) +X struct compiling *c; +X node *n; +X{ +X object *v; +X REQ(n, classdef); +X /* +X classdef: 'class' NAME parameters ['=' baselist] ':' suite +X baselist: atom arguments (',' atom arguments)* +X arguments: '(' [testlist] ')' +X */ +X if (NCH(n) == 7) +X com_bases(c, CHILD(n, 4)); +X else +X com_addoparg(c, LOAD_CONST, com_addconst(c, None)); +X v = (object *)compile(n, c->c_filename); +X if (v == NULL) +X c->c_errors++; +X else { +X int i = com_addconst(c, v); +X com_addoparg(c, LOAD_CONST, i); +X com_addbyte(c, BUILD_FUNCTION); +X com_addbyte(c, UNARY_CALL); +X com_addbyte(c, BUILD_CLASS); +X com_addopname(c, STORE_NAME, CHILD(n, 1)); +X DECREF(v); +X } +X} +X +Xstatic void +Xcom_node(c, n) +X struct compiling *c; +X node *n; +X{ +X switch (TYPE(n)) { +X +X /* Definition nodes */ +X +X case funcdef: +X com_funcdef(c, n); +X break; +X case classdef: +X com_classdef(c, n); +X break; +X +X /* Trivial parse tree nodes */ +X +X case stmt: +X case flow_stmt: +X com_node(c, CHILD(n, 0)); +X break; +X +X case simple_stmt: +X case compound_stmt: +X com_addoparg(c, SET_LINENO, n->n_lineno); +X com_node(c, CHILD(n, 0)); +X break; +X +X /* Statement nodes */ +X +X case expr_stmt: +X com_expr_stmt(c, n); +X break; +X case print_stmt: +X com_print_stmt(c, n); +X break; +X case del_stmt: /* 'del' exprlist NEWLINE */ +X com_assign(c, CHILD(n, 1), 0/*delete*/); +X break; +X case pass_stmt: +X break; +X case break_stmt: +X if (c->c_loops == 0) { +X err_setstr(TypeError, "'break' outside loop"); +X c->c_errors++; +X } +X com_addbyte(c, BREAK_LOOP); +X break; +X case return_stmt: +X com_return_stmt(c, n); +X break; +X case raise_stmt: +X com_raise_stmt(c, n); +X break; +X case import_stmt: +X com_import_stmt(c, n); +X break; +X case if_stmt: +X com_if_stmt(c, n); +X break; +X case while_stmt: +X com_while_stmt(c, n); +X break; +X case for_stmt: +X com_for_stmt(c, n); +X break; +X case try_stmt: +X com_try_stmt(c, n); +X break; +X case suite: +X com_suite(c, n); +X break; +X +X /* Expression nodes */ +X +X case testlist: +X com_list(c, n); +X break; +X case test: +X com_test(c, n); +X break; +X case and_test: +X com_and_test(c, n); +X break; +X case not_test: +X com_not_test(c, n); +X break; +X case comparison: +X com_comparison(c, n); +X break; +X case exprlist: +X com_list(c, n); +X break; +X case expr: +X com_expr(c, n); +X break; +X case term: +X com_term(c, n); +X break; +X case factor: +X com_factor(c, n); +X break; +X case atom: +X com_atom(c, n); +X break; +X +X default: +X fprintf(stderr, "node type %d\n", TYPE(n)); +X err_setstr(SystemError, "com_node: unexpected node type"); +X c->c_errors++; +X } +X} +X +Xstatic void com_fplist PROTO((struct compiling *, node *)); +X +Xstatic void +Xcom_fpdef(c, n) +X struct compiling *c; +X node *n; +X{ +X REQ(n, fpdef); /* fpdef: NAME | '(' fplist ')' */ +X if (TYPE(CHILD(n, 0)) == LPAR) +X com_fplist(c, CHILD(n, 1)); +X else +X com_addopname(c, STORE_NAME, CHILD(n, 0)); +X} +X +Xstatic void +Xcom_fplist(c, n) +X struct compiling *c; +X node *n; +X{ +X REQ(n, fplist); /* fplist: fpdef (',' fpdef)* */ +X if (NCH(n) == 1) { +X com_fpdef(c, CHILD(n, 0)); +X } +X else { +X int i; +X com_addoparg(c, UNPACK_TUPLE, (NCH(n)+1)/2); +X for (i = 0; i < NCH(n); i += 2) +X com_fpdef(c, CHILD(n, i)); +X } +X} +X +Xstatic void +Xcom_file_input(c, n) +X struct compiling *c; +X node *n; +X{ +X int i; +X REQ(n, file_input); /* (NEWLINE | stmt)* ENDMARKER */ +X for (i = 0; i < NCH(n); i++) { +X node *ch = CHILD(n, i); +X if (TYPE(ch) != ENDMARKER && TYPE(ch) != NEWLINE) +X com_node(c, ch); +X } +X} +X +X/* Top-level compile-node interface */ +X +Xstatic void +Xcompile_funcdef(c, n) +X struct compiling *c; +X node *n; +X{ +X node *ch; +X REQ(n, funcdef); /* funcdef: 'def' NAME parameters ':' suite */ +X ch = CHILD(n, 2); /* parameters: '(' [fplist] ')' */ +X ch = CHILD(ch, 1); /* ')' | fplist */ +X if (TYPE(ch) == RPAR) +X com_addbyte(c, REFUSE_ARGS); +X else { +X com_addbyte(c, REQUIRE_ARGS); +X com_fplist(c, ch); +X } +X c->c_infunction = 1; +X com_node(c, CHILD(n, 4)); +X c->c_infunction = 0; +X com_addoparg(c, LOAD_CONST, com_addconst(c, None)); +X com_addbyte(c, RETURN_VALUE); +X} +X +Xstatic void +Xcompile_node(c, n) +X struct compiling *c; +X node *n; +X{ +X com_addoparg(c, SET_LINENO, n->n_lineno); +X +X switch (TYPE(n)) { +X +X case single_input: /* One interactive command */ +X /* NEWLINE | simple_stmt | compound_stmt NEWLINE */ +X com_addbyte(c, REFUSE_ARGS); +X n = CHILD(n, 0); +X if (TYPE(n) != NEWLINE) +X com_node(c, n); +X com_addoparg(c, LOAD_CONST, com_addconst(c, None)); +X com_addbyte(c, RETURN_VALUE); +X break; +X +X case file_input: /* A whole file, or built-in function exec() */ +X com_addbyte(c, REFUSE_ARGS); +X com_file_input(c, n); +X com_addoparg(c, LOAD_CONST, com_addconst(c, None)); +X com_addbyte(c, RETURN_VALUE); +X break; +X +X case expr_input: /* Built-in function eval() */ +X com_addbyte(c, REFUSE_ARGS); +X com_node(c, CHILD(n, 0)); +X com_addbyte(c, RETURN_VALUE); +X break; +X +X case eval_input: /* Built-in function input() */ +X com_addbyte(c, REFUSE_ARGS); +X com_node(c, CHILD(n, 0)); +X com_addbyte(c, RETURN_VALUE); +X break; +X +X case funcdef: /* A function definition */ +X compile_funcdef(c, n); +X break; +X +X case classdef: /* A class definition */ +X /* 'class' NAME parameters ['=' baselist] ':' suite */ +X com_addbyte(c, REFUSE_ARGS); +X com_node(c, CHILD(n, NCH(n)-1)); +X com_addbyte(c, LOAD_LOCALS); +X com_addbyte(c, RETURN_VALUE); +X break; +X +X default: +X fprintf(stderr, "node type %d\n", TYPE(n)); +X err_setstr(SystemError, "compile_node: unexpected node type"); +X c->c_errors++; +X } +X} +X +Xcodeobject * +Xcompile(n, filename) +X node *n; +X char *filename; +X{ +X struct compiling sc; +X codeobject *co; +X if (!com_init(&sc, filename)) +X return NULL; +X compile_node(&sc, n); +X com_done(&sc); +X if (sc.c_errors == 0) +X co = newcodeobject(sc.c_code, sc.c_consts, sc.c_names, filename); +X else +X co = NULL; +X com_free(&sc); +X return co; +X} +EOF +fi +if test -s 'src/graminit.c' +then echo '*** I will not over-write existing file src/graminit.c' +else +echo 'x - src/graminit.c' +sed 's/^X//' > 'src/graminit.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#include "pgenheaders.h" +X#include "grammar.h" +Xstatic arc arcs_0_0[3] = { +X {2, 1}, +X {3, 1}, +X {4, 2}, +X}; +Xstatic arc arcs_0_1[1] = { +X {0, 1}, +X}; +Xstatic arc arcs_0_2[1] = { +X {2, 1}, +X}; +Xstatic state states_0[3] = { +X {3, arcs_0_0}, +X {1, arcs_0_1}, +X {1, arcs_0_2}, +X}; +Xstatic arc arcs_1_0[3] = { +X {2, 0}, +X {6, 0}, +X {7, 1}, +X}; +Xstatic arc arcs_1_1[1] = { +X {0, 1}, +X}; +Xstatic state states_1[2] = { +X {3, arcs_1_0}, +X {1, arcs_1_1}, +X}; +Xstatic arc arcs_2_0[1] = { +X {9, 1}, +X}; +Xstatic arc arcs_2_1[1] = { +X {2, 2}, +X}; +Xstatic arc arcs_2_2[1] = { +X {0, 2}, +X}; +Xstatic state states_2[3] = { +X {1, arcs_2_0}, +X {1, arcs_2_1}, +X {1, arcs_2_2}, +X}; +Xstatic arc arcs_3_0[1] = { +X {9, 1}, +X}; +Xstatic arc arcs_3_1[1] = { +X {7, 2}, +X}; +Xstatic arc arcs_3_2[1] = { +X {0, 2}, +X}; +Xstatic state states_3[3] = { +X {1, arcs_3_0}, +X {1, arcs_3_1}, +X {1, arcs_3_2}, +X}; +Xstatic arc arcs_4_0[1] = { +X {12, 1}, +X}; +Xstatic arc arcs_4_1[1] = { +X {13, 2}, +X}; +Xstatic arc arcs_4_2[1] = { +X {14, 3}, +X}; +Xstatic arc arcs_4_3[1] = { +X {15, 4}, +X}; +Xstatic arc arcs_4_4[1] = { +X {16, 5}, +X}; +Xstatic arc arcs_4_5[1] = { +X {0, 5}, +X}; +Xstatic state states_4[6] = { +X {1, arcs_4_0}, +X {1, arcs_4_1}, +X {1, arcs_4_2}, +X {1, arcs_4_3}, +X {1, arcs_4_4}, +X {1, arcs_4_5}, +X}; +Xstatic arc arcs_5_0[1] = { +X {17, 1}, +X}; +Xstatic arc arcs_5_1[2] = { +X {18, 2}, +X {19, 3}, +X}; +Xstatic arc arcs_5_2[1] = { +X {19, 3}, +X}; +Xstatic arc arcs_5_3[1] = { +X {0, 3}, +X}; +Xstatic state states_5[4] = { +X {1, arcs_5_0}, +X {2, arcs_5_1}, +X {1, arcs_5_2}, +X {1, arcs_5_3}, +X}; +Xstatic arc arcs_6_0[1] = { +X {20, 1}, +X}; +Xstatic arc arcs_6_1[2] = { +X {21, 0}, +X {0, 1}, +X}; +Xstatic state states_6[2] = { +X {1, arcs_6_0}, +X {2, arcs_6_1}, +X}; +Xstatic arc arcs_7_0[2] = { +X {13, 1}, +X {17, 2}, +X}; +Xstatic arc arcs_7_1[1] = { +X {0, 1}, +X}; +Xstatic arc arcs_7_2[1] = { +X {18, 3}, +X}; +Xstatic arc arcs_7_3[1] = { +X {19, 1}, +X}; +Xstatic state states_7[4] = { +X {2, arcs_7_0}, +X {1, arcs_7_1}, +X {1, arcs_7_2}, +X {1, arcs_7_3}, +X}; +Xstatic arc arcs_8_0[2] = { +X {3, 1}, +X {4, 1}, +X}; +Xstatic arc arcs_8_1[1] = { +X {0, 1}, +X}; +Xstatic state states_8[2] = { +X {2, arcs_8_0}, +X {1, arcs_8_1}, +X}; +Xstatic arc arcs_9_0[6] = { +X {22, 1}, +X {23, 1}, +X {24, 1}, +X {25, 1}, +X {26, 1}, +X {27, 1}, +X}; +Xstatic arc arcs_9_1[1] = { +X {0, 1}, +X}; +Xstatic state states_9[2] = { +X {6, arcs_9_0}, +X {1, arcs_9_1}, +X}; +Xstatic arc arcs_10_0[1] = { +X {28, 1}, +X}; +Xstatic arc arcs_10_1[2] = { +X {29, 0}, +X {2, 2}, +X}; +Xstatic arc arcs_10_2[1] = { +X {0, 2}, +X}; +Xstatic state states_10[3] = { +X {1, arcs_10_0}, +X {2, arcs_10_1}, +X {1, arcs_10_2}, +X}; +Xstatic arc arcs_11_0[1] = { +X {30, 1}, +X}; +Xstatic arc arcs_11_1[2] = { +X {31, 2}, +X {2, 3}, +X}; +Xstatic arc arcs_11_2[2] = { +X {21, 1}, +X {2, 3}, +X}; +Xstatic arc arcs_11_3[1] = { +X {0, 3}, +X}; +Xstatic state states_11[4] = { +X {1, arcs_11_0}, +X {2, arcs_11_1}, +X {2, arcs_11_2}, +X {1, arcs_11_3}, +X}; +Xstatic arc arcs_12_0[1] = { +X {32, 1}, +X}; +Xstatic arc arcs_12_1[1] = { +X {28, 2}, +X}; +Xstatic arc arcs_12_2[1] = { +X {2, 3}, +X}; +Xstatic arc arcs_12_3[1] = { +X {0, 3}, +X}; +Xstatic state states_12[4] = { +X {1, arcs_12_0}, +X {1, arcs_12_1}, +X {1, arcs_12_2}, +X {1, arcs_12_3}, +X}; +Xstatic arc arcs_13_0[1] = { +X {33, 1}, +X}; +Xstatic arc arcs_13_1[1] = { +X {2, 2}, +X}; +Xstatic arc arcs_13_2[1] = { +X {0, 2}, +X}; +Xstatic state states_13[3] = { +X {1, arcs_13_0}, +X {1, arcs_13_1}, +X {1, arcs_13_2}, +X}; +Xstatic arc arcs_14_0[3] = { +X {34, 1}, +X {35, 1}, +X {36, 1}, +X}; +Xstatic arc arcs_14_1[1] = { +X {0, 1}, +X}; +Xstatic state states_14[2] = { +X {3, arcs_14_0}, +X {1, arcs_14_1}, +X}; +Xstatic arc arcs_15_0[1] = { +X {37, 1}, +X}; +Xstatic arc arcs_15_1[1] = { +X {2, 2}, +X}; +Xstatic arc arcs_15_2[1] = { +X {0, 2}, +X}; +Xstatic state states_15[3] = { +X {1, arcs_15_0}, +X {1, arcs_15_1}, +X {1, arcs_15_2}, +X}; +Xstatic arc arcs_16_0[1] = { +X {38, 1}, +X}; +Xstatic arc arcs_16_1[2] = { +X {9, 2}, +X {2, 3}, +X}; +Xstatic arc arcs_16_2[1] = { +X {2, 3}, +X}; +Xstatic arc arcs_16_3[1] = { +X {0, 3}, +X}; +Xstatic state states_16[4] = { +X {1, arcs_16_0}, +X {2, arcs_16_1}, +X {1, arcs_16_2}, +X {1, arcs_16_3}, +X}; +Xstatic arc arcs_17_0[1] = { +X {39, 1}, +X}; +Xstatic arc arcs_17_1[1] = { +X {40, 2}, +X}; +Xstatic arc arcs_17_2[2] = { +X {21, 3}, +X {2, 4}, +X}; +Xstatic arc arcs_17_3[1] = { +X {40, 5}, +X}; +Xstatic arc arcs_17_4[1] = { +X {0, 4}, +X}; +Xstatic arc arcs_17_5[1] = { +X {2, 4}, +X}; +Xstatic state states_17[6] = { +X {1, arcs_17_0}, +X {1, arcs_17_1}, +X {2, arcs_17_2}, +X {1, arcs_17_3}, +X {1, arcs_17_4}, +X {1, arcs_17_5}, +X}; +Xstatic arc arcs_18_0[2] = { +X {41, 1}, +X {42, 2}, +X}; +Xstatic arc arcs_18_1[1] = { +X {13, 3}, +X}; +Xstatic arc arcs_18_2[1] = { +X {13, 4}, +X}; +Xstatic arc arcs_18_3[2] = { +X {21, 1}, +X {2, 5}, +X}; +Xstatic arc arcs_18_4[1] = { +X {41, 6}, +X}; +Xstatic arc arcs_18_5[1] = { +X {0, 5}, +X}; +Xstatic arc arcs_18_6[2] = { +X {43, 7}, +X {13, 8}, +X}; +Xstatic arc arcs_18_7[1] = { +X {2, 5}, +X}; +Xstatic arc arcs_18_8[2] = { +X {21, 9}, +X {2, 5}, +X}; +Xstatic arc arcs_18_9[1] = { +X {13, 8}, +X}; +Xstatic state states_18[10] = { +X {2, arcs_18_0}, +X {1, arcs_18_1}, +X {1, arcs_18_2}, +X {2, arcs_18_3}, +X {1, arcs_18_4}, +X {1, arcs_18_5}, +X {2, arcs_18_6}, +X {1, arcs_18_7}, +X {2, arcs_18_8}, +X {1, arcs_18_9}, +X}; +Xstatic arc arcs_19_0[6] = { +X {44, 1}, +X {45, 1}, +X {46, 1}, +X {47, 1}, +X {11, 1}, +X {48, 1}, +X}; +Xstatic arc arcs_19_1[1] = { +X {0, 1}, +X}; +Xstatic state states_19[2] = { +X {6, arcs_19_0}, +X {1, arcs_19_1}, +X}; +Xstatic arc arcs_20_0[1] = { +X {49, 1}, +X}; +Xstatic arc arcs_20_1[1] = { +X {31, 2}, +X}; +Xstatic arc arcs_20_2[1] = { +X {15, 3}, +X}; +Xstatic arc arcs_20_3[1] = { +X {16, 4}, +X}; +Xstatic arc arcs_20_4[3] = { +X {50, 1}, +X {51, 5}, +X {0, 4}, +X}; +Xstatic arc arcs_20_5[1] = { +X {15, 6}, +X}; +Xstatic arc arcs_20_6[1] = { +X {16, 7}, +X}; +Xstatic arc arcs_20_7[1] = { +X {0, 7}, +X}; +Xstatic state states_20[8] = { +X {1, arcs_20_0}, +X {1, arcs_20_1}, +X {1, arcs_20_2}, +X {1, arcs_20_3}, +X {3, arcs_20_4}, +X {1, arcs_20_5}, +X {1, arcs_20_6}, +X {1, arcs_20_7}, +X}; +Xstatic arc arcs_21_0[1] = { +X {52, 1}, +X}; +Xstatic arc arcs_21_1[1] = { +X {31, 2}, +X}; +Xstatic arc arcs_21_2[1] = { +X {15, 3}, +X}; +Xstatic arc arcs_21_3[1] = { +X {16, 4}, +X}; +Xstatic arc arcs_21_4[2] = { +X {51, 5}, +X {0, 4}, +X}; +Xstatic arc arcs_21_5[1] = { +X {15, 6}, +X}; +Xstatic arc arcs_21_6[1] = { +X {16, 7}, +X}; +Xstatic arc arcs_21_7[1] = { +X {0, 7}, +X}; +Xstatic state states_21[8] = { +X {1, arcs_21_0}, +X {1, arcs_21_1}, +X {1, arcs_21_2}, +X {1, arcs_21_3}, +X {2, arcs_21_4}, +X {1, arcs_21_5}, +X {1, arcs_21_6}, +X {1, arcs_21_7}, +X}; +Xstatic arc arcs_22_0[1] = { +X {53, 1}, +X}; +Xstatic arc arcs_22_1[1] = { +X {28, 2}, +X}; +Xstatic arc arcs_22_2[1] = { +X {54, 3}, +X}; +Xstatic arc arcs_22_3[1] = { +X {28, 4}, +X}; +Xstatic arc arcs_22_4[1] = { +X {15, 5}, +X}; +Xstatic arc arcs_22_5[1] = { +X {16, 6}, +X}; +Xstatic arc arcs_22_6[2] = { +X {51, 7}, +X {0, 6}, +X}; +Xstatic arc arcs_22_7[1] = { +X {15, 8}, +X}; +Xstatic arc arcs_22_8[1] = { +X {16, 9}, +X}; +Xstatic arc arcs_22_9[1] = { +X {0, 9}, +X}; +Xstatic state states_22[10] = { +X {1, arcs_22_0}, +X {1, arcs_22_1}, +X {1, arcs_22_2}, +X {1, arcs_22_3}, +X {1, arcs_22_4}, +X {1, arcs_22_5}, +X {2, arcs_22_6}, +X {1, arcs_22_7}, +X {1, arcs_22_8}, +X {1, arcs_22_9}, +X}; +Xstatic arc arcs_23_0[1] = { +X {55, 1}, +X}; +Xstatic arc arcs_23_1[1] = { +X {15, 2}, +X}; +Xstatic arc arcs_23_2[1] = { +X {16, 3}, +X}; +Xstatic arc arcs_23_3[3] = { +X {56, 1}, +X {57, 4}, +X {0, 3}, +X}; +Xstatic arc arcs_23_4[1] = { +X {15, 5}, +X}; +Xstatic arc arcs_23_5[1] = { +X {16, 6}, +X}; +Xstatic arc arcs_23_6[1] = { +X {0, 6}, +X}; +Xstatic state states_23[7] = { +X {1, arcs_23_0}, +X {1, arcs_23_1}, +X {1, arcs_23_2}, +X {3, arcs_23_3}, +X {1, arcs_23_4}, +X {1, arcs_23_5}, +X {1, arcs_23_6}, +X}; +Xstatic arc arcs_24_0[1] = { +X {58, 1}, +X}; +Xstatic arc arcs_24_1[2] = { +X {40, 2}, +X {0, 1}, +X}; +Xstatic arc arcs_24_2[2] = { +X {21, 3}, +X {0, 2}, +X}; +Xstatic arc arcs_24_3[1] = { +X {40, 4}, +X}; +Xstatic arc arcs_24_4[1] = { +X {0, 4}, +X}; +Xstatic state states_24[5] = { +X {1, arcs_24_0}, +X {2, arcs_24_1}, +X {2, arcs_24_2}, +X {1, arcs_24_3}, +X {1, arcs_24_4}, +X}; +Xstatic arc arcs_25_0[2] = { +X {3, 1}, +X {2, 2}, +X}; +Xstatic arc arcs_25_1[1] = { +X {0, 1}, +X}; +Xstatic arc arcs_25_2[1] = { +X {59, 3}, +X}; +Xstatic arc arcs_25_3[2] = { +X {2, 3}, +X {6, 4}, +X}; +Xstatic arc arcs_25_4[3] = { +X {6, 4}, +X {2, 4}, +X {60, 1}, +X}; +Xstatic state states_25[5] = { +X {2, arcs_25_0}, +X {1, arcs_25_1}, +X {1, arcs_25_2}, +X {2, arcs_25_3}, +X {3, arcs_25_4}, +X}; +Xstatic arc arcs_26_0[1] = { +X {61, 1}, +X}; +Xstatic arc arcs_26_1[2] = { +X {62, 0}, +X {0, 1}, +X}; +Xstatic state states_26[2] = { +X {1, arcs_26_0}, +X {2, arcs_26_1}, +X}; +Xstatic arc arcs_27_0[1] = { +X {63, 1}, +X}; +Xstatic arc arcs_27_1[2] = { +X {64, 0}, +X {0, 1}, +X}; +Xstatic state states_27[2] = { +X {1, arcs_27_0}, +X {2, arcs_27_1}, +X}; +Xstatic arc arcs_28_0[2] = { +X {65, 1}, +X {66, 2}, +X}; +Xstatic arc arcs_28_1[1] = { +X {63, 2}, +X}; +Xstatic arc arcs_28_2[1] = { +X {0, 2}, +X}; +Xstatic state states_28[3] = { +X {2, arcs_28_0}, +X {1, arcs_28_1}, +X {1, arcs_28_2}, +X}; +Xstatic arc arcs_29_0[1] = { +X {40, 1}, +X}; +Xstatic arc arcs_29_1[2] = { +X {67, 0}, +X {0, 1}, +X}; +Xstatic state states_29[2] = { +X {1, arcs_29_0}, +X {2, arcs_29_1}, +X}; +Xstatic arc arcs_30_0[6] = { +X {68, 1}, +X {69, 2}, +X {29, 3}, +X {54, 3}, +X {65, 4}, +X {70, 5}, +X}; +Xstatic arc arcs_30_1[3] = { +X {29, 3}, +X {69, 3}, +X {0, 1}, +X}; +Xstatic arc arcs_30_2[2] = { +X {29, 3}, +X {0, 2}, +X}; +Xstatic arc arcs_30_3[1] = { +X {0, 3}, +X}; +Xstatic arc arcs_30_4[1] = { +X {54, 3}, +X}; +Xstatic arc arcs_30_5[2] = { +X {65, 3}, +X {0, 5}, +X}; +Xstatic state states_30[6] = { +X {6, arcs_30_0}, +X {3, arcs_30_1}, +X {2, arcs_30_2}, +X {1, arcs_30_3}, +X {1, arcs_30_4}, +X {2, arcs_30_5}, +X}; +Xstatic arc arcs_31_0[1] = { +X {71, 1}, +X}; +Xstatic arc arcs_31_1[3] = { +X {72, 0}, +X {73, 0}, +X {0, 1}, +X}; +Xstatic state states_31[2] = { +X {1, arcs_31_0}, +X {3, arcs_31_1}, +X}; +Xstatic arc arcs_32_0[1] = { +X {74, 1}, +X}; +Xstatic arc arcs_32_1[4] = { +X {43, 0}, +X {75, 0}, +X {76, 0}, +X {0, 1}, +X}; +Xstatic state states_32[2] = { +X {1, arcs_32_0}, +X {4, arcs_32_1}, +X}; +Xstatic arc arcs_33_0[3] = { +X {72, 1}, +X {73, 1}, +X {77, 2}, +X}; +Xstatic arc arcs_33_1[1] = { +X {74, 3}, +X}; +Xstatic arc arcs_33_2[2] = { +X {78, 2}, +X {0, 2}, +X}; +Xstatic arc arcs_33_3[1] = { +X {0, 3}, +X}; +Xstatic state states_33[4] = { +X {3, arcs_33_0}, +X {1, arcs_33_1}, +X {2, arcs_33_2}, +X {1, arcs_33_3}, +X}; +Xstatic arc arcs_34_0[7] = { +X {17, 1}, +X {79, 2}, +X {81, 3}, +X {83, 4}, +X {13, 5}, +X {84, 5}, +X {85, 5}, +X}; +Xstatic arc arcs_34_1[2] = { +X {9, 6}, +X {19, 5}, +X}; +Xstatic arc arcs_34_2[2] = { +X {9, 7}, +X {80, 5}, +X}; +Xstatic arc arcs_34_3[1] = { +X {82, 5}, +X}; +Xstatic arc arcs_34_4[1] = { +X {9, 8}, +X}; +Xstatic arc arcs_34_5[1] = { +X {0, 5}, +X}; +Xstatic arc arcs_34_6[1] = { +X {19, 5}, +X}; +Xstatic arc arcs_34_7[1] = { +X {80, 5}, +X}; +Xstatic arc arcs_34_8[1] = { +X {83, 5}, +X}; +Xstatic state states_34[9] = { +X {7, arcs_34_0}, +X {2, arcs_34_1}, +X {2, arcs_34_2}, +X {1, arcs_34_3}, +X {1, arcs_34_4}, +X {1, arcs_34_5}, +X {1, arcs_34_6}, +X {1, arcs_34_7}, +X {1, arcs_34_8}, +X}; +Xstatic arc arcs_35_0[3] = { +X {17, 1}, +X {79, 2}, +X {87, 3}, +X}; +Xstatic arc arcs_35_1[2] = { +X {9, 4}, +X {19, 5}, +X}; +Xstatic arc arcs_35_2[1] = { +X {86, 6}, +X}; +Xstatic arc arcs_35_3[1] = { +X {13, 5}, +X}; +Xstatic arc arcs_35_4[1] = { +X {19, 5}, +X}; +Xstatic arc arcs_35_5[1] = { +X {0, 5}, +X}; +Xstatic arc arcs_35_6[1] = { +X {80, 5}, +X}; +Xstatic state states_35[7] = { +X {3, arcs_35_0}, +X {2, arcs_35_1}, +X {1, arcs_35_2}, +X {1, arcs_35_3}, +X {1, arcs_35_4}, +X {1, arcs_35_5}, +X {1, arcs_35_6}, +X}; +Xstatic arc arcs_36_0[2] = { +X {40, 1}, +X {15, 2}, +X}; +Xstatic arc arcs_36_1[2] = { +X {15, 2}, +X {0, 1}, +X}; +Xstatic arc arcs_36_2[2] = { +X {40, 3}, +X {0, 2}, +X}; +Xstatic arc arcs_36_3[1] = { +X {0, 3}, +X}; +Xstatic state states_36[4] = { +X {2, arcs_36_0}, +X {2, arcs_36_1}, +X {2, arcs_36_2}, +X {1, arcs_36_3}, +X}; +Xstatic arc arcs_37_0[1] = { +X {40, 1}, +X}; +Xstatic arc arcs_37_1[2] = { +X {21, 2}, +X {0, 1}, +X}; +Xstatic arc arcs_37_2[2] = { +X {40, 1}, +X {0, 2}, +X}; +Xstatic state states_37[3] = { +X {1, arcs_37_0}, +X {2, arcs_37_1}, +X {2, arcs_37_2}, +X}; +Xstatic arc arcs_38_0[1] = { +X {31, 1}, +X}; +Xstatic arc arcs_38_1[2] = { +X {21, 2}, +X {0, 1}, +X}; +Xstatic arc arcs_38_2[2] = { +X {31, 1}, +X {0, 2}, +X}; +Xstatic state states_38[3] = { +X {1, arcs_38_0}, +X {2, arcs_38_1}, +X {2, arcs_38_2}, +X}; +Xstatic arc arcs_39_0[1] = { +X {88, 1}, +X}; +Xstatic arc arcs_39_1[1] = { +X {13, 2}, +X}; +Xstatic arc arcs_39_2[1] = { +X {14, 3}, +X}; +Xstatic arc arcs_39_3[2] = { +X {29, 4}, +X {15, 5}, +X}; +Xstatic arc arcs_39_4[1] = { +X {89, 6}, +X}; +Xstatic arc arcs_39_5[1] = { +X {16, 7}, +X}; +Xstatic arc arcs_39_6[1] = { +X {15, 5}, +X}; +Xstatic arc arcs_39_7[1] = { +X {0, 7}, +X}; +Xstatic state states_39[8] = { +X {1, arcs_39_0}, +X {1, arcs_39_1}, +X {1, arcs_39_2}, +X {2, arcs_39_3}, +X {1, arcs_39_4}, +X {1, arcs_39_5}, +X {1, arcs_39_6}, +X {1, arcs_39_7}, +X}; +Xstatic arc arcs_40_0[1] = { +X {77, 1}, +X}; +Xstatic arc arcs_40_1[1] = { +X {90, 2}, +X}; +Xstatic arc arcs_40_2[2] = { +X {21, 0}, +X {0, 2}, +X}; +Xstatic state states_40[3] = { +X {1, arcs_40_0}, +X {1, arcs_40_1}, +X {2, arcs_40_2}, +X}; +Xstatic arc arcs_41_0[1] = { +X {17, 1}, +X}; +Xstatic arc arcs_41_1[2] = { +X {9, 2}, +X {19, 3}, +X}; +Xstatic arc arcs_41_2[1] = { +X {19, 3}, +X}; +Xstatic arc arcs_41_3[1] = { +X {0, 3}, +X}; +Xstatic state states_41[4] = { +X {1, arcs_41_0}, +X {2, arcs_41_1}, +X {1, arcs_41_2}, +X {1, arcs_41_3}, +X}; +Xstatic dfa dfas[42] = { +X {256, "single_input", 0, 3, states_0, +X "\004\060\002\100\343\006\262\000\000\203\072\001"}, +X {257, "file_input", 0, 2, states_1, +X "\204\060\002\100\343\006\262\000\000\203\072\001"}, +X {258, "expr_input", 0, 3, states_2, +X "\000\040\002\000\000\000\000\000\002\203\072\000"}, +X {259, "eval_input", 0, 3, states_3, +X "\000\040\002\000\000\000\000\000\002\203\072\000"}, +X {260, "funcdef", 0, 6, states_4, +X "\000\020\000\000\000\000\000\000\000\000\000\000"}, +X {261, "parameters", 0, 4, states_5, +X "\000\000\002\000\000\000\000\000\000\000\000\000"}, +X {262, "fplist", 0, 2, states_6, +X "\000\040\002\000\000\000\000\000\000\000\000\000"}, +X {263, "fpdef", 0, 4, states_7, +X "\000\040\002\000\000\000\000\000\000\000\000\000"}, +X {264, "stmt", 0, 2, states_8, +X "\000\060\002\100\343\006\262\000\000\203\072\001"}, +X {265, "simple_stmt", 0, 2, states_9, +X "\000\040\002\100\343\006\000\000\000\203\072\000"}, +X {266, "expr_stmt", 0, 3, states_10, +X "\000\040\002\000\000\000\000\000\000\203\072\000"}, +X {267, "print_stmt", 0, 4, states_11, +X "\000\000\000\100\000\000\000\000\000\000\000\000"}, +X {268, "del_stmt", 0, 4, states_12, +X "\000\000\000\000\001\000\000\000\000\000\000\000"}, +X {269, "pass_stmt", 0, 3, states_13, +X "\000\000\000\000\002\000\000\000\000\000\000\000"}, +X {270, "flow_stmt", 0, 2, states_14, +X "\000\000\000\000\340\000\000\000\000\000\000\000"}, +X {271, "break_stmt", 0, 3, states_15, +X "\000\000\000\000\040\000\000\000\000\000\000\000"}, +X {272, "return_stmt", 0, 4, states_16, +X "\000\000\000\000\100\000\000\000\000\000\000\000"}, +X {273, "raise_stmt", 0, 6, states_17, +X "\000\000\000\000\200\000\000\000\000\000\000\000"}, +X {274, "import_stmt", 0, 10, states_18, +X "\000\000\000\000\000\006\000\000\000\000\000\000"}, +X {275, "compound_stmt", 0, 2, states_19, +X "\000\020\000\000\000\000\262\000\000\000\000\001"}, +X {276, "if_stmt", 0, 8, states_20, +X "\000\000\000\000\000\000\002\000\000\000\000\000"}, +X {277, "while_stmt", 0, 8, states_21, +X "\000\000\000\000\000\000\020\000\000\000\000\000"}, +X {278, "for_stmt", 0, 10, states_22, +X "\000\000\000\000\000\000\040\000\000\000\000\000"}, +X {279, "try_stmt", 0, 7, states_23, +X "\000\000\000\000\000\000\200\000\000\000\000\000"}, +X {280, "except_clause", 0, 5, states_24, +X "\000\000\000\000\000\000\000\004\000\000\000\000"}, +X {281, "suite", 0, 5, states_25, +X "\004\040\002\100\343\006\000\000\000\203\072\000"}, +X {282, "test", 0, 2, states_26, +X "\000\040\002\000\000\000\000\000\002\203\072\000"}, +X {283, "and_test", 0, 2, states_27, +X "\000\040\002\000\000\000\000\000\002\203\072\000"}, +X {284, "not_test", 0, 3, states_28, +X "\000\040\002\000\000\000\000\000\002\203\072\000"}, +X {285, "comparison", 0, 2, states_29, +X "\000\040\002\000\000\000\000\000\000\203\072\000"}, +X {286, "comp_op", 0, 6, states_30, +X "\000\000\000\040\000\000\100\000\162\000\000\000"}, +X {287, "expr", 0, 2, states_31, +X "\000\040\002\000\000\000\000\000\000\203\072\000"}, +X {288, "term", 0, 2, states_32, +X "\000\040\002\000\000\000\000\000\000\203\072\000"}, +X {289, "factor", 0, 4, states_33, +X "\000\040\002\000\000\000\000\000\000\203\072\000"}, +X {290, "atom", 0, 9, states_34, +X "\000\040\002\000\000\000\000\000\000\200\072\000"}, +X {291, "trailer", 0, 7, states_35, +X "\000\000\002\000\000\000\000\000\000\200\200\000"}, +X {292, "subscript", 0, 4, states_36, +X "\000\240\002\000\000\000\000\000\000\203\072\000"}, +X {293, "exprlist", 0, 3, states_37, +X "\000\040\002\000\000\000\000\000\000\203\072\000"}, +X {294, "testlist", 0, 3, states_38, +X "\000\040\002\000\000\000\000\000\002\203\072\000"}, +X {295, "classdef", 0, 8, states_39, +X "\000\000\000\000\000\000\000\000\000\000\000\001"}, +X {296, "baselist", 0, 3, states_40, +X "\000\040\002\000\000\000\000\000\000\200\072\000"}, +X {297, "arguments", 0, 4, states_41, +X "\000\000\002\000\000\000\000\000\000\000\000\000"}, +X}; +Xstatic label labels[91] = { +X {0, "EMPTY"}, +X {256, 0}, +X {4, 0}, +X {265, 0}, +X {275, 0}, +X {257, 0}, +X {264, 0}, +X {0, 0}, +X {258, 0}, +X {294, 0}, +X {259, 0}, +X {260, 0}, +X {1, "def"}, +X {1, 0}, +X {261, 0}, +X {11, 0}, +X {281, 0}, +X {7, 0}, +X {262, 0}, +X {8, 0}, +X {263, 0}, +X {12, 0}, +X {266, 0}, +X {267, 0}, +X {269, 0}, +X {268, 0}, +X {270, 0}, +X {274, 0}, +X {293, 0}, +X {22, 0}, +X {1, "print"}, +X {282, 0}, +X {1, "del"}, +X {1, "pass"}, +X {271, 0}, +X {272, 0}, +X {273, 0}, +X {1, "break"}, +X {1, "return"}, +X {1, "raise"}, +X {287, 0}, +X {1, "import"}, +X {1, "from"}, +X {16, 0}, +X {276, 0}, +X {277, 0}, +X {278, 0}, +X {279, 0}, +X {295, 0}, +X {1, "if"}, +X {1, "elif"}, +X {1, "else"}, +X {1, "while"}, +X {1, "for"}, +X {1, "in"}, +X {1, "try"}, +X {280, 0}, +X {1, "finally"}, +X {1, "except"}, +X {5, 0}, +X {6, 0}, +X {283, 0}, +X {1, "or"}, +X {284, 0}, +X {1, "and"}, +X {1, "not"}, +X {285, 0}, +X {286, 0}, +X {20, 0}, +X {21, 0}, +X {1, "is"}, +X {288, 0}, +X {14, 0}, +X {15, 0}, +X {289, 0}, +X {17, 0}, +X {24, 0}, +X {290, 0}, +X {291, 0}, +X {9, 0}, +X {10, 0}, +X {26, 0}, +X {27, 0}, +X {25, 0}, +X {2, 0}, +X {3, 0}, +X {292, 0}, +X {23, 0}, +X {1, "class"}, +X {296, 0}, +X {297, 0}, +X}; +Xgrammar gram = { +X 42, +X dfas, +X {91, labels}, +X 256 +X}; +EOF +fi +if test -s 'src/objimpl.h' +then echo '*** I will not over-write existing file src/objimpl.h' +else +echo 'x - src/objimpl.h' +sed 's/^X//' > 'src/objimpl.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/* +X123456789-123456789-123456789-123456789-123456789-123456789-123456789-12 +X +XAdditional macros for modules that implement new object types. +XYou must first include "object.h". +X +XNEWOBJ(type, typeobj) allocates memory for a new object of the given +Xtype; here 'type' must be the C structure type used to represent the +Xobject and 'typeobj' the address of the corresponding type object. +XReference count and type pointer are filled in; the rest of the bytes of +Xthe object are *undefined*! The resulting expression type is 'type *'. +XThe size of the object is actually determined by the tp_basicsize field +Xof the type object. +X +XNEWVAROBJ(type, typeobj, n) is similar but allocates a variable-size +Xobject with n extra items. The size is computer as tp_basicsize plus +Xn * tp_itemsize. This fills in the ob_size field as well. +X*/ +X +Xextern object *newobject PROTO((typeobject *)); +Xextern varobject *newvarobject PROTO((typeobject *, unsigned int)); +X +X#define NEWOBJ(type, typeobj) ((type *) newobject(typeobj)) +X#define NEWVAROBJ(type, typeobj, n) ((type *) newvarobject(typeobj, n)) +X +Xextern int StopPrint; /* Set when printing is interrupted */ +EOF +fi +echo 'Part 03 out of 21 of pack.out complete.' +exit 0 diff --git a/shar/python-0.9.1-04-21.shar b/shar/python-0.9.1-04-21.shar new file mode 100644 index 0000000..5f1cbee --- /dev/null +++ b/shar/python-0.9.1-04-21.shar @@ -0,0 +1,2755 @@ +: 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 04 out of 21:' +if test -s 'demo/sgi/gl_panel/flying/freeze.s' +then echo '*** I will not over-write existing file demo/sgi/gl_panel/flying/freeze.s' +else +echo 'x - demo/sgi/gl_panel/flying/freeze.s' +sed 's/^X//' > 'demo/sgi/gl_panel/flying/freeze.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 "frames per second") +X(al (pnl_toggle_button (name "freeze") +X(prop help creator:user-act-help) +X(label "freeze") +X(x 0.25) +X(y 4.3) +X(w 1.45) +X(h 0.6) +X(labeltype 16) +X(downfunc move-then-resize) +X) +X(pnl_scale_chart (name "mystrip") +X(prop help creator:user-act-help) +X(x 0.25) +X(y 0.25) +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 'src/cstubs' +then echo '*** I will not over-write existing file src/cstubs' +else +echo 'x - src/cstubs' +sed 's/^X//' > 'src/cstubs' << 'EOF' +X/* +XInput used to generate the Python module "glmodule.c". +XThe stub generator is a Python script called "cgen". +X +XEach definition must be contained on one line: +X +X +X +X can be: void, short, long (XXX maybe others?) +X +X can be: char, string, short, float, long, or double +X string indicates a null terminated string; +X if is char and begins with a *, the * is stripped +X and is changed into string +X +X has the form or [] +X where can be +X s: arg is sent +X r: arg is received (arg is a pointer) +X and can be (N and I are numbers): +X N +X argI +X retval +X N*argI +X N*retval +X*/ +X +X#include +X#include +X +X#include "allobjects.h" +X#include "import.h" +X#include "modsupport.h" +X#include "cgensupport.h" +X +X/* +XSome stubs are too complicated for the stub generator. +XWe can include manually written versions of them here. +XA line starting with '%' gives the name of the function so the stub +Xgenerator can include it in the table of functions. +X*/ +X +X/* +Xvarray -- an array of v.. calls. +XThe argument is an array (maybe list or tuple) of points. +XEach point must be a tuple or list of coordinates (x, y, z). +XThe points may be 2- or 3-dimensional but must all have the +Xsame dimension. Float and int values may be mixed however. +XThe points are always converted to 3D double precision points +Xby assuming z=0.0 if necessary (as indicated in the man page), +Xand for each point v3d() is called. +X*/ +X +X% varray +X +Xstatic object * +Xgl_varray(self, args) +X object *self; +X object *args; +X{ +X object *v, *w; +X int i, n, width; +X double vec[3]; +X object * (*getitem) FPROTO((object *, int)); +X +X if (!getiobjectarg(args, 1, 0, &v)) +X return NULL; +X +X if (is_listobject(v)) { +X n = getlistsize(v); +X getitem = getlistitem; +X } +X else if (is_tupleobject(v)) { +X n = gettuplesize(v); +X getitem = gettupleitem; +X } +X else { +X err_badarg(); +X return NULL; +X } +X +X if (n == 0) { +X INCREF(None); +X return None; +X } +X if (n > 0) +X w = (*getitem)(v, 0); +X +X width = 0; +X if (w == NULL) { +X } +X else if (is_listobject(w)) { +X width = getlistsize(w); +X } +X else if (is_tupleobject(w)) { +X width = gettuplesize(w); +X } +X +X switch (width) { +X case 2: +X vec[2] = 0.0; +X /* Fall through */ +X case 3: +X break; +X default: +X err_badarg(); +X return NULL; +X } +X +X for (i = 0; i < n; i++) { +X w = (*getitem)(v, i); +X if (!getidoublearray(w, 1, 0, width, vec)) +X return NULL; +X v3d(vec); +X } +X +X INCREF(None); +X return None; +X} +X +X/* +Xvnarray, nvarray -- an array of n3f and v3f calls. +XThe argument is an array (list or tuple) of pairs of points and normals. +XEach pair is a tuple (NOT a list) of a point and a normal for that point. +XEach point or normal must be a tuple (NOT a list) of coordinates (x, y, z). +XThree coordinates must be given. Float and int values may be mixed. +XFor each pair, n3f() is called for the normal, and then v3f() is called +Xfor the vector. +X +Xvnarray and nvarray differ only in the order of the vector and normal in +Xthe pair: vnarray expects (v, n) while nvarray expects (n, v). +X*/ +X +Xstatic object *gen_nvarray(); /* Forward */ +X +X% nvarray +X +Xstatic object * +Xgl_nvarray(self, args) +X object *self; +X object *args; +X{ +X return gen_nvarray(args, 0); +X} +X +X% vnarray +X +Xstatic object * +Xgl_vnarray(self, args) +X object *self; +X object *args; +X{ +X return gen_nvarray(args, 1); +X} +X +X/* Generic, internal version of {nv,nv}array: inorm indicates the +X argument order, 0: normal first, 1: vector first. */ +X +Xstatic object * +Xgen_nvarray(args, inorm) +X object *args; +X int inorm; +X{ +X object *v, *w, *wnorm, *wvec; +X int i, n; +X float norm[3], vec[3]; +X object * (*getitem) FPROTO((object *, int)); +X +X if (!getiobjectarg(args, 1, 0, &v)) +X return NULL; +X +X if (is_listobject(v)) { +X n = getlistsize(v); +X getitem = getlistitem; +X } +X else if (is_tupleobject(v)) { +X n = gettuplesize(v); +X getitem = gettupleitem; +X } +X else { +X err_badarg(); +X return NULL; +X } +X +X for (i = 0; i < n; i++) { +X w = (*getitem)(v, i); +X if (!is_tupleobject(w) || gettuplesize(w) != 2) { +X err_badarg(); +X return NULL; +X } +X wnorm = gettupleitem(w, inorm); +X wvec = gettupleitem(w, 1 - inorm); +X if (!getifloatarray(wnorm, 1, 0, 3, norm) || +X !getifloatarray(wvec, 1, 0, 3, vec)) +X return NULL; +X n3f(norm); +X v3f(vec); +X } +X +X INCREF(None); +X return None; +X} +X +X/* nurbssurface(s_knots[], t_knots[], ctl[][], s_order, t_order, type). +X The dimensions of ctl[] are computed as follows: +X [len(s_knots) - s_order], [len(t_knots) - t_order] +X*/ +X +X% nurbssurface +X +Xstatic object * +Xgl_nurbssurface(self, args) +X object *self; +X object *args; +X{ +X long arg1 ; +X double * arg2 ; +X long arg3 ; +X double * arg4 ; +X double *arg5 ; +X long arg6 ; +X long arg7 ; +X long arg8 ; +X long ncoords; +X long s_byte_stride, t_byte_stride; +X long s_nctl, t_nctl; +X long s, t; +X object *v, *w, *pt; +X double *pnext; +X if (!getilongarraysize(args, 6, 0, &arg1)) +X return NULL; +X if ((arg2 = NEW(double, arg1 )) == NULL) { +X return err_nomem(); +X } +X if (!getidoublearray(args, 6, 0, arg1 , arg2)) +X return NULL; +X if (!getilongarraysize(args, 6, 1, &arg3)) +X return NULL; +X if ((arg4 = NEW(double, arg3 )) == NULL) { +X return err_nomem(); +X } +X if (!getidoublearray(args, 6, 1, arg3 , arg4)) +X return NULL; +X if (!getilongarg(args, 6, 3, &arg6)) +X return NULL; +X if (!getilongarg(args, 6, 4, &arg7)) +X return NULL; +X if (!getilongarg(args, 6, 5, &arg8)) +X return NULL; +X if (arg8 == N_XYZ) +X ncoords = 3; +X else if (arg8 == N_XYZW) +X ncoords = 4; +X else { +X err_badarg(); +X return NULL; +X } +X s_nctl = arg1 - arg6; +X t_nctl = arg3 - arg7; +X if (!getiobjectarg(args, 6, 2, &v)) +X return NULL; +X if (!is_listobject(v) || getlistsize(v) != s_nctl) { +X err_badarg(); +X return NULL; +X } +X if ((arg5 = NEW(double, s_nctl*t_nctl*ncoords )) == NULL) { +X return err_nomem(); +X } +X pnext = arg5; +X for (s = 0; s < s_nctl; s++) { +X w = getlistitem(v, s); +X if (w == NULL || !is_listobject(w) || +X getlistsize(w) != t_nctl) { +X err_badarg(); +X return NULL; +X } +X for (t = 0; t < t_nctl; t++) { +X pt = getlistitem(w, t); +X if (!getidoublearray(pt, 1, 0, ncoords, pnext)) +X return NULL; +X pnext += ncoords; +X } +X } +X s_byte_stride = sizeof(double) * ncoords; +X t_byte_stride = s_byte_stride * s_nctl; +X nurbssurface( arg1 , arg2 , arg3 , arg4 , +X s_byte_stride , t_byte_stride , arg5 , arg6 , arg7 , arg8 ); +X DEL(arg2); +X DEL(arg4); +X DEL(arg5); +X INCREF(None); +X return None; +X} +X +X/* nurbscurve(knots, ctlpoints, order, type). +X The length of ctlpoints is len(knots)-order. */ +X +X%nurbscurve +X +Xstatic object * +Xgl_nurbscurve(self, args) +X object *self; +X object *args; +X{ +X long arg1 ; +X double * arg2 ; +X long arg3 ; +X double * arg4 ; +X long arg5 ; +X long arg6 ; +X int ncoords, npoints; +X int i; +X object *v; +X double *pnext; +X if (!getilongarraysize(args, 4, 0, &arg1)) +X return NULL; +X if ((arg2 = NEW(double, arg1 )) == NULL) { +X return err_nomem(); +X } +X if (!getidoublearray(args, 4, 0, arg1 , arg2)) +X return NULL; +X if (!getilongarg(args, 4, 2, &arg5)) +X return NULL; +X if (!getilongarg(args, 4, 3, &arg6)) +X return NULL; +X if (arg6 == N_ST) +X ncoords = 2; +X else if (arg6 == N_STW) +X ncoords = 3; +X else { +X err_badarg(); +X return NULL; +X } +X npoints = arg1 - arg5; +X if (!getiobjectarg(args, 4, 1, &v)) +X return NULL; +X if (!is_listobject(v) || getlistsize(v) != npoints) { +X err_badarg(); +X return NULL; +X } +X if ((arg4 = NEW(double, npoints*ncoords )) == NULL) { +X return err_nomem(); +X } +X pnext = arg4; +X for (i = 0; i < npoints; i++) { +X if (!getidoublearray(getlistitem(v, i), 1, 0, ncoords, pnext)) +X return NULL; +X pnext += ncoords; +X } +X arg3 = (sizeof(double)) * ncoords; +X nurbscurve( arg1 , arg2 , arg3 , arg4 , arg5 , arg6 ); +X DEL(arg2); +X DEL(arg4); +X INCREF(None); +X return None; +X} +X +X/* pwlcurve(points, type). +X Points is a list of points. Type must be N_ST. */ +X +X%pwlcurve +X +Xstatic object * +Xgl_pwlcurve(self, args) +X object *self; +X object *args; +X{ +X object *v; +X long type; +X double *data, *pnext; +X long npoints, ncoords; +X int i; +X if (!getiobjectarg(args, 2, 0, &v)) +X return NULL; +X if (!getilongarg(args, 2, 1, &type)) +X return NULL; +X if (!is_listobject(v)) { +X err_badarg(); +X return NULL; +X } +X npoints = getlistsize(v); +X if (type == N_ST) +X ncoords = 2; +X else { +X err_badarg(); +X return NULL; +X } +X if ((data = NEW(double, npoints*ncoords)) == NULL) { +X return err_nomem(); +X } +X pnext = data; +X for (i = 0; i < npoints; i++) { +X if (!getidoublearray(getlistitem(v, i), 1, 0, ncoords, pnext)) +X return NULL; +X pnext += ncoords; +X } +X pwlcurve(npoints, data, sizeof(double)*ncoords, type); +X DEL(data); +X INCREF(None); +X return None; +X} +X +X +X/* Picking and Selecting */ +X +Xstatic short *pickbuffer = NULL; +Xstatic long pickbuffersize; +X +Xstatic object * +Xpick_select(args, func) +X object *args; +X void (*func)(); +X{ +X if (!getilongarg(args, 1, 0, &pickbuffersize)) +X return NULL; +X if (pickbuffer != NULL) { +X err_setstr(RuntimeError, +X "pick/gselect: already picking/selecting"); +X return NULL; +X } +X if ((pickbuffer = NEW(short, pickbuffersize)) == NULL) { +X return err_nomem(); +X } +X (*func)(pickbuffer, pickbuffersize); +X INCREF(None); +X return None; +X} +X +Xstatic object * +Xendpick_select(args, func) +X object *args; +X long (*func)(); +X{ +X object *v, *w; +X int i, nhits, n; +X if (!getnoarg(args)) +X return NULL; +X if (pickbuffer == NULL) { +X err_setstr(RuntimeError, +X "endpick/endselect: not in pick/select mode"); +X return NULL; +X } +X nhits = (*func)(pickbuffer); +X if (nhits < 0) { +X nhits = -nhits; /* How to report buffer overflow otherwise? */ +X } +X /* Scan the buffer to see how many integers */ +X n = 0; +X for (; nhits > 0; nhits--) { +X n += 1 + pickbuffer[n]; +X } +X v = newlistobject(n); +X if (v == NULL) +X return NULL; +X /* XXX Could do it nicer and interpret the data structure here, +X returning a list of lists. But this can be done in Python... */ +X for (i = 0; i < n; i++) { +X w = newintobject((long)pickbuffer[i]); +X if (w == NULL) { +X DECREF(v); +X return NULL; +X } +X setlistitem(v, i, w); +X } +X DEL(pickbuffer); +X pickbuffer = NULL; +X return v; +X} +X +Xextern void pick(), gselect(); +Xextern long endpick(), endselect(); +X +X%pick +Xstatic object *gl_pick(self, args) object *self, *args; { +X return pick_select(args, pick); +X} +X +X%endpick +Xstatic object *gl_endpick(self, args) object *self, *args; { +X return endpick_select(args, endpick); +X} +X +X%gselect +Xstatic object *gl_gselect(self, args) object *self, *args; { +X return pick_select(args, gselect); +X} +X +X%endselect +Xstatic object *gl_endselect(self, args) object *self, *args; { +X return endpick_select(args, endselect); +X} +X +X +X/* XXX The generator botches this one. Here's a quick hack to fix it. */ +X +X% getmatrix float r[16] +X +Xstatic object * +Xgl_getmatrix(self, args) +X object *self; +X object *args; +X{ +X float arg1 [ 16 ] ; +X object *v, *w; +X int i; +X getmatrix( arg1 ); +X v = newlistobject(16); +X if (v == NULL) { +X return err_nomem(); +X } +X for (i = 0; i < 16; i++) { +X w = mknewfloatobject(arg1[i]); +X if (w == NULL) { +X DECREF(v); +X return NULL; +X } +X setlistitem(v, i, w); +X } +X return v; +X} +X +X/* End of manually written stubs */ +X +X%% +X +Xlong getshade +Xvoid devport short s long s +Xvoid rdr2i long s long s +Xvoid rectfs short s short s short s short s +Xvoid rects short s short s short s short s +Xvoid rmv2i long s long s +Xvoid noport +Xvoid popviewport +Xvoid clear +Xvoid clearhitcode +Xvoid closeobj +Xvoid cursoff +Xvoid curson +Xvoid doublebuffer +Xvoid finish +Xvoid gconfig +Xvoid ginit +Xvoid greset +Xvoid multimap +Xvoid onemap +Xvoid popattributes +Xvoid popmatrix +Xvoid pushattributes +Xvoid pushmatrix +Xvoid pushviewport +Xvoid qreset +Xvoid RGBmode +Xvoid singlebuffer +Xvoid swapbuffers +Xvoid gsync +Xvoid tpon +Xvoid tpoff +Xvoid clkon +Xvoid clkoff +Xvoid ringbell +X#void callfunc +Xvoid gbegin +Xvoid textinit +Xvoid initnames +Xvoid pclos +Xvoid popname +Xvoid spclos +Xvoid zclear +Xvoid screenspace +Xvoid reshapeviewport +Xvoid winpush +Xvoid winpop +Xvoid foreground +Xvoid endfullscrn +Xvoid endpupmode +Xvoid fullscrn +Xvoid pupmode +Xvoid winconstraints +Xvoid pagecolor short s +Xvoid textcolor short s +Xvoid color short s +Xvoid curveit short s +Xvoid font short s +Xvoid linewidth short s +Xvoid setlinestyle short s +Xvoid setmap short s +Xvoid swapinterval short s +Xvoid writemask short s +Xvoid textwritemask short s +Xvoid qdevice short s +Xvoid unqdevice short s +Xvoid curvebasis short s +Xvoid curveprecision short s +Xvoid loadname short s +Xvoid passthrough short s +Xvoid pushname short s +Xvoid setmonitor short s +Xvoid setshade short s +Xvoid setpattern short s +Xvoid pagewritemask short s +X# +Xvoid callobj long s +Xvoid delobj long s +Xvoid editobj long s +Xvoid makeobj long s +Xvoid maketag long s +Xvoid chunksize long s +Xvoid compactify long s +Xvoid deltag long s +Xvoid lsrepeat long s +Xvoid objinsert long s +Xvoid objreplace long s +Xvoid winclose long s +Xvoid blanktime long s +Xvoid freepup long s +X# This is not in the library!? +X###void pupcolor long s +X# +Xvoid backbuffer long s +Xvoid frontbuffer long s +Xvoid lsbackup long s +Xvoid resetls long s +Xvoid lampon long s +Xvoid lampoff long s +Xvoid setbell long s +Xvoid blankscreen long s +Xvoid depthcue long s +Xvoid zbuffer long s +Xvoid backface long s +X# +Xvoid cmov2i long s long s +Xvoid draw2i long s long s +Xvoid move2i long s long s +Xvoid pnt2i long s long s +Xvoid patchbasis long s long s +Xvoid patchprecision long s long s +Xvoid pdr2i long s long s +Xvoid pmv2i long s long s +Xvoid rpdr2i long s long s +Xvoid rpmv2i long s long s +Xvoid xfpt2i long s long s +Xvoid objdelete long s long s +Xvoid patchcurves long s long s +Xvoid minsize long s long s +Xvoid maxsize long s long s +Xvoid keepaspect long s long s +Xvoid prefsize long s long s +Xvoid stepunit long s long s +Xvoid fudge long s long s +Xvoid winmove long s long s +X# +Xvoid attachcursor short s short s +Xvoid deflinestyle short s short s +Xvoid noise short s short s +Xvoid picksize short s short s +Xvoid qenter short s short s +Xvoid setdepth short s short s +Xvoid cmov2s short s short s +Xvoid draw2s short s short s +Xvoid move2s short s short s +Xvoid pdr2s short s short s +Xvoid pmv2s short s short s +Xvoid pnt2s short s short s +Xvoid rdr2s short s short s +Xvoid rmv2s short s short s +Xvoid rpdr2s short s short s +Xvoid rpmv2s short s short s +Xvoid xfpt2s short s short s +X# +Xvoid cmov2 float s float s +Xvoid draw2 float s float s +Xvoid move2 float s float s +Xvoid pnt2 float s float s +Xvoid pdr2 float s float s +Xvoid pmv2 float s float s +Xvoid rdr2 float s float s +Xvoid rmv2 float s float s +Xvoid rpdr2 float s float s +Xvoid rpmv2 float s float s +Xvoid xfpt2 float s float s +X# +Xvoid loadmatrix float s[16] +Xvoid multmatrix float s[16] +Xvoid crv float s[16] +Xvoid rcrv float s[16] +X# +X# Methods that have strings. +X# +Xvoid addtopup long s char *s long s +Xvoid charstr char *s +Xvoid getport char *s +Xlong strwidth char *s +Xlong winopen char *s +Xvoid wintitle char *s +X# +X# Methods that have 1 long (# of elements) and an array +X# +Xvoid polf long s float s[3*arg1] +Xvoid polf2 long s float s[2*arg1] +Xvoid poly long s float s[3*arg1] +Xvoid poly2 long s float s[2*arg1] +Xvoid crvn long s float s[3*arg1] +Xvoid rcrvn long s float s[4*arg1] +X# +Xvoid polf2i long s long s[2*arg1] +Xvoid polfi long s long s[3*arg1] +Xvoid poly2i long s long s[2*arg1] +Xvoid polyi long s long s[3*arg1] +X# +Xvoid polf2s long s short s[2*arg1] +Xvoid polfs long s short s[3*arg1] +Xvoid polys long s short s[3*arg1] +Xvoid poly2s long s short s[2*arg1] +X# +Xvoid defcursor short s short s[16] +Xvoid writepixels short s short s[arg1] +Xvoid defbasis long s float s[16] +Xvoid gewrite short s short s[arg1] +X# +Xvoid rotate short s char s +X# This is not in the library!? +X###void setbutton short s char s +Xvoid rot float s char s +X# +Xvoid circfi long s long s long s +Xvoid circi long s long s long s +Xvoid cmovi long s long s long s +Xvoid drawi long s long s long s +Xvoid movei long s long s long s +Xvoid pnti long s long s long s +Xvoid newtag long s long s long s +Xvoid pdri long s long s long s +Xvoid pmvi long s long s long s +Xvoid rdri long s long s long s +Xvoid rmvi long s long s long s +Xvoid rpdri long s long s long s +Xvoid rpmvi long s long s long s +Xvoid xfpti long s long s long s +X# +Xvoid circ float s float s float s +Xvoid circf float s float s float s +Xvoid cmov float s float s float s +Xvoid draw float s float s float s +Xvoid move float s float s float s +Xvoid pnt float s float s float s +Xvoid scale float s float s float s +Xvoid translate float s float s float s +Xvoid pdr float s float s float s +Xvoid pmv float s float s float s +Xvoid rdr float s float s float s +Xvoid rmv float s float s float s +Xvoid rpdr float s float s float s +Xvoid rpmv float s float s float s +Xvoid xfpt float s float s float s +X# +Xvoid RGBcolor short s short s short s +Xvoid RGBwritemask short s short s short s +Xvoid setcursor short s short s short s +Xvoid tie short s short s short s +Xvoid circfs short s short s short s +Xvoid circs short s short s short s +Xvoid cmovs short s short s short s +Xvoid draws short s short s short s +Xvoid moves short s short s short s +Xvoid pdrs short s short s short s +Xvoid pmvs short s short s short s +Xvoid pnts short s short s short s +Xvoid rdrs short s short s short s +Xvoid rmvs short s short s short s +Xvoid rpdrs short s short s short s +Xvoid rpmvs short s short s short s +Xvoid xfpts short s short s short s +Xvoid curorigin short s short s short s +Xvoid cyclemap short s short s short s +X# +Xvoid patch float s[16] float s[16] float s[16] +Xvoid splf long s float s[3*arg1] short s[arg1] +Xvoid splf2 long s float s[2*arg1] short s[arg1] +Xvoid splfi long s long s[3*arg1] short s[arg1] +Xvoid splf2i long s long s[2*arg1] short s[arg1] +Xvoid splfs long s short s[3*arg1] short s[arg1] +Xvoid splf2s long s short s[2*arg1] short s[arg1] +Xvoid defpattern short s short s short s[arg2*arg2/16] +X# +Xvoid rpatch float s[16] float s[16] float s[16] float s[16] +X# +X# routines that send 4 floats +X# +Xvoid ortho2 float s float s float s float s +Xvoid rect float s float s float s float s +Xvoid rectf float s float s float s float s +Xvoid xfpt4 float s float s float s float s +X# +Xvoid textport short s short s short s short s +Xvoid mapcolor short s short s short s short s +Xvoid scrmask short s short s short s short s +Xvoid setvaluator short s short s short s short s +Xvoid viewport short s short s short s short s +Xvoid shaderange short s short s short s short s +Xvoid xfpt4s short s short s short s short s +Xvoid rectfi long s long s long s long s +Xvoid recti long s long s long s long s +Xvoid xfpt4i long s long s long s long s +Xvoid prefposition long s long s long s long s +X# +Xvoid arc float s float s float s short s short s +Xvoid arcf float s float s float s short s short s +Xvoid arcfi long s long s long s short s short s +Xvoid arci long s long s long s short s short s +X# +Xvoid bbox2 short s short s float s float s float s float s +Xvoid bbox2i short s short s long s long s long s long s +Xvoid bbox2s short s short s short s short s short s short s +Xvoid blink short s short s short s short s short s +Xvoid ortho float s float s float s float s float s float s +Xvoid window float s float s float s float s float s float s +Xvoid lookat float s float s float s float s float s float s short s +X# +Xvoid perspective short s float s float s float s +Xvoid polarview float s short s short s short s +X# XXX getichararray not supported +X#void writeRGB short s char s[arg1] char s[arg1] char s[arg1] +X# +Xvoid arcfs short s short s short s short s short s +Xvoid arcs short s short s short s short s short s +Xvoid rectcopy short s short s short s short s short s short s +Xvoid RGBcursor short s short s short s short s short s short s short s +X# +Xlong getbutton short s +Xlong getcmmode +Xlong getlsbackup +Xlong getresetls +Xlong getdcm +Xlong getzbuffer +Xlong ismex +Xlong isobj long s +Xlong isqueued short s +Xlong istag long s +X# +Xlong genobj +Xlong gentag +Xlong getbuffer +Xlong getcolor +Xlong getdisplaymode +Xlong getfont +Xlong getheight +Xlong gethitcode +Xlong getlstyle +Xlong getlwidth +Xlong getmap +Xlong getplanes +Xlong getwritemask +Xlong qtest +Xlong getlsrepeat +Xlong getmonitor +Xlong getopenobj +Xlong getpattern +Xlong winget +Xlong winattach +Xlong getothermonitor +Xlong newpup +X# +Xlong getvaluator short s +Xvoid winset long s +Xlong dopup long s +Xvoid getdepth short r short r +Xvoid getcpos short r short r +Xvoid getsize long r long r +Xvoid getorigin long r long r +Xvoid getviewport short r short r short r short r +Xvoid gettp short r short r short r short r +Xvoid getgpos float r float r float r float r +Xvoid winposition long s long s long s long s +Xvoid gRGBcolor short r short r short r +Xvoid gRGBmask short r short r short r +Xvoid getscrmask short r short r short r short r +Xvoid gRGBcursor short r short r short r short r short r short r short r short r long * +Xvoid getmcolor short s short r short r short r +Xvoid mapw long s short s short s float r float r float r float r float r float r +Xvoid mapw2 long s short s short s float r float r +Xvoid defrasterfont short s short s short s Fontchar s[arg3] short s short s[4*arg5] +Xlong qread short r +Xvoid getcursor short r short r short r long r +X# +X# For these we receive arrays of stuff +X# +Xvoid getdev long s short s[arg1] short r[arg1] +X#XXX not generated correctly yet +X#void getmatrix float r[16] +Xlong readpixels short s short r[retval] +Xlong readRGB short s char r[retval] char r[retval] char r[retval] +Xlong blkqread short s short r[arg1] +X# +X# New 4D routines +X# +Xvoid cmode +Xvoid concave long s +Xvoid curstype long s +Xvoid drawmode long s +Xvoid gammaramp short s[256] short s[256] short s[256] +Xlong getbackface +Xlong getdescender +Xlong getdrawmode +Xlong getmmode +Xlong getsm +Xlong getvideo long s +Xvoid imakebackground +Xvoid lmbind short s short s +Xvoid lmdef long s long s long s float s[arg3] +Xvoid mmode long s +Xvoid normal float s[3] +Xvoid overlay long s +Xvoid RGBrange short s short s short s short s short s short s short s short s +Xvoid setvideo long s long s +Xvoid shademodel long s +Xvoid underlay long s +X# +X# New Personal Iris/GT Routines +X# +Xvoid bgnclosedline +Xvoid bgnline +Xvoid bgnpoint +Xvoid bgnpolygon +Xvoid bgnsurface +Xvoid bgntmesh +Xvoid bgntrim +Xvoid endclosedline +Xvoid endline +Xvoid endpoint +Xvoid endpolygon +Xvoid endsurface +Xvoid endtmesh +Xvoid endtrim +Xvoid blendfunction long s long s +Xvoid c3f float s[3] +Xvoid c3i long s[3] +Xvoid c3s short s[3] +Xvoid c4f float s[4] +Xvoid c4i long s[4] +Xvoid c4s short s[4] +Xvoid colorf float s +Xvoid cpack long s +Xvoid czclear long s long s +Xvoid dglclose long s +Xlong dglopen char *s long s +Xlong getgdesc long s +Xvoid getnurbsproperty long s float r +Xvoid glcompat long s long s +Xvoid iconsize long s long s +Xvoid icontitle char *s +Xvoid lRGBrange short s short s short s short s short s short s long s long s +Xvoid linesmooth long s +Xvoid lmcolor long s +Xvoid logicop long s +Xlong lrectread short s short s short s short s long r[retval] +Xvoid lrectwrite short s short s short s short s long s[(arg2-arg1+1)*(arg4-arg3+1)] +Xlong rectread short s short s short s short s short r[retval] +Xvoid rectwrite short s short s short s short s short s[(arg2-arg1+1)*(arg4-arg3+1)] +Xvoid lsetdepth long s long s +Xvoid lshaderange short s short s long s long s +Xvoid n3f float s[3] +Xvoid noborder +Xvoid pntsmooth long s +Xvoid readsource long s +Xvoid rectzoom float s float s +Xvoid sbox float s float s float s float s +Xvoid sboxi long s long s long s long s +Xvoid sboxs short s short s short s short s +Xvoid sboxf float s float s float s float s +Xvoid sboxfi long s long s long s long s +Xvoid sboxfs short s short s short s short s +Xvoid setnurbsproperty long s float s +Xvoid setpup long s long s long s +Xvoid smoothline long s +Xvoid subpixel long s +Xvoid swaptmesh +Xlong swinopen long s +Xvoid v2f float s[2] +Xvoid v2i long s[2] +Xvoid v2s short s[2] +Xvoid v3f float s[3] +Xvoid v3i long s[3] +Xvoid v3s short s[3] +Xvoid v4f float s[4] +Xvoid v4i long s[4] +Xvoid v4s short s[4] +Xvoid videocmd long s +Xlong windepth long s +Xvoid wmpack long s +Xvoid zdraw long s +Xvoid zfunction long s +Xvoid zsource long s +Xvoid zwritemask long s +X# +X# uses doubles +X# +Xvoid v2d double s[2] +Xvoid v3d double s[3] +Xvoid v4d double s[4] +EOF +fi +if test -s 'src/stdwinmodule.c' +then echo '*** I will not over-write existing file src/stdwinmodule.c' +else +echo 'x - src/stdwinmodule.c' +sed 's/^X//' > 'src/stdwinmodule.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/* Stdwin module */ +X +X/* Stdwin itself is a module, not a separate object type. +X Object types defined here: +X wp: a window +X dp: a drawing structure (only one can exist at a time) +X mp: a menu +X tp: a textedit block +X*/ +X +X/* Rules for translating C stdwin function calls into Python stwin: +X - All names drop their initial letter 'w' +X - Functions with a window as first parameter are methods of window objects +X - There is no equivalent for wclose(); just delete the window object +X (all references to it!) (XXX maybe this is a bad idea) +X - w.begindrawing() returns a drawing object +X - There is no equivalent for wenddrawing(win); just delete the drawing +X object (all references to it!) (XXX maybe this is a bad idea) +X - Functions that may only be used inside wbegindrawing / wendddrawing +X are methods of the drawing object; this includes the text measurement +X functions (which however have doubles as module functions). +X - Methods of the drawing object drop an initial 'draw' from their name +X if they have it, e.g., wdrawline() --> d.line() +X - The obvious type conversions: int --> intobject; string --> stringobject +X - A text parameter followed by a length parameter is only a text (string) +X parameter in Python +X - A point or other pair of horizontal and vertical coordinates is always +X a pair of integers in Python +X - Two points forming a rectangle or endpoints of a line segment are a +X pair of points in Python +X - The arguments to d.elarc() are three points. +X - The functions wgetclip() and wsetclip() are translated into +X stdwin.getcutbuffer() and stdwin.setcutbuffer(); 'clip' is really +X a bad word for what these functions do (clipping has a different +X meaning in the drawing world), while cutbuffer is standard X jargon. +X XXX This must change again in the light of changes to stdwin! +X - For textedit, similar rules hold, but they are less strict. +X XXX more? +X*/ +X +X#include "allobjects.h" +X +X#include "modsupport.h" +X +X#include "stdwin.h" +X +X/* Window and menu object types declared here because of forward references */ +X +Xtypedef struct { +X OB_HEAD +X object *w_title; +X WINDOW *w_win; +X object *w_attr; /* Attributes dictionary */ +X} windowobject; +X +Xextern typeobject Windowtype; /* Really static, forward */ +X +X#define is_windowobject(wp) ((wp)->ob_type == &Windowtype) +X +Xtypedef struct { +X OB_HEAD +X MENU *m_menu; +X int m_id; +X object *m_attr; /* Attributes dictionary */ +X} menuobject; +X +Xextern typeobject Menutype; /* Really static, forward */ +X +X#define is_menuobject(mp) ((mp)->ob_type == &Menutype) +X +X +X/* Strongly stdwin-specific argument handlers */ +X +Xstatic int +Xgetmousedetail(v, ep) +X object *v; +X EVENT *ep; +X{ +X if (v == NULL || !is_tupleobject(v) || gettuplesize(v) != 4) +X return err_badarg(); +X return getintintarg(gettupleitem(v, 0), +X &ep->u.where.h, &ep->u.where.v) && +X getintarg(gettupleitem(v, 1), &ep->u.where.clicks) && +X getintarg(gettupleitem(v, 2), &ep->u.where.button) && +X getintarg(gettupleitem(v, 3), &ep->u.where.mask); +X} +X +Xstatic int +Xgetmenudetail(v, ep) +X object *v; +X EVENT *ep; +X{ +X object *mp; +X if (v == NULL || !is_tupleobject(v) || gettuplesize(v) != 2) +X return err_badarg(); +X mp = gettupleitem(v, 0); +X if (mp == NULL || !is_menuobject(mp)) +X return err_badarg(); +X ep->u.m.id = ((menuobject *)mp) -> m_id; +X return getintarg(gettupleitem(v, 1), &ep->u.m.item); +X} +X +Xstatic int +Xgeteventarg(v, ep) +X object *v; +X EVENT *ep; +X{ +X object *wp, *detail; +X int a[4]; +X if (v == NULL || !is_tupleobject(v) || gettuplesize(v) != 3) +X return err_badarg(); +X if (!getintarg(gettupleitem(v, 0), &ep->type)) +X return 0; +X wp = gettupleitem(v, 1); +X if (wp == None) +X ep->window = NULL; +X else if (wp == NULL || !is_windowobject(wp)) +X return err_badarg(); +X else +X ep->window = ((windowobject *)wp) -> w_win; +X detail = gettupleitem(v, 2); +X switch (ep->type) { +X case WE_CHAR: +X if (!is_stringobject(detail) || getstringsize(detail) != 1) +X return err_badarg(); +X ep->u.character = getstringvalue(detail)[0]; +X return 1; +X case WE_COMMAND: +X return getintarg(detail, &ep->u.command); +X case WE_DRAW: +X if (!getrectarg(detail, a)) +X return 0; +X ep->u.area.left = a[0]; +X ep->u.area.top = a[1]; +X ep->u.area.right = a[2]; +X ep->u.area.bottom = a[3]; +X return 1; +X case WE_MOUSE_DOWN: +X case WE_MOUSE_UP: +X case WE_MOUSE_MOVE: +X return getmousedetail(detail, ep); +X case WE_MENU: +X return getmenudetail(detail, ep); +X default: +X return 1; +X } +X} +X +X +X/* Return construction tools */ +X +Xstatic object * +Xmakepoint(a, b) +X int a, b; +X{ +X object *v; +X object *w; +X if ((v = newtupleobject(2)) == NULL) +X return NULL; +X if ((w = newintobject((long)a)) == NULL || +X settupleitem(v, 0, w) != 0 || +X (w = newintobject((long)b)) == NULL || +X settupleitem(v, 1, w) != 0) { +X DECREF(v); +X return NULL; +X } +X return v; +X} +X +Xstatic object * +Xmakerect(a, b, c, d) +X int a, b, c, d; +X{ +X object *v; +X object *w; +X if ((v = newtupleobject(2)) == NULL) +X return NULL; +X if ((w = makepoint(a, b)) == NULL || +X settupleitem(v, 0, w) != 0 || +X (w = makepoint(c, d)) == NULL || +X settupleitem(v, 1, w) != 0) { +X DECREF(v); +X return NULL; +X } +X return v; +X} +X +Xstatic object * +Xmakemouse(hor, ver, clicks, button, mask) +X int hor, ver, clicks, button, mask; +X{ +X object *v; +X object *w; +X if ((v = newtupleobject(4)) == NULL) +X return NULL; +X if ((w = makepoint(hor, ver)) == NULL || +X settupleitem(v, 0, w) != 0 || +X (w = newintobject((long)clicks)) == NULL || +X settupleitem(v, 1, w) != 0 || +X (w = newintobject((long)button)) == NULL || +X settupleitem(v, 2, w) != 0 || +X (w = newintobject((long)mask)) == NULL || +X settupleitem(v, 3, w) != 0) { +X DECREF(v); +X return NULL; +X } +X return v; +X} +X +Xstatic object * +Xmakemenu(mp, item) +X object *mp; +X int item; +X{ +X object *v; +X object *w; +X if ((v = newtupleobject(2)) == NULL) +X return NULL; +X INCREF(mp); +X if (settupleitem(v, 0, mp) != 0 || +X (w = newintobject((long)item)) == NULL || +X settupleitem(v, 1, w) != 0) { +X DECREF(v); +X return NULL; +X } +X return v; +X} +X +X +X/* Drawing objects */ +X +Xtypedef struct { +X OB_HEAD +X windowobject *d_ref; +X} drawingobject; +X +Xstatic drawingobject *Drawing; /* Set to current drawing object, or NULL */ +X +X/* Drawing methods */ +X +Xstatic void +Xdrawing_dealloc(dp) +X drawingobject *dp; +X{ +X wenddrawing(dp->d_ref->w_win); +X Drawing = NULL; +X DECREF(dp->d_ref); +X free((char *)dp); +X} +X +Xstatic object * +Xdrawing_generic(dp, args, func) +X drawingobject *dp; +X object *args; +X void (*func) FPROTO((int, int, int, int)); +X{ +X int a[4]; +X if (!getrectarg(args, a)) +X return NULL; +X (*func)(a[0], a[1], a[2], a[3]); +X INCREF(None); +X return None; +X} +X +Xstatic object * +Xdrawing_line(dp, args) +X drawingobject *dp; +X object *args; +X{ +X drawing_generic(dp, args, wdrawline); +X} +X +Xstatic object * +Xdrawing_xorline(dp, args) +X drawingobject *dp; +X object *args; +X{ +X drawing_generic(dp, args, wxorline); +X} +X +Xstatic object * +Xdrawing_circle(dp, args) +X drawingobject *dp; +X object *args; +X{ +X int a[3]; +X if (!getpointintarg(args, a)) +X return NULL; +X wdrawcircle(a[0], a[1], a[2]); +X INCREF(None); +X return None; +X} +X +Xstatic object * +Xdrawing_elarc(dp, args) +X drawingobject *dp; +X object *args; +X{ +X int a[6]; +X if (!get3pointarg(args, a)) +X return NULL; +X wdrawelarc(a[0], a[1], a[2], a[3], a[4], a[5]); +X INCREF(None); +X return None; +X} +X +Xstatic object * +Xdrawing_box(dp, args) +X drawingobject *dp; +X object *args; +X{ +X drawing_generic(dp, args, wdrawbox); +X} +X +Xstatic object * +Xdrawing_erase(dp, args) +X drawingobject *dp; +X object *args; +X{ +X drawing_generic(dp, args, werase); +X} +X +Xstatic object * +Xdrawing_paint(dp, args) +X drawingobject *dp; +X object *args; +X{ +X drawing_generic(dp, args, wpaint); +X} +X +Xstatic object * +Xdrawing_invert(dp, args) +X drawingobject *dp; +X object *args; +X{ +X drawing_generic(dp, args, winvert); +X} +X +Xstatic object * +Xdrawing_cliprect(dp, args) +X drawingobject *dp; +X object *args; +X{ +X drawing_generic(dp, args, wcliprect); +X} +X +Xstatic object * +Xdrawing_noclip(dp, args) +X drawingobject *dp; +X object *args; +X{ +X if (!getnoarg(args)) +X return NULL; +X wnoclip(); +X INCREF(None); +X return None; +X} +X +Xstatic object * +Xdrawing_shade(dp, args) +X drawingobject *dp; +X object *args; +X{ +X int a[5]; +X if (!getrectintarg(args, a)) +X return NULL; +X wshade(a[0], a[1], a[2], a[3], a[4]); +X INCREF(None); +X return None; +X} +X +Xstatic object * +Xdrawing_text(dp, args) +X drawingobject *dp; +X object *args; +X{ +X int a[2]; +X object *s; +X if (!getpointstrarg(args, a, &s)) +X return NULL; +X wdrawtext(a[0], a[1], getstringvalue(s), (int)getstringsize(s)); +X INCREF(None); +X return None; +X} +X +X/* The following four are also used as stdwin functions */ +X +Xstatic object * +Xdrawing_lineheight(dp, args) +X drawingobject *dp; +X object *args; +X{ +X if (!getnoarg(args)) +X return NULL; +X return newintobject((long)wlineheight()); +X} +X +Xstatic object * +Xdrawing_baseline(dp, args) +X drawingobject *dp; +X object *args; +X{ +X if (!getnoarg(args)) +X return NULL; +X return newintobject((long)wbaseline()); +X} +X +Xstatic object * +Xdrawing_textwidth(dp, args) +X drawingobject *dp; +X object *args; +X{ +X object *s; +X if (!getstrarg(args, &s)) +X return NULL; +X return newintobject( +X (long)wtextwidth(getstringvalue(s), (int)getstringsize(s))); +X} +X +Xstatic object * +Xdrawing_textbreak(dp, args) +X drawingobject *dp; +X object *args; +X{ +X object *s; +X int a; +X if (!getstrintarg(args, &s, &a)) +X return NULL; +X return newintobject( +X (long)wtextbreak(getstringvalue(s), (int)getstringsize(s), a)); +X} +X +Xstatic struct methodlist drawing_methods[] = { +X {"box", drawing_box}, +X {"circle", drawing_circle}, +X {"cliprect", drawing_cliprect}, +X {"elarc", drawing_elarc}, +X {"erase", drawing_erase}, +X {"invert", drawing_invert}, +X {"line", drawing_line}, +X {"noclip", drawing_noclip}, +X {"paint", drawing_paint}, +X {"shade", drawing_shade}, +X {"text", drawing_text}, +X {"xorline", drawing_xorline}, +X +X /* Text measuring methods: */ +X {"baseline", drawing_baseline}, +X {"lineheight", drawing_lineheight}, +X {"textbreak", drawing_textbreak}, +X {"textwidth", drawing_textwidth}, +X {NULL, NULL} /* sentinel */ +X}; +X +Xstatic object * +Xdrawing_getattr(wp, name) +X drawingobject *wp; +X char *name; +X{ +X return findmethod(drawing_methods, (object *)wp, name); +X} +X +Xstatic typeobject Drawingtype = { +X OB_HEAD_INIT(&Typetype) +X 0, /*ob_size*/ +X "drawing", /*tp_name*/ +X sizeof(drawingobject), /*tp_size*/ +X 0, /*tp_itemsize*/ +X /* methods */ +X drawing_dealloc, /*tp_dealloc*/ +X 0, /*tp_print*/ +X drawing_getattr, /*tp_getattr*/ +X 0, /*tp_setattr*/ +X 0, /*tp_compare*/ +X 0, /*tp_repr*/ +X}; +X +X +X/* Text(edit) objects */ +X +Xtypedef struct { +X OB_HEAD +X TEXTEDIT *t_text; +X windowobject *t_ref; +X object *t_attr; /* Attributes dictionary */ +X} textobject; +X +Xextern typeobject Texttype; /* Really static, forward */ +X +Xstatic textobject * +Xnewtextobject(wp, left, top, right, bottom) +X windowobject *wp; +X int left, top, right, bottom; +X{ +X textobject *tp; +X tp = NEWOBJ(textobject, &Texttype); +X if (tp == NULL) +X return NULL; +X tp->t_attr = NULL; +X INCREF(wp); +X tp->t_ref = wp; +X tp->t_text = tecreate(wp->w_win, left, top, right, bottom); +X if (tp->t_text == NULL) { +X DECREF(tp); +X return (textobject *) err_nomem(); +X } +X return tp; +X} +X +X/* Text(edit) methods */ +X +Xstatic void +Xtext_dealloc(tp) +X textobject *tp; +X{ +X if (tp->t_text != NULL) +X tefree(tp->t_text); +X if (tp->t_attr != NULL) +X DECREF(tp->t_attr); +X DECREF(tp->t_ref); +X DEL(tp); +X} +X +Xstatic object * +Xtext_arrow(self, args) +X textobject *self; +X object *args; +X{ +X int code; +X if (!getintarg(args, &code)) +X return NULL; +X tearrow(self->t_text, code); +X INCREF(None); +X return None; +X} +X +Xstatic object * +Xtext_draw(self, args) +X textobject *self; +X object *args; +X{ +X register TEXTEDIT *tp = self->t_text; +X int a[4]; +X int left, top, right, bottom; +X if (!getrectarg(args, a)) +X return NULL; +X if (Drawing != NULL) { +X err_setstr(RuntimeError, "not drawing"); +X return NULL; +X } +X /* Clip to text area and ignore if area is empty */ +X left = tegetleft(tp); +X top = tegettop(tp); +X right = tegetright(tp); +X bottom = tegetbottom(tp); +X if (a[0] < left) a[0] = left; +X if (a[1] < top) a[1] = top; +X if (a[2] > right) a[2] = right; +X if (a[3] > bottom) a[3] = bottom; +X if (a[0] < a[2] && a[1] < a[3]) { +X /* Hide/show focus around draw call; these are undocumented, +X but required here to get the highlighting correct. +X The call to werase is also required for this reason. +X Finally, this forces us to require (above) that we are NOT +X already drawing. */ +X tehidefocus(tp); +X wbegindrawing(self->t_ref->w_win); +X werase(a[0], a[1], a[2], a[3]); +X tedrawnew(tp, a[0], a[1], a[2], a[3]); +X wenddrawing(self->t_ref->w_win); +X teshowfocus(tp); +X } +X INCREF(None); +X return None; +X} +X +Xstatic object * +Xtext_event(self, args) +X textobject *self; +X object *args; +X{ +X register TEXTEDIT *tp = self->t_text; +X EVENT e; +X if (!geteventarg(args, &e)) +X return NULL; +X if (e.type == WE_MOUSE_DOWN) { +X /* Cheat at the margins */ +X int width, height; +X wgetdocsize(e.window, &width, &height); +X if (e.u.where.h < 0 && tegetleft(tp) == 0) +X e.u.where.h = 0; +X else if (e.u.where.h > width && tegetright(tp) == width) +X e.u.where.h = width; +X if (e.u.where.v < 0 && tegettop(tp) == 0) +X e.u.where.v = 0; +X else if (e.u.where.v > height && tegetright(tp) == height) +X e.u.where.v = height; +X } +X return newintobject((long) teevent(tp, &e)); +X} +X +Xstatic object * +Xtext_getfocus(self, args) +X textobject *self; +X object *args; +X{ +X if (!getnoarg(args)) +X return NULL; +X return makepoint(tegetfoc1(self->t_text), tegetfoc2(self->t_text)); +X} +X +Xstatic object * +Xtext_getfocustext(self, args) +X textobject *self; +X object *args; +X{ +X int f1, f2; +X char *text; +X if (!getnoarg(args)) +X return NULL; +X f1 = tegetfoc1(self->t_text); +X f2 = tegetfoc2(self->t_text); +X text = tegettext(self->t_text); +X return newsizedstringobject(text + f1, f2-f1); +X} +X +Xstatic object * +Xtext_getrect(self, args) +X textobject *self; +X object *args; +X{ +X if (!getnoarg(args)) +X return NULL; +X return makerect(tegetleft(self->t_text), +X tegettop(self->t_text), +X tegetright(self->t_text), +X tegetbottom(self->t_text)); +X} +X +Xstatic object * +Xtext_gettext(self, args) +X textobject *self; +X object *args; +X{ +X if (!getnoarg(args)) +X return NULL; +X return newsizedstringobject(tegettext(self->t_text), +X tegetlen(self->t_text)); +X} +X +Xstatic object * +Xtext_move(self, args) +X textobject *self; +X object *args; +X{ +X int a[4]; +X if (!getrectarg(args, a)) +X return NULL; +X temovenew(self->t_text, a[0], a[1], a[2], a[3]); +X INCREF(None); +X return None; +X} +X +Xstatic object * +Xtext_setfocus(self, args) +X textobject *self; +X object *args; +X{ +X int a[2]; +X if (!getpointarg(args, a)) +X return NULL; +X tesetfocus(self->t_text, a[0], a[1]); +X INCREF(None); +X return None; +X} +X +Xstatic object * +Xtext_replace(self, args) +X textobject *self; +X object *args; +X{ +X object *text; +X if (!getstrarg(args, &text)) +X return NULL; +X tereplace(self->t_text, getstringvalue(text)); +X INCREF(None); +X return None; +X} +X +Xstatic struct methodlist text_methods[] = { +X "arrow", text_arrow, +X "draw", text_draw, +X "event", text_event, +X "getfocus", text_getfocus, +X "getfocustext", text_getfocustext, +X "getrect", text_getrect, +X "gettext", text_gettext, +X "move", text_move, +X "replace", text_replace, +X "setfocus", text_setfocus, +X {NULL, NULL} /* sentinel */ +X}; +X +Xstatic object * +Xtext_getattr(tp, name) +X textobject *tp; +X char *name; +X{ +X if (tp->t_attr != NULL) { +X object *v = dictlookup(tp->t_attr, name); +X if (v != NULL) { +X INCREF(v); +X return v; +X } +X } +X return findmethod(text_methods, (object *)tp, name); +X} +X +Xstatic int +Xtext_setattr(tp, name, v) +X textobject *tp; +X char *name; +X object *v; +X{ +X if (tp->t_attr == NULL) { +X tp->t_attr = newdictobject(); +X if (tp->t_attr == NULL) +X return -1; +X } +X if (v == NULL) +X return dictremove(tp->t_attr, name); +X else +X return dictinsert(tp->t_attr, name, v); +X} +X +Xstatic typeobject Texttype = { +X OB_HEAD_INIT(&Typetype) +X 0, /*ob_size*/ +X "textedit", /*tp_name*/ +X sizeof(textobject), /*tp_size*/ +X 0, /*tp_itemsize*/ +X /* methods */ +X text_dealloc, /*tp_dealloc*/ +X 0, /*tp_print*/ +X text_getattr, /*tp_getattr*/ +X text_setattr, /*tp_setattr*/ +X 0, /*tp_compare*/ +X 0, /*tp_repr*/ +X}; +X +X +X/* Menu objects */ +X +X#define IDOFFSET 10 /* Menu IDs we use start here */ +X#define MAXNMENU 20 /* Max #menus we allow */ +Xstatic menuobject *menulist[MAXNMENU]; +X +Xstatic menuobject * +Xnewmenuobject(title) +X object *title; +X{ +X int id; +X MENU *menu; +X menuobject *mp; +X for (id = 0; id < MAXNMENU; id++) { +X if (menulist[id] == NULL) +X break; +X } +X if (id >= MAXNMENU) +X return (menuobject *) err_nomem(); +X menu = wmenucreate(id + IDOFFSET, getstringvalue(title)); +X if (menu == NULL) +X return (menuobject *) err_nomem(); +X mp = NEWOBJ(menuobject, &Menutype); +X if (mp != NULL) { +X mp->m_menu = menu; +X mp->m_id = id + IDOFFSET; +X mp->m_attr = NULL; +X menulist[id] = mp; +X } +X else +X wmenudelete(menu); +X return mp; +X} +X +X/* Menu methods */ +X +Xstatic void +Xmenu_dealloc(mp) +X menuobject *mp; +X{ +X +X int id = mp->m_id - IDOFFSET; +X if (id >= 0 && id < MAXNMENU && menulist[id] == mp) { +X menulist[id] = NULL; +X } +X wmenudelete(mp->m_menu); +X if (mp->m_attr != NULL) +X DECREF(mp->m_attr); +X DEL(mp); +X} +X +Xstatic object * +Xmenu_additem(self, args) +X menuobject *self; +X object *args; +X{ +X object *text; +X int shortcut; +X if (is_tupleobject(args)) { +X object *v; +X if (!getstrstrarg(args, &text, &v)) +X return NULL; +X if (getstringsize(v) != 1) { +X err_badarg(); +X return NULL; +X } +X shortcut = *getstringvalue(v) & 0xff; +X } +X else { +X if (!getstrarg(args, &text)) +X return NULL; +X shortcut = -1; +X } +X wmenuadditem(self->m_menu, getstringvalue(text), shortcut); +X INCREF(None); +X return None; +X} +X +Xstatic object * +Xmenu_setitem(self, args) +X menuobject *self; +X object *args; +X{ +X int index; +X object *text; +X if (!getintstrarg(args, &index, &text)) +X return NULL; +X wmenusetitem(self->m_menu, index, getstringvalue(text)); +X INCREF(None); +X return None; +X} +X +Xstatic object * +Xmenu_enable(self, args) +X menuobject *self; +X object *args; +X{ +X int index; +X int flag; +X if (!getintintarg(args, &index, &flag)) +X return NULL; +X wmenuenable(self->m_menu, index, flag); +X INCREF(None); +X return None; +X} +X +Xstatic object * +Xmenu_check(self, args) +X menuobject *self; +X object *args; +X{ +X int index; +X int flag; +X if (!getintintarg(args, &index, &flag)) +X return NULL; +X wmenucheck(self->m_menu, index, flag); +X INCREF(None); +X return None; +X} +X +Xstatic struct methodlist menu_methods[] = { +X "additem", menu_additem, +X "setitem", menu_setitem, +X "enable", menu_enable, +X "check", menu_check, +X {NULL, NULL} /* sentinel */ +X}; +X +Xstatic object * +Xmenu_getattr(mp, name) +X menuobject *mp; +X char *name; +X{ +X if (mp->m_attr != NULL) { +X object *v = dictlookup(mp->m_attr, name); +X if (v != NULL) { +X INCREF(v); +X return v; +X } +X } +X return findmethod(menu_methods, (object *)mp, name); +X} +X +Xstatic int +Xmenu_setattr(mp, name, v) +X menuobject *mp; +X char *name; +X object *v; +X{ +X if (mp->m_attr == NULL) { +X mp->m_attr = newdictobject(); +X if (mp->m_attr == NULL) +X return -1; +X } +X if (v == NULL) +X return dictremove(mp->m_attr, name); +X else +X return dictinsert(mp->m_attr, name, v); +X} +X +Xstatic typeobject Menutype = { +X OB_HEAD_INIT(&Typetype) +X 0, /*ob_size*/ +X "menu", /*tp_name*/ +X sizeof(menuobject), /*tp_size*/ +X 0, /*tp_itemsize*/ +X /* methods */ +X menu_dealloc, /*tp_dealloc*/ +X 0, /*tp_print*/ +X menu_getattr, /*tp_getattr*/ +X menu_setattr, /*tp_setattr*/ +X 0, /*tp_compare*/ +X 0, /*tp_repr*/ +X}; +X +X +X/* Windows */ +X +X#define MAXNWIN 50 +Xstatic windowobject *windowlist[MAXNWIN]; +X +X/* Window methods */ +X +Xstatic void +Xwindow_dealloc(wp) +X windowobject *wp; +X{ +X if (wp->w_win != NULL) { +X int tag = wgettag(wp->w_win); +X if (tag >= 0 && tag < MAXNWIN) +X windowlist[tag] = NULL; +X else +X fprintf(stderr, "XXX help! tag %d in window_dealloc\n", +X tag); +X wclose(wp->w_win); +X } +X DECREF(wp->w_title); +X if (wp->w_attr != NULL) +X DECREF(wp->w_attr); +X free((char *)wp); +X} +X +Xstatic void +Xwindow_print(wp, fp, flags) +X windowobject *wp; +X FILE *fp; +X int flags; +X{ +X fprintf(fp, "", getstringvalue(wp->w_title)); +X} +X +Xstatic object * +Xwindow_begindrawing(wp, args) +X windowobject *wp; +X object *args; +X{ +X drawingobject *dp; +X if (!getnoarg(args)) +X return NULL; +X if (Drawing != NULL) { +X err_setstr(RuntimeError, "already drawing"); +X return NULL; +X } +X dp = NEWOBJ(drawingobject, &Drawingtype); +X if (dp == NULL) +X return NULL; +X Drawing = dp; +X INCREF(wp); +X dp->d_ref = wp; +X wbegindrawing(wp->w_win); +X return (object *)dp; +X} +X +Xstatic object * +Xwindow_change(wp, args) +X windowobject *wp; +X object *args; +X{ +X int a[4]; +X if (!getrectarg(args, a)) +X return NULL; +X wchange(wp->w_win, a[0], a[1], a[2], a[3]); +X INCREF(None); +X return None; +X} +X +Xstatic object * +Xwindow_gettitle(wp, args) +X windowobject *wp; +X object *args; +X{ +X if (!getnoarg(args)) +X return NULL; +X INCREF(wp->w_title); +X return wp->w_title; +X} +X +Xstatic object * +Xwindow_getwinsize(wp, args) +X windowobject *wp; +X object *args; +X{ +X int width, height; +X if (!getnoarg(args)) +X return NULL; +X wgetwinsize(wp->w_win, &width, &height); +X return makepoint(width, height); +X} +X +Xstatic object * +Xwindow_getdocsize(wp, args) +X windowobject *wp; +X object *args; +X{ +X int width, height; +X if (!getnoarg(args)) +X return NULL; +X wgetdocsize(wp->w_win, &width, &height); +X return makepoint(width, height); +X} +X +Xstatic object * +Xwindow_getorigin(wp, args) +X windowobject *wp; +X object *args; +X{ +X int width, height; +X if (!getnoarg(args)) +X return NULL; +X wgetorigin(wp->w_win, &width, &height); +X return makepoint(width, height); +X} +X +Xstatic object * +Xwindow_scroll(wp, args) +X windowobject *wp; +X object *args; +X{ +X int a[6]; +X if (!getrectpointarg(args, a)) +X return NULL; +X wscroll(wp->w_win, a[0], a[1], a[2], a[3], a[4], a[5]); +X INCREF(None); +X return None; +X} +X +Xstatic object * +Xwindow_setdocsize(wp, args) +X windowobject *wp; +X object *args; +X{ +X int a[2]; +X if (!getpointarg(args, a)) +X return NULL; +X wsetdocsize(wp->w_win, a[0], a[1]); +X INCREF(None); +X return None; +X} +X +Xstatic object * +Xwindow_setorigin(wp, args) +X windowobject *wp; +X object *args; +X{ +X int a[2]; +X if (!getpointarg(args, a)) +X return NULL; +X wsetorigin(wp->w_win, a[0], a[1]); +X INCREF(None); +X return None; +X} +X +Xstatic object * +Xwindow_settitle(wp, args) +X windowobject *wp; +X object *args; +X{ +X object *title; +X if (!getstrarg(args, &title)) +X return NULL; +X DECREF(wp->w_title); +X INCREF(title); +X wp->w_title = title; +X wsettitle(wp->w_win, getstringvalue(title)); +X INCREF(None); +X return None; +X} +X +Xstatic object * +Xwindow_show(wp, args) +X windowobject *wp; +X object *args; +X{ +X int a[4]; +X if (!getrectarg(args, a)) +X return NULL; +X wshow(wp->w_win, a[0], a[1], a[2], a[3]); +X INCREF(None); +X return None; +X} +X +Xstatic object * +Xwindow_settimer(wp, args) +X windowobject *wp; +X object *args; +X{ +X int a; +X if (!getintarg(args, &a)) +X return NULL; +X wsettimer(wp->w_win, a); +X INCREF(None); +X return None; +X} +X +Xstatic object * +Xwindow_menucreate(self, args) +X windowobject *self; +X object *args; +X{ +X menuobject *mp; +X object *title; +X if (!getstrarg(args, &title)) +X return NULL; +X wmenusetdeflocal(1); +X mp = newmenuobject(title); +X if (mp == NULL) +X return NULL; +X wmenuattach(self->w_win, mp->m_menu); +X return (object *)mp; +X} +X +Xstatic object * +Xwindow_textcreate(self, args) +X windowobject *self; +X object *args; +X{ +X textobject *tp; +X int a[4]; +X if (!getrectarg(args, a)) +X return NULL; +X return (object *) +X newtextobject(self, a[0], a[1], a[2], a[3]); +X} +X +Xstatic object * +Xwindow_setselection(self, args) +X windowobject *self; +X object *args; +X{ +X int sel; +X object *str; +X int ok; +X if (!getintstrarg(args, &sel, &str)) +X return NULL; +X ok = wsetselection(self->w_win, sel, +X getstringvalue(str), (int)getstringsize(str)); +X return newintobject(ok); +X} +X +Xstatic object * +Xwindow_setwincursor(self, args) +X windowobject *self; +X object *args; +X{ +X object *str; +X CURSOR *c; +X if (!getstrarg(args, &str)) +X return NULL; +X c = wfetchcursor(getstringvalue(str)); +X if (c == NULL) { +X err_setstr(RuntimeError, "no such cursor"); +X return NULL; +X } +X wsetwincursor(self->w_win, c); +X INCREF(None); +X return None; +X} +X +Xstatic struct methodlist window_methods[] = { +X {"begindrawing",window_begindrawing}, +X {"change", window_change}, +X {"getdocsize", window_getdocsize}, +X {"getorigin", window_getorigin}, +X {"gettitle", window_gettitle}, +X {"getwinsize", window_getwinsize}, +X {"menucreate", window_menucreate}, +X {"scroll", window_scroll}, +X {"setwincursor",window_setwincursor}, +X {"setdocsize", window_setdocsize}, +X {"setorigin", window_setorigin}, +X {"setselection",window_setselection}, +X {"settimer", window_settimer}, +X {"settitle", window_settitle}, +X {"show", window_show}, +X {"textcreate", window_textcreate}, +X {NULL, NULL} /* sentinel */ +X}; +X +Xstatic object * +Xwindow_getattr(wp, name) +X windowobject *wp; +X char *name; +X{ +X if (wp->w_attr != NULL) { +X object *v = dictlookup(wp->w_attr, name); +X if (v != NULL) { +X INCREF(v); +X return v; +X } +X } +X return findmethod(window_methods, (object *)wp, name); +X} +X +Xstatic int +Xwindow_setattr(wp, name, v) +X windowobject *wp; +X char *name; +X object *v; +X{ +X if (wp->w_attr == NULL) { +X wp->w_attr = newdictobject(); +X if (wp->w_attr == NULL) +X return -1; +X } +X if (v == NULL) +X return dictremove(wp->w_attr, name); +X else +X return dictinsert(wp->w_attr, name, v); +X} +X +Xstatic typeobject Windowtype = { +X OB_HEAD_INIT(&Typetype) +X 0, /*ob_size*/ +X "window", /*tp_name*/ +X sizeof(windowobject), /*tp_size*/ +X 0, /*tp_itemsize*/ +X /* methods */ +X window_dealloc, /*tp_dealloc*/ +X window_print, /*tp_print*/ +X window_getattr, /*tp_getattr*/ +X window_setattr, /*tp_setattr*/ +X 0, /*tp_compare*/ +X 0, /*tp_repr*/ +X}; +X +X/* Stdwin methods */ +X +Xstatic object * +Xstdwin_open(sw, args) +X object *sw; +X object *args; +X{ +X int tag; +X object *title; +X windowobject *wp; +X if (!getstrarg(args, &title)) +X return NULL; +X for (tag = 0; tag < MAXNWIN; tag++) { +X if (windowlist[tag] == NULL) +X break; +X } +X if (tag >= MAXNWIN) +X return err_nomem(); +X wp = NEWOBJ(windowobject, &Windowtype); +X if (wp == NULL) +X return NULL; +X INCREF(title); +X wp->w_title = title; +X wp->w_win = wopen(getstringvalue(title), (void (*)()) NULL); +X wp->w_attr = NULL; +X if (wp->w_win == NULL) { +X DECREF(wp); +X return NULL; +X } +X windowlist[tag] = wp; +X wsettag(wp->w_win, tag); +X return (object *)wp; +X} +X +Xstatic object * +Xstdwin_get_poll_event(poll, args) +X int poll; +X object *args; +X{ +X EVENT e; +X object *v, *w; +X if (!getnoarg(args)) +X return NULL; +X if (Drawing != NULL) { +X err_setstr(RuntimeError, "cannot getevent() while drawing"); +X return NULL; +X } +X/* again: */ +X if (poll) { +X if (!wpollevent(&e)) { +X INCREF(None); +X return None; +X } +X } +X else +X wgetevent(&e); +X if (e.type == WE_COMMAND && e.u.command == WC_CANCEL) { +X /* Turn keyboard interrupts into exceptions */ +X err_set(KeyboardInterrupt); +X return NULL; +X } +X/* +X if (e.window == NULL && (e.type == WE_COMMAND || e.type == WE_CHAR)) +X goto again; +X*/ +X if (e.type == WE_COMMAND && e.u.command == WC_CLOSE) { +X /* Turn WC_CLOSE commands into WE_CLOSE events */ +X e.type = WE_CLOSE; +X } +X v = newtupleobject(3); +X if (v == NULL) +X return NULL; +X if ((w = newintobject((long)e.type)) == NULL) { +X DECREF(v); +X return NULL; +X } +X settupleitem(v, 0, w); +X if (e.window == NULL) +X w = None; +X else { +X int tag = wgettag(e.window); +X if (tag < 0 || tag >= MAXNWIN || windowlist[tag] == NULL) +X w = None; +X else +X w = (object *)windowlist[tag]; +X#ifdef sgi +X /* XXX Trap for unexplained weird bug */ +X if ((long)w == (long)0x80000001) { +X err_setstr(SystemError, +X "bad pointer in stdwin.getevent()"); +X return NULL; +X } +X#endif +X } +X INCREF(w); +X settupleitem(v, 1, w); +X switch (e.type) { +X case WE_CHAR: +X { +X char c[1]; +X c[0] = e.u.character; +X w = newsizedstringobject(c, 1); +X } +X break; +X case WE_COMMAND: +X w = newintobject((long)e.u.command); +X break; +X case WE_DRAW: +X w = makerect(e.u.area.left, e.u.area.top, +X e.u.area.right, e.u.area.bottom); +X break; +X case WE_MOUSE_DOWN: +X case WE_MOUSE_MOVE: +X case WE_MOUSE_UP: +X w = makemouse(e.u.where.h, e.u.where.v, +X e.u.where.clicks, +X e.u.where.button, +X e.u.where.mask); +X break; +X case WE_MENU: +X if (e.u.m.id >= IDOFFSET && e.u.m.id < IDOFFSET+MAXNMENU && +X menulist[e.u.m.id - IDOFFSET] != NULL) +X w = (object *)menulist[e.u.m.id - IDOFFSET]; +X else +X w = None; +X w = makemenu(w, e.u.m.item); +X break; +X case WE_LOST_SEL: +X w = newintobject((long)e.u.sel); +X break; +X default: +X w = None; +X INCREF(w); +X break; +X } +X if (w == NULL) { +X DECREF(v); +X return NULL; +X } +X settupleitem(v, 2, w); +X return v; +X} +X +Xstatic object * +Xstdwin_getevent(sw, args) +X object *sw; +X object *args; +X{ +X return stdwin_get_poll_event(0, args); +X} +X +Xstatic object * +Xstdwin_pollevent(sw, args) +X object *sw; +X object *args; +X{ +X return stdwin_get_poll_event(1, args); +X} +X +Xstatic object * +Xstdwin_setdefwinpos(sw, args) +X object *sw; +X object *args; +X{ +X int a[2]; +X if (!getpointarg(args, a)) +X return NULL; +X wsetdefwinpos(a[0], a[1]); +X INCREF(None); +X return None; +X} +X +Xstatic object * +Xstdwin_setdefwinsize(sw, args) +X object *sw; +X object *args; +X{ +X int a[2]; +X if (!getpointarg(args, a)) +X return NULL; +X wsetdefwinsize(a[0], a[1]); +X INCREF(None); +X return None; +X} +X +Xstatic object * +Xstdwin_getdefwinpos(wp, args) +X windowobject *wp; +X object *args; +X{ +X int h, v; +X if (!getnoarg(args)) +X return NULL; +X wgetdefwinpos(&h, &v); +X return makepoint(h, v); +X} +X +Xstatic object * +Xstdwin_getdefwinsize(wp, args) +X windowobject *wp; +X object *args; +X{ +X int width, height; +X if (!getnoarg(args)) +X return NULL; +X wgetdefwinsize(&width, &height); +X return makepoint(width, height); +X} +X +Xstatic object * +Xstdwin_menucreate(self, args) +X object *self; +X object *args; +X{ +X object *title; +X if (!getstrarg(args, &title)) +X return NULL; +X wmenusetdeflocal(0); +X return (object *)newmenuobject(title); +X} +X +Xstatic object * +Xstdwin_askfile(self, args) +X object *self; +X object *args; +X{ +X object *prompt, *dflt; +X int new, ret; +X char buf[256]; +X if (!getstrstrintarg(args, &prompt, &dflt, &new)) +X return NULL; +X strncpy(buf, getstringvalue(dflt), sizeof buf); +X buf[sizeof buf - 1] = '\0'; +X ret = waskfile(getstringvalue(prompt), buf, sizeof buf, new); +X if (!ret) { +X err_set(KeyboardInterrupt); +X return NULL; +X } +X return newstringobject(buf); +X} +X +Xstatic object * +Xstdwin_askync(self, args) +X object *self; +X object *args; +X{ +X object *prompt; +X int new, ret; +X if (!getstrintarg(args, &prompt, &new)) +X return NULL; +X ret = waskync(getstringvalue(prompt), new); +X if (ret < 0) { +X err_set(KeyboardInterrupt); +X return NULL; +X } +X return newintobject((long)ret); +X} +X +Xstatic object * +Xstdwin_askstr(self, args) +X object *self; +X object *args; +X{ +X object *prompt, *dflt; +X int ret; +X char buf[256]; +X if (!getstrstrarg(args, &prompt, &dflt)) +X return NULL; +X strncpy(buf, getstringvalue(dflt), sizeof buf); +X buf[sizeof buf - 1] = '\0'; +X ret = waskstr(getstringvalue(prompt), buf, sizeof buf); +X if (!ret) { +X err_set(KeyboardInterrupt); +X return NULL; +X } +X return newstringobject(buf); +X} +X +Xstatic object * +Xstdwin_message(self, args) +X object *self; +X object *args; +X{ +X object *msg; +X if (!getstrarg(args, &msg)) +X return NULL; +X wmessage(getstringvalue(msg)); +X INCREF(None); +X return None; +X} +X +Xstatic object * +Xstdwin_fleep(self, args) +X object *self; +X object *args; +X{ +X if (!getnoarg(args)) +X return NULL; +X wfleep(); +X INCREF(None); +X return None; +X} +X +Xstatic object * +Xstdwin_setcutbuffer(self, args) +X object *self; +X object *args; +X{ +X int i; +X object *str; +X if (!getintstrarg(args, &i, &str)) +X return NULL; +X wsetcutbuffer(i, getstringvalue(str), getstringsize(str)); +X INCREF(None); +X return None; +X} +X +Xstatic object * +Xstdwin_getcutbuffer(self, args) +X object *self; +X object *args; +X{ +X int i; +X char *str; +X int len; +X if (!getintarg(args, &i)) +X return NULL; +X str = wgetcutbuffer(i, &len); +X if (str == NULL) { +X str = ""; +X len = 0; +X } +X return newsizedstringobject(str, len); +X} +X +Xstatic object * +Xstdwin_rotatecutbuffers(self, args) +X object *self; +X object *args; +X{ +X int i; +X if (!getintarg(args, &i)) +X return NULL; +X wrotatecutbuffers(i); +X INCREF(None); +X return None; +X} +X +Xstatic object * +Xstdwin_getselection(self, args) +X object *self; +X object *args; +X{ +X int sel; +X char *data; +X int len; +X if (!getintarg(args, &sel)) +X return NULL; +X data = wgetselection(sel, &len); +X if (data == NULL) { +X data = ""; +X len = 0; +X } +X return newsizedstringobject(data, len); +X} +X +Xstatic object * +Xstdwin_resetselection(self, args) +X object *self; +X object *args; +X{ +X int sel; +X if (!getintarg(args, &sel)) +X return NULL; +X wresetselection(sel); +X INCREF(None); +X return None; +X} +X +Xstatic struct methodlist stdwin_methods[] = { +X {"askfile", stdwin_askfile}, +X {"askstr", stdwin_askstr}, +X {"askync", stdwin_askync}, +X {"fleep", stdwin_fleep}, +X {"getselection", stdwin_getselection}, +X {"getcutbuffer", stdwin_getcutbuffer}, +X {"getdefwinpos", stdwin_getdefwinpos}, +X {"getdefwinsize", stdwin_getdefwinsize}, +X {"getevent", stdwin_getevent}, +X {"menucreate", stdwin_menucreate}, +X {"message", stdwin_message}, +X {"open", stdwin_open}, +X {"pollevent", stdwin_pollevent}, +X {"resetselection", stdwin_resetselection}, +X {"rotatecutbuffers", stdwin_rotatecutbuffers}, +X {"setcutbuffer", stdwin_setcutbuffer}, +X {"setdefwinpos", stdwin_setdefwinpos}, +X {"setdefwinsize", stdwin_setdefwinsize}, +X +X /* Text measuring methods borrow code from drawing objects: */ +X {"baseline", drawing_baseline}, +X {"lineheight", drawing_lineheight}, +X {"textbreak", drawing_textbreak}, +X {"textwidth", drawing_textwidth}, +X {NULL, NULL} /* sentinel */ +X}; +X +Xvoid +Xinitstdwin() +X{ +X static int inited; +X if (!inited) { +X winit(); +X inited = 1; +X } +X initmodule("stdwin", stdwin_methods); +X} +EOF +fi +echo 'Part 04 out of 21 of pack.out complete.' +exit 0 diff --git a/shar/python-0.9.1-05-21.shar b/shar/python-0.9.1-05-21.shar new file mode 100644 index 0000000..2d7f035 --- /dev/null +++ b/shar/python-0.9.1-05-21.shar @@ -0,0 +1,2528 @@ +: 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 05 out of 21:' +if test -s 'demo/sgi/audio_stdwin/README' +then echo '*** I will not over-write existing file demo/sgi/audio_stdwin/README' +else +echo 'x - demo/sgi/audio_stdwin/README' +sed 's/^X//' > 'demo/sgi/audio_stdwin/README' << 'EOF' +XThree programs that provide a user interface based upon STDWIN to the +Xaudio device of the SGI 4D/25. These scripts also demonstrate the power +Xof a set of window interface classes implemented in Python that simplify +Xthe construction of all sorts of buttons, etc. +X +Xjukebox Browses a directory full of sound samples and lets you +X play selected ones. (Probably not fully functional, it +X requires a conversion program.) +X +Xrec A tape recorder that lets you record a sound sample, +X play it back, and save it to a file. Various options to +X set sampling rate, volume etc. When idle it doubles +X as a VU meter. +X +Xvumeter A VU meter that displays a history of the volume of +X sound recently sampled from the microphone. +EOF +fi +if test -s 'src/panelmodule.c' +then echo '*** I will not over-write existing file src/panelmodule.c' +else +echo 'x - src/panelmodule.c' +sed 's/^X//' > 'src/panelmodule.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/* Panel module. +X Interface to the NASA Ames "panel library" for the SGI Graphics Library +X by David Tristram. +X +X NOTE: the panel library dumps core if you don't create a window before +X calling pnl.mkpanel(). A call to gl.winopen() suffices. +X If you don't want a window to be created, call gl.noport() before +X gl.winopen(). +X*/ +X +X#include +X#include +X#include +X +X#include "allobjects.h" +X#include "import.h" +X#include "modsupport.h" +X#include "cgensupport.h" +X +X +X/* The offsetof() macro calculates the offset of a structure member +X in its structure. Unfortunately this cannot be written down portably, +X hence it is standardized by ANSI C. For pre-ANSI C compilers, +X we give a version here that works usually (but watch out!): */ +X +X#ifndef offsetof +X#define offsetof(type, member) ( (int) & ((type*)0) -> member ) +X#endif +X +X +X/* Panel objects */ +X +Xtypedef struct { +X OB_HEAD +X Panel *ob_panel; +X object *ob_paneldict; +X} panelobject; +X +Xextern typeobject Paneltype; /* Really static, forward */ +X +X#define is_panelobject(v) ((v)->ob_type == &Paneltype) +X +X +X/* Actuator objects */ +X +Xtypedef struct { +X OB_HEAD +X Actuator *ob_actuator; +X} actuatorobject; +X +Xextern typeobject Actuatortype; /* Really static, forward */ +X +X#define is_actuatorobject(v) ((v)->ob_type == &Actuatortype) +X +Xstatic object *newactuatorobject(); /* Forward */ +X +X +X/* Since we allow different types of members than the functions from +X structmember.c, the memberlist stuff is replicated here. +X (Historically, it originated in this file and later became a generic +X feature.) */ +X +X/* An array of memberlist structures defines the name, type and offset +X of selected members of a C structure. These can be read by +X panel_getmember() and set by panel_setmember() (except if their +X READONLY flag is set). The array must be terminated with an entry +X whose name pointer is NULL. */ +X +Xstruct memberlist { +X char *name; +X int type; +X int offset; +X int readonly; +X}; +X +X/* Types */ +X#define T_SHORT 0 +X#define T_DEVICE T_SHORT +X#define T_LONG 1 +X#define T_INT T_LONG +X#define T_BOOL T_LONG +X#define T_FLOAT 2 +X#define T_COORD T_FLOAT +X#define T_STRING 3 +X#define T_FUNC 4 +X#define T_ACTUATOR 5 +X +X/* Readonly flag */ +X#define READONLY 1 +X#define RO READONLY /* Shorthand */ +X +Xstatic object * +Xpanel_getmember(addr, mlist, name) +X char *addr; +X struct memberlist *mlist; +X char *name; +X{ +X object *v; +X register struct memberlist *l; +X +X for (l = mlist; l->name != NULL; l++) { +X if (strcmp(l->name, name) == 0) { +X addr += l->offset; +X switch (l->type) { +X case T_SHORT: +X v = newintobject((long) *(short*)addr); +X break; +X case T_LONG: +X v = newintobject(*(long*)addr); +X break; +X case T_FLOAT: +X v = newfloatobject(*(float*)addr); +X break; +X case T_STRING: +X if (*(char**)addr == NULL) { +X INCREF(None); +X v = None; +X } +X else +X v = newstringobject(*(char**)addr); +X break; +X case T_ACTUATOR: +X v = newactuatorobject(*(Actuator**)addr); +X break; +X default: +X err_badarg(); +X v = NULL; +X } +X return v; +X } +X } +X err_setstr(NameError, name); +X return NULL; +X} +X +X/* Attempt to set a member. Return: 0 if OK; 1 if not found; -1 if error */ +X +Xstatic int +Xpanel_setmember(addr, mlist, name, v) +X char *addr; +X struct memberlist *mlist; +X char *name; +X object *v; +X{ +X register struct memberlist *l; +X +X for (l = mlist; l->name != NULL; l++) { +X if (strcmp(l->name, name) == 0) { +X if (l->readonly) { +X err_setstr(TypeError, "read-only member"); +X return -1; +X } +X addr += l->offset; +X switch (l->type) { +X case T_SHORT: +X if (!is_intobject(v)) { +X err_setstr(TypeError, "int expected"); +X return -1; +X } +X *(short*)addr = getintvalue(v); +X break; +X case T_LONG: +X if (!is_intobject(v)) { +X err_setstr(TypeError, "int expected"); +X return -1; +X } +X *(long*)addr = getintvalue(v); +X break; +X case T_FLOAT: +X if (is_intobject(v)) +X *(float*)addr = getintvalue(v); +X else if (is_floatobject(v)) +X *(float*)addr = getfloatvalue(v); +X else { +X err_setstr(TypeError,"float expected"); +X return -1; +X } +X break; +X case T_STRING: +X /* XXX Should free(*(char**)addr) here +X but it's dangerous since we don't know +X if we set the label ourselves */ +X if (v == None) +X *(char**)addr = NULL; +X else if (!is_stringobject(v)) { +X err_setstr(TypeError, +X "string expected"); +X return -1; +X } +X else +X *(char**)addr = +X strdup(getstringvalue(v)); +X break; +X case T_ACTUATOR: +X if (v == None) +X *(Actuator**)addr = NULL; +X else if (!is_actuatorobject(v)) { +X err_setstr(TypeError, +X "actuator expected"); +X return -1; +X } +X else +X *(Actuator**)addr = +X ((actuatorobject *)v)->ob_actuator; +X break; +X default: +X err_setstr(SystemError, "unknown member type"); +X return -1; +X } +X return 0; /* Found it */ +X } +X } +X +X return 1; /* Not found */ +X} +X +X +X/* Panel object methods */ +X +Xstatic object * +Xpanel_addpanel(self, args) +X panelobject *self; +X object *args; +X{ +X if (!getnoarg(args)) +X return NULL; +X pnl_addpanel(self->ob_panel); +X INCREF(None); +X return None; +X} +X +Xstatic object * +Xpanel_endgroup(self, args) +X panelobject *self; +X object *args; +X{ +X if (!getnoarg(args)) +X return NULL; +X pnl_endgroup(self->ob_panel); +X INCREF(None); +X return None; +X} +X +Xstatic object * +Xpanel_fixpanel(self, args) +X panelobject *self; +X object *args; +X{ +X if (!getnoarg(args)) +X return NULL; +X pnl_fixpanel(self->ob_panel); +X INCREF(None); +X return None; +X} +X +Xstatic object * +Xpanel_strwidth(self, args) +X panelobject *self; +X object *args; +X{ +X object *v; +X double width; +X if (!getstrarg(args, &v)) +X return NULL; +X width = pnl_strwidth(self->ob_panel, getstringvalue(v)); +X return newfloatobject(width); +X} +X +Xstatic struct methodlist panel_methods[] = { +X {"addpanel", panel_addpanel}, +X {"endgroup", panel_endgroup}, +X {"fixpanel", panel_fixpanel}, +X {"strwidth", panel_strwidth}, +X {NULL, NULL} /* sentinel */ +X}; +X +Xstatic object * +Xnewpanelobject() +X{ +X panelobject *p; +X p = NEWOBJ(panelobject, &Paneltype); +X if (p == NULL) +X return NULL; +X p->ob_panel = pnl_mkpanel(); +X if ((p->ob_paneldict = newdictobject()) == NULL) { +X DECREF(p); +X return NULL; +X } +X return (object *)p; +X} +X +Xstatic void +Xpanel_dealloc(p) +X panelobject *p; +X{ +X pnl_delpanel(p->ob_panel); +X if (p->ob_paneldict != NULL) +X DECREF(p->ob_paneldict); +X DEL(p); +X} +X +X +X/* Table of panel members */ +X +X#define PANOFF(member) offsetof(Panel, member) +X +Xstatic struct memberlist panel_memberlist[] = { +X {"id", T_SHORT, PANOFF(id), READONLY}, +X {"a", T_ACTUATOR, PANOFF(a), READONLY}, +X {"al", T_ACTUATOR, PANOFF(al), READONLY}, +X {"lastgroup", T_ACTUATOR, PANOFF(lastgroup), READONLY}, +X +X {"active", T_BOOL, PANOFF(active)}, +X {"selectable", T_BOOL, PANOFF(selectable)}, +X +X {"x", T_LONG, PANOFF(x)}, +X {"y", T_LONG, PANOFF(y)}, +X {"w", T_LONG, PANOFF(w)}, +X {"h", T_LONG, PANOFF(h)}, +X +X {"minx", T_COORD, PANOFF(minx)}, +X {"maxx", T_COORD, PANOFF(maxx)}, +X {"miny", T_COORD, PANOFF(miny)}, +X {"maxy", T_COORD, PANOFF(maxy)}, +X +X {"cw", T_COORD, PANOFF(cw)}, +X {"ch", T_COORD, PANOFF(ch)}, +X +X {"gid", T_LONG, PANOFF(gid), READONLY}, +X {"usergid", T_LONG, PANOFF(usergid), READONLY}, +X +X {"vobj", T_LONG, PANOFF(vobj), READONLY}, +X {"ppu", T_FLOAT, PANOFF(ppu)}, +X +X {"label", T_STRING, PANOFF(label)}, +X +X /* Panel callbacks are not supported */ +X +X {"visible", T_BOOL, PANOFF(visible)}, +X {"somedirty", T_INT, PANOFF(somedirty)}, +X {"dirtycnt", T_INT, PANOFF(dirtycnt)}, +X +X /* T_PANEL is not supported */ +X /* +X {"next", T_PANEL, PANOFF(next), READONLY}, +X */ +X +X {NULL, 0, 0} /* Sentinel */ +X}; +X +Xstatic object * +Xpanel_getattr(p, name) +X panelobject *p; +X char *name; +X{ +X object *v; +X +X v = dictlookup(p->ob_paneldict, name); +X if (v != NULL) { +X INCREF(v); +X return v; +X } +X +X v = findmethod(panel_methods, (object *)p, name); +X if (v != NULL) +X return v; +X err_clear(); +X return panel_getmember((char *)p->ob_panel, panel_memberlist, name); +X} +X +Xstatic int +Xpanel_setattr(p, name, v) +X panelobject *p; +X char *name; +X object *v; +X{ +X int err; +X +X /* We don't allow deletion of attributes */ +X if (v == NULL) { +X err_setstr(TypeError, "read-only panel attribute"); +X return -1; +X } +X err = panel_setmember((char *)p->ob_panel, panel_memberlist, name, v); +X if (err != 1) +X return err; +X return dictinsert(p->ob_paneldict, name, v); +X} +X +Xstatic typeobject Paneltype = { +X OB_HEAD_INIT(&Typetype) +X 0, /*ob_size*/ +X "panel", /*tp_name*/ +X sizeof(panelobject), /*tp_size*/ +X 0, /*tp_itemsize*/ +X /* methods */ +X panel_dealloc, /*tp_dealloc*/ +X 0, /*tp_print*/ +X panel_getattr, /*tp_getattr*/ +X panel_setattr, /*tp_setattr*/ +X 0, /*tp_compare*/ +X 0, /*tp_repr*/ +X}; +X +X +X/* Descriptions of actuator-specific data members */ +X +Xstruct memberlist slider_spec[] = { +X {"mode", T_INT, offsetof(Slider, mode)}, +X {"finefactor", T_FLOAT, offsetof(Slider, finefactor)}, +X {"differentialfactor", +X T_FLOAT, offsetof(Slider, differentialfactor)}, +X {"valsave", T_FLOAT, offsetof(Slider, valsave), RO}, +X {"wsave", T_COORD, offsetof(Slider, wsave)}, +X {"bh", T_COORD, offsetof(Slider, bh)}, +X {NULL} +X}; +X +X#define palette_spec slider_spec +X +Xstruct memberlist puck_spec[] = { +X /* Actuators already have members x and y, so the Puck's x and y +X have different names */ +X {"puck_x", T_FLOAT, offsetof(Puck, x)}, +X {"puck_y", T_FLOAT, offsetof(Puck, y)}, +X {NULL} +X}; +X +Xstruct memberlist dial_spec[] = { +X {"mode", T_INT, offsetof(Dial, mode)}, +X {"finefactor", T_FLOAT, offsetof(Dial, finefactor)}, +X {"valsave", T_FLOAT, offsetof(Dial, valsave), RO}, +X {"wsave", T_COORD, offsetof(Dial, wsave)}, +X {"winds", T_FLOAT, offsetof(Dial, winds)}, +X {NULL} +X}; +X +Xstruct memberlist slideroid_spec[] = { +X {"mode", T_INT, offsetof(Slideroid, mode)}, +X {"finemode", T_BOOL, offsetof(Slideroid, finemode)}, +X {"resetmode", T_BOOL, offsetof(Slideroid, resetmode)}, +X /* XXX Can't do resettarget (pointer to float) */ +X /* XXX This makes resetval pretty useless... */ +X /* +X {"resetval", T_FLOAT, offsetof(Slideroid, resetval)}, +X */ +X {"valsave", T_FLOAT, offsetof(Slideroid, valsave), RO}, +X {"wsave", T_COORD, offsetof(Slideroid, wsave)}, +X {NULL} +X}; +X +Xstruct memberlist stripchart_spec[] = { +X {"firstpt", T_INT, offsetof(Stripchart, firstpt), RO}, +X {"lastpt", T_INT, offsetof(Stripchart, lastpt), RO}, +X {"Bind_Low", T_BOOL, offsetof(Stripchart, Bind_Low)}, +X {"Bind_High", T_BOOL, offsetof(Stripchart, Bind_High)}, +X /* XXX Can't do y (array of floats) */ +X {"lowlabel", T_ACTUATOR, offsetof(Stripchart, lowlabel), RO}, +X {"highlabel", T_ACTUATOR, offsetof(Stripchart, highlabel), RO}, +X {NULL} +X}; +X +Xstruct memberlist typein_spec[] = { +X /* Note: these should be readonly after the actuator is added +X to a panel */ +X {"str", T_STRING, offsetof(Typein, str)}, +X {"len", T_INT, offsetof(Typein, len)}, +X {NULL} +X}; +X +Xstruct memberlist typeout_spec[] = { +X {"mode", T_INT, offsetof(Typeout, mode)}, +X /* XXX The buffer is managed by the actuator; but how do we +X add text? */ +X {"buf", T_STRING, offsetof(Typeout, buf), READONLY}, +X {"delimstr", T_STRING, offsetof(Typeout, delimstr)}, +X {"start", T_INT, offsetof(Typeout, start)}, +X {"dot", T_INT, offsetof(Typeout, dot)}, +X {"mark", T_INT, offsetof(Typeout, mark)}, +X {"col", T_INT, offsetof(Typeout, col)}, +X {"lin", T_INT, offsetof(Typeout, lin)}, +X {"len", T_INT, offsetof(Typeout, len)}, +X {"size", T_INT, offsetof(Typeout, size)}, +X {NULL} +X}; +X +Xstruct memberlist mouse_spec[] = { +X /* Actuators already have members x and y, so the Mouse's x and y +X have different names */ +X {"mouse_x", T_FLOAT, offsetof(Mouse, x)}, +X {"mouse_y", T_FLOAT, offsetof(Mouse, y)}, +X {NULL} +X}; +X +X#define MULOFF(member) offsetof(Multislider, member) +X +Xstruct memberlist multislider_spec[] = { +X {"mode", T_INT, MULOFF(mode)}, +X {"n", T_INT, MULOFF(n)}, +X {"finefactor", T_FLOAT, MULOFF(finefactor)}, +X {"wsave", T_COORD, MULOFF(wsave)}, +X {"sa", T_ACTUATOR, MULOFF(sa)}, +X {"bh", T_COORD, MULOFF(bh)}, +X {"clrx", T_COORD, MULOFF(clrx)}, +X {"clry", T_COORD, MULOFF(clry)}, +X {"clrw", T_COORD, MULOFF(clrw)}, +X {"clrh", T_COORD, MULOFF(clrh)}, +X /* XXX acttype? */ +X {NULL} +X}; +X +X/* XXX Still to do: +X Frame +X Icon +X Cycle +X Scroll +X Menu +X*/ +X +X/* List of known actuator initializer functions */ +X +Xstruct { +X char *name; +X void (*func)(); +X struct memberlist *spec; +X} initializerlist[] = { +X {"analog_bar", pnl_analog_bar}, +X {"analog_meter", pnl_analog_meter}, +X {"button", pnl_button}, +X {"cycle", pnl_cycle}, +X /* Doesn't exist: */ +X/* {"dhslider", pnl_dhslider, slider_spec}, */ +X {"dial", pnl_dial, dial_spec}, +X {"down_arrow_button", pnl_down_arrow_button}, +X {"down_double_arrow_button", pnl_down_double_arrow_button}, +X {"dvslider", pnl_dvslider, slider_spec}, +X {"filled_hslider", pnl_filled_hslider, slider_spec}, +X {"filled_slider", pnl_filled_slider, slider_spec}, +X {"filled_vslider", pnl_filled_vslider, slider_spec}, +X {"floating_puck", pnl_floating_puck, puck_spec}, +X {"frame", pnl_frame}, +X {"graphframe", pnl_graphframe}, +X {"hmultislider", pnl_hmultislider, multislider_spec}, +X {"hmultislider_bar", pnl_hmultislider_bar}, +X {"hmultislider_open_bar", pnl_hmultislider_open_bar}, +X {"hpalette", pnl_hpalette, palette_spec}, +X {"hslider", pnl_hslider, slider_spec}, +X {"icon", pnl_icon}, +X {"icon_menu", pnl_icon_menu}, +X {"label", pnl_label}, +X {"left_arrow_button", pnl_left_arrow_button}, +X {"left_double_arrow_button", pnl_left_double_arrow_button}, +X {"menu", pnl_menu}, +X {"menu_item", pnl_menu_item}, +X {"meter", pnl_meter}, +X {"mouse", pnl_mouse, mouse_spec}, +X {"multislider", pnl_multislider, multislider_spec}, +X {"multislider_bar", pnl_multislider_bar}, +X {"multislider_open_bar", pnl_multislider_open_bar}, +X {"palette", pnl_palette, palette_spec}, +X {"puck", pnl_puck, puck_spec}, +X {"radio_button", pnl_radio_button}, +X {"radio_check_button", pnl_radio_check_button}, +X {"right_arrow_button", pnl_right_arrow_button}, +X {"right_double_arrow_button", pnl_right_double_arrow_button}, +X {"rubber_puck", pnl_rubber_puck, puck_spec}, +X {"scale_chart", pnl_scale_chart, stripchart_spec}, +X {"scroll", pnl_scroll}, +X {"signal", pnl_signal}, +X {"slider", pnl_slider, slider_spec}, +X {"slideroid", pnl_slideroid, slideroid_spec}, +X {"strip_chart", pnl_strip_chart, stripchart_spec}, +X {"sub_menu", pnl_sub_menu}, +X {"toggle_button", pnl_toggle_button}, +X {"typein", pnl_typein, typein_spec}, +X {"typeout", pnl_typeout, typeout_spec}, +X {"up_arrow_button", pnl_up_arrow_button}, +X {"up_double_arrow_button", pnl_up_double_arrow_button}, +X {"viewframe", pnl_viewframe}, +X {"vmultislider", pnl_vmultislider, multislider_spec}, +X {"vmultislider_bar", pnl_vmultislider_bar}, +X {"vmultislider_open_bar", pnl_vmultislider_open_bar}, +X {"vpalette", pnl_vpalette, palette_spec}, +X {"vslider", pnl_vslider, slider_spec}, +X {"wide_button", pnl_wide_button}, +X {NULL, NULL} /* Sentinel */ +X}; +X +X +X/* Pseudo downfunc etc. */ +X +Xstatic Actuator *down_pend, *active_pend, *up_pend; +X +Xstatic void +Xdownfunc(a) +X Actuator *a; +X{ +X if (down_pend == NULL) +X down_pend = a; +X} +X +Xstatic void +Xactivefunc(a) +X Actuator *a; +X{ +X if (active_pend == NULL) +X active_pend = a; +X} +X +Xstatic void +Xupfunc(a) +X Actuator *a; +X{ +X if (up_pend == NULL) +X up_pend = a; +X} +X +X +X/* Lay-out for the user data */ +X +Xstruct userdata { +X object *dict; /* Dictionary object for additional attributes */ +X struct memberlist *spec; /* Actuator-specific members */ +X}; +X +X +X/* Create a new actuator; the actuator type is given as a string */ +X +Xstatic Actuator * +Xmakeactuator(name) +X char *name; +X{ +X Actuator *act; +X void (*initializer)() = NULL; +X int i; +X struct userdata *u; +X for (i = 0; initializerlist[i].name != NULL; i++) { +X if (strcmp(initializerlist[i].name, name) == 0) { +X initializer = initializerlist[i].func; +X break; +X } +X } +X if (initializerlist[i].name == NULL) { +X err_badarg(); +X return NULL; +X } +X u = NEW(struct userdata, 1); +X if (u == NULL) { +X err_nomem(); +X return NULL; +X } +X u->dict = NULL; +X u->spec = initializerlist[i].spec; +X act = pnl_mkact(initializer); +X act->u = (char *)u; +X act->downfunc = downfunc; +X act->activefunc = activefunc; +X act->upfunc = upfunc; +X return act; +X} +X +X +X/* Actuator objects methods */ +X +Xstatic object * +Xactuator_addact(self, args) +X actuatorobject *self; +X object *args; +X{ +X Panel *p; +X if (!is_panelobject(args)) { +X err_badarg(); +X return NULL; +X } +X p = ((panelobject *)args) -> ob_panel; +X pnl_addact(self->ob_actuator, p); +X INCREF(None); +X return None; +X} +X +Xstatic object * +Xactuator_addsubact(self, args) +X actuatorobject *self; +X object *args; +X{ +X Actuator *a; +X if (!is_actuatorobject(args)) { +X err_badarg(); +X return NULL; +X } +X a = ((actuatorobject *)args) -> ob_actuator; +X pnl_addsubact(self->ob_actuator, a); +X INCREF(None); +X return None; +X} +X +Xstatic object * +Xactuator_delact(self, args) +X actuatorobject *self; +X object *args; +X{ +X Panel *p; +X if (!getnoarg(args)) +X return NULL; +X pnl_delact(self->ob_actuator); +X INCREF(None); +X return None; +X} +X +Xstatic object * +Xactuator_fixact(self, args) +X actuatorobject *self; +X object *args; +X{ +X Panel *p; +X if (!getnoarg(args)) +X return NULL; +X pnl_fixact(self->ob_actuator); +X INCREF(None); +X return None; +X} +X +Xstatic object * +Xactuator_tprint(self, args) +X actuatorobject *self; +X object *args; +X{ +X object *str; +X if (self->ob_actuator->type != PNL_TYPEOUT) { +X err_setstr(TypeError, "tprint for non-typeout panel"); +X return NULL; +X } +X if (!getstrarg(args, &str)) +X return NULL; +X tprint(self->ob_actuator, getstringvalue(str)); +X /* XXX Can't turn tprint's errors into exceptions, sorry */ +X INCREF(None); +X return None; +X} +X +Xstatic struct methodlist actuator_methods[] = { +X {"addact", actuator_addact}, +X {"addsubact", actuator_addsubact}, +X {"delact", actuator_delact}, +X {"fixact", actuator_fixact}, +X {"tprint", actuator_tprint}, +X {NULL, NULL} /* sentinel */ +X}; +X +Xstatic object * +Xnewactuatorobject(act) +X Actuator *act; +X{ +X actuatorobject *a; +X if (act == NULL) { +X INCREF(None); +X return None; +X } +X a = NEWOBJ(actuatorobject, &Actuatortype); +X if (a == NULL) +X return NULL; +X a->ob_actuator = act; +X return (object *)a; +X} +X +Xstatic void +Xactuator_dealloc(a) +X actuatorobject *a; +X{ +X /* Do NOT delete the actuator; most actuator objects are created +X to hold a temporary reference to an actuator, like one gotten +X from pnl_dopanel(). */ +X +X DEL(a); +X} +X +X +X/* Table of actuator members */ +X +X#define ACTOFF(member) offsetof(Actuator, member) +X +Xstruct memberlist act_memberlist[] = { +X {"id", T_SHORT, ACTOFF(id), READONLY}, +X +X /* T_PANEL is not defined */ +X /* +X {"p", T_PANEL, ACTOFF(p), READONLY}, +X */ +X +X {"pa", T_ACTUATOR, ACTOFF(pa), READONLY}, +X {"ca", T_ACTUATOR, ACTOFF(ca), READONLY}, +X {"al", T_ACTUATOR, ACTOFF(al), READONLY}, +X {"na", T_INT, ACTOFF(na), READONLY}, +X {"type", T_INT, ACTOFF(type), READONLY}, +X {"active", T_BOOL, ACTOFF(active)}, +X +X {"x", T_COORD, ACTOFF(x)}, +X {"y", T_COORD, ACTOFF(y)}, +X {"w", T_COORD, ACTOFF(w)}, +X {"h", T_COORD, ACTOFF(h)}, +X +X {"lx", T_COORD, ACTOFF(lx)}, +X {"ly", T_COORD, ACTOFF(ly)}, +X {"lw", T_COORD, ACTOFF(lw)}, +X {"lh", T_COORD, ACTOFF(lh)}, +X {"ld", T_COORD, ACTOFF(ld)}, +X +X {"val", T_FLOAT, ACTOFF(val)}, +X {"extval", T_FLOAT, ACTOFF(extval)}, +X {"initval", T_FLOAT, ACTOFF(initval)}, +X {"maxval", T_FLOAT, ACTOFF(maxval)}, +X {"minval", T_FLOAT, ACTOFF(minval)}, +X {"scalefactor", T_FLOAT, ACTOFF(scalefactor)}, +X +X {"label", T_STRING, ACTOFF(label)}, +X {"key", T_DEVICE, ACTOFF(key)}, +X {"labeltype", T_INT, ACTOFF(labeltype)}, +X +X /* Internal callbacks are not supported; +X user callbacks are treated special! */ +X +X {"dirtycnt", T_INT, ACTOFF(dirtycnt)}, +X +X /* members u and data are accessed differently */ +X +X {"automatic", T_BOOL, ACTOFF(automatic)}, +X {"selectable", T_BOOL, ACTOFF(selectable)}, +X {"visible", T_BOOL, ACTOFF(visible)}, +X {"beveled", T_BOOL, ACTOFF(beveled)}, +X +X {"group", T_ACTUATOR, ACTOFF(group), READONLY}, +X {"next", T_ACTUATOR, ACTOFF(next), READONLY}, +X +X {NULL, 0, 0} /* Sentinel */ +X}; +X +X +X/* Potential name conflicts between attributes are solved as follows. +X - Actuator-specific attributes always override generic attributes. +X - When reading, the dictionary has overrides everything else; +X when writing, everything else overrides the dictionary. +X - When reading, methods are tried last. +X*/ +X +Xstatic object * +Xactuator_getattr(a, name) +X actuatorobject *a; +X char *name; +X{ +X Actuator *act = a->ob_actuator; +X struct userdata *u = (struct userdata *) act->u; +X object *v; +X +X if (u != NULL) { +X /* 1. Try the dictionary */ +X if (u->dict != NULL) { +X v = dictlookup(u->dict, name); +X if (v != NULL) { +X INCREF(v); +X return v; +X } +X } +X +X /* 2. Try actuator-specific attributes */ +X if (u->spec != NULL) { +X v = panel_getmember(act->data, u->spec, name); +X if (v != NULL) +X return v; +X err_clear(); +X } +X } +X +X /* 3. Try generic actuator attributes */ +X v = panel_getmember((char *)act, act_memberlist, name); +X if (v != NULL) +X return v; +X +X /* 4. Try methods */ +X err_clear(); +X return findmethod(actuator_methods, (object *)a, name); +X} +X +Xstatic int +Xactuator_setattr(a, name, v) +X actuatorobject *a; +X char *name; +X object *v; +X{ +X Actuator *act = a->ob_actuator; +X struct userdata *u = (struct userdata *) act->u; +X int err; +X +X /* 0. We don't allow deletion of attributes */ +X if (v == NULL) { +X err_setstr(TypeError, "read-only actuator attribute"); +X return -1; +X } +X +X /* 1. Try actuator-specific attributes */ +X if (u != NULL && u->spec != NULL) { +X err = panel_setmember(act->data, u->spec, name, v); +X if (err != 1) +X return err; +X } +X +X /* 2. Try generic actuator attributes */ +X err = panel_setmember((char *)act, act_memberlist, name, v); +X if (err != 1) +X return err; +X +X /* 3. Try the dictionary */ +X if (u != NULL) { +X if (u->dict == NULL && (u->dict = newdictobject()) == NULL) +X return NULL; +X return dictinsert(u->dict, name, v); +X } +X +X err_setstr(NameError, name); +X return -1; +X} +X +Xstatic int +Xactuator_compare(v, w) +X actuatorobject *v, *w; +X{ +X long i = (long)v->ob_actuator; +X long j = (long)w->ob_actuator; +X return (i < j) ? -1 : (i > j) ? 1 : 0; +X} +X +Xstatic typeobject Actuatortype = { +X OB_HEAD_INIT(&Typetype) +X 0, /*ob_size*/ +X "actuator", /*tp_name*/ +X sizeof(actuatorobject), /*tp_size*/ +X 0, /*tp_itemsize*/ +X /* methods */ +X actuator_dealloc, /*tp_dealloc*/ +X 0, /*tp_print*/ +X actuator_getattr, /*tp_getattr*/ +X actuator_setattr, /*tp_setattr*/ +X actuator_compare, /*tp_compare*/ +X 0, /*tp_repr*/ +X}; +X +X +X/* The panel module itself */ +X +Xstatic object * +Xmodule_mkpanel(self, args) +X object *self; +X object *args; +X{ +X if (!getnoarg(args)) +X return NULL; +X return newpanelobject(); +X} +X +Xstatic object * +Xmodule_mkact(self, args) +X object *self; +X object *args; +X{ +X object *v; +X Actuator *a; +X if (!getstrarg(args, &v)) +X return NULL; +X a = makeactuator(getstringvalue(v)); +X if (a == NULL) +X return NULL; +X return newactuatorobject(a); +X} +X +Xstatic object * +Xmodule_dopanel(self, args) +X object *self; +X object *args; +X{ +X Actuator *a; +X object *v, *w; +X if (!getnoarg(args)) +X return NULL; +X a = pnl_dopanel(); +X v = newtupleobject(4); +X if (v == NULL) +X return NULL; +X settupleitem(v, 0, newactuatorobject(a)); +X settupleitem(v, 1, newactuatorobject(down_pend)); +X settupleitem(v, 2, newactuatorobject(active_pend)); +X settupleitem(v, 3, newactuatorobject(up_pend)); +X down_pend = active_pend = up_pend = NULL; +X return v; +X} +X +Xstatic object * +Xmodule_drawpanel(self, args) +X object *self; +X object *args; +X{ +X if (!getnoarg(args)) +X return NULL; +X pnl_drawpanel(); +X INCREF(None); +X return None; +X} +X +Xstatic object * +Xmodule_needredraw(self, args) +X object *self; +X object *args; +X{ +X if (!getnoarg(args)) +X return NULL; +X pnl_needredraw(); +X INCREF(None); +X return None; +X} +X +Xstatic object * +Xmodule_userredraw(self, args) +X object *self; +X object *args; +X{ +X short wid; +X if (!getnoarg(args)) +X return NULL; +X wid = pnl_userredraw(); +X return newintobject((long)wid); +X} +X +Xstatic object * +Xmodule_block(self, args) +X object *self; +X object *args; +X{ +X int flag; +X if (!getintarg(args, &flag)) +X return NULL; +X pnl_block = flag; +X INCREF(None); +X return None; +X} +X +Xstatic struct methodlist module_methods[] = { +X {"block", module_block}, +X {"dopanel", module_dopanel}, +X {"drawpanel", module_drawpanel}, +X {"mkpanel", module_mkpanel}, +X {"mkact", module_mkact}, +X {"needredraw", module_needredraw}, +X {"userredraw", module_userredraw}, +X {NULL, NULL} /* sentinel */ +X}; +X +Xvoid +Xinitpanel() +X{ +X /* Setting pnl_block to 1 would greatly reduce the CPU usage +X of an idle application. Unfortunately it also breaks our +X little hacks to get callback functions in Python called. +X So we clear pnl_block here. You can set/clear pnl_block +X from Python using pnl.block(flag). It works if you have +X no upfuncs. */ +X pnl_block = 0; +X initmodule("pnl", module_methods); +X} +EOF +fi +if test -s 'src/regexp.c' +then echo '*** I will not over-write existing file src/regexp.c' +else +echo 'x - src/regexp.c' +sed 's/^X//' > 'src/regexp.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/* +X * regcomp and regexec -- regsub and regerror are elsewhere +X * +X * Copyright (c) 1986 by University of Toronto. +X * Written by Henry Spencer. Not derived from licensed software. +X#ifdef MULTILINE +X * Changed by Guido van Rossum, CWI, Amsterdam +X * for multi-line support. +X#endif +X * +X * Permission is granted to anyone to use this software for any +X * purpose on any computer system, and to redistribute it freely, +X * subject to the following restrictions: +X * +X * 1. The author is not responsible for the consequences of use of +X * this software, no matter how awful, even if they arise +X * from defects in it. +X * +X * 2. The origin of this software must not be misrepresented, either +X * by explicit claim or by omission. +X * +X * 3. Altered versions must be plainly marked as such, and must not +X * be misrepresented as being the original software. +X * +X * Beware that some of this code is subtly aware of the way operator +X * precedence is structured in regular expressions. Serious changes in +X * regular-expression syntax might require a total rethink. +X */ +X#include +X#include "PROTO.h" +X#include "malloc.h" +X#undef ANY /* Conflicting identifier defined in malloc.h */ +X#include /* XXX Remove if not found */ +X#include "regexp.h" +X#include "regmagic.h" +X +X#ifdef MULTILINE +X/* +X * Defining MULTILINE turns on the following changes in the semantics: +X * 1. The '.' operator matches all characters except a newline. +X * 2. The '^' operator matches at the beginning of the string or after +X * a newline. (Anchored matches are retried after each newline.) +X * 3. The '$' operator matches at the end of the string or before +X * a newline. +X * 4. A '\' followed by an 'n' matches a newline. (This is an +X * unfortunate exception to the rule that '\' followed by a +X * character matches that character...) +X * +X * Also, there is a new function reglexec(prog, string, offset) +X * which searches for a match starting at 'string+offset'; +X * it differs from regexec(prog, string+offset) in assuming +X * that the line begins at 'string'. +X */ +X#endif +X +X/* +X * The "internal use only" fields in regexp.h are present to pass info from +X * compile to execute that permits the execute phase to run lots faster on +X * simple cases. They are: +X * +X * regstart char that must begin a match; '\0' if none obvious +X * reganch is the match anchored (at beginning-of-line only)? +X * regmust string (pointer into program) that match must include, or NULL +X * regmlen length of regmust string +X * +X * Regstart and reganch permit very fast decisions on suitable starting points +X * for a match, cutting down the work a lot. Regmust permits fast rejection +X * of lines that cannot possibly match. The regmust tests are costly enough +X * that regcomp() supplies a regmust only if the r.e. contains something +X * potentially expensive (at present, the only such thing detected is * or + +X * at the start of the r.e., which can involve a lot of backup). Regmlen is +X * supplied because the test in regexec() needs it and regcomp() is computing +X * it anyway. +X */ +X +X/* +X * Structure for regexp "program". This is essentially a linear encoding +X * of a nondeterministic finite-state machine (aka syntax charts or +X * "railroad normal form" in parsing technology). Each node is an opcode +X * plus a "next" pointer, possibly plus an operand. "Next" pointers of +X * all nodes except BRANCH implement concatenation; a "next" pointer with +X * a BRANCH on both ends of it is connecting two alternatives. (Here we +X * have one of the subtle syntax dependencies: an individual BRANCH (as +X * opposed to a collection of them) is never concatenated with anything +X * because of operator precedence.) The operand of some types of node is +X * a literal string; for others, it is a node leading into a sub-FSM. In +X * particular, the operand of a BRANCH node is the first node of the branch. +X * (NB this is *not* a tree structure: the tail of the branch connects +X * to the thing following the set of BRANCHes.) The opcodes are: +X */ +X +X/* definition number opnd? meaning */ +X#define END 0 /* no End of program. */ +X#define BOL 1 /* no Match "" at beginning of line. */ +X#define EOL 2 /* no Match "" at end of line. */ +X#define ANY 3 /* no Match any one character. */ +X#define ANYOF 4 /* str Match any character in this string. */ +X#define ANYBUT 5 /* str Match any character not in this string. */ +X#define BRANCH 6 /* node Match this alternative, or the next... */ +X#define BACK 7 /* no Match "", "next" ptr points backward. */ +X#define EXACTLY 8 /* str Match this string. */ +X#define NOTHING 9 /* no Match empty string. */ +X#define STAR 10 /* node Match this (simple) thing 0 or more times. */ +X#define PLUS 11 /* node Match this (simple) thing 1 or more times. */ +X#define OPEN 20 /* no Mark this point in input as start of #n. */ +X /* OPEN+1 is number 1, etc. */ +X#define CLOSE 30 /* no Analogous to OPEN. */ +X +X/* +X * Opcode notes: +X * +X * BRANCH The set of branches constituting a single choice are hooked +X * together with their "next" pointers, since precedence prevents +X * anything being concatenated to any individual branch. The +X * "next" pointer of the last BRANCH in a choice points to the +X * thing following the whole choice. This is also where the +X * final "next" pointer of each individual branch points; each +X * branch starts with the operand node of a BRANCH node. +X * +X * BACK Normal "next" pointers all implicitly point forward; BACK +X * exists to make loop structures possible. +X * +X * STAR,PLUS '?', and complex '*' and '+', are implemented as circular +X * BRANCH structures using BACK. Simple cases (one character +X * per match) are implemented with STAR and PLUS for speed +X * and to minimize recursive plunges. +X * +X * OPEN,CLOSE ...are numbered at compile time. +X */ +X +X/* +X * A node is one char of opcode followed by two chars of "next" pointer. +X * "Next" pointers are stored as two 8-bit pieces, high order first. The +X * value is a positive offset from the opcode of the node containing it. +X * An operand, if any, simply follows the node. (Note that much of the +X * code generation knows about this implicit relationship.) +X * +X * Using two bytes for the "next" pointer is vast overkill for most things, +X * but allows patterns to get big without disasters. +X */ +X#define OP(p) (*(p)) +X#define NEXT(p) (((*((p)+1)&0377)<<8) + (*((p)+2)&0377)) +X#define OPERAND(p) ((p) + 3) +X +X/* +X * See regmagic.h for one further detail of program structure. +X */ +X +X +X/* +X * Utility definitions. +X */ +X#ifndef CHARBITS +X#define UCHARAT(p) ((int)*(unsigned char *)(p)) +X#else +X#define UCHARAT(p) ((int)*(p)&CHARBITS) +X#endif +X +X#define FAIL(m) { regerror(m); return(NULL); } +X#define ISMULT(c) ((c) == '*' || (c) == '+' || (c) == '?') +X#define META "^$.[()|?+*\\" +X +X/* +X * Flags to be passed up and down. +X */ +X#define HASWIDTH 01 /* Known never to match null string. */ +X#define SIMPLE 02 /* Simple enough to be STAR/PLUS operand. */ +X#define SPSTART 04 /* Starts with * or +. */ +X#define WORST 0 /* Worst case. */ +X +X/* +X * Global work variables for regcomp(). +X */ +Xstatic char *regparse; /* Input-scan pointer. */ +Xstatic int regnpar; /* () count. */ +Xstatic char regdummy; +Xstatic char *regcode; /* Code-emit pointer; ®dummy = don't. */ +Xstatic long regsize; /* Code size. */ +X#ifdef MULTILINE +Xstatic int regnl; /* '\n' detected. */ +X#endif +X +X/* +X * Forward declarations for regcomp()'s friends. +X */ +X#ifndef STATIC +X#define STATIC static +X#endif +XSTATIC char *reg(); +XSTATIC char *regbranch(); +XSTATIC char *regpiece(); +XSTATIC char *regatom(); +XSTATIC char *regnode(); +XSTATIC char *regnext(); +XSTATIC void regc(); +XSTATIC void reginsert(); +XSTATIC void regtail(); +XSTATIC void regoptail(); +X#ifdef STRCSPN +XSTATIC int strcspn(); +X#endif +X +X/* +X - regcomp - compile a regular expression into internal code +X * +X * We can't allocate space until we know how big the compiled form will be, +X * but we can't compile it (and thus know how big it is) until we've got a +X * place to put the code. So we cheat: we compile it twice, once with code +X * generation turned off and size counting turned on, and once "for real". +X * This also means that we don't allocate space until we are sure that the +X * thing really will compile successfully, and we never have to move the +X * code and thus invalidate pointers into it. (Note that it has to be in +X * one piece because free() must be able to free it all.) +X * +X * Beware that the optimization-preparation code in here knows about some +X * of the structure of the compiled regexp. +X */ +Xregexp * +Xregcomp(exp) +Xchar *exp; +X{ +X register regexp *r; +X register char *scan; +X register char *longest; +X register int len; +X int flags; +X +X if (exp == NULL) +X FAIL("NULL argument"); +X +X /* First pass: determine size, legality. */ +X regparse = exp; +X regnpar = 1; +X regsize = 0L; +X regcode = ®dummy; +X#ifdef MULTILINE +X regnl = 0; +X#endif +X regc(MAGIC); +X if (reg(0, &flags) == NULL) +X return(NULL); +X +X /* Small enough for pointer-storage convention? */ +X if (regsize >= 32767L) /* Probably could be 65535L. */ +X FAIL("regexp too big"); +X +X /* Allocate space. */ +X r = (regexp *)malloc(sizeof(regexp) + (unsigned)regsize); +X if (r == NULL) +X FAIL("out of space"); +X +X /* Second pass: emit code. */ +X regparse = exp; +X regnpar = 1; +X regcode = r->program; +X regc(MAGIC); +X if (reg(0, &flags) == NULL) +X return(NULL); +X +X /* Dig out information for optimizations. */ +X r->regstart = '\0'; /* Worst-case defaults. */ +X r->reganch = 0; +X r->regmust = NULL; +X r->regmlen = 0; +X scan = r->program+1; /* First BRANCH. */ +X if (OP(regnext(scan)) == END) { /* Only one top-level choice. */ +X scan = OPERAND(scan); +X +X /* Starting-point info. */ +X if (OP(scan) == EXACTLY) +X r->regstart = *OPERAND(scan); +X else if (OP(scan) == BOL) +X r->reganch++; +X +X /* +X * If there's something expensive in the r.e., find the +X * longest literal string that must appear and make it the +X * regmust. Resolve ties in favor of later strings, since +X * the regstart check works with the beginning of the r.e. +X * and avoiding duplication strengthens checking. Not a +X * strong reason, but sufficient in the absence of others. +X */ +X#ifdef MULTILINE +X if ((flags&SPSTART) && !regnl) { +X#else +X if (flags&SPSTART) { +X#endif +X longest = NULL; +X len = 0; +X for (; scan != NULL; scan = regnext(scan)) +X if (OP(scan) == EXACTLY && strlen(OPERAND(scan)) >= len) { +X longest = OPERAND(scan); +X len = strlen(OPERAND(scan)); +X } +X r->regmust = longest; +X r->regmlen = len; +X } +X } +X +X return(r); +X} +X +X/* +X - reg - regular expression, i.e. main body or parenthesized thing +X * +X * Caller must absorb opening parenthesis. +X * +X * Combining parenthesis handling with the base level of regular expression +X * is a trifle forced, but the need to tie the tails of the branches to what +X * follows makes it hard to avoid. +X */ +Xstatic char * +Xreg(paren, flagp) +Xint paren; /* Parenthesized? */ +Xint *flagp; +X{ +X register char *ret; +X register char *br; +X register char *ender; +X register int parno; +X int flags; +X +X *flagp = HASWIDTH; /* Tentatively. */ +X +X /* Make an OPEN node, if parenthesized. */ +X if (paren) { +X if (regnpar >= NSUBEXP) +X FAIL("too many ()"); +X parno = regnpar; +X regnpar++; +X ret = regnode(OPEN+parno); +X } else +X ret = NULL; +X +X /* Pick up the branches, linking them together. */ +X br = regbranch(&flags); +X if (br == NULL) +X return(NULL); +X if (ret != NULL) +X regtail(ret, br); /* OPEN -> first. */ +X else +X ret = br; +X if (!(flags&HASWIDTH)) +X *flagp &= ~HASWIDTH; +X *flagp |= flags&SPSTART; +X while (*regparse == '|') { +X regparse++; +X br = regbranch(&flags); +X if (br == NULL) +X return(NULL); +X regtail(ret, br); /* BRANCH -> BRANCH. */ +X if (!(flags&HASWIDTH)) +X *flagp &= ~HASWIDTH; +X *flagp |= flags&SPSTART; +X } +X +X /* Make a closing node, and hook it on the end. */ +X ender = regnode((paren) ? CLOSE+parno : END); +X regtail(ret, ender); +X +X /* Hook the tails of the branches to the closing node. */ +X for (br = ret; br != NULL; br = regnext(br)) +X regoptail(br, ender); +X +X /* Check for proper termination. */ +X if (paren && *regparse++ != ')') { +X FAIL("unmatched ()"); +X } else if (!paren && *regparse != '\0') { +X if (*regparse == ')') { +X FAIL("unmatched ()"); +X } else +X FAIL("junk on end"); /* "Can't happen". */ +X /* NOTREACHED */ +X } +X +X return(ret); +X} +X +X/* +X - regbranch - one alternative of an | operator +X * +X * Implements the concatenation operator. +X */ +Xstatic char * +Xregbranch(flagp) +Xint *flagp; +X{ +X register char *ret; +X register char *chain; +X register char *latest; +X int flags; +X +X *flagp = WORST; /* Tentatively. */ +X +X ret = regnode(BRANCH); +X chain = NULL; +X while (*regparse != '\0' && *regparse != '|' && *regparse != ')') { +X latest = regpiece(&flags); +X if (latest == NULL) +X return(NULL); +X *flagp |= flags&HASWIDTH; +X if (chain == NULL) /* First piece. */ +X *flagp |= flags&SPSTART; +X else +X regtail(chain, latest); +X chain = latest; +X } +X if (chain == NULL) /* Loop ran zero times. */ +X (void) regnode(NOTHING); +X +X return(ret); +X} +X +X/* +X - regpiece - something followed by possible [*+?] +X * +X * Note that the branching code sequences used for ? and the general cases +X * of * and + are somewhat optimized: they use the same NOTHING node as +X * both the endmarker for their branch list and the body of the last branch. +X * It might seem that this node could be dispensed with entirely, but the +X * endmarker role is not redundant. +X */ +Xstatic char * +Xregpiece(flagp) +Xint *flagp; +X{ +X register char *ret; +X register char op; +X register char *next; +X int flags; +X +X ret = regatom(&flags); +X if (ret == NULL) +X return(NULL); +X +X op = *regparse; +X if (!ISMULT(op)) { +X *flagp = flags; +X return(ret); +X } +X +X if (!(flags&HASWIDTH) && op != '?') +X FAIL("*+ operand could be empty"); +X *flagp = (op != '+') ? (WORST|SPSTART) : (WORST|HASWIDTH); +X +X if (op == '*' && (flags&SIMPLE)) +X reginsert(STAR, ret); +X else if (op == '*') { +X /* Emit x* as (x&|), where & means "self". */ +X reginsert(BRANCH, ret); /* Either x */ +X regoptail(ret, regnode(BACK)); /* and loop */ +X regoptail(ret, ret); /* back */ +X regtail(ret, regnode(BRANCH)); /* or */ +X regtail(ret, regnode(NOTHING)); /* null. */ +X } else if (op == '+' && (flags&SIMPLE)) +X reginsert(PLUS, ret); +X else if (op == '+') { +X /* Emit x+ as x(&|), where & means "self". */ +X next = regnode(BRANCH); /* Either */ +X regtail(ret, next); +X regtail(regnode(BACK), ret); /* loop back */ +X regtail(next, regnode(BRANCH)); /* or */ +X regtail(ret, regnode(NOTHING)); /* null. */ +X } else if (op == '?') { +X /* Emit x? as (x|) */ +X reginsert(BRANCH, ret); /* Either x */ +X regtail(ret, regnode(BRANCH)); /* or */ +X next = regnode(NOTHING); /* null. */ +X regtail(ret, next); +X regoptail(ret, next); +X } +X regparse++; +X if (ISMULT(*regparse)) +X FAIL("nested *?+"); +X +X return(ret); +X} +X +X/* +X - regatom - the lowest level +X * +X * Optimization: gobbles an entire sequence of ordinary characters so that +X * it can turn them into a single node, which is smaller to store and +X * faster to run. Backslashed characters are exceptions, each becoming a +X * separate node; the code is simpler that way and it's not worth fixing. +X */ +Xstatic char * +Xregatom(flagp) +Xint *flagp; +X{ +X register char *ret; +X int flags; +X +X *flagp = WORST; /* Tentatively. */ +X +X switch (*regparse++) { +X case '^': +X ret = regnode(BOL); +X break; +X case '$': +X ret = regnode(EOL); +X break; +X case '.': +X ret = regnode(ANY); +X *flagp |= HASWIDTH|SIMPLE; +X break; +X case '[': { +X register int class; +X register int classend; +X +X if (*regparse == '^') { /* Complement of range. */ +X ret = regnode(ANYBUT); +X regparse++; +X } else +X ret = regnode(ANYOF); +X if (*regparse == ']' || *regparse == '-') +X regc(*regparse++); +X while (*regparse != '\0' && *regparse != ']') { +X if (*regparse == '-') { +X regparse++; +X if (*regparse == ']' || *regparse == '\0') +X regc('-'); +X else { +X class = UCHARAT(regparse-2)+1; +X classend = UCHARAT(regparse); +X if (class > classend+1) +X FAIL("invalid [] range"); +X for (; class <= classend; class++) +X regc(class); +X regparse++; +X } +X } else +X regc(*regparse++); +X } +X regc('\0'); +X if (*regparse != ']') +X FAIL("unmatched []"); +X regparse++; +X *flagp |= HASWIDTH|SIMPLE; +X } +X break; +X case '(': +X ret = reg(1, &flags); +X if (ret == NULL) +X return(NULL); +X *flagp |= flags&(HASWIDTH|SPSTART); +X break; +X case '\0': +X case '|': +X case ')': +X FAIL("internal urp"); /* Supposed to be caught earlier. */ +X break; +X case '?': +X case '+': +X case '*': +X FAIL("?+* follows nothing"); +X break; +X case '\\': +X if (*regparse == '\0') +X FAIL("trailing \\"); +X ret = regnode(EXACTLY); +X#ifdef MULTILINE +X if (*regparse == 'n') { +X regc('\n'); +X regparse++; +X regnl++; +X } +X else +X#endif +X regc(*regparse++); +X regc('\0'); +X *flagp |= HASWIDTH|SIMPLE; +X break; +X default: { +X register int len; +X register char ender; +X +X regparse--; +X len = strcspn(regparse, META); +X if (len <= 0) +X FAIL("internal disaster"); +X ender = *(regparse+len); +X if (len > 1 && ISMULT(ender)) +X len--; /* Back off clear of ?+* operand. */ +X *flagp |= HASWIDTH; +X if (len == 1) +X *flagp |= SIMPLE; +X ret = regnode(EXACTLY); +X while (len > 0) { +X#ifdef MULTILINE +X if (*regparse == '\n') +X regnl++; +X#endif +X regc(*regparse++); +X len--; +X } +X regc('\0'); +X } +X break; +X } +X +X return(ret); +X} +X +X/* +X - regnode - emit a node +X */ +Xstatic char * /* Location. */ +Xregnode(op) +Xchar op; +X{ +X register char *ret; +X register char *ptr; +X +X ret = regcode; +X if (ret == ®dummy) { +X regsize += 3; +X return(ret); +X } +X +X ptr = ret; +X *ptr++ = op; +X *ptr++ = '\0'; /* Null "next" pointer. */ +X *ptr++ = '\0'; +X regcode = ptr; +X +X return(ret); +X} +X +X/* +X - regc - emit (if appropriate) a byte of code +X */ +Xstatic void +Xregc(b) +Xchar b; +X{ +X if (regcode != ®dummy) +X *regcode++ = b; +X else +X regsize++; +X} +X +X/* +X - reginsert - insert an operator in front of already-emitted operand +X * +X * Means relocating the operand. +X */ +Xstatic void +Xreginsert(op, opnd) +Xchar op; +Xchar *opnd; +X{ +X register char *src; +X register char *dst; +X register char *place; +X +X if (regcode == ®dummy) { +X regsize += 3; +X return; +X } +X +X src = regcode; +X regcode += 3; +X dst = regcode; +X while (src > opnd) +X *--dst = *--src; +X +X place = opnd; /* Op node, where operand used to be. */ +X *place++ = op; +X *place++ = '\0'; +X *place++ = '\0'; +X} +X +X/* +X - regtail - set the next-pointer at the end of a node chain +X */ +Xstatic void +Xregtail(p, val) +Xchar *p; +Xchar *val; +X{ +X register char *scan; +X register char *temp; +X register int offset; +X +X if (p == ®dummy) +X return; +X +X /* Find last node. */ +X scan = p; +X for (;;) { +X temp = regnext(scan); +X if (temp == NULL) +X break; +X scan = temp; +X } +X +X if (OP(scan) == BACK) +X offset = scan - val; +X else +X offset = val - scan; +X *(scan+1) = (offset>>8)&0377; +X *(scan+2) = offset&0377; +X} +X +X/* +X - regoptail - regtail on operand of first argument; nop if operandless +X */ +Xstatic void +Xregoptail(p, val) +Xchar *p; +Xchar *val; +X{ +X /* "Operandless" and "op != BRANCH" are synonymous in practice. */ +X if (p == NULL || p == ®dummy || OP(p) != BRANCH) +X return; +X regtail(OPERAND(p), val); +X} +X +X/* +X * regexec and friends +X */ +X +X/* +X * Global work variables for regexec(). +X */ +Xstatic char *reginput; /* String-input pointer. */ +Xstatic char *regbol; /* Beginning of input, for ^ check. */ +Xstatic char **regstartp; /* Pointer to startp array. */ +Xstatic char **regendp; /* Ditto for endp. */ +X +X/* +X * Forwards. +X */ +XSTATIC int regtry(); +XSTATIC int regmatch(); +XSTATIC int regrepeat(); +X +X#ifdef DEBUG +Xint regnarrate = 0; +Xvoid regdump(); +XSTATIC char *regprop(); +X#endif +X +X/* +X - regexec - match a regexp against a string +X */ +Xint +Xregexec(prog, string) +Xregister regexp *prog; +Xregister char *string; +X{ +X register char *s; +X extern char *strchr(); +X +X /* Be paranoid... */ +X if (prog == NULL || string == NULL) { +X regerror("NULL parameter"); +X return(0); +X } +X +X#ifdef MULTILINE +X /* Check for \n in string, and if so, call the more general routine. */ +X if (strchr(string, '\n') != NULL) +X return reglexec(prog, string, 0); +X#endif +X +X /* Check validity of program. */ +X if (UCHARAT(prog->program) != MAGIC) { +X regerror("corrupted program"); +X return(0); +X } +X +X /* If there is a "must appear" string, look for it. */ +X if (prog->regmust != NULL) { +X s = string; +X while ((s = strchr(s, prog->regmust[0])) != NULL) { +X if (strncmp(s, prog->regmust, prog->regmlen) == 0) +X break; /* Found it. */ +X s++; +X } +X if (s == NULL) /* Not present. */ +X return(0); +X } +X +X /* Mark beginning of line for ^ . */ +X regbol = string; +X +X /* Simplest case: anchored match need be tried only once. */ +X if (prog->reganch) +X return(regtry(prog, string)); +X +X /* Messy cases: unanchored match. */ +X s = string; +X if (prog->regstart != '\0') +X /* We know what char it must start with. */ +X while ((s = strchr(s, prog->regstart)) != NULL) { +X if (regtry(prog, s)) +X return(1); +X s++; +X } +X else +X /* We don't -- general case. */ +X do { +X if (regtry(prog, s)) +X return(1); +X } while (*s++ != '\0'); +X +X /* Failure. */ +X return(0); +X} +X +X#ifdef MULTILINE +X/* +X - reglexec - match a regexp against a long string buffer, starting at offset +X */ +Xint +Xreglexec(prog, string, offset) +Xregister regexp *prog; +Xregister char *string; +X{ +X register char *s; +X extern char *strchr(); +X +X /* Be paranoid... */ +X if (prog == NULL || string == NULL) { +X regerror("NULL parameter"); +X return(0); +X } +X +X /* Check validity of program. */ +X if (UCHARAT(prog->program) != MAGIC) { +X regerror("corrupted program"); +X return(0); +X } +X +X /* (Don't look for "must appear" string -- string can be long.) */ +X +X /* Mark beginning of line for ^ . */ +X regbol = string; +X +X /* Apply offset. +X Assume 0 <= offset <= strlen(string), but don't check, +X as string can be long. */ +X s= string + offset; +X +X /* Anchored match need be tried only at line starts. */ +X if (prog->reganch) { +X while (!regtry(prog, s)) { +X s = strchr(s, '\n'); +X if (s == NULL) +X return(0); +X s++; +X } +X return(1); +X } +X +X /* Messy cases: unanchored match. */ +X if (prog->regstart != '\0') +X /* We know what char it must start with. */ +X while ((s = strchr(s, prog->regstart)) != NULL) { +X if (regtry(prog, s)) +X return(1); +X s++; +X } +X else +X /* We don't -- general case. */ +X do { +X if (regtry(prog, s)) +X return(1); +X } while (*s++ != '\0'); +X +X /* Failure. */ +X return(0); +X} +X#endif +X +X/* +X - regtry - try match at specific point +X */ +Xstatic int /* 0 failure, 1 success */ +Xregtry(prog, string) +Xregexp *prog; +Xchar *string; +X{ +X register int i; +X register char **sp; +X register char **ep; +X +X reginput = string; +X regstartp = prog->startp; +X regendp = prog->endp; +X +X sp = prog->startp; +X ep = prog->endp; +X for (i = NSUBEXP; i > 0; i--) { +X *sp++ = NULL; +X *ep++ = NULL; +X } +X if (regmatch(prog->program + 1)) { +X prog->startp[0] = string; +X prog->endp[0] = reginput; +X return(1); +X } else +X return(0); +X} +X +X/* +X - regmatch - main matching routine +X * +X * Conceptually the strategy is simple: check to see whether the current +X * node matches, call self recursively to see whether the rest matches, +X * and then act accordingly. In practice we make some effort to avoid +X * recursion, in particular by going through "ordinary" nodes (that don't +X * need to know whether the rest of the match failed) by a loop instead of +X * by recursion. +X */ +Xstatic int /* 0 failure, 1 success */ +Xregmatch(prog) +Xchar *prog; +X{ +X register char *scan; /* Current node. */ +X char *next; /* Next node. */ +X extern char *strchr(); +X +X scan = prog; +X#ifdef DEBUG +X if (scan != NULL && regnarrate) +X fprintf(stderr, "%s(\n", regprop(scan)); +X#endif +X while (scan != NULL) { +X#ifdef DEBUG +X if (regnarrate) +X fprintf(stderr, "%s...\n", regprop(scan)); +X#endif +X next = regnext(scan); +X +X switch (OP(scan)) { +X case BOL: +X#ifdef MULTILINE +X if (!(reginput == regbol || +X reginput > regbol && *(reginput-1) == '\n')) +X#else +X if (reginput != regbol) +X#endif +X return(0); +X break; +X case EOL: +X#ifdef MULTILINE +X if (*reginput != '\0' && *reginput != '\n') +X#else +X if (*reginput != '\0') +X#endif +X return(0); +X break; +X case ANY: +X#ifdef MULTILINE +X if (*reginput == '\0' || *reginput == '\n') +X#else +X if (*reginput == '\0') +X#endif +X return(0); +X reginput++; +X break; +X case EXACTLY: { +X register int len; +X register char *opnd; +X +X opnd = OPERAND(scan); +X /* Inline the first character, for speed. */ +X if (*opnd != *reginput) +X return(0); +X len = strlen(opnd); +X if (len > 1 && strncmp(opnd, reginput, len) != 0) +X return(0); +X reginput += len; +X } +X break; +X case ANYOF: +X if (*reginput == '\0' || strchr(OPERAND(scan), *reginput) == NULL) +X return(0); +X reginput++; +X break; +X case ANYBUT: +X#ifdef MULTILINE +X if (*reginput == '\0' || *reginput == '\n' || +X strchr(OPERAND(scan), *reginput) != NULL) +X#else +X if (*reginput == '\0' || strchr(OPERAND(scan), *reginput) != NULL) +X#endif +X return(0); +X reginput++; +X break; +X case NOTHING: +X break; +X case BACK: +X break; +X case OPEN+1: +X case OPEN+2: +X case OPEN+3: +X case OPEN+4: +X case OPEN+5: +X case OPEN+6: +X case OPEN+7: +X case OPEN+8: +X case OPEN+9: { +X register int no; +X register char *save; +X +X no = OP(scan) - OPEN; +X save = reginput; +X +X if (regmatch(next)) { +X /* +X * Don't set startp if some later +X * invocation of the same parentheses +X * already has. +X */ +X if (regstartp[no] == NULL) +X regstartp[no] = save; +X return(1); +X } else +X return(0); +X } +X break; +X case CLOSE+1: +X case CLOSE+2: +X case CLOSE+3: +X case CLOSE+4: +X case CLOSE+5: +X case CLOSE+6: +X case CLOSE+7: +X case CLOSE+8: +X case CLOSE+9: { +X register int no; +X register char *save; +X +X no = OP(scan) - CLOSE; +X save = reginput; +X +X if (regmatch(next)) { +X /* +X * Don't set endp if some later +X * invocation of the same parentheses +X * already has. +X */ +X if (regendp[no] == NULL) +X regendp[no] = save; +X return(1); +X } else +X return(0); +X } +X break; +X case BRANCH: { +X register char *save; +X +X if (OP(next) != BRANCH) /* No choice. */ +X next = OPERAND(scan); /* Avoid recursion. */ +X else { +X do { +X save = reginput; +X if (regmatch(OPERAND(scan))) +X return(1); +X reginput = save; +X scan = regnext(scan); +X } while (scan != NULL && OP(scan) == BRANCH); +X return(0); +X /* NOTREACHED */ +X } +X } +X break; +X case STAR: +X case PLUS: { +X register char nextch; +X register int no; +X register char *save; +X register int min; +X +X /* +X * Lookahead to avoid useless match attempts +X * when we know what character comes next. +X */ +X nextch = '\0'; +X if (OP(next) == EXACTLY) +X nextch = *OPERAND(next); +X min = (OP(scan) == STAR) ? 0 : 1; +X save = reginput; +X no = regrepeat(OPERAND(scan)); +X while (no >= min) { +X /* If it could work, try it. */ +X if (nextch == '\0' || *reginput == nextch) +X if (regmatch(next)) +X return(1); +X /* Couldn't or didn't -- back up. */ +X no--; +X reginput = save + no; +X } +X return(0); +X } +X break; +X case END: +X return(1); /* Success! */ +X break; +X default: +X regerror("memory corruption"); +X return(0); +X break; +X } +X +X scan = next; +X } +X +X /* +X * We get here only if there's trouble -- normally "case END" is +X * the terminating point. +X */ +X regerror("corrupted pointers"); +X return(0); +X} +X +X/* +X - regrepeat - repeatedly match something simple, report how many +X */ +Xstatic int +Xregrepeat(p) +Xchar *p; +X{ +X register int count = 0; +X register char *scan; +X register char *opnd; +X#ifdef MULTILINE +X register char *eol; +X#endif +X +X scan = reginput; +X opnd = OPERAND(p); +X switch (OP(p)) { +X case ANY: +X#ifdef MULTILINE +X if ((eol = strchr(scan, '\n')) != NULL) { +X count += eol - scan; +X scan = eol; +X break; +X } +X#endif +X count = strlen(scan); +X scan += count; +X break; +X case EXACTLY: +X while (*opnd == *scan) { +X count++; +X scan++; +X } +X break; +X case ANYOF: +X while (*scan != '\0' && strchr(opnd, *scan) != NULL) { +X count++; +X scan++; +X } +X break; +X case ANYBUT: +X#ifdef MULTILINE +X while (*scan != '\0' && *scan != '\n' && +X strchr(opnd, *scan) == NULL) { +X#else +X while (*scan != '\0' && strchr(opnd, *scan) == NULL) { +X#endif +X count++; +X scan++; +X } +X break; +X default: /* Oh dear. Called inappropriately. */ +X regerror("internal foulup"); +X count = 0; /* Best compromise. */ +X break; +X } +X reginput = scan; +X +X return(count); +X} +X +X/* +X - regnext - dig the "next" pointer out of a node +X */ +Xstatic char * +Xregnext(p) +Xregister char *p; +X{ +X register int offset; +X +X if (p == ®dummy) +X return(NULL); +X +X offset = NEXT(p); +X if (offset == 0) +X return(NULL); +X +X if (OP(p) == BACK) +X return(p-offset); +X else +X return(p+offset); +X} +X +X#ifdef DEBUG +X +XSTATIC char *regprop(); +X +X/* +X - regdump - dump a regexp onto stdout in vaguely comprehensible form +X */ +Xvoid +Xregdump(r) +Xregexp *r; +X{ +X register char *s; +X register char op = EXACTLY; /* Arbitrary non-END op. */ +X register char *next; +X extern char *strchr(); +X +X +X s = r->program + 1; +X while (op != END) { /* While that wasn't END last time... */ +X op = OP(s); +X printf("%2d%s", (int)(s-r->program), regprop(s)); /* Where, what. */ +X next = regnext(s); +X if (next == NULL) /* Next ptr. */ +X printf("(0)"); +X else +X printf("(%d)", (int)((s-r->program)+(next-s))); +X s += 3; +X if (op == ANYOF || op == ANYBUT || op == EXACTLY) { +X /* Literal string, where present. */ +X while (*s != '\0') { +X#ifdef MULTILINE +X if (*s == '\n') +X printf("\\n"); +X else +X#endif +X putchar(*s); +X s++; +X } +X s++; +X } +X putchar('\n'); +X } +X +X /* Header fields of interest. */ +X if (r->regstart != '\0') +X printf("start `%c' ", r->regstart); +X if (r->reganch) +X printf("anchored "); +X if (r->regmust != NULL) +X printf("must have \"%s\"", r->regmust); +X printf("\n"); +X} +X +X/* +X - regprop - printable representation of opcode +X */ +Xstatic char * +Xregprop(op) +Xchar *op; +X{ +X register char *p; +X static char buf[50]; +X +X (void) strcpy(buf, ":"); +X +X switch (OP(op)) { +X case BOL: +X p = "BOL"; +X break; +X case EOL: +X p = "EOL"; +X break; +X case ANY: +X p = "ANY"; +X break; +X case ANYOF: +X p = "ANYOF"; +X break; +X case ANYBUT: +X p = "ANYBUT"; +X break; +X case BRANCH: +X p = "BRANCH"; +X break; +X case EXACTLY: +X p = "EXACTLY"; +X break; +X case NOTHING: +X p = "NOTHING"; +X break; +X case BACK: +X p = "BACK"; +X break; +X case END: +X p = "END"; +X break; +X case OPEN+1: +X case OPEN+2: +X case OPEN+3: +X case OPEN+4: +X case OPEN+5: +X case OPEN+6: +X case OPEN+7: +X case OPEN+8: +X case OPEN+9: +X sprintf(buf+strlen(buf), "OPEN%d", (int)(OP(op)-OPEN)); +X p = NULL; +X break; +X case CLOSE+1: +X case CLOSE+2: +X case CLOSE+3: +X case CLOSE+4: +X case CLOSE+5: +X case CLOSE+6: +X case CLOSE+7: +X case CLOSE+8: +X case CLOSE+9: +X sprintf(buf+strlen(buf), "CLOSE%d", (int)(OP(op)-CLOSE)); +X p = NULL; +X break; +X case STAR: +X p = "STAR"; +X break; +X case PLUS: +X p = "PLUS"; +X break; +X default: +X regerror("corrupted opcode"); +X break; +X } +X if (p != NULL) +X (void) strcat(buf, p); +X return(buf); +X} +X#endif +X +X/* +X * The following is provided for those people who do not have strcspn() in +X * their C libraries. They should get off their butts and do something +X * about it; at least one public-domain implementation of those (highly +X * useful) string routines has been published on Usenet. +X */ +X#ifdef STRCSPN +X/* +X * strcspn - find length of initial segment of s1 consisting entirely +X * of characters not from s2 +X */ +X +Xstatic int +Xstrcspn(s1, s2) +Xchar *s1; +Xchar *s2; +X{ +X register char *scan1; +X register char *scan2; +X register int count; +X +X count = 0; +X for (scan1 = s1; *scan1 != '\0'; scan1++) { +X for (scan2 = s2; *scan2 != '\0';) /* ++ mov