[comp.sources.misc] v09i047: popi, The Digital Darkroom, Part01/09

richb@sunaus.sun.oz.AU (Rich Burridge) (12/13/89)

Posting-number: Volume 9, Issue 47
Submitted-by: Rich Burridge <richb@sunaus.sun.oz.AU>
Archive-name: popi/part01

---- Cut Here and unpack ----
#!/bin/sh
# shar:	Shell Archiver  (v1.22)
#	Packed Tue Dec 12 13:35:05 EST 1989 by stard!richb
#	from directory /extra/richb/rich_stuff/popi
#
# This is part 1 of a multipart archive                                    
# do not concatenate these parts, unpack them in order with /bin/sh        
#
#	Run the following text with /bin/sh to create:
#	  Makefile
#	  README
#	  TODO
#	  amiga.c
#	  apollo.c
#	  atariterm.c
#	  expr.c
#	  ibmpc.c
#	  io.c
#	  kerterm.c
#	  main.c
#	  mgr.c
#	  graphics.h
#	  news.c
#	  nulldev.c
#	  patchlevel.h
#	  polar.c
#	  popi.h
#	  popi.icon
#	  popi.ps
#	  run.c
#	  popi.prj
#	  powerc.prj
#	  popi.1
#	  special.c
#	  graphics.c
#	  lex.c
#	  sunview.c
#	  x11.c
#	  xview.c
#	  popi.msc
#	  dmr.Z
#
if test -r s2_seq_.tmp
then echo "Must unpack archives in sequence!"
     next=`cat s2_seq_.tmp`; echo "Please unpack part $next next"
     exit 1; fi
echo "x - extracting Makefile (Text)"
sed 's/^X//' << 'Funky_Stuff' > Makefile &&
X#
X#  Makefile for popi the graphics editor.
X#
X#  @(#)Makefile 1.13 89/12/12
X#
X#  Popi was originally written by Gerard J. Holzmann - AT&T Bell Labs.
X#  This version is based on the code in his Prentice Hall book,
X#  "Beyond Photography - the digital darkroom," ISBN 0-13-074410-7,
X#  which is copyright (c) 1988 by Bell Telephone Laboratories, Inc. 
X#
X#  Permission is given to distribute these extensions, as long as these
X#  introductory messages are not removed, and no monies are exchanged.
X#
X#  No responsibility is taken for any errors or inaccuracies inherent
X#  either to the comments or the code of this program, but if reported
X#  (see README file) then an attempt will be made to fix them.
X#
X#-------------------------------------------------------------------
X#  This makefile is extremely ugly, but does work in a multitude
X#  of different environments.
X#-------------------------------------------------------------------
X#
X#  There are various small changes needed when compiling popi on
X#  different systems. These have been isolated here, and should
X#  be uncommented if needed.
X#
X#  If you are running under BSD unix, uncomment the two lines:
X#
XSYS		= -DBSD
XINSTALL         = install
X#
X#	Otherwise, define your BSD style install command
X#INSTALL        = bsdinstall
X#	Or install by hand
X#INSTALL	= :
X#
X#  For System V, uncomment the next line.
X#
X#SYS		= -DSYSV
X#
X#  If you not running under a BSD4.[12] derived system, the parameters
X#  to the select call are different, and this definition should be
X#  uncommented. You need to uncomment this for SunOS v3.x.
X#
X#SELTYPE	= -DNO_4_3SELECT
X#
X#  Most existing versions of unix use a pointer to a function
X#  returning an integer as the return type of signal(). Newer systems
X#  use pointer to function returning void. If this is the case,
X#  uncomment the next line.
X#
X#SIGRET         = -DSIGRET=void
X#
X#  If you are running X11R2 on a Sun4, then the popi executable
X#  needs to be statically linked to work correctly, so the following
X#  line should be uncommented.
X#
X#LDX11FLAGS     = -Bstatic
X#
X#  The X11 include directory should be specified here if required
X#
X#X11HOME		= /home/openwin
X#X11INCDIR	= -I$(X11HOME)/include
X#
X#  If you are compiling the MGR version, then the following
X#  definitions should be uncommented.
X#
X#MGRHOME        = /usr/mgr
X#MGRPARAM        = -DMGRHOME=\"$(MGRHOME)\"
X#MGRINCDIR       = -I$(MGRHOME)/include
X#
X#  If you are compiling the NeWS version, then you need to uncomment
X#  the following line.
X#
X#NEWSFILE        = -DNEWSGIVEN -DNEWSFILE=\"$(LIBDIR)/popi.ps\"
X#
X#  If you are compiling the XView version, then the following two lines
X#  should be uncommented.
X#
X#XVIEWINCDIR      = -I$(XVIEWHOME)/include
X#XVIEWLIBDIR      = -L$(XVIEWHOME)/lib
X#
X#  If you are running on a Sun and you have some kind of floating
X#  point co-processor, then uncomment this line, and set accordingly.
X#
X#SUNFLOAT             = -fswitch
X#
X#  If you are running Dynix (sequent) compatible parallel make,
X#  uncomment the following line.
X#
X#P		= &
X#
X#  If you are running on a sequent and want to use the
X#  parallel programming library, uncomment the following 2 lines.
X#
X#PLIB		= -lpps
X#PFLAGS		= -Y -DSEQPAR
X#
X#
X#  Name of your favourite C compiler
X#	Standard unix
XCC		= cc
X#	Gnu C
X#CC		= gcc
X#	Borland's Turbo C
X#CC		= tcc
X#	Microsoft C
X#CC		= cl
X#	Microsoft Quick C
X#CC		= qcl
X#	Mix Power C
X#CC		= pc
X#	Lattice C for Amiga or DOS
X#CC		= lc
X#
X#  Suffix used for object files
X#	Normal
XO		= o
X#	Dos
X#O		= obj
X#	Mix Power C
X#O		= mix
X#
X#  Suffix (including the `.') for executable files
X#	Normal
XE		=
X#	Dos
X#E		= .exe
X#
X#  Compiler option for specifying exectable name
X#	Unix (must have a space after the `-o')
XEXE		= -o $(NOTHING)
X#	Turbo C (must not have a trailing space)
X#EXE		= -e
X#
X#  Your system remove command
X#	Standard unix
XRM		= rm -f
X#	Dos
X#RM		= del
X#	Amiga
X#RM		= delete
X#
X#  Your system copy command
X#	Standard unix
XCP		= cp
X#	DOS and Amiga
X#CP		= copy
X#
X#
X#  Specify any flags to be used with your C compiler.
X#	Standard unix
XOCFLAGS		= -g
X#	Turbo C (also set BGIPATH to the location of your .bgi files)
X#OCFLAGS		= -DBGIPATH=c:\\util\\tc\\bgi -G -O -Z -d -v -w
X#	Microsoft Quick C
X#OCFLAGS		= -W3 -AS
X#	Mix Power C
X#OCFLAGS		= -ms
X#	Lattice C for Amiga (ansi compliance, winge, fast FP).
X#OCFLAGS		= -caf -ff
X#
X#  Specify any extra flags to be passed to the linker
XOLDFLAGS	=
X#
X#-------------------------------------------------------------------
X
XBINARIES	= apollo_popi atari_popi mgr_popi null_popi ps_popi sv_popi \
X		  x11_popi xv_popi
XBINDIR          = /usr/local/bin
XLIBDIR          = /usr/local/lib
XMANDIR          = /usr/man/man$(MANSECT)
XMANSECT         = l
XCFLAGS		= $(OCFLAGS) $(SYS) $(SELTYPE) $(SIGRET) $(X11INCDIR) \
X		    $(NEWSFILE) $(MGRPARAM) $(MGRINCDIR) \
X		    $(XVIEWINCDIR) $(PFLAGS)
XLDFLAGS         = $(OLDFLAGS) $(LDX11FLAGS)
XHDRS		= popi.h graphics.h
XIMAGES          = popi.icon
XSTDOBJS		= expr.$(O) io.$(O) lex.$(O) main.$(O) polar.$(O) run.$(O) \
X		  special.$(O)
XLIBS		= -lm $(PLIB)
XSTDSRCS		= expr.c io.c lex.c main.c polar.c run.c special.c
XOTHERSRCS1	= amiga.c apollo.c atariterm.c graphics.c kerterm.c mgr.c
XOTHERSRCS2	= news.c nulldev.c ibmpc.c sunview.c x11.c xview.c popi.ps
X
XOTHERSRCS       = $(OTHERSRCS1) $(OTHERSRCS2)
XTARGET		= popi$(E)
X
XAMIGALIBS	=
XAMIGAOBJS	= $(STDOBJS) amiga.o
XAMIGASRCS	= $(STDSRCS) amiga.c
X
XAPOLLOLIBS	= $(LIBS)
XAPOLLOOBJS	= $(STDOBJS) apollo.$(O)
XAPOLLOSRCS	= $(STDSRCS) apollo.c
X
XATARILIBS       = $(LIBS)
XATARIOBJS       = $(STDOBJS) atariterm.$(O)
XATARISRCS       = $(STDSRCS) atariterm.c
X
XIBMPCLIBS	= $(LIBS)
XIBMPCOBJS	= $(STDOBJS) ibmpc.$(O)
XIBMPCSRCS	= $(STDSRCS) ibmpc.c
X
XKERLIBS         = $(LIBS)
XKEROBJS         = $(STDOBJS) kerterm.$(O)
XKERSRCS         = $(STDSRCS) kerterm.c
X
XMGRLIBS         = $(LIBS) $(MGRHOME)/lib/libmgr.a
XMGROBJS         = $(STDOBJS) graphics.$(O) mgr.$(O)
XMGRSRCS         = $(STDSRCS) graphics.c mgr.c
X 
XNULLLIBS        = $(LIBS)
XNULLOBJS        = $(STDOBJS) nulldev.$(O)
XNULLSRCS        = $(STDSRCS) nulldev.c
X
XPSLIBS          = $(LIBS) $$NEWSHOME/lib/libcps.a
XPSOBJS          = $(STDOBJS) graphics.$(O) news.$(O)
XPSSRCS          = $(STDSRCS) graphics.c news.c
X 
XSVLIBS          = $(LIBS) -lsuntool -lsunwindow -lpixrect
XSVOBJS          = $(STDOBJS) graphics.$(O) sunview.$(O)
XSVSRCS          = $(STDSRCS) graphics.c sunview.c
X 
XX11LIBS         = $(LIBS) $(X11HOME)/lib/libX11.a
XX11OBJS         = $(STDOBJS) graphics.$(O) x11.$(O)
XX11SRCS         = $(STDSRCS) graphics.c x11.c
X 
XXVLIBS          = $(LIBS) -lpixrect -lxview -lX11
XXVOBJS          = $(STDOBJS) graphics.$(O) xview.$(O)
XXVSRCS          = $(STDSRCS) graphics.c xview.c
X 
XOTHERS          = Makefile README TODO popi.1 patchlevel.h \
X		  popi.msc popi.prj powerc.prj
XSRCS            = $(STDSRCS) $(OTHERSRCS)
XALL		= $(SRCS) $(IMAGES) $(HDRS) $(OTHERS)
X
Xhelp:   
X		@echo
X		@echo "You need to specify one of the following options:"
X		@echo
X		@echo make amiga      - to make the Amiga version.
X		@echo make apollo     - to make the Apollo version.
X		@echo make atari      - to make the Atari version.
X		@echo make ibmpc      - to make the PC version.
X		@echo make kermit     - to make the Kermit version.
X		@echo make mgr        - to make the MGR version.
X		@echo make news       - to make the NeWS version.
X		@echo make nulldev    - to make the null device version.
X		@echo make sunview    - to make the SunView version.
X		@echo make x11        - to make the X11 version.
X		@echo make xview      - to make the XView version.
X		@echo
X
Xall:		$(BINARIES)
X
Xamiga:		amiga_popi
X		-delete popi
X		rename amiga_popi popi
X
Xapollo:		apollo_popi$(E)
X		$(CP) apollo_popi$(E) $(TARGET)
X
Xatari:          atari_popi$(E)
X		$(CP) atari_popi$(E) $(TARGET)
X
Xibmpc:		ibmpc_popi$(E)
X		$(CP) ibmpc_popi$(E) $(TARGET)
X
Xkermit:         ker_popi$(E)
X		$(CP) ker_popi$(E) $(TARGET)
X
Xmgr:            mgr_popi$(E)
X		$(CP) mgr_popi$(E) $(TARGET)
X
Xnews:           ps_popi$(E)
X		$(CP) ps_popi$(E) $(TARGET)
X
Xnulldev:        null_popi$(E)
X		$(CP) null_popi$(E) $(TARGET)
X
Xsunview:        sv_popi$(E)
X		$(CP) sv_popi$(E) $(TARGET)
X
Xx11:            x11_popi$(E)
X		$(CP) x11_popi$(E) $(TARGET)
X
Xxview:          xv_popi$(E)
X		$(CP) xv_popi$(E) $(TARGET)
X
Xamiga_popi:$(P)   $(AMIGAOBJS)
X		blink from lib:c.o $(AMIGAOBJS) to amiga_popi lib lib:lcmffp.lib lib:lc.lib lib:amiga.lib sc sd nd
X
Xapollo_popi$(E):	$(APOLLOOBJS)
X		$(CC) $(EXE)apollo_popi $(LDFLAGS) $(APOLLOOBJS) $(APOLLOLIBS)
X
Xatari_popi$(E):$(P)   $(ATARIOBJS)
X		$(CC) $(EXE)atari_popi $(LDFLAGS) $(ATARIOBJS) $(ATARILIBS)
X
Xibmpc_popi$(E):	$(IBMPCOBJS)
X		$(CC) $(EXE)ibmpc_popi $(LDFLAGS) $(IBMPCOBJS) $(IBMPCLIBS)
X
Xker_popi$(E):$(P)     $(KEROBJS)
X		$(CC) $(EXE)ker_popi $(LDFLAGS) $(KEROBJS) $(KERLIBS)
X
Xmgr_popi$(E):$(P)     $(MGROBJS)
X		$(CC) $(EXE)mgr_popi $(LDFLAGS) $(MGROBJS) $(MGRLIBS)
X        
Xnull_popi$(E):$(P)    $(NULLOBJS)
X		$(CC) $(EXE)null_popi $(LDFLAGS) $(NULLOBJS) $(NULLLIBS)
X
Xps_popi$(E):$(P)      $(PSOBJS)
X		$(CC) $(EXE)ps_popi $(LDFLAGS) $(PSOBJS) $(PSLIBS)
X        
Xsv_popi$(E):      $(SVOBJS)
X		$(CC) $(EXE)sv_popi $(LDFLAGS) $(SVOBJS) $(SVLIBS)
X        
Xx11_popi$(E):$(P)     $(X11OBJS)
X		$(CC) $(LDX11FLAGS) $(EXE)x11_popi $(LDFLAGS) $(X11OBJS) $(X11LIBS)
X 
Xxv_popi$(E):$(P)      $(XVOBJS)
X		$(CC) $(EXE)xv_popi $(LDFLAGS) $(XVIEWLIBDIR) $(XVOBJS) $(XVLIBS)
X
Xinstall:        $(BINARIES)
X		$(INSTALL) -s -m 751 popi $(BINDIR)
X		$(INSTALL) -c -m 644 popi.ps $(LIBDIR)
X		$(INSTALL) -c -m 644 popi.1 $(MANDIR)/popi.$(MANSECT)
X
Xbackup:
X		$(CP) $(ALL) backdir
X
Xclean:
X		$(RM) *.$(O)
X		$(RM) popi$(E)
X		$(RM) $(BINARIES) core popi.tar popi.tar.Z
X
Xlint:
X		lint $(OTHERFLAGS) $(SVSRCS) $(SVLIBS)
X		lint $(OTHERFLAGS) $(ATARISRCS) $(ATARILIBS)
X		lint $(OTHERFLAGS) $(NULLSRCS) $(NULLLIBS)
X		lint $(OTHERFLAGS) $(MGRSRCS)
X		lint $(OTHERFLAGS) $(PSSRCS)
X		lint $(OTHERFLAGS) $(X11SRCS) $(X11LIBS)
X		lint $(OTHERFLAGS) $(XVSRCS)
X
Xshar:
X		shar.script $(STDSRCS) > archive.1
X		shar.script $(OTHERSRCS1) > archive.2
X		shar.script $(OTHERSRCS2) > archive.3
X		shar.script $(IMAGES) $(HDRS) $(OTHERS) > archive.4
X
Xtape:
X		tar cvbf 126 /dev/rst0 $(ALL)
X
Xdownload:	popi.arc
X		sb -a popi.arc
X
Xtar:		popi.tar
X
Xpopi.tar:	$(ALL)
X		tar cvf popi.tar $(ALL)
X
Xarc: popi.arc
X
Xpopi.arc:	$(ALL)
X		arc a popi.arc $?
X
Xzoo: popi.zoo
X
Xpopi.zoo:	$(ALL)
X		zoo -add popi.zoo $?
X
Xcreate:         SCCS
X		-sccs create $(SRCS) $(HDRS) $(IMAGES) $(OTHERS)
X
XSCCS:
X		mkdir SCCS
X		chmod 755 SCCS
X
Xapollo.$(O):	apollo.c $(HDRS)
Xatariterm.$(O):	atariterm.c $(HDRS)
Xexpr.$(O):	expr.c $(HDRS)
Xgraphics.$(O):	graphics.c $(HDRS)
Xio.$(O):	io.c $(HDRS)
Xkerterm.$(O):	kerterm.c $(HDRS)
Xlex.$(O):	lex.c $(HDRS)
Xmain.$(O):	main.c $(HDRS) patchlevel.h
Xmgr.$(O):       mgr.c $(HDRS) $(IMAGES)
Xnews.$(O):	news.c $(HDRS) $(IMAGES)
Xnulldev.$(O):	nulldev.c $(HDRS)
Xrun.$(O):	run.c $(HDRS)
Xspecial.$(O):	special.c $(HDRS)
Xsunview.$(O):	sunview.c $(HDRS) $(IMAGES)
Xx11.$(O):	x11.c $(HDRS) $(IMAGES)
Xxview.$(O):	xview.c $(HDRS) $(IMAGES)
Funky_Stuff
chmod 0444 Makefile || echo "restore of Makefile fails"
set `wc -c Makefile`;Sum=$1
if test "$Sum" != "10877"
then echo original size 10877, current size $Sum;fi
echo "x - extracting README (Text)"
sed 's/^X//' << 'Funky_Stuff' > README &&
X
XREADME - 12th December 1989.
X
XThis is version 2.1 of popi.
X
XPopi was originally written by Gerard J. Holzmann - AT&T Bell Labs.
XThis version is based on the code in his Prentice Hall book,
X"Beyond Photography - the digital darkroom," ISBN 0-13-074410-7,
Xwhich is copyright (c) 1988 by Bell Telephone Laboratories, Inc.
X
XPermission is given to distribute these extensions, as long as these
Xintroductory messages are not removed, and no monies are exchanged.
XSpecial thanks to Gerard for allowing this distribution.
X
XSee the manual page for more details.
X
XDevice drivers are currently included for:
X	Amiga
X	    Works with Lattice C 5.04, but you'ld better have at
X	    least 2M of memory, or restrict yourself to small (128by128)
X	    images.
X	Apollo
X	Atari terminal
X	Kermit terminal
X	MGR
X	NeWS
X            Works with NeWS v1.1 and OpenWindows v1.0.
X	PC
X	    Works with Turbo C, Microsoft C (including Quick C)
X	    and Mix Software's Power C. There is support for
X	    the common graphics cards (CGA, EGA, VGA, HGC) and
X	    additionally, the Turbo C graphics library routines
X	    can be used for non-standard cards if you have
X	    the appropriate .BGI file.
X	SunView
X            Works with SunOS v3.x and SunOS v4.x.
X	X11
X            Works with X11r2 and X11r3.
X	XView
X            Needs the XView toolkit source distribution or Open Windows v1.0.
X	null
X	    For those with no graphics screen, this enables
X	    you to just use one of the printer options.
X
XOutput is available for:
X	PostScript
X	Epson printers.
X
XThis code has been tested on various Sun equipment; 3/60, 3/80, 4/110 and
X386i using the SunView, MGR, X11, NeWS and XView drivers, a Sequent using the
XAtari driver and X11 with a Sigma Data X terminal, a MIPS using an NCD X
Xterminal and an Apollo DN1000 with the X11 driver. Plus the kermit and PC
Xversion of various PC's.
X
XWe'd be interested to hear what other machines you get it working on, so
Xthat we can keep this list up to date.
X
XSee the beginning of the Makefile for details of what you might have
Xto tweak in order to get this working under different O/Ss or on other
Xmachines, and also how to compile and link the different versions.
X
XNote that the Makefile is very generic. Considerable speedups can be obtained
Xby using different compile and link options, plus inline libraries.
X
XThere is a TODO file included which lists current bugs, and the
Xenhancements that will be added in the future.
X
XHISTORY
XThis program was first released to aus.sources in July 1989 in
Xconjunction with a competition held prior to this year's Australian
XUnix Systems User's Group Conference and Exhibition. The best
Xtransformation of Dennis Ritchie's face (as judged by Dennis)
Xwas put on T-shirts that were given to each conference delegate.
XBug-fixes, improvements and new drivers were garnered. A number of
Xvendors had popi running at the exhibition.
X
X
XAcknowledgements
X
XThanks go to:
X	John Pritchard and James Ashton for bug reports and fixes;
X	Tim Roper for System V diffs;
X	Tim Lambert for the Apollo driver;
X	Mark Andrews and Andrew Nicholson for help with the NeWS driver;
X	Frank Crawford for the kermit terminal driver;
X	Peter Chubb for the Amiga work.
X
XPlease pass suggestions for further improvement, comments, bugs and
Xflames back to me (Rich), at the address below, and I'll forward the
Xappropriate ones on to Stephen.
X
XIf you make any bug fixes changes or improvements please let us know so
Xthat we can add them to the main distribution. More device drivers are
Xparticularily welcome.
X
X    Rich Burridge & Stephen Frede.
X
XRich Burridge,          DOMAIN: richb@sunaus.oz.au
XPHONE: +61 2 413 2666   UUCP:   {uunet,mcvax,ukc}!munnari!sunaus.oz!richb
X
XStephen Frede,          DOMAIN: stephenf@softway.oz.au 
XPHONE: +61 2 698 2322   UUCP:   {uunet,mcvax,ukc}!munnari!softway.oz!stephenf
Funky_Stuff
chmod 0444 README || echo "restore of README fails"
set `wc -c README`;Sum=$1
if test "$Sum" != "3800"
then echo original size 3800, current size $Sum;fi
echo "x - extracting TODO (Text)"
sed 's/^X//' << 'Funky_Stuff' > TODO &&
X
X@(#)TODO 1.3 89/12/12
X
XProblems.
X---------
X
X* With the SunView, MGR, NeWS, X11 and XView versions, the #list command
X  needs to output somewhere better that stdout.
X
X* Handling of image files with extensions (eg: dmr.oil), needs to be
X  included.
X
X* The following problem exists with the NeWS version:
X  (i)   The soft cursor is not being correctly positioned in the dialog box.
X
X* The following problem exists with the XView version:
X  (i)   The cursors are not correctly changing.
X
X* The following problem exists with the X11 version with the MIT server:
X  (i)   Colormap (really grayscale map) handling is incorrect. The colourmap
X        should be dynamic and not static.
X
XEnhancements.
X-------------
X
X* Ability to use multiple machines via a remote procedural call
X  mechanism would speed the program up considerably.
X
X* The operation stack should be floating point. This would be available
X  via a compile-time option.
X
X* The graphics interface for the workstation generic graphics drivers,
X  needs to be substantially improved. Inclusion of a scrollbar to view
X  previous commands, the ability to cut and paste commands, menu buttons
X  to iconise and quit, picture settings etc..
X
X* Ability to output images in Sun rasterfile format.
X
X* Add in online help.
X
X* Parametrise some of the special functions, such as genepson.
X
X* Better dithering for monochrome drivers and epson.
X
X* Variables and comma operator, for expression optimisation
X  eg new[x,y] = (t = old[x,y] / 2) < Z/10 ? t/2 : t
X  or whatever.
X
X* Fix up the parsing a bit. Want a better way of dealing with
X  floating point numbers and names.
X
X* Fix up the way images are stored (instead of fixed length array).
X
X* The run time interpreter could be self modifying code. That
X  is, instead of compiling pseudo-operations onto the parse
X  stack, generate real machine code to do the same thing; then
X  execute this inside run().
X
X* Catch signals and longjmp() to prompt. Need to call driver-
X  specific signal handler to clean up in the middle of an image.
X
X* Optimise initial new[x,y] to @
X
X* In I/O, change isalpha() test to allow digits and '_'.
X
X* Do proper optimisation, including precalculation of vectors in run().
X
X* Convert NeWS driver to use classes.
X
X* Grayscale "colour" MGR version.
X
X* Think about rgb colour handling.
X
X* The PC version should use appropriate pointer typedefs (using nonstandard
X  memory reference keywords if available) for the image data.
X
X* When I compile popi with any but the small memory model, it hangs,
X  even on a small image that works with the small model version.
X  I need to look into this.
X
X* PC version again: need to add support for remaining standard board
X  types. Also need to do compiler-independant adapter detection.
X
X* Take a deep breath and allow the PC driver to (optionally) be compiled
X  with graphics.c.
X
X* Need to get command-line option processing right, allowing it to
X  be passed to disp_init, but still giving an error message for
X  unrecognised options.
X
X* It would be good to have something a bit better than the simplistic
X  dithering currently used for drivers that can only display a few
X  greyscales. This should be factored out into graphics.c or something.
Funky_Stuff
chmod 0444 TODO || echo "restore of TODO fails"
set `wc -c TODO`;Sum=$1
if test "$Sum" != "3193"
then echo original size 3193, current size $Sum;fi
echo "x - extracting amiga.c (Text)"
sed 's/^X//' << 'Funky_Stuff' > amiga.c &&
X/*LINTLIBRARY*/
X#ifndef lint
Xstatic char sccsid[] = "@(#)amiga.c 1.3 89/12/11" ;
X#endif
X
X/*  @(#)amiga.c 1.2 89/12/04
X *
X *  Popi device driver for the Amiga.
X *  Written by Peter Chubb - Softway Pty Ltd.
X *
X *  Popi was originally written by Gerard J. Holzmann - AT&T Bell Labs.
X *  This version is based on the code in his Prentice Hall book,
X *  "Beyond Photography - the digital darkroom," ISBN 0-13-074410-7,
X *  which is copyright (c) 1988 by Bell Telephone Laboratories, Inc. 
X *
X *  Permission is given to distribute these extensions, as long as these
X *  introductory messages are not removed, and no monies are exchanged.
X *
X *  No responsibility is taken for any errors or inaccuracies inherent
X *  either to the comments or the code of this program, but if reported
X *  (see README file) then an attempt will be made to fix them.
X */
X
X#include "popi.h"
X#include "graphics.h"
X#include <exec/types.h>
X#include <intuition/intuition.h>
X#include <proto/graphics.h>
X#include <proto/intuition.h>
X#define Debug _X
X#include <proto/exec.h>
X
X/*  There are ten exportable routines used by the popi program.
X *
X *  These are:
X *
X *  disp_init(argc, argv)    - called from main at the start.
X *  disp_finish()            - called from main prior to exit.
X *  disp_imgstart()          - called prior to drawing an image.
X *  disp_imgend()            - called after drawing an image.
X *  disp_putline(line, y)    - to draw an image scanline.
X *  disp_getchar()           - to get the next character typed.
X *  disp_ungetc(c)           - put back the last character typed.
X *  disp_prompt()            - display popi prompt and clear input buffer.
X *  disp_error(errtype)      - display error message.
X *  disp_percentdone(n)      - display percentage value of conversion.
X */
X
X
Xstatic struct NewScreen NewScreen = {
X	0, /* LeftEdge */
X	0, /* TopEdge */
X	512, /* Width */
X	512, /* HEight */
X	4, /* No. Bitplanes */
X	0, 1, /* DetailPen, BlockPen */
X	HIRES | LACE, /* ViewModes */
X	CUSTOMSCREEN, /* Screen type */
X	(struct TextAttr *)NULL,	/* default font */
X	"popi",		/* Screen Title */
X	(struct Gadget *)NULL, /* Gadget list */
X	(struct BitMap *)NULL /* custom bitmap */
X };
X
Xstruct IntuitionBase *IntuitionBase;
Xstruct GfxBase *GfxBase;
Xstatic struct Screen *disp;
X
X/*ARGSUSED*/
Xvoid
Xdisp_init(argc,argv)           /* called from main at the atart. */
Xint argc;
Xchar *argv[];
X{
X  long cnum;
X
X  if((IntuitionBase = (struct IntuitionBase *) OpenLibrary("intuition.library", 0))
X	== NULL){
X	fprintf(stderr, "Couldn't open intuition\n");
X	exit(10);
X  }
X  if((GfxBase = (struct GfxBase *)OpenLibrary("graphics.library", 0))==NULL){
X	fprintf(stderr, "Couldn't open Graphics library\n");
X	CloseLibrary((struct Library *)IntuitionBase);
X	exit(10);
X  }
X
X  if((disp = OpenScreen(&NewScreen)) == NULL){
X	fprintf(stderr, "Couldn't open new screen\n");
X	CloseLibrary((struct Library *)IntuitionBase);
X	CloseLibrary((struct Library *)GfxBase);
X	exit(10);
X  }
X  SetDrMd((&(disp->RastPort)), (long)JAM1);
X  for(cnum = 0; cnum < 16; cnum++)
X	SetRGB4(&(disp->ViewPort), cnum, cnum, cnum, cnum);   
X
X}
X
X
Xvoid
Xdisp_finish()                  /* called from main prior to exit. */
X{
X    CloseScreen(disp);
X    CloseLibrary((struct Library *)IntuitionBase);
X    CloseLibrary((struct Library *)GfxBase);
X}
X
X
Xvoid
Xdisp_imgstart()                /* called prior to drawing an image. */
X{
X	ScreenToFront(disp);
X}
X
X
Xvoid
Xdisp_imgend()                  /* called after drawing an image. */
X{
X}
X
X
Xvoid
Xdisp_putline(line, y)		/* called to draw image scanline y. */
Xpixel_t *line;
Xint y;
X{
X    short x;
X
X    for (x = 0; x < Xsize;)
X    {
X	SetAPen(&(disp->RastPort), (long)((*line++)>>4));
X	WritePixel(&(disp->RastPort), (long)x++, (long)y);
X    }
X}
X
X
Xdisp_getchar()                 /* get next user typed character. */
X{
X  return(getchar());
X}
X
X
X/*ARGSUSED*/
Xvoid
Xdisp_ungetc(c)                 /* put back the last character typed. */
Xchar c;
X{
X    UNGETC(c, stdin);
X}
X
X
Xdisp_prompt()                  /* display popi prompt. */
X{
X  PRINTF("-> ");
X  return 3;
X}
X
X
Xvoid
Xdisp_error(errtype, pos)            /* display error message. */
Xint	errtype,
X	pos;
X{
X    extern int  errno;
X    extern char *sys_errlist[];
X
X    if (errtype & ERR_PARSE)
X    {
X        int     i;
X 
X        for (i=1; i < pos; ++i)
X            PUTC('-', stderr);
X        PUTC('^', stderr);
X        PUTC('\n', stderr);
X    }
X 
X    FPRINTF(stderr, "%s\n", ErrBuf);
X    /* we assume errno hasn't been reset by the preceding output */
X    if (errtype & ERR_SYS)
X        FPRINTF(stderr, "\t(%s)\n", sys_errlist[errno]);
X}
X
Xvoid
Xdisp_percentdone(percent)
Xint	percent;
X{
X    static int	lastpercent = 100;
X
X    if (!Verbose)
X	return;
X    if (percent == 100)
X    {
X	printf("\r    \n");
X	return;
X    }
X    if (percent != lastpercent && percent % 5 == 0)
X    {
X	printf("\r%2d%% ", percent);
X	fflush(stdout);
X	lastpercent = percent;
X    }
X}
Funky_Stuff
chmod 0444 amiga.c || echo "restore of amiga.c fails"
set `wc -c amiga.c`;Sum=$1
if test "$Sum" != "4861"
then echo original size 4861, current size $Sum;fi
echo "x - extracting apollo.c (Text)"
sed 's/^X//' << 'Funky_Stuff' > apollo.c &&
X/*LINTLIBRARY*/
X
X/*  @(#)apollo.c 1.3 89/12/11
X *
X *  Popi device driver for an Apollo display.
X *  Written by Tim Lambert - University of New South Wales.
X *
X *  Popi was originally written by Gerard J. Holzmann - AT&T Bell Labs.
X *  This version is based on the code in his Prentice Hall book,
X *  "Beyond Photography - the digital darkroom," ISBN 0-13-074410-7,
X *  which is copyright (c) 1988 by Bell Telephone Laboratories, Inc. 
X *
X *  Permission is given to distribute these extensions, as long as these
X *  introductory messages are not removed, and no monies are exchanged.
X *
X *  No responsibility is taken for any errors or inaccuracies inherent
X *  either to the comments or the code of this program, but if reported
X *  (see README file) then an attempt will be made to fix them.
X */
X
X#include "popi.h"
X#include "graphics.h"
X#include <apollo/base.h>
X#include <apollo/gpr.h>
X#include <apollo/pad.h>
X#include <apollo/error.h>
X
X/* geometry, and x11_display are used for x11 options - we don't use them */
Xchar x11_display[MAXLINE] ;       /* X11 display information. */
Xchar geometry[MAXLINE] ;          /* X11 geometry information. */
X
X/*  There are ten exportable routines used by the popi program.
X *
X *  These are:
X *
X *  disp_init(argc, argv)    - called from main at the start.
X *  disp_finish()            - called from main prior to exit.
X *  disp_imgstart()          - called prior to drawing an image.
X *  disp_imgend()            - called after drawing an image.
X *  disp_putline(line, y)    - to draw an image scanline.
X *  disp_getchar()           - to get the next character typed.
X *  disp_ungetc(c)           - put back the last character typed.
X *  disp_prompt()            - display popi prompt and clear input buffer.
X *  disp_error(errtype)      - display error message.
X *  disp_percentdone(n)      - display percentage value of conversion.
X */
X
Xstatus_$t            status;
Xgpr_$bitmap_desc_t   display_bitmap;
Xgpr_$offset_t        display_bitmap_size;
Xgpr_$rgb_plane_t     hi_plane;
X
X#define  RES  8
Xint dither[RES][RES] = {        /* dither matrix */
X  {   0, 128,  32, 160,   8, 136,  40, 168, },
X  { 192,  64, 224,  96, 200,  72, 232, 104, },
X  {  48, 176,  16, 144,  56, 184,  24, 152, },
X  { 240, 112, 208,  80, 248, 120, 216,  88, },
X  {  12, 140,  44, 172,   4, 132,  36, 164, },
X  { 204,  76, 236, 108, 196,  68, 228, 100, },
X  {  60, 188,  28, 156,  52, 180,  20, 148, },
X  { 252, 124, 220,  92, 244, 116, 212,  84, },
X} ;
Xvoid check(char *messagex)
X{
X   if (status.all)
X   {   error_$print (status);
X       printf("Error occurred while %s.\n", messagex);
X   }
X}
X
X/*ARGSUSED*/
Xvoid
Xdisp_init(argc,argv)           /* called from main at the atart. */
Xint argc;
Xchar *argv[];
X{
Xstatic short int         unit = 1;
Xstatic short int         disp_len = sizeof(gpr_$disp_char_t);
X       short int         disp_len_returned;
X       short int         unobscured;
Xgpr_$disp_char_t     display_characteristics;
Xstatic gpr_$display_mode_t mode = gpr_$direct;
X        stream_$id_t         graphics_str;
X        pad_$window_desc_t   window;
X        gpr_$color_vector_t  colour_map;
X        short int            i;
X        int                  intense;
X        gpr_$rgb_plane_t     plane;
X
X   gpr_$inq_disp_characteristics(mode, unit, disp_len,
X                                 &display_characteristics,
X                                  &disp_len_returned, &status);
X   check("in disp_init after inquiring");
X
X   display_bitmap_size.x_size = Xsize;
X   display_bitmap_size.y_size = Ysize;
X   hi_plane                   = display_characteristics.n_planes - 1;
X
X   window.top   =  0;     window.left   =  0;
X   window.width =  Xsize;   window.height =  Ysize;
X   pad_$create_window((char *)NULL,0,pad_$transcript,unit,window,&graphics_str,&status);
X   pad_$set_full_window(graphics_str,(short)1,&window,&status);
X   pad_$set_border(graphics_str,(short)1,false,&status);
X   pad_$set_auto_close(graphics_str,(short)1,true,&status);
X   gpr_$init(mode, graphics_str, display_bitmap_size,
X             hi_plane, &display_bitmap, &status);
X   check("in disp_init after initializing");
X   gpr_$set_auto_refresh(true,&status);
X   gpr_$set_obscured_opt(gpr_$pop_if_obs,&status);
X   gpr_$set_cursor_active(true,&status);
X   pad_$def_pfk(graphics_str,"M3  ","=",1,&status); /* M3 reports current cursor position */
X   pad_$def_pfk(graphics_str,"M3U ","",0,&status); /* just in case M3U does something */
X   for(plane=0;plane<=hi_plane;plane++)
X	gpr_$set_raster_op(plane,gpr_$rop_not_dst,&status);  /* so that horiz_line below uses XOR */
X   if(hi_plane==7){ /* 8 plane colour display */
X       /* first 16 colours are used by DM, so we'll use remaining 240,
X          mapping intensities in the range 0..255 to entries 16..255 */
X       gpr_$inq_color_map( 0, 256, colour_map, &status );
X       for(i=16;i<=255;i++){
X           intense = (255*(i-16)/240);
X           colour_map[i] = (intense << 16) + (intense << 8) + intense;
X       }
X       gpr_$acquire_display(&status);
X       gpr_$set_color_map( 0, 256, colour_map, &status );
X       gpr_$release_display(&status);
X   }
X}
X
X
Xvoid
Xdisp_finish()                  /* called from main prior to exit. */
X{
X    gpr_$terminate(false,&status);
X}
X
X
Xvoid
Xdisp_imgstart()                /* called prior to drawing an image. */
X{
X}
X
X
Xvoid
Xdisp_imgend()                  /* called after drawing an image. */
X{
X}
X
X
Xvoid
Xdisp_putline(line, y)		/* called to draw image scanline y. */
Xpixel_t *line;
Xint y;
X{
Xlinteger pixel_array[2000];
Xstatic gpr_$window_t                  scanline = {{0,0},{1,1}};
Xint x;
Xfor (x=0;x<Xsize;x++){
X    if (hi_plane==7){
X        pixel_array[x] = (gpr_$pixel_value_t) line[x]*240/256 +16;
X    } else {
X        pixel_array[x] = !(line[x] >= dither[y % RES][x % RES]);
X    }
X}
Xscanline.window_size.y_size = (short)1;
Xscanline.window_size.x_size = (short)Xsize;
Xscanline.window_base.y_coord = (short)y;
Xgpr_$set_obscured_opt(gpr_$pop_if_obs,&status);
Xgpr_$acquire_display(&status); check("acquiring display");
Xgpr_$write_pixels((gpr_$pixel_value_t *)pixel_array,scanline,&status); check("write pixels");
Xgpr_$release_display(&status); 
X}
X
X
Xdisp_getchar()                 /* get next user typed character. */
X{
X  return(getchar());
X}
X
X
X/*ARGSUSED*/
Xvoid
Xdisp_ungetc(c)                 /* put back the last character typed. */
Xchar c;
X{
X    UNGETC(c, stdin);
X}
X
X
Xdisp_prompt()                  /* display popi prompt. */
X{
X  PRINTF("-> ");
X  return 3;
X}
X
X
Xvoid
Xdisp_error(errtype, pos)            /* display error message. */
Xint	errtype,
X	pos;
X{
X    extern int  errno;
X    extern char *sys_errlist[];
X
X    if (errtype & ERR_PARSE)
X    {
X        int     i;
X 
X        for (i=1; i < pos; ++i)
X            PUTC('-', stderr);
X        PUTC('^', stderr);
X        PUTC('\n', stderr);
X    }
X 
X    FPRINTF(stderr, "%s\n", ErrBuf);
X    /* we assume errno hasn't been reset by the preceding output */
X    if (errtype & ERR_SYS)
X        FPRINTF(stderr, "\t(%s)\n", sys_errlist[errno]);
X}
X
Xvoid horiz_line(percent)
Xint percent;
X/* draw a horizontal line percent % of the way down */
X{
X#define MAX_WINDOWS 50
X    gpr_$window_t vis_list[MAX_WINDOWS];
X    int i;
X    short int slots_total;
X    short int x,y;
X
X    y = Ysize * percent / 100;
X    x = Xsize;
X
X    gpr_$set_obscured_opt(gpr_$ok_if_obs,&status);
X    gpr_$acquire_display(&status); check("acquiring display");
X    gpr_$inq_vis_list (MAX_WINDOWS, &slots_total, vis_list, &status); check("inq vis list");
X    for(i=0; i<slots_total; i++){
X      gpr_$set_clip_window (vis_list[i], &status) ; check("set clip window");
X      gpr_$move(0,y,&status);
X      gpr_$line(x,y,&status);
X    }
X    gpr_$release_display(&status);
X}
X
X
X
Xvoid
Xdisp_percentdone(percent)                
Xint	percent;                             
X{                                        
X    static int	lastpercent = 100;
X                                         
X    if (percent != lastpercent){
X        horiz_line(percent);
X	if(!(percent == 0 || percent == 100))
X	    horiz_line(lastpercent);
X	lastpercent = percent;                  
X    }                                    
X}                                        
X
Funky_Stuff
chmod 0444 apollo.c || echo "restore of apollo.c fails"
set `wc -c apollo.c`;Sum=$1
if test "$Sum" != "8108"
then echo original size 8108, current size $Sum;fi
echo "x - extracting atariterm.c (Text)"
sed 's/^X//' << 'Funky_Stuff' > atariterm.c &&
X/*LINTLIBRARY*/
X
X/*  @(#)atariterm.c 1.9 89/12/11
X *
X *  Popi graphics driver for atari TERM windows.
X *  Written by Stephen Frede, Softway Pty Ltd.
X *
X *  Popi was originally written by Gerard J. Holzmann - AT&T Bell Labs.
X *  This version is based on the code in his Prentice Hall book,
X *  "Beyond Photography - the digital darkroom," ISBN 0-13-074410-7,
X *  which is copyright (c) 1988 by Bell Telephone Laboratories, Inc. 
X *
X *  Permission is given to distribute these extensions, as long as these
X *  introductory messages are not removed, and no monies are exchanged.
X *
X *  No responsibility is taken for any errors or inaccuracies inherent
X *  either to the comments or the code of this program, but if reported
X *  (see README file) then an attempt will be made to fix them.
X */
X
X
X#include <stdio.h>
X#include <sys/types.h>
X#include "popi.h"
X
Xthresh[BITSPERPIXEL][BITSPERPIXEL] =
X{        /* Array containing threshold values. */
X    {   0, 128,  32, 160,   8, 136,  40, 168, },
X    { 192,  64, 224,  96, 200,  72, 232, 104, },
X    {  48, 176,  16, 144,  56, 184,  24, 152, },
X    { 240, 112, 208,  80, 248, 120, 216,  88, },
X    {  12, 140,  44, 172,   4, 132,  36, 164, },
X    { 204,  76, 236, 108, 196,  68, 228, 100, },
X    {  60, 188,  28, 156,  52, 180,  20, 148, },
X    { 252, 124, 220,  92, 244, 116, 212,  84, },
X};
X
Xint	ImgInProgress = 0;
X
X/*  There are ten exportable routines used by the popi program.
X *
X *  These are:
X *
X *  disp_init(argc, argv)    - called from main at the start.
X *  disp_finish()            - called from main prior to exit.
X *  disp_imgstart()          - called prior to drawing an image.
X *  disp_imgend()            - called after drawing an image.
X *  disp_putline(line, y)    - to draw an image scanline.
X *  disp_getchar()           - to get the next character typed.
X *  disp_ungetc(c)           - put back the last character typed.
X *  disp_prompt()            - display popi prompt and clear input buffer.
X *  disp_error(errtype)      - display error message.
X *  disp_percentdone(n)      - display percentage value of conversion.
X */
X
X/*ARGSUSED*/
Xvoid
Xdisp_init(argc,argv)
Xint argc;
Xchar *argv[];
X{
X}
X
Xvoid
Xdisp_finish()
X{
X}
X
Xvoid
Xdisp_imgstart()
X{
X    ImgInProgress = 1;
X
X    putchar('\033');
X    putchar('[');
X    putchar('?');
X    putchar('3');
X    putchar('2');
X    putchar('h');
X    putchar('\033');
X    putchar('[');
X    putchar('2');
X    putchar('J');
X    putchar('\033');
X    putchar('[');
X    putchar(';');
X    putchar('H');
X}
X
Xvoid
Xdisp_imgend()
X{
X    ImgInProgress = 0;
X
X    putchar('\033');
X    putchar('[');
X    putchar('?');
X    putchar('3');
X    putchar('2');
X    putchar('l');
X}
X
Xvoid
Xdisp_putline(line,y)                     /* Output scanline y. */
Xpixel_t *line;
Xint y;
X{
X    int x;
X    short wd;
X    int bit;
X
X    for (x = 0; x < Xsize;)
X    {
X	wd = 0;
X	for (bit = 15; bit >= 0; --bit, ++x)
X	    if (*line++ < thresh[y % BITSPERPIXEL][x % BITSPERPIXEL])
X		wd |= 1 << bit;
X	putchar('0' + ((wd >> 10) & 0x3f));
X	putchar('0' + ((wd >> 5) & 0x1f));
X	putchar('0' + (wd & 0x1f));
X    }
X    putchar('\n');
X}
X
X
Xdisp_getchar()          /* Get next user typed character. */
X{
X    return(getchar());
X}
X
X
Xvoid
Xdisp_ungetc(c)         /* Put back the last character typed. */
Xchar c ;
X{
X    UNGETC(c, stdin);
X}
X
X
X
Xdisp_prompt()         /* Display popi prompt and clear input line. */
X{
X    PRINTF("-> ");
X    return 3;
X}
X
X
Xvoid
Xdisp_error(errtype, pos)         /* Display error message. */
Xint	errtype,
X	pos;
X{
X    extern int  errno;
X    extern char *sys_errlist[];
X
X    if (errtype & ERR_PARSE)
X    {
X        int     i;
X 
X        for (i=1; i < pos; ++i)
X            PUTC('-', stderr);
X        PUTC('^', stderr);
X        PUTC('\n', stderr);
X    }
X 
X    FPRINTF(stderr, "%s\n", ErrBuf);
X    /* we assume errno hasn't been reset by the preceding output */
X    if (errtype & ERR_SYS)
X        FPRINTF(stderr, "\t(%s)\n", sys_errlist[errno]);
X}
X
Xvoid
Xdisp_percentdone(percent)
Xint	percent;
X{
X    static int	lastpercent = 100;
X
X    if (!Verbose || ImgInProgress)
X	return;
X
X    if (percent == 100)
X    {
X	printf("\r    \r");
X	return;
X    }
X
X    if
X    (
X	percent != lastpercent
X	/* && percent % 5 == 0 */
X    )
X    {
X	printf("\r%2d%% ", percent);
X	fflush(stdout);
X	lastpercent = percent;
X    }
X}
Funky_Stuff
chmod 0444 atariterm.c || echo "restore of atariterm.c fails"
set `wc -c atariterm.c`;Sum=$1
if test "$Sum" != "4251"
then echo original size 4251, current size $Sum;fi
echo "x - extracting expr.c (Text)"
sed 's/^X//' << 'Funky_Stuff' > expr.c &&
X/*  @(#)expr.c 1.9 89/12/11
X *
X *  Parser routines used by the popi program.
X *
X *  Popi was originally written by Gerard J. Holzmann - AT&T Bell Labs.
X *  This version is based on the code in his Prentice Hall book,
X *  "Beyond Photography - the digital darkroom," ISBN 0-13-074410-7,
X *  which is copyright (c) 1988 by Bell Telephone Laboratories, Inc. 
X *
X *  Permission is given to distribute these extensions, as long as these
X *  introductory messages are not removed, and no monies are exchanged.
X *
X *  No responsibility is taken for any errors or inaccuracies inherent
X *  either to the comments or the code of this program, but if reported
X *  (see README file) then an attempt will be made to fix them.
X */
X
X#include <stdio.h>
X#include <ctype.h>
X#include "popi.h"
X
Xint lat;      /* look ahead token */
Xint	prs = 0;
Xparse_t	parsed[MAXTOKENS];
Xint	RangeCheck = 1;
X
X/* prototypes for local functions */
Xvoid	expr P((void)),
X	level P((int)),
X	factor P((void)),
X	fileref P((int, int)),
X	expect P((int)),
X	emit P((int));
X
X#define	MAX_SAME_PREC	5	/* max length row of op[], +1 */
X
Xstatic int op[][MAX_SAME_PREC] =
X{
X    { POW },
X    { '*', },		/* Do mul before div, to avoid int underflow */
X    { '/', '%' },
X    { '+', '-' },
X    { LSHIFT, RSHIFT },
X    { '>', '<',  GE, LE },
X    { EQ, NE },
X    { '&' },
X    { '^' },
X    { '|' },
X    { AND },
X    { OR },
X};
X
X/* I was using NELS(op) here (see popi.h) but Microsoft Quick C
X * gets this wrong (it thinks sizeof *op == sizeof op).
X */
X/*#define PREC_LEVELS	NELS(op)	/**/
X#define PREC_LEVELS	(sizeof op / sizeof (int [MAX_SAME_PREC]))
X
Xstatic void
Xemit(what)
Xint	what;
X{
X    DEBUG((Debug,
X	    what < 127 && isprint(what)
X	    ? "emit('%c' (%d))\n"
X	    : "emit(%d)\n",
X	    what, what
X	    ));
X
X    if (prs >= MAXTOKENS)
X    {
X	SPRINTF(ErrBuf, "expression too long");
X	error(ERR_PARSE);
X    }
X    parsed[prs++] = what;
X}
X
X/*
X *	Token is either CLVAL or CRVAL, indicating
X *	an lvalue or an rvalue. We actually
X *	determine if the coordinates are polar or cartesian.
X *
X */
Xstatic void
Xfileref(val, tok)
Xint val, tok;
X{
X    DEBUG((Debug, "fileref(val=%d, tok=%d)\n", val, tok));
X
X    if (val < 0 || val >= nsrc || src[val].str == (char *) 0)
X    {
X	SPRINTF(ErrBuf, "bad file number: %d", val - 1);
X	error(ERR_PARSE);
X    }
X
X    emit(VALUE);
X    emit(val);
X    if (lat == '[')
X    {
X	/* cartesian coordinate reference */
X	lex();
X	expr();
X	expect(',');
X	expr();
X	expect(']');		/* [x, y] */
X	emit(tok);
X	return;
X    }
X
X    if (lat == '{')
X    {
X	/* polar coordinate reference */
X	lex();
X	expr();
X	expect(',');
X	expr();
X	expect('}');		/* {r, a} */
X	emit(tok == CLVAL ? PLVAL : PRVAL);
X	return;
X    }
X
X    /* default (no index specified) is [x, y] */
X    emit('x');
X    emit('y');
X    emit(tok);
X}
X
X
X/*
X * factor	= '(' expr ')'
X *		| UNARYOP factor
X *		| FNCALL1 '(' expr ')'
X *		| FNCALL2 '(' expr ',' expr ')'
X *
X * UNARYOP	= '!'
X *		| '~'
X *
X * FNCALL1	= 'sin'
X *		| 'cos'
X *		| 'log'
X *		| 'sqrt'
X *		| 'abs'
X *
X * FNCALL2	= 'atan'
X */
Xstatic void
Xfactor()
X{
X    int n;
X    int	token;
X
X    DEBUG((Debug, "factor() lat='%c'\n", lat));
X
X    switch (token = lat)
X    {
X	case '(':
X	    lex();
X	    expr();
X	    expect(')');
X	    break;
X
X	case '-':
X	    lex();
X	    factor();
X	    if (parsed[prs-2] == VALUE)		/* constant evaluation */
X		parsed[prs-1] = -parsed[prs-1];
X	    else
X		emit(UMIN);
X	    break;
X
X	case '!':
X	    lex();
X	    factor();
X	    if (parsed[prs-2] == VALUE)
X		parsed[prs-1] = !parsed[prs-1];
X	    else
X		emit(token);
X	    break;
X
X	case '~':
X	    lex();
X	    factor();
X	    if (parsed[prs-2] == VALUE)
X		parsed[prs-1] = ~parsed[prs-1];
X	    else
X		emit(token);
X	    break;
X
X	case INAME:
X	    n = lexval;
X	    lex();
X	    fileref(n+1, CRVAL);
X	    break;
X
X	case '$':
X	    lex();
X	    expect(VALUE);
X	    fileref(lexval+1, CRVAL);
X	    break;
X
X	case VALUE:
X	    emit(VALUE);
X	    emit(lexval);
X	    lex();
X	    break;
X
X	case 'r':
X	case 'a':
X	    MakePolar();	/* Create polar coordinate lookup tables */
X	    /* fall through */
X	case 'y':
X	case 'x':
X	    emit(lat);
X	    lex();
X	    break;
X
X	case RAND:
X	    lex();
X	    expect('(');
X	    expect(')');
X	    emit(RAND);
X	    break;
X
X	case SIN:
X	case COS:
X	case LOG:
X	case SQRT:
X	case ABS:
X	    lex();
X	    expect('(');
X	    expr();
X	    expect(')');
X	    if (parsed[prs-2] == VALUE)
X	    {
X		switch (token)
X		{
X		    case SIN:
X			parsed[prs-1] = (parse_t) sin((double) DtoR(parsed[prs-1]));
X			break;
X		    case COS:
X			parsed[prs-1] = (parse_t) cos((double) DtoR(parsed[prs-1]));
X			break;
X		    case LOG:
X			parsed[prs-1] = (parse_t) log((double)parsed[prs-1]);
X			break;
X		    case SQRT:
X			parsed[prs-1] = (parse_t) sqrt((double)parsed[prs-1]);
X			break;
X		    case ABS:
X			if (parsed[prs-1] < 0)
X			    parsed[prs-1] = -parsed[prs-1];
X			break;
X		}
X	    }
X	    else
X		emit(token);
X	    break;
X
X	case ATAN:
X	case HYPOT:
X	    lex();
X	    expect('(');
X	    expr();
X	    expect(',');
X	    expr();
X	    expect(')');
X	    emit(token);
X	    break;
X
X	default:
X	    SPRINTF(ErrBuf, "expr: syntax error (expected factor)");
X	    error(ERR_PARSE);
X	    break;
X    }
X}
X
X
X/*
X *	Recursive descent parser for binary operators as specified
X *	in the op[] array above.
X *
X * term	= factor BINARYOP term
X */
Xstatic void
Xlevel(nr)
Xint nr;
X{
X    int i;
X    extern int noerr;
X
X    DEBUG((Debug, "level(%d) lat='%c'\n", nr, lat));
X
X    if (nr < 0)
X    {
X	factor();
X	return;
X    }
X
X    level(nr-1);
X
X    for (i = 0; op[nr][i] != 0 && noerr; i++)
X	if (lat == op[nr][i])
X	{
X	    /* LHS of op is already on parse string;
X	     * process RHS and then emit the operator
X	     */
X	    lex();
X	    level(nr);
X	    /*
X	     * Do a little compile-time constant evaluation here
X	     *
X	     *	If the parse string looks like this:
X	     *			<= prs
X	     *	+	value		(prs - 1)	RHS
X	     *	^	VALUE		(prs - 2)
X	     *	v	value		(prs - 3)	LHS
X	     *	-	VALUE		(prs - 4)
X	     * then instead of emitting the operation, we can evaluate.
X	     */
X	    if (prs >= 4 && parsed[prs-2] == VALUE && parsed[prs-4] == VALUE)
X	    {
X		parse_t	*dest = &parsed[prs-3],
X			*src = &parsed[prs-1];
X
X		DEBUG((Debug, "Optimise: %ld %ld '%c'(%d) ", *dest, *src, lat, lat));
X		switch(op[nr][i])
X		{
X		    case POW:
X			*dest = (parse_t) pow((double) *dest, (double) *src);
X			break;
X
X		    case '*':
X			*dest *= *src;
X			break;
X
X		    case '/':
X			if (*src == 0)
X			    *dest = Zmax;
X			else
X			    *dest /= *src;
X			break;
X
X		    case '%':
X			if (*src != 0)
X			    *dest %= *src;
X			break;
X			    
X		    case '+':
X			*dest += *src;
X			break;
X
X		    case '-':
X			*dest -= *src;
X			break;
X
X		    case LSHIFT:
X			*dest  <<= *src;
X			break;
X
X		    case RSHIFT:
X			*dest >>= *src;
X			break;
X
X		    case '>':
X			*dest = *dest > *src;
X			break;
X
X		    case '<':
X			*dest = *dest < *src;
X			break;
X
X		    case GE:
X			*dest = *dest >= *src;
X			break;
X
X		    case LE:
X			*dest = *dest <= *src;
X			break;
X
X		    case EQ:
X			*dest = *dest == *src;
X			break;
X
X		    case NE:
X			*dest = *dest != *src;
X			break;
X
X		    case '&':
X			*dest &= *src;
X			break;
X
X		    case '^':
X			*dest ^= *src;
X			break;
X
X		    case '|':
X			*dest |= *src;
X			break;
X
X		    case AND:
X			*dest = *dest && *src;
X			break;
X
X		    case OR:
X			*dest = *dest || *src;
X			break;
X
X		    default:
X			SPRINTF(ErrBuf,
X			    "Unrecognised token (%d) found during optimisation",
X			    lat);
X			error(ERR_SNARK);
X			break;
X		}
X		prs -= 2;
X		DEBUG((Debug, "=> %ld\n", *dest));
X	    }
X	    else
X		emit(op[nr][i]);
X	    break;
X	}
X}
X
X#ifndef __MSC__		/* MSC gets scope rules wrong */
Funky_Stuff
echo "End of part 1"
echo "File expr.c is continued in part 2"
echo "2" > s2_seq_.tmp
exit 0