Edition 8 Version of pic (May 1985).
authorJaap Akkerhuis <jaap@ucbvax.Berkeley.EDU>
Wed, 24 Jul 1985 02:21:28 +0000 (18:21 -0800)
committerJaap Akkerhuis <jaap@ucbvax.Berkeley.EDU>
Wed, 24 Jul 1985 02:21:28 +0000 (18:21 -0800)
Local hacks from jaap.

SCCS-vsn: local/ditroff/ditroff.okeeffe/pic/Makefile 1.2
SCCS-vsn: local/ditroff/ditroff.okeeffe/pic/arcgen.c 2.1
SCCS-vsn: local/ditroff/ditroff.okeeffe/pic/blockgen.c 2.1
SCCS-vsn: local/ditroff/ditroff.okeeffe/pic/boxgen.c 2.1
SCCS-vsn: local/ditroff/ditroff.okeeffe/pic/circgen.c 2.1
SCCS-vsn: local/ditroff/ditroff.okeeffe/pic/linegen.c 2.1
SCCS-vsn: local/ditroff/ditroff.okeeffe/pic/main.c 2.1
SCCS-vsn: local/ditroff/ditroff.okeeffe/pic/misc.c 2.1
SCCS-vsn: local/ditroff/ditroff.okeeffe/pic/movegen.c 2.1
SCCS-vsn: local/ditroff/ditroff.okeeffe/pic/pic.h 2.1
SCCS-vsn: local/ditroff/ditroff.okeeffe/pic/picl.l 2.1
SCCS-vsn: local/ditroff/ditroff.okeeffe/pic/picy.y 2.1
SCCS-vsn: local/ditroff/ditroff.okeeffe/pic/pltroff.c 2.1
SCCS-vsn: local/ditroff/ditroff.okeeffe/pic/print.c 2.1
SCCS-vsn: local/ditroff/ditroff.okeeffe/pic/symtab.c 2.1
SCCS-vsn: local/ditroff/ditroff.okeeffe/pic/textgen.c 2.1

16 files changed:
usr/src/local/ditroff/ditroff.okeeffe/pic/Makefile
usr/src/local/ditroff/ditroff.okeeffe/pic/arcgen.c
usr/src/local/ditroff/ditroff.okeeffe/pic/blockgen.c
usr/src/local/ditroff/ditroff.okeeffe/pic/boxgen.c
usr/src/local/ditroff/ditroff.okeeffe/pic/circgen.c
usr/src/local/ditroff/ditroff.okeeffe/pic/linegen.c
usr/src/local/ditroff/ditroff.okeeffe/pic/main.c
usr/src/local/ditroff/ditroff.okeeffe/pic/misc.c
usr/src/local/ditroff/ditroff.okeeffe/pic/movegen.c
usr/src/local/ditroff/ditroff.okeeffe/pic/pic.h
usr/src/local/ditroff/ditroff.okeeffe/pic/picl.l
usr/src/local/ditroff/ditroff.okeeffe/pic/picy.y
usr/src/local/ditroff/ditroff.okeeffe/pic/pltroff.c
usr/src/local/ditroff/ditroff.okeeffe/pic/print.c
usr/src/local/ditroff/ditroff.okeeffe/pic/symtab.c
usr/src/local/ditroff/ditroff.okeeffe/pic/textgen.c

index dd99bbd..09c5642 100644 (file)
@@ -1,17 +1,17 @@
 #
 #
-#      Makefile        (CWI)   1.1     85/07/19
+#      Makefile        (CWI)   1.2     85/07/23
 #
 #
-CFLAGS= -O
+CFLAGS= -g
 YFLAGS= -d
 DESTDIR=
 BINDIR=/usr/local
 OFILES = main.o print.o misc.o symtab.o blockgen.o boxgen.o circgen.o \
 YFLAGS= -d
 DESTDIR=
 BINDIR=/usr/local
 OFILES = main.o print.o misc.o symtab.o blockgen.o boxgen.o circgen.o \
-       arcgen.o linegen.o movegen.o troffgen.o textgen.o \
-       pic2.o pltroff.o
+       picy.o arcgen.o linegen.o movegen.o textgen.o \
+       input.o for.o pltroff.o
 OLDOFILES = OLDmain.o print.o misc.o symtab.o blockgen.o boxgen.o circgen.o \
        arcgen.o linegen.o movegen.o troffgen.o textgen.o \
        pic2.o OLDpltroff.o
 OLDOFILES = OLDmain.o print.o misc.o symtab.o blockgen.o boxgen.o circgen.o \
        arcgen.o linegen.o movegen.o troffgen.o textgen.o \
        pic2.o OLDpltroff.o
-OBJECTS= pic pltroff vpic
+OBJECTS= pic
 
 all: ${OBJECTS}
 
 
 all: ${OBJECTS}
 
@@ -19,9 +19,11 @@ pic: picy.o picl.o ${OFILES}
        cc -o pic picy.o picl.o ${OFILES} -lm
 
 pltroff:       driver.o pltroff.o
        cc -o pic picy.o picl.o ${OFILES} -lm
 
 pltroff:       driver.o pltroff.o
+       @echo "not supported"
        cc -o pltroff pltroff.o driver.o -lm
 
 vpic:  picy.o picl.o ${OLDOFILES}
        cc -o pltroff pltroff.o driver.o -lm
 
 vpic:  picy.o picl.o ${OLDOFILES}
+       @echo "not supported"
        cc -o vpic picy.o picl.o ${OLDOFILES} -lm
 
 OLDpltroff.o:  pltroff.c
        cc -o vpic picy.o picl.o ${OLDOFILES} -lm
 
 OLDpltroff.o:  pltroff.c
index 118d6a5..3d02092 100644 (file)
@@ -1,12 +1,12 @@
 #ifndef lint
 #ifndef lint
-static char sccsid[] = "@(#)arcgen.c   1.1 (CWI) 85/07/19";
+static char sccsid[] = "@(#)arcgen.c   2.1 (CWI) 85/07/23";
 #endif lint
 #endif lint
-
 #include       <stdio.h>
 #include       <stdio.h>
+#include       <math.h>
 #include       "pic.h"
 #include       "y.tab.h"
 
 #include       "pic.h"
 #include       "y.tab.h"
 
-struct obj *arcgen(type)       /* handles circular and (eventually) elliptical arcs */
+obj *arcgen(type)      /* handles circular and (eventually) elliptical arcs */
 {
        static float prevw = HT10;
        static float prevh = HT5;
 {
        static float prevw = HT10;
        static float prevh = HT5;
@@ -16,57 +16,66 @@ struct obj *arcgen(type)    /* handles circular and (eventually) elliptical arcs */
        static int dctrx[2][4] ={ 0, -1, 0, 1, 0, 1, 0, -1 };
        static int dctry[2][4] ={ 1, 0, -1, 0, -1, 0, 1, 0 };
        static int nexthv[2][4] ={ U_DIR, L_DIR, D_DIR, R_DIR, D_DIR, R_DIR, U_DIR, L_DIR };
        static int dctrx[2][4] ={ 0, -1, 0, 1, 0, 1, 0, -1 };
        static int dctry[2][4] ={ 1, 0, -1, 0, -1, 0, 1, 0 };
        static int nexthv[2][4] ={ U_DIR, L_DIR, D_DIR, R_DIR, D_DIR, R_DIR, U_DIR, L_DIR };
-       double sqrt(), atan2(), sin(), cos();
-       float dx2, dy2, ht, phi, r, d;
-       int i, head, to, at, cw, invis;
-       struct obj *p, *ppos;
+       float dx2, dy2, ht, phi, r, d, ddval;
+       int i, head, to, at, cw, invis, ddtype;
+       obj *p, *ppos;
        float fromx, fromy, tox, toy;
        float fromx, fromy, tox, toy;
+       Attr *ap;
 
        prevrad = getfval("arcrad");
        prevh = getfval("arrowht");
        prevw = getfval("arrowwid");
        fromx = curx;
        fromy = cury;
 
        prevrad = getfval("arcrad");
        prevh = getfval("arrowht");
        prevw = getfval("arrowwid");
        fromx = curx;
        fromy = cury;
-       head = to = at = cw = invis = 0;
+       head = to = at = cw = invis = ddtype = 0;
        for (i = 0; i < nattr; i++) {
        for (i = 0; i < nattr; i++) {
-               switch (attr[i].a_type) {
-               case LJUST: case RJUST: case CENTER: case SPREAD: case FILL: case ABOVE: case BELOW:
-                       savetext(attr[i].a_type, attr[i].a_val.p);
+               ap = &attr[i];
+               switch (ap->a_type) {
+               case TEXTATTR:
+                       savetext(ap->a_sub, ap->a_val.p);
                        break;
                case HEAD:
                        break;
                case HEAD:
-                       head += attr[i].a_val.i;
+                       head += ap->a_val.i;
                        break;
                case INVIS:
                        invis = INVIS;
                        break;
                        break;
                case INVIS:
                        invis = INVIS;
                        break;
+               case DOT:
+               case DASH:
+                       ddtype = ap->a_type==DOT ? DOTBIT : DASHBIT;
+                       if (ap->a_sub == DEFAULT)
+                               ddval = getfval("dashwid");
+                       else
+                               ddval = ap->a_val.f;
+                       break;
                case HEIGHT:    /* length of arrowhead */
                case HEIGHT:    /* length of arrowhead */
-                       prevh = attr[i].a_val.f;
+                       prevh = ap->a_val.f;
                        break;
                case WIDTH:     /* width of arrowhead */
                        break;
                case WIDTH:     /* width of arrowhead */
-                       prevw = attr[i].a_val.f;
+                       prevw = ap->a_val.f;
                        break;
                case RADIUS:
                        break;
                case RADIUS:
-                       prevrad = attr[i].a_val.f;
+                       prevrad = ap->a_val.f;
                        break;
                case DIAMETER:
                        break;
                case DIAMETER:
-                       prevrad = attr[i].a_val.f / 2;
+                       prevrad = ap->a_val.f / 2;
                        break;
                case CW:
                        cw = 1;
                        break;
                case FROM:      /* start point of arc */
                        break;
                case CW:
                        cw = 1;
                        break;
                case FROM:      /* start point of arc */
-                       ppos = attr[i].a_val.o;
+                       ppos = ap->a_val.o;
                        fromx = ppos->o_x;
                        fromy = ppos->o_y;
                        break;
                case TO:        /* end point of arc */
                        fromx = ppos->o_x;
                        fromy = ppos->o_y;
                        break;
                case TO:        /* end point of arc */
-                       ppos = attr[i].a_val.o;
+                       ppos = ap->a_val.o;
                        tox = ppos->o_x;
                        toy = ppos->o_y;
                        to++;
                        break;
                case AT:        /* center of arc */
                        tox = ppos->o_x;
                        toy = ppos->o_y;
                        to++;
                        break;
                case AT:        /* center of arc */
-                       ppos = attr[i].a_val.o;
+                       ppos = ap->a_val.o;
                        curx = ppos->o_x;
                        cury = ppos->o_y;
                        at = 1;
                        curx = ppos->o_x;
                        cury = ppos->o_y;
                        at = 1;
@@ -95,7 +104,9 @@ struct obj *arcgen(type)     /* handles circular and (eventually) elliptical arcs */
        else if (!at) {
                dx2 = (tox - fromx) / 2;
                dy2 = (toy - fromy) / 2;
        else if (!at) {
                dx2 = (tox - fromx) / 2;
                dy2 = (toy - fromy) / 2;
-               phi = atan2(dy2, dx2) + (cw ? -PI2 : PI2);
+               phi = atan2(dy2, dx2) + (cw ? -PI/2 : PI/2);
+               if (prevrad <= 0.0)
+                       prevrad = dx2*dx2+dy2*dy2;
                for (r=prevrad; (d = r*r - (dx2*dx2+dy2*dy2)) <= 0.0; r *= 2)
                        ;       /* this kludge gets around too-small radii */
                prevrad = r;
                for (r=prevrad; (d = r*r - (dx2*dx2+dy2*dy2)) <= 0.0; r *= 2)
                        ;       /* this kludge gets around too-small radii */
                prevrad = r;
@@ -120,9 +131,7 @@ struct obj *arcgen(type)    /* handles circular and (eventually) elliptical arcs */
                        head = HEAD1;
        }
        p = makenode(type, 7);
                        head = HEAD1;
        }
        p = makenode(type, 7);
-       /* these are wrong in general */
-       extreme(fromx, fromy);
-       extreme(tox, toy);
+       arc_extreme(fromx, fromy, tox, toy, curx, cury);
        p->o_val[0] = fromx;
        p->o_val[1] = fromy;
        p->o_val[2] = tox;
        p->o_val[0] = fromx;
        p->o_val[1] = fromy;
        p->o_val[2] = tox;
@@ -137,9 +146,78 @@ struct obj *arcgen(type)   /* handles circular and (eventually) elliptical arcs */
        p->o_val[4] = prevw;
        p->o_val[5] = prevh;
        p->o_val[6] = prevrad;
        p->o_val[4] = prevw;
        p->o_val[5] = prevh;
        p->o_val[6] = prevrad;
-       p->o_attr = head | (cw ? CW_ARC : 0) | invis;
+       p->o_attr = head | (cw ? CW_ARC : 0) | invis | ddtype;
+       if (head)
+               p->o_nhead = getfval("arrowhead");
        dprintf("arc rad %g at %g %g from %g %g to %g %g head %g %g\n",
                prevrad, p->o_x, p->o_y,
                p->o_val[0], p->o_val[1], p->o_val[2], p->o_val[3], p->o_val[4], p->o_val[5]);
        return(p);
 }
        dprintf("arc rad %g at %g %g from %g %g to %g %g head %g %g\n",
                prevrad, p->o_x, p->o_y,
                p->o_val[0], p->o_val[1], p->o_val[2], p->o_val[3], p->o_val[4], p->o_val[5]);
        return(p);
 }
+
+/***************************************************************************
+   bounding box of a circular arc             Eric Grosse  24 May 84
+
+Conceptually, this routine generates a list consisting of the start,
+end, and whichever north, east, south, and west points lie on the arc.
+The bounding box is then the range of this list.
+    list = {start,end}
+    j = quadrant(start)
+    k = quadrant(end)
+    if( j==k && long way 'round )  append north,west,south,east
+    else
+      while( j != k )
+         append center+radius*[j-th of north,west,south,east unit vectors]
+         j += 1  (mod 4)
+    return( bounding box of list )
+The following code implements this, with simple optimizations.
+***********************************************************************/
+
+
+arc_extreme(x0, y0, x1, y1, xc, yc)
+       double x0, y0, x1, y1, xc, yc;  /* start, end, center */
+{
+       /* assumes center isn't too far out */
+       double r, x, y, xmin, ymin, xmax, ymax;
+       int j, k;
+       x0 -= xc; y0 -= yc;     /* move to center */
+       x1 -= xc; y1 -= yc;
+       xmin = (x0<x1)?x0:x1; ymin = (y0<y1)?y0:y1;
+       xmax = (x0>x1)?x0:x1; ymax = (y0>y1)?y0:y1;
+       r = sqrt(x0*x0 + y0*y0);
+       if (r > 0.0) {
+               j = quadrant(x0,y0);
+               k = quadrant(x1,y1);
+               if (j == k && y1*x0 < x1*y0) {
+                       /* viewed as complex numbers, if Im(z1/z0)<0, arc is big */
+                       if( xmin > -r) xmin = -r; if( ymin > -r) ymin = -r;
+                       if( xmax <  r) xmax =  r; if( ymax <  r) ymax =  r;
+               } else {
+                       while (j != k) {
+                               switch (j) {
+                                       case 1: if( ymax <  r) ymax =  r; break; /* north */
+                                       case 2: if( xmin > -r) xmin = -r; break; /* west */
+                                       case 3: if( ymin > -r) ymin = -r; break; /* south */
+                                       case 4: if( xmax <  r) xmax =  r; break; /* east */
+                               }
+                               j = j%4 + 1;
+                       }
+               }
+       }
+       xmin += xc; ymin += yc;
+       xmax += xc; ymax += yc;
+       extreme(xmin, ymin);
+       extreme(xmax, ymax);
+}
+
+quadrant(x,y)
+       double x, y;
+{
+       if (     x>=0.0 && y> 0.0) return(1);
+       else if( x< 0.0 && y>=0.0) return(2);
+       else if( x<=0.0 && y< 0.0) return(3);
+       else if( x> 0.0 && y<=0.0) return(4);
+       else
+               { fprintf(stderr,"can't happen: x,y=%g,%g",x,y); exit(1);}
+}
+
index 6207752..6d421b6 100644 (file)
@@ -1,61 +1,77 @@
 #ifndef lint
 #ifndef lint
-static char sccsid[] = "@(#)blockgen.c 1.1 (CWI) 85/07/19";
+static char sccsid[] = "@(#)blockgen.c 2.1 (CWI) 85/07/23";
 #endif lint
 #endif lint
-
 #include       <stdio.h>
 #include       "pic.h"
 #include       "y.tab.h"
 
 #include       <stdio.h>
 #include       "pic.h"
 #include       "y.tab.h"
 
+#define        NBRACK  20      /* depth of [...] */
+#define        NBRACE  20      /* depth of {...} */
 
 
-struct pushstack stack[20];
+struct pushstack stack[NBRACK];
 int    nstack  = 0;
 int    nstack  = 0;
+struct pushstack bracestack[NBRACE];
+int    nbstack = 0;
 
 
-struct obj *leftthing(c)       /* called for {... or [... */
+obj *leftthing(c)      /* called for {... or [... */
+                       /* really ought to be separate functions */
        int c;
 {
        int c;
 {
-       struct obj *p;
+       obj *p;
 
 
-       stack[nstack].p_x = curx;
-       stack[nstack].p_y = cury;
-       stack[nstack].p_hvmode = hvmode;
        if (c == '[') {
        if (c == '[') {
+               if (nstack >= NBRACK)
+                       fatal("[...] nested too deep");
+               stack[nstack].p_x = curx;
+               stack[nstack].p_y = cury;
+               stack[nstack].p_hvmode = hvmode;
                curx = cury = 0;
                stack[nstack].p_xmin = xmin;
                stack[nstack].p_xmax = xmax;
                stack[nstack].p_ymin = ymin;
                stack[nstack].p_ymax = ymax;
                curx = cury = 0;
                stack[nstack].p_xmin = xmin;
                stack[nstack].p_xmax = xmax;
                stack[nstack].p_ymin = ymin;
                stack[nstack].p_ymax = ymax;
+               nstack++;
                xmin = ymin = 30000;
                xmax = ymax = -30000;
                p = makenode(BLOCK, 7);
                p->o_val[4] = nobj;     /* 1st item within [...] */
                if (p->o_nobj != nobj-1)
                        fprintf(stderr, "nobjs wrong%d %d\n", p->o_nobj, nobj);
                xmin = ymin = 30000;
                xmax = ymax = -30000;
                p = makenode(BLOCK, 7);
                p->o_val[4] = nobj;     /* 1st item within [...] */
                if (p->o_nobj != nobj-1)
                        fprintf(stderr, "nobjs wrong%d %d\n", p->o_nobj, nobj);
-       }
-       else
+       } else {
+               if (nbstack >= NBRACK)
+                       fatal("{...} nested too deep");
+               bracestack[nbstack].p_x = curx;
+               bracestack[nbstack].p_y = cury;
+               bracestack[nbstack].p_hvmode = hvmode;
+               nbstack++;
                p = NULL;
                p = NULL;
-       nstack++;
+       }
        return(p);
 }
 
        return(p);
 }
 
-struct obj *rightthing(p, c)   /* called for ... ] or ... } */
-       struct obj *p;
+obj *rightthing(p, c)  /* called for ... ] or ... } */
+       obj *p;
 {
 {
-       struct obj *q;
+       obj *q;
 
 
-       nstack--;
-       curx = stack[nstack].p_x;
-       cury = stack[nstack].p_y;
-       hvmode = stack[nstack].p_hvmode;
        if (c == '}') {
        if (c == '}') {
+               nbstack--;
+               curx = bracestack[nbstack].p_x;
+               cury = bracestack[nbstack].p_y;
+               hvmode = bracestack[nbstack].p_hvmode;
                q = makenode(MOVE, 0);
                dprintf("M %g %g\n", curx, cury);
        } else {
                q = makenode(MOVE, 0);
                dprintf("M %g %g\n", curx, cury);
        } else {
+               nstack--;
+               curx = stack[nstack].p_x;
+               cury = stack[nstack].p_y;
+               hvmode = stack[nstack].p_hvmode;
                q = makenode(BLOCKEND, 7);
                q->o_val[4] = p->o_nobj + 1;    /* back pointer */
                p->o_val[5] = q->o_nobj - 1;    /* forward pointer */
                p->o_val[0] = xmin; p->o_val[1] = ymin;
                p->o_val[2] = xmax; p->o_val[3] = ymax;
                q = makenode(BLOCKEND, 7);
                q->o_val[4] = p->o_nobj + 1;    /* back pointer */
                p->o_val[5] = q->o_nobj - 1;    /* forward pointer */
                p->o_val[0] = xmin; p->o_val[1] = ymin;
                p->o_val[2] = xmax; p->o_val[3] = ymax;
-               p->o_dotdash = q->o_dotdash = (int) stack[nstack+1].p_symtab;
+               p->o_symtab = q->o_symtab = stack[nstack+1].p_symtab;
                xmin = stack[nstack].p_xmin;
                ymin = stack[nstack].p_ymin;
                xmax = stack[nstack].p_xmax;
                xmin = stack[nstack].p_xmin;
                ymin = stack[nstack].p_ymin;
                xmax = stack[nstack].p_xmax;
@@ -64,18 +80,15 @@ struct obj *rightthing(p, c)        /* called for ... ] or ... } */
        return(q);
 }
 
        return(q);
 }
 
-struct obj *blockgen(p, type, q)       /* handles [...] */
-       struct obj *p, *q;
+obj *blockgen(p, type, q)      /* handles [...] */
+       obj *p, *q;
        int type;
 {
        int type;
 {
-       static float prevh = HT;
-       static float prevw = WID;       /* golden mean, sort of */
-       int i, invis, at, ddtype;
-       float ddval;
-       int with;
-       float h, w, xwith, ywith;
+       int i, invis, at, ddtype, with;
+       float ddval, h, w, xwith, ywith;
        float x0, y0, x1, y1, cx, cy;
        float x0, y0, x1, y1, cx, cy;
-       struct obj *ppos;
+       obj *ppos;
+       Attr *ap;
 
        invis = at = 0;
        with = xwith = ywith = 0;
 
        invis = at = 0;
        with = xwith = ywith = 0;
@@ -86,28 +99,25 @@ struct obj *blockgen(p, type, q)    /* handles [...] */
        cy = (p->o_val[3] + p->o_val[1]) / 2;
        dprintf("cx,cy=%g,%g\n", cx, cy);
        for (i = 0; i < nattr; i++) {
        cy = (p->o_val[3] + p->o_val[1]) / 2;
        dprintf("cx,cy=%g,%g\n", cx, cy);
        for (i = 0; i < nattr; i++) {
-               switch (attr[i].a_type) {
+               ap = &attr[i];
+               switch (ap->a_type) {
                case HEIGHT:
                case HEIGHT:
-                       h = attr[i].a_val.f;
+                       h = ap->a_val.f;
                        break;
                case WIDTH:
                        break;
                case WIDTH:
-                       w = attr[i].a_val.f;
-                       break;
-               case SAME:
-                       h = prevh;
-                       w = prevw;
+                       w = ap->a_val.f;
                        break;
                case WITH:
                        break;
                case WITH:
-                       with = attr[i].a_val.i; /* corner */
+                       with = ap->a_val.i;     /* corner */
                        break;
                case PLACE:     /* actually with position ... */
                        break;
                case PLACE:     /* actually with position ... */
-                       ppos = attr[i].a_val.o;
+                       ppos = ap->a_val.o;
                        xwith = cx - ppos->o_x;
                        ywith = cy - ppos->o_y;
                        with = PLACE;
                        break;
                case AT:
                        xwith = cx - ppos->o_x;
                        ywith = cy - ppos->o_y;
                        with = PLACE;
                        break;
                case AT:
-                       ppos = attr[i].a_val.o;
+                       ppos = ap->a_val.o;
                        curx = ppos->o_x;
                        cury = ppos->o_y;
                        at++;
                        curx = ppos->o_x;
                        cury = ppos->o_y;
                        at++;
@@ -115,8 +125,8 @@ struct obj *blockgen(p, type, q)    /* handles [...] */
                case INVIS:
                        invis = INVIS;
                        break;
                case INVIS:
                        invis = INVIS;
                        break;
-               case LJUST: case RJUST: case CENTER: case SPREAD: case FILL: case ABOVE: case BELOW:
-                       savetext(attr[i].a_type, attr[i].a_val.p);
+               case TEXTATTR:
+                       savetext(ap->a_sub, ap->a_val.p);
                        break;
                }
        }
                        break;
                }
        }
@@ -175,15 +185,13 @@ struct obj *blockgen(p, type, q)  /* handles [...] */
                q->o_val[i] = p->o_val[i];
        stack[nstack+1].p_symtab = NULL;        /* so won't be found again */
        blockadj(p);    /* fix up coords for enclosed blocks */
                q->o_val[i] = p->o_val[i];
        stack[nstack+1].p_symtab = NULL;        /* so won't be found again */
        blockadj(p);    /* fix up coords for enclosed blocks */
-       prevh = h;
-       prevw = w;
        return(p);
 }
 
 blockadj(p)    /* adjust coords in block starting at p */
        return(p);
 }
 
 blockadj(p)    /* adjust coords in block starting at p */
-       struct obj *p;
+       obj *p;
 {
 {
-       struct obj *q;
+       obj *q;
        float dx, dy;
        int n, lev;
 
        float dx, dy;
        int n, lev;
 
index 769783e..e58b3cd 100644 (file)
@@ -1,21 +1,19 @@
 #ifndef lint
 #ifndef lint
-static char sccsid[] = "@(#)boxgen.c   1.1 (CWI) 85/07/19";
+static char sccsid[] = "@(#)boxgen.c   2.1 (CWI) 85/07/23";
 #endif lint
 #endif lint
-
 #include       <stdio.h>
 #include       "pic.h"
 #include       "y.tab.h"
 
 #include       <stdio.h>
 #include       "pic.h"
 #include       "y.tab.h"
 
-struct obj *boxgen(type)
+obj *boxgen(type)
 {
        static float prevh = HT;
        static float prevw = WID;       /* golden mean, sort of */
 {
        static float prevh = HT;
        static float prevw = WID;       /* golden mean, sort of */
-       int i, invis, at, ddtype;
+       int i, invis, at, ddtype, with;
        float ddval, xwith, ywith;
        float ddval, xwith, ywith;
-       int with;
-       float h, w;
-       float x0, y0, x1, y1;
-       struct obj *p, *ppos;
+       float h, w, x0, y0, x1, y1;
+       obj *p, *ppos;
+       Attr *ap;
 
        h = getfval("boxht");
        w = getfval("boxwid");
 
        h = getfval("boxht");
        w = getfval("boxwid");
@@ -23,22 +21,23 @@ struct obj *boxgen(type)
        with = xwith = ywith = 0;
        ddtype = ddval = 0;
        for (i = 0; i < nattr; i++) {
        with = xwith = ywith = 0;
        ddtype = ddval = 0;
        for (i = 0; i < nattr; i++) {
-               switch (attr[i].a_type) {
+               ap = &attr[i];
+               switch (ap->a_type) {
                case HEIGHT:
                case HEIGHT:
-                       h = attr[i].a_val.f;
+                       h = ap->a_val.f;
                        break;
                case WIDTH:
                        break;
                case WIDTH:
-                       w = attr[i].a_val.f;
+                       w = ap->a_val.f;
                        break;
                case SAME:
                        h = prevh;
                        w = prevw;
                        break;
                case WITH:
                        break;
                case SAME:
                        h = prevh;
                        w = prevw;
                        break;
                case WITH:
-                       with = attr[i].a_val.i; /* corner */
+                       with = ap->a_val.i;     /* corner */
                        break;
                case AT:
                        break;
                case AT:
-                       ppos = attr[i].a_val.o;
+                       ppos = ap->a_val.o;
                        curx = ppos->o_x;
                        cury = ppos->o_y;
                        at++;
                        curx = ppos->o_x;
                        cury = ppos->o_y;
                        at++;
@@ -48,13 +47,14 @@ struct obj *boxgen(type)
                        break;
                case DOT:
                case DASH:
                        break;
                case DOT:
                case DASH:
-                       ddtype = attr[i].a_type;
-                       ddval = attr[i].a_val.f;
-                       if (ddval == 0)
+                       ddtype = ap->a_type==DOT ? DOTBIT : DASHBIT;
+                       if (ap->a_sub == DEFAULT)
                                ddval = getfval("dashwid");
                                ddval = getfval("dashwid");
+                       else
+                               ddval = ap->a_val.f;
                        break;
                        break;
-               case LJUST: case RJUST: case CENTER: case SPREAD: case FILL: case ABOVE: case BELOW:
-                       savetext(attr[i].a_type, attr[i].a_val.p);
+               case TEXTATTR:
+                       savetext(ap->a_sub, ap->a_val.p);
                        break;
                }
        }
                        break;
                }
        }
@@ -91,9 +91,8 @@ struct obj *boxgen(type)
        p = makenode(BOX, 2);
        p->o_val[0] = w;
        p->o_val[1] = h;
        p = makenode(BOX, 2);
        p->o_val[0] = w;
        p->o_val[1] = h;
-       p->o_dotdash = ddtype;
        p->o_ddval = ddval;
        p->o_ddval = ddval;
-       p->o_attr = invis;
+       p->o_attr = invis | ddtype;
        dprintf("B %g %g %g %g at %g %g, h=%g, w=%g\n", x0, y0, x1, y1, curx, cury, h, w);
        if (isright(hvmode))
                curx = x1;
        dprintf("B %g %g %g %g at %g %g, h=%g, w=%g\n", x0, y0, x1, y1, curx, cury, h, w);
        if (isright(hvmode))
                curx = x1;
index 3d278d8..4a0f45a 100644 (file)
@@ -1,22 +1,22 @@
 #ifndef lint
 #ifndef lint
-static char sccsid[] = "@(#)circgen.c  1.1 (CWI) 85/07/19";
+static char sccsid[] = "@(#)circgen.c  2.1 (CWI) 85/07/23";
 #endif lint
 #endif lint
-
 #include       <stdio.h>
 #include       "pic.h"
 #include       "y.tab.h"
 
 #include       <stdio.h>
 #include       "pic.h"
 #include       "y.tab.h"
 
-struct obj *circgen(type)
+obj *circgen(type)
 {
        static float rad[2] = { HT2, WID2 };
        static float rad2[2] = { HT2, HT2 };
        static float x0, y0, x1, y1, x2, y2;
 {
        static float rad[2] = { HT2, WID2 };
        static float rad2[2] = { HT2, HT2 };
        static float x0, y0, x1, y1, x2, y2;
-       int i, at, t, invis, with;
+       int i, at, t, invis, ddtype, with;
        float xwith, ywith;
        float xwith, ywith;
-       float r, r2;
-       struct obj *p, *ppos;
+       float r, r2, ddval;
+       obj *p, *ppos;
+       Attr *ap;
 
 
-       at = invis = 0;
+       at = invis = ddtype = 0;
        with = xwith = ywith = 0;
        t = (type == CIRCLE) ? 0 : 1;
        if (type == CIRCLE)
        with = xwith = ywith = 0;
        t = (type == CIRCLE) ? 0 : 1;
        if (type == CIRCLE)
@@ -25,30 +25,31 @@ struct obj *circgen(type)
                r = getfval("ellipsewid") / 2;
                r2 = getfval("ellipseht") / 2;
        }
                r = getfval("ellipsewid") / 2;
                r2 = getfval("ellipseht") / 2;
        }
-       for (i = 0; i < nattr; i++)
-               switch (attr[i].a_type) {
-               case LJUST: case RJUST: case CENTER: case SPREAD: case FILL: case ABOVE: case BELOW:
-                       savetext(attr[i].a_type, attr[i].a_val.p);
+       for (i = 0; i < nattr; i++) {
+               ap = &attr[i];
+               switch (ap->a_type) {
+               case TEXTATTR:
+                       savetext(ap->a_sub, ap->a_val.p);
                        break;
                case RADIUS:
                        break;
                case RADIUS:
-                       r = attr[i].a_val.f;
+                       r = ap->a_val.f;
                        break;
                case DIAMETER:
                case WIDTH:
                        break;
                case DIAMETER:
                case WIDTH:
-                       r = attr[i].a_val.f / 2;
+                       r = ap->a_val.f / 2;
                        break;
                case HEIGHT:
                        break;
                case HEIGHT:
-                       r2 = attr[i].a_val.f / 2;
+                       r2 = ap->a_val.f / 2;
                        break;
                case SAME:
                        r = rad[t];
                        r2 = rad2[t];
                        break;
                case WITH:
                        break;
                case SAME:
                        r = rad[t];
                        r2 = rad2[t];
                        break;
                case WITH:
-                       with = attr[i].a_val.i;
+                       with = ap->a_val.i;
                        break;
                case AT:
                        break;
                case AT:
-                       ppos = attr[i].a_val.o;
+                       ppos = ap->a_val.o;
                        curx = ppos->o_x;
                        cury = ppos->o_y;
                        at++;
                        curx = ppos->o_x;
                        cury = ppos->o_y;
                        at++;
@@ -56,7 +57,16 @@ struct obj *circgen(type)
                case INVIS:
                        invis = INVIS;
                        break;
                case INVIS:
                        invis = INVIS;
                        break;
+               case DOT:
+               case DASH:
+                       ddtype = ap->a_type==DOT ? DOTBIT : DASHBIT;
+                       if (ap->a_sub == DEFAULT)
+                               ddval = getfval("dashwid");
+                       else
+                               ddval = ap->a_val.f;
+                       break;
                }
                }
+       }
        if (type == CIRCLE)
                r2 = r; /* probably superfluous */
        if (with) {
        if (type == CIRCLE)
                r2 = r; /* probably superfluous */
        if (with) {
@@ -89,7 +99,7 @@ struct obj *circgen(type)
        if (r <= 0 || r2 <= 0) {
                yyerror("%s has invalid radius %g\n", (type==CIRCLE) ? "circle" : "ellipse", r<r2 ? r : r2);
        }
        if (r <= 0 || r2 <= 0) {
                yyerror("%s has invalid radius %g\n", (type==CIRCLE) ? "circle" : "ellipse", r<r2 ? r : r2);
        }
-       p->o_attr = invis;
+       p->o_attr = invis | ddtype;
        extreme(curx+r, cury+r2);
        extreme(curx-r, cury-r2);
        if (type == CIRCLE)
        extreme(curx+r, cury+r2);
        extreme(curx-r, cury-r2);
        if (type == CIRCLE)
index ed96313..87b35ad 100644 (file)
@@ -1,28 +1,27 @@
 #ifndef lint
 #ifndef lint
-static char sccsid[] = "@(#)linegen.c  1.1 (CWI) 85/07/19";
+static char sccsid[] = "@(#)linegen.c  2.1 (CWI) 85/07/23";
 #endif lint
 #endif lint
-
 #include       <stdio.h>
 #include       "pic.h"
 #include       "y.tab.h"
 
 #include       <stdio.h>
 #include       "pic.h"
 #include       "y.tab.h"
 
-struct obj *linegen(type)
+obj *linegen(type)
 {
        static float prevdx = HT;
        static float prevdy = 0;
        static float prevw = HT10;
        static float prevh = HT5;
 {
        static float prevdx = HT;
        static float prevdy = 0;
        static float prevw = HT10;
        static float prevh = HT5;
-       int i, j, some, head, ddtype, invis;
+       int i, j, some, head, ddtype, invis, chop;
        float ddval, chop1, chop2, x0, y0, x1, y1;
        float ddval, chop1, chop2, x0, y0, x1, y1;
-       int chop;
        double sin(), cos(), atan2(), theta;
        float defx, defy;
        double sin(), cos(), atan2(), theta;
        float defx, defy;
-       struct obj *p, *ppos;
+       obj *p, *ppos;
        static int xtab[] = { 1, 0, -1, 0 };    /* R=0, U=1, L=2, D=3 */
        static int ytab[] = { 0, 1, 0, -1 };
        float dx[50], dy[50];
        int ndxy;
        float nx, ny;
        static int xtab[] = { 1, 0, -1, 0 };    /* R=0, U=1, L=2, D=3 */
        static int ytab[] = { 0, 1, 0, -1 };
        float dx[50], dy[50];
        int ndxy;
        float nx, ny;
+       Attr *ap;
 
        nx = curx;
        ny = cury;
 
        nx = curx;
        ny = cury;
@@ -34,28 +33,30 @@ struct obj *linegen(type)
        chop = chop1 = chop2 = 0;
        ddtype = ddval = 0;
        for (i = 0; i < nattr; i++) {
        chop = chop1 = chop2 = 0;
        ddtype = ddval = 0;
        for (i = 0; i < nattr; i++) {
-               switch (attr[i].a_type) {
-               case LJUST: case RJUST: case CENTER: case SPREAD: case FILL: case ABOVE: case BELOW:
-                       savetext(attr[i].a_type, attr[i].a_val.p);
+               ap = &attr[i];
+               switch (ap->a_type) {
+               case TEXTATTR:
+                       savetext(ap->a_sub, ap->a_val.p);
                        break;
                case HEAD:
                        break;
                case HEAD:
-                       head += attr[i].a_val.i;
+                       head += ap->a_val.i;
                        break;
                case INVIS:
                        invis = INVIS;
                        break;
                case CHOP:
                        if (chop++ == 0)
                        break;
                case INVIS:
                        invis = INVIS;
                        break;
                case CHOP:
                        if (chop++ == 0)
-                               chop1 = chop2 = attr[i].a_val.f;
+                               chop1 = chop2 = ap->a_val.f;
                        else
                        else
-                               chop2 = attr[i].a_val.f;
+                               chop2 = ap->a_val.f;
                        break;
                case DOT:
                case DASH:
                        break;
                case DOT:
                case DASH:
-                       ddtype = attr[i].a_type;
-                       ddval = attr[i].a_val.f;
-                       if (ddval == 0)
+                       ddtype = ap->a_type==DOT ? DOTBIT : DASHBIT;
+                       if (ap->a_sub == DEFAULT)
                                ddval = getfval("dashwid");
                                ddval = getfval("dashwid");
+                       else
+                               ddval = ap->a_val.f;
                        break;
                case SAME:
                        dx[ndxy] = prevdx;
                        break;
                case SAME:
                        dx[ndxy] = prevdx;
@@ -63,30 +64,30 @@ struct obj *linegen(type)
                        some++;
                        break;
                case LEFT:
                        some++;
                        break;
                case LEFT:
-                       dx[ndxy] -= (attr[i].a_val.f==0) ? defx : attr[i].a_val.f;
+                       dx[ndxy] -= (ap->a_sub==DEFAULT) ? defx : ap->a_val.f;
                        some++;
                        hvmode = L_DIR;
                        break;
                case RIGHT:
                        some++;
                        hvmode = L_DIR;
                        break;
                case RIGHT:
-                       dx[ndxy] += (attr[i].a_val.f==0) ? defx : attr[i].a_val.f;
+                       dx[ndxy] += (ap->a_sub==DEFAULT) ? defx : ap->a_val.f;
                        some++;
                        hvmode = R_DIR;
                        break;
                case UP:
                        some++;
                        hvmode = R_DIR;
                        break;
                case UP:
-                       dy[ndxy] += (attr[i].a_val.f==0) ? defy : attr[i].a_val.f;
+                       dy[ndxy] += (ap->a_sub==DEFAULT) ? defy : ap->a_val.f;
                        some++;
                        hvmode = U_DIR;
                        break;
                case DOWN:
                        some++;
                        hvmode = U_DIR;
                        break;
                case DOWN:
-                       dy[ndxy] -= (attr[i].a_val.f==0) ? defy : attr[i].a_val.f;
+                       dy[ndxy] -= (ap->a_sub==DEFAULT) ? defy : ap->a_val.f;
                        some++;
                        hvmode = D_DIR;
                        break;
                case HEIGHT:    /* length of arrowhead */
                        some++;
                        hvmode = D_DIR;
                        break;
                case HEIGHT:    /* length of arrowhead */
-                       prevh = attr[i].a_val.f;
+                       prevh = ap->a_val.f;
                        break;
                case WIDTH:     /* width of arrowhead */
                        break;
                case WIDTH:     /* width of arrowhead */
-                       prevw = attr[i].a_val.f;
+                       prevw = ap->a_val.f;
                        break;
                case TO:
                        if (some) {
                        break;
                case TO:
                        if (some) {
@@ -101,7 +102,13 @@ struct obj *linegen(type)
                        some++;
                        break;
                case BY:
                        some++;
                        break;
                case BY:
-                       ppos = attr[i].a_val.o;
+                       if (some) {
+                               nx += dx[ndxy];
+                               ny += dy[ndxy];
+                               ndxy++;
+                               dx[ndxy] = dy[ndxy] = some = 0;
+                       }
+                       ppos = ap->a_val.o;
                        dx[ndxy] = ppos->o_x;
                        dy[ndxy] = ppos->o_y;
                        some++;
                        dx[ndxy] = ppos->o_x;
                        dy[ndxy] = ppos->o_y;
                        some++;
@@ -116,7 +123,7 @@ struct obj *linegen(type)
                        break;
                case FROM:
                case AT:
                        break;
                case FROM:
                case AT:
-                       ppos = attr[i].a_val.o;
+                       ppos = ap->a_val.o;
                        nx = curx = ppos->o_x;
                        ny = cury = ppos->o_y;
                        break;
                        nx = curx = ppos->o_x;
                        ny = cury = ppos->o_y;
                        break;
@@ -155,28 +162,42 @@ struct obj *linegen(type)
                dy[0] -= y0;
                dx[ndxy-1] -= x1;
                dy[ndxy-1] -= y1;
                dy[0] -= y0;
                dx[ndxy-1] -= x1;
                dy[ndxy-1] -= y1;
-               if(dbg)printf("chopping %g %g %g %g; cur=%g,%g end=%g,%g\n",
+               dprintf("chopping %g %g %g %g; cur=%g,%g end=%g,%g\n",
                        x0, y0, x1, y1, curx, cury, nx, ny);
        }
        p = makenode(type, 5 + 2 * ndxy);
        curx = p->o_val[0] = nx;
        cury = p->o_val[1] = ny;
        if (head || type == ARROW) {
                        x0, y0, x1, y1, curx, cury, nx, ny);
        }
        p = makenode(type, 5 + 2 * ndxy);
        curx = p->o_val[0] = nx;
        cury = p->o_val[1] = ny;
        if (head || type == ARROW) {
+               p->o_nhead = getfval("arrowhead");
                p->o_val[2] = prevw;
                p->o_val[3] = prevh;
                if (head == 0)
                        head = HEAD2;   /* default arrow head */
        }
                p->o_val[2] = prevw;
                p->o_val[3] = prevh;
                if (head == 0)
                        head = HEAD2;   /* default arrow head */
        }
-       p->o_attr = head | invis;
+       p->o_attr = head | invis | ddtype;
        p->o_val[4] = ndxy;
        nx = p->o_x;
        ny = p->o_y;
        for (i = 0, j = 5; i < ndxy; i++, j += 2) {
                p->o_val[j] = dx[i];
                p->o_val[j+1] = dy[i];
        p->o_val[4] = ndxy;
        nx = p->o_x;
        ny = p->o_y;
        for (i = 0, j = 5; i < ndxy; i++, j += 2) {
                p->o_val[j] = dx[i];
                p->o_val[j+1] = dy[i];
-               extreme(nx += dx[i], ny += dy[i]);
+               if (type == LINE)
+                       extreme(nx += dx[i], ny += dy[i]);
+               else if (type == SPLINE && i < ndxy-1) {
+                       /* to compute approx extreme of spline at p,
+                       /* compute midway between p-1 and p+1,
+                       /* then go 3/4 from there to p */
+                       float ex, ey, xi, yi, xi1, yi1;
+                       xi = nx + dx[i]; yi = ny + dy[i];       /* p */
+                       xi1 = xi + dx[i+1]; yi1 = yi + dy[i+1]; /* p+1 */
+                       ex = (nx+xi1)/2; ey = (ny+yi1)/2;       /* midway */
+                       ex += 0.75*(xi-ex); ey += 0.75*(yi-ey);
+                       extreme(ex, ey);
+                       nx = xi; ny = yi;
+               }
+                       
        }
        }
-       p->o_dotdash = ddtype;
        p->o_ddval = ddval;
        if (dbg) {
                printf("S or L from %g %g to %g %g with %d elements:\n", p->o_x, p->o_y, curx, cury, ndxy);
        p->o_ddval = ddval;
        if (dbg) {
                printf("S or L from %g %g to %g %g with %d elements:\n", p->o_x, p->o_y, curx, cury, ndxy);
@@ -187,8 +208,3 @@ struct obj *linegen(type)
        extreme(curx, cury);
        return(p);
 }
        extreme(curx, cury);
        return(p);
 }
-
-struct obj *splinegen(type)
-{
-       linegen(type);
-}
index 46dce90..b1833ad 100644 (file)
@@ -1,18 +1,21 @@
 #ifndef lint
 #ifndef lint
-static char sccsid[] = "@(#)main.c     1.1 (CWI) 85/07/19";
+static char sccsid[] = "@(#)main.c     2.1 (CWI) 85/07/23";
 #endif lint
 #endif lint
-
 #include       <stdio.h>
 #include       <stdio.h>
+#include       <signal.h>
 #include       "pic.h"
 #include       "y.tab.h"
 
 #include       "pic.h"
 #include       "y.tab.h"
 
-struct obj     *objlist[MAXOBJ];       /* store the elements here */
+obj    **objlist = 0;  /* store the elements here */
+int    nobjlist = 0;           /* size of objlist array */
 int    nobj    = 0;
 
 int    nobj    = 0;
 
-struct attr    attr[40];       /* attributes stored here as collected */
+Attr   *attr;  /* attributes stored here as collected */
+int    nattrlist = 0;
 int    nattr   = 0;    /* number of entries in attr_list */
 
 int    nattr   = 0;    /* number of entries in attr_list */
 
-struct text    text[MAXTEXT];  /* text strings stored here as collected */
+Text   *text   = 0;    /* text strings stored here as collected */
+int    ntextlist = 0;          /* size of text[] array */
 int    ntext   = 0;
 int    ntext1  = 0;    /* record ntext here on entry to each figure */
 
 int    ntext   = 0;
 int    ntext1  = 0;    /* record ntext here on entry to each figure */
 
@@ -26,50 +29,10 @@ int codegen = 0;    /* 1=>output for this picture; 0=>no output */
 float  deltx   = 6;    /* max x value in output, for scaling */
 float  delty   = 6;    /* max y value in output, for scaling */
 int    dbg     = 0;
 float  deltx   = 6;    /* max x value in output, for scaling */
 float  delty   = 6;    /* max y value in output, for scaling */
 int    dbg     = 0;
-extern FILE    *yyin,  /* input file pointer */
-               *skeldb; /* output pointer for dbg messeges */
 int    lineno  = 0;
 char   *filename       = "-";
 int    synerr  = 0;
 char   *cmdname;
 int    lineno  = 0;
 char   *filename       = "-";
 int    synerr  = 0;
 char   *cmdname;
-int    crop    = 1;    /* trim off exterior white space if non-zero */
-extern int     useDline;       /* if set, use \D for all lines */
-
-/* You may want to change this if you don't have a 202... */
-
-/*
- *#ifdef       APS
- *     int     devtype = DEVAPS;
- *     int     res     = 723;
- *     int     DX      = 3;
- *     int     DY      = 3;
- *
- *#ifdef 202
- *     int     devtype = DEV202;
- *     int     res     = 972;  /* default is 202 *
- *     int     DX      = 4;    /* used only for old-style troff *
- *     int     DY      = 4;
- */
-#ifdef OLDTROFF
-/* mandatory values for graphic systems CAT: */
-int    devtype = DEVCAT;
-int    res     = 432;
-int    DX = 3;
-int    DY = 3;
-#else
-       int     devtype = DEVHAR;
-       int     res     = 1445; /* default is HARRIS */
-       int     DX      = 4;    /* used only for old-style troff */
-       int     DY      = 4;
-#endif
-
-float  hshift  = 0;    /* move this far left for text (in em's) */
-float  vshift  = 0.2;  /* this far down */
-
-float  sxmin;          /* lower limit from s command */
-float  symin;
-float  sxmax   = 4096; /* upper */
-float  symax   = 4096;
 
 float  xmin    = 30000;        /* min values found in actual data */
 float  ymin    = 30000;
 
 float  xmin    = 30000;        /* min values found in actual data */
 float  ymin    = 30000;
@@ -77,87 +40,94 @@ float       xmax    = -30000;       /* max */
 float  ymax    = -30000;
 
 main(argc, argv)
 float  ymax    = -30000;
 
 main(argc, argv)
-       char **argv;
+       char *argv[];
 {
 {
+       char buf[20];
+       extern int fpecatch();
+
+       signal(SIGFPE, fpecatch);
        cmdname = argv[0];
        while (argc > 1 && *argv[1] == '-') {
                switch (argv[1][1]) {
        cmdname = argv[0];
        while (argc > 1 && *argv[1] == '-') {
                switch (argv[1][1]) {
-               case 'T':
-                       if (strcmp(&argv[1][2], "aps") == 0) {
-                               res = 723;
-                               devtype = DEVAPS;
-                               DX = DY = 1;
-                       } else if (strcmp(&argv[1][2], "cat") == 0) {
-                               res = 432;
-                               devtype = DEVCAT;
-                               DX = DY = 3;
-                       } else if (strcmp(&argv[1][2], "ver") == 0) {
-                               res = 200;
-                               devtype = DEVVER;
-                               DX = DY = 1;
-                       } else if (strcmp(&argv[1][2], "450") == 0) {
-                               res = 240;
-                               devtype = DEV450;
-                       } else if (strcmp(&argv[1][2], "har") == 0) {
-                               res = 1445;
-                               devtype = DEVHAR;
-                       } else {
-                               res = atoi(&argv[1][2]);
-                       }
-                       break;
                case 'd':
                case 'd':
-                       dbg = 1;
-                       break;
-               case 'D':
-#                      ifdef OLDTROFF
-                       useDline = !useDline;
-#                      endif
+                       dbg = atoi(&argv[1][2]);
+                       if (dbg == 0)
+                               dbg = 1;
                        break;
                }
                argc--;
                argv++;
        }
                        break;
                }
                argc--;
                argv++;
        }
-#      ifndef OLDTROFF
-       useDline = 1;
-#      endif
-#
        setdefaults();
        setdefaults();
+       objlist = (obj **) grow(objlist, "objlist", nobjlist += 1000, sizeof(obj *));
+       text = (Text *) grow(text, "text", ntextlist += 1000, sizeof(Text));
+       attr = (Attr *) grow(attr, "attr", nattrlist += 100, sizeof(Attr));
+
+       sprintf(buf, "/%d/", getpid());
+       pushsrc(String, buf);
+       definition("pid");
+
+       pushsrc(File, curfile = infile);
        if (argc <= 1) {
        if (argc <= 1) {
-               yyin = stdin;
-               getdata(yyin);
+               curfile->fin = stdin;
+               curfile->fname = tostring("-");
+               getdata(curfile);
        } else
                while (argc-- > 1) {
        } else
                while (argc-- > 1) {
-                       if ((yyin = fopen(*++argv, "r")) == NULL) {
-                               fprintf(stderr, "pic: can't open %s\n", *argv);
+                       if ((curfile->fin = fopen(*++argv, "r")) == NULL) {
+                               fprintf(stderr, "%s: can't open %s\n", cmdname, *argv);
                                exit(1);
                        }
                                exit(1);
                        }
-                       filename = *argv;
-                       getdata(yyin);
-                       fclose(yyin);
+                       curfile->fname = tostring(*argv);
+                       getdata(curfile);
+                       fclose(curfile->fin);
+                       free(curfile->fname);
                }
        exit(0);
 }
 
                }
        exit(0);
 }
 
+fpecatch()
+{
+       fatal("floating point exception");
+}
+
+char *grow(ptr, name, num, size)       /* make array bigger */
+       char *ptr, *name;
+       int num, size;
+{
+       char *p;
+
+       if (ptr == NULL)
+               p = malloc(num * size);
+       else
+               p = realloc(ptr, num * size);
+       if (p == NULL)
+               fatal("can't grow %s to %d", name, num * size);
+       return p;
+}
+
 static struct {
        char *name;
        float val;
 static struct {
        char *name;
        float val;
+       short scalable;         /* 1 => adjust when "scale" changes */
 } defaults[] ={
 } defaults[] ={
-       "scale", SCALE,
-       "lineht", HT,
-       "linewid", HT,
-       "moveht", HT,
-       "movewid", HT,
-       "dashwid", HT10,
-       "boxht", HT,
-       "boxwid", WID,
-       "circlerad", HT2,
-       "arcrad", HT2,
-       "ellipseht", HT,
-       "ellipsewid", WID,
-       "arrowht", HT5,
-       "arrowwid", HT10,
-       "textht", HT,
-       "textwid", WID,
+       "scale", SCALE, 1,
+       "lineht", HT, 1,
+       "linewid", HT, 1,
+       "moveht", HT, 1,
+       "movewid", HT, 1,
+       "dashwid", HT10, 1,
+       "boxht", HT, 1,
+       "boxwid", WID, 1,
+       "circlerad", HT2, 1,
+       "arcrad", HT2, 1,
+       "ellipseht", HT, 1,
+       "ellipsewid", WID, 1,
+       "arrowht", HT5, 1,
+       "arrowwid", HT10, 1,
+       "arrowhead", 2, 0,              /* arrowhead style */
+       "textht", 0.0, 1,               /* 6 lines/inch is also a useful value */
+       "textwid", 0.0, 1,
        NULL, 0
 };
 
        NULL, 0
 };
 
@@ -172,6 +142,23 @@ setdefaults()      /* set default sizes for variables like boxht */
        }
 }
 
        }
 }
 
+resetvar()     /* reset variables listed */
+{
+       int i, j;
+
+       if (nattr == 0) {       /* none listed, so do all */
+               setdefaults();
+               return;
+       }
+       for (i = 0; i < nattr; i++) {
+               for (j = 0; defaults[j].name != NULL; j++)
+                       if (strcmp(defaults[j].name, attr[i].a_val.p) == 0) {
+                               setfval(defaults[j].name, defaults[j].val);
+                               free(attr[i].a_val.p);
+                               break;
+                       }
+       }
+}
 
 checkscale(s)  /* if s is "scale", adjust default variables */
        char *s;
 
 checkscale(s)  /* if s is "scale", adjust default variables */
        char *s;
@@ -182,70 +169,70 @@ checkscale(s)     /* if s is "scale", adjust default variables */
        if (strcmp(s, "scale") == 0) {
                scale = getfval("scale");
                for (i = 1; defaults[i].name != NULL; i++)
        if (strcmp(s, "scale") == 0) {
                scale = getfval("scale");
                for (i = 1; defaults[i].name != NULL; i++)
-                       setfval(defaults[i].name, defaults[i].val * scale);
+                       if (defaults[i].scalable)
+                               setfval(defaults[i].name, defaults[i].val * scale);
        }
 }
 
        }
 }
 
-getdata(fin)
-       register FILE *fin;
+getdata()
 {
 {
-       char buf[1000], buf1[50];
-       FILE *svyyin;
-       int svlineno;
-       char *svfilename, *p;
+       char *p, buf[1000], buf1[100];
+       int ln;
 
 
-       lineno = 0;
-       while (fgets(buf, sizeof buf, fin) != NULL) {
-               lineno++;
+       curfile->lineno = 0;
+       printf(".lf 1 %s\n", curfile->fname);
+       while (fgets(buf, sizeof buf, curfile->fin) != NULL) {
+               curfile->lineno++;
                if (*buf == '.' && *(buf+1) == 'P' && *(buf+2) == 'S') {
                        for (p = &buf[3]; *p == ' '; p++)
                                ;
                        if (*p++ == '<') {
                if (*buf == '.' && *(buf+1) == 'P' && *(buf+2) == 'S') {
                        for (p = &buf[3]; *p == ' '; p++)
                                ;
                        if (*p++ == '<') {
-                               svyyin = yyin;
-                               svlineno = lineno;
-                               svfilename = filename;
+                               Infile svfile;
+                               svfile = *curfile;
                                sscanf(p, "%s", buf1);
                                sscanf(p, "%s", buf1);
-                               if ((yyin = fopen(buf1, "r")) == NULL) {
-                                       fprintf(stderr, "pic: can't open %s\n", buf1);
-                                       exit(1);
-                               }
-                               lineno = 0;
-                               filename = p;
-                               getdata(yyin);
-                               fclose(yyin);
-                               lineno = svlineno;
-                               yyin = svyyin;
-                               filename = svfilename;
+                               if ((curfile->fin=fopen(buf1, "r")) == NULL)
+                                       fatal("can't open %s", buf1);
+                               curfile->fname = tostring(buf1);
+                               getdata();
+                               fclose(curfile->fin);
+                               free(curfile->fname);
+                               *curfile = svfile;
+                               printf(".lf %d %s\n", curfile->lineno, curfile->fname);
                                continue;
                        }
                        reset();
                        yyparse();
                                continue;
                        }
                        reset();
                        yyparse();
-                       /* yylval now contains 'E' or 'F' from .PE or .PF */
-                       if (buf[3] == ' ')      /* assume next thing is width */
-                               deltx = delty = atof(&buf[4]);
-                       else {
-                               deltx = xmax - xmin;
-                               if (deltx <= 0)
-                                       deltx = ymax - ymin;
-                               deltx /= getfval("scale");
-                               delty = deltx;
+                       /* yylval.i now contains 'E' or 'F' from .PE or .PF */
+
+                       deltx = (xmax - xmin) / getfval("scale");
+                       delty = (ymax - ymin) / getfval("scale");
+                       if (buf[3] == ' ') {    /* next things are wid & ht */
+                               if (sscanf(&buf[4],"%f%f",&deltx,&delty) < 2)
+                                       delty = deltx * (ymax-ymin) / (xmax-xmin);
                        }
                        }
-                       dprintf("deltx = %.3f\n", deltx);
+                       dprintf("deltx = %g, delty = %g\n", deltx, delty);
                        if (codegen && !synerr) {
                                openpl(&buf[3]);        /* puts out .PS, with ht & wid stuck in */
                        if (codegen && !synerr) {
                                openpl(&buf[3]);        /* puts out .PS, with ht & wid stuck in */
+                               printf(".lf %d\n", curfile->lineno+1);
                                print();        /* assumes \n at end */
                                print();        /* assumes \n at end */
-                               closepl(yylval.p);      /* does the .PE/F */
+                               closepl(yylval.i);      /* does the .PE/F */
                        }
                        }
+                       printf(".lf %d\n", curfile->lineno+1);
                        fflush(stdout);
                        fflush(stdout);
-               }
-               else
+               } else if (buf[0] == '.' && buf[1] == 'l' && buf[2] == 'f') {
+                       if (sscanf(buf+3, "%d %s", &ln, buf1) == 2) {
+                               free(curfile->fname);
+                               printf(".lf %d %s\n", curfile->lineno = ln, curfile->fname = tostring(buf1));
+                       } else
+                               printf(".lf %d\n", curfile->lineno = ln);
+               } else
                        fputs(buf, stdout);
        }
 }
 
 reset()
 {
                        fputs(buf, stdout);
        }
 }
 
 reset()
 {
-       struct obj *op;
+       obj *op;
        int i;
        struct symtab *p;
        extern int nstack;
        int i;
        struct symtab *p;
        extern int nstack;
@@ -253,20 +240,19 @@ reset()
        for (i = 0; i < nobj; i++) {
                op = objlist[i];
                if (op->o_type == BLOCK)
        for (i = 0; i < nobj; i++) {
                op = objlist[i];
                if (op->o_type == BLOCK)
-                       freesymtab(op->o_dotdash);      /* funny place */
+                       freesymtab(op->o_symtab);
                free(objlist[i]);
        }
        nobj = 0;
        nattr = 0;
        for (i = 0; i < ntext; i++)
                free(objlist[i]);
        }
        nobj = 0;
        nattr = 0;
        for (i = 0; i < ntext; i++)
-               free(text[i].t_val);
+               if (text[i].t_val)
+                       free(text[i].t_val);
        ntext = ntext1 = 0;
        codegen = synerr = 0;
        nstack = 0;
        curx = cury = 0;
        hvmode = R_DIR;
        ntext = ntext1 = 0;
        codegen = synerr = 0;
        nstack = 0;
        curx = cury = 0;
        hvmode = R_DIR;
-       sxmin = symin = 0;
-       sxmax = symax = 4096;
        xmin = ymin = 30000;
        xmax = ymax = -30000;
 }
        xmin = ymin = 30000;
        xmax = ymax = -30000;
 }
index 43614db..e1f8646 100644 (file)
@@ -1,12 +1,11 @@
 #ifndef lint
 #ifndef lint
-static char sccsid[] = "@(#)misc.c     1.1 (CWI) 85/07/19";
+static char sccsid[] = "@(#)misc.c     2.1 (CWI) 85/07/23";
 #endif lint
 #endif lint
-
 #include       <stdio.h>
 #include       "pic.h"
 #include       "y.tab.h"
 
 #include       <stdio.h>
 #include       "pic.h"
 #include       "y.tab.h"
 
-setdir(n)      /* set direction from n */
+setdir(n)      /* set direction (hvmode) from LEFT, RIGHT, etc. */
        int n;
 {
        switch (n) {
        int n;
 {
        switch (n) {
@@ -18,8 +17,18 @@ setdir(n)    /* set direction from n */
        return(hvmode);
 }
 
        return(hvmode);
 }
 
+curdir()       /* convert current dir (hvmode) to RIGHT, LEFT, etc. */
+{
+       switch (hvmode) {
+       case R_DIR:     return RIGHT;
+       case L_DIR:     return LEFT;
+       case U_DIR:     return UP;
+       case D_DIR:     return DOWN;
+       }
+}
+
 float getcomp(p, t)    /* return component of a position */
 float getcomp(p, t)    /* return component of a position */
-       struct obj *p;
+       obj *p;
        int t;
 {
        switch (t) {
        int t;
 {
        switch (t) {
@@ -60,16 +69,86 @@ float getcomp(p, t) /* return component of a position */
        }
 }
 
        }
 }
 
-makeattr(type, val)    /* add attribute type and val */
-       int type;
+float  exprlist[100];
+int    nexpr   = 0;
+
+exprsave(f)
+       float f;
+{
+       exprlist[nexpr++] = f;
+}
+
+char *sprintgen(fmt)
+       char *fmt;
+{
+       int i;
+       char buf[1000];
+
+       sprintf(buf, fmt, exprlist[0], exprlist[1], exprlist[2], exprlist[3], exprlist[4]);
+       nexpr = 0;
+       free(fmt);
+       return tostring(buf);
+}
+
+makefattr(type, sub, f)        /* float attr */
+       int type, sub;
+       float f;
+{
+       YYSTYPE val;
+       val.f = f;
+       makeattr(type, sub, val);
+}
+
+makeoattr(type, o)     /* obj* attr */
+       obj *o;
+{
+       YYSTYPE val;
+       val.o = o;
+       makeattr(type, 0, val);
+}
+
+makeiattr(type, i)     /* int attr */
+       int i;
+{
+       YYSTYPE val;
+       val.i = i;
+       makeattr(type, 0, val);
+}
+
+maketattr(sub, p)      /* text attribute: takes two */
+       char *p;
+{
+       YYSTYPE val;
+       val.p = p;
+       makeattr(TEXTATTR, sub, val);
+}
+
+addtattr(sub)          /* add text attrib to existing item */
+{
+       attr[nattr-1].a_sub |= sub;
+}
+
+makevattr(p)   /* varname attribute */
+       char *p;
+{
+       YYSTYPE val;
+       val.p = p;
+       makeattr(VARNAME, 0, val);
+}
+
+makeattr(type, sub, val)       /* add attribute type and val */
+       int type, sub;
        YYSTYPE val;
 {
        if (type == 0 && val.i == 0) {  /* clear table for next stat */
                nattr = 0;
                return;
        }
        YYSTYPE val;
 {
        if (type == 0 && val.i == 0) {  /* clear table for next stat */
                nattr = 0;
                return;
        }
-       dprintf("attr %d:  %d %d\n", nattr, type, val.i);
+       if (nattr >= nattrlist)
+               attr = (Attr *) grow(attr, "attr", nattrlist += 100, sizeof(Attr));
+       dprintf("attr %d:  %d %d %d\n", nattr, type, sub, val.i);
        attr[nattr].a_type = type;
        attr[nattr].a_type = type;
+       attr[nattr].a_sub = sub;
        attr[nattr].a_val = val;
        nattr++;
 }
        attr[nattr].a_val = val;
        nattr++;
 }
@@ -77,13 +156,13 @@ makeattr(type, val)        /* add attribute type and val */
 printexpr(f)   /* print expression for debugging */
        float f;
 {
 printexpr(f)   /* print expression for debugging */
        float f;
 {
-       dprintf("%g\n", f);
+       printf("%g\n", f);
 }
 
 printpos(p)    /* print position for debugging */
 }
 
 printpos(p)    /* print position for debugging */
-       struct obj *p;
+       obj *p;
 {
 {
-       dprintf("%g, %g\n", p->o_x, p->o_y);
+       printf("%g, %g\n", p->o_x, p->o_y);
 }
 
 char *tostring(s)
 }
 
 char *tostring(s)
@@ -100,10 +179,10 @@ char *tostring(s)
        return(p);
 }
 
        return(p);
 }
 
-struct obj *makepos(x, y)      /* make a osition cell */
+obj *makepos(x, y)     /* make a osition cell */
        float x, y;
 {
        float x, y;
 {
-       struct obj *p;
+       obj *p;
 
        p = makenode(PLACE, 0);
        p->o_x = x;
 
        p = makenode(PLACE, 0);
        p->o_x = x;
@@ -111,11 +190,11 @@ struct obj *makepos(x, y) /* make a osition cell */
        return(p);
 }
 
        return(p);
 }
 
-struct obj *makebetween(f, p1, p2)     /* make position between p1 and p2 */
+obj *makebetween(f, p1, p2)    /* make position between p1 and p2 */
        float f;
        float f;
-       struct obj *p1, *p2;
+       obj *p1, *p2;
 {
 {
-       struct obj *p;
+       obj *p;
 
        dprintf("fraction = %.2f\n", f);
        p = makenode(PLACE, 0);
 
        dprintf("fraction = %.2f\n", f);
        p = makenode(PLACE, 0);
@@ -124,13 +203,25 @@ struct obj *makebetween(f, p1, p2)        /* make position between p1 and p2 */
        return(p);
 }
 
        return(p);
 }
 
-struct obj *getpos(p, corner)  /* find position of point */
-       struct obj *p;
+obj *getpos(p, corner) /* find position of point */
+       obj *p;
+       int corner;
+{
+       float x, y;
+
+       whatpos(p, corner, &x, &y);
+       return makepos(x, y);
+}
+
+whatpos(p, corner, px, py)     /* what is the position (no side effect) */
+       obj *p;
        int corner;
        int corner;
+       float *px, *py;
 {
        float x, y, x1, y1;
 {
        float x, y, x1, y1;
+       extern double sqrt();
 
 
-       dprintf("getpos %o %d\n", p, corner);
+       dprintf("whatpos %o %d\n", p, corner);
        x = p->o_x;
        y = p->o_y;
        x1 = p->o_val[0];
        x = p->o_x;
        y = p->o_y;
        x1 = p->o_val[0];
@@ -151,12 +242,33 @@ struct obj *getpos(p, corner)     /* find position of point */
                case NW:        x -= x1 / 2; y += y1 / 2; break;
                case START:
                        if (p->o_type == BLOCK)
                case NW:        x -= x1 / 2; y += y1 / 2; break;
                case START:
                        if (p->o_type == BLOCK)
-                               return getpos(objlist[(int)p->o_val[2]], START);
+                               return whatpos(objlist[(int)p->o_val[2]], START, px, py);
                case END:
                        if (p->o_type == BLOCK)
                case END:
                        if (p->o_type == BLOCK)
-                               return getpos(objlist[(int)p->o_val[3]], END);
+                               return whatpos(objlist[(int)p->o_val[3]], END, px, py);
                }
                break;
                }
                break;
+       case ARC:
+               switch (corner) {
+               case START:
+                       if (p->o_attr & CW_ARC) {
+                               x = p->o_val[2]; y = p->o_val[3];
+                       } else {
+                               x = x1; y = y1;
+                       }
+                       break;
+               case END:
+                       if (p->o_attr & CW_ARC) {
+                               x = x1; y = y1;
+                       } else {
+                               x = p->o_val[2]; y = p->o_val[3];
+                       }
+                       break;
+               }
+               if (corner == START || corner == END)
+                       break;
+               x1 = y1 = sqrt((x1-x)*(x1-x) + (y1-y)*(y1-y));
+               /* Fall Through! */
        case CIRCLE:
        case ELLIPSE:
                switch (corner) {
        case CIRCLE:
        case ELLIPSE:
                switch (corner) {
@@ -177,6 +289,7 @@ struct obj *getpos(p, corner)       /* find position of point */
                switch (corner) {
                case START:     break;  /* already in place */
                case END:       x = x1; y = y1; break;
                switch (corner) {
                case START:     break;  /* already in place */
                case END:       x = x1; y = y1; break;
+               default: /* change! */
                case CENTER:    x = (x+x1)/2; y = (y+y1)/2; break;
                case NORTH:     if (y1 > y) { x = x1; y = y1; } break;
                case SOUTH:     if (y1 < y) { x = x1; y = y1; } break;
                case CENTER:    x = (x+x1)/2; y = (y+y1)/2; break;
                case NORTH:     if (y1 > y) { x = x1; y = y1; } break;
                case SOUTH:     if (y1 < y) { x = x1; y = y1; } break;
@@ -184,40 +297,23 @@ struct obj *getpos(p, corner)     /* find position of point */
                case WEST:      if (x1 < x) { x = x1; y = y1; } break;
                }
                break;
                case WEST:      if (x1 < x) { x = x1; y = y1; } break;
                }
                break;
-       case ARC:
-               switch (corner) {
-               case START:
-                       if (p->o_attr & CW_ARC) {
-                               x = p->o_val[2]; y = p->o_val[3];
-                       } else {
-                               x = x1; y = y1;
-                       }
-                       break;
-               case END:
-                       if (p->o_attr & CW_ARC) {
-                               x = x1; y = y1;
-                       } else {
-                               x = p->o_val[2]; y = p->o_val[3];
-                       }
-                       break;
-               }
-               break;
        }
        }
-       dprintf("getpos returns %g %g\n", x, y);
-       return(makepos(x, y));
+       dprintf("whatpos returns %g %g\n", x, y);
+       *px = x;
+       *py = y;
 }
 
 }
 
-struct obj *gethere(n) /* make a place for curx,cury */
+obj *gethere(n)        /* make a place for curx,cury */
 {
        dprintf("gethere %g %g\n", curx, cury);
        return(makepos(curx, cury));
 }
 
 {
        dprintf("gethere %g %g\n", curx, cury);
        return(makepos(curx, cury));
 }
 
-struct obj *getlast(n, t)      /* find n-th previous occurrence of type t */
+obj *getlast(n, t)     /* find n-th previous occurrence of type t */
        int n, t;
 {
        int i, k;
        int n, t;
 {
        int i, k;
-       struct obj *p;
+       obj *p;
 
        k = n;
        for (i = nobj-1; i >= 0; i--) {
 
        k = n;
        for (i = nobj-1; i >= 0; i--) {
@@ -237,11 +333,11 @@ struct obj *getlast(n, t) /* find n-th previous occurrence of type t */
        return(NULL);
 }
 
        return(NULL);
 }
 
-struct obj *getfirst(n, t)     /* find n-th occurrence of type t */
+obj *getfirst(n, t)    /* find n-th occurrence of type t */
        int n, t;
 {
        int i, k;
        int n, t;
 {
        int i, k;
-       struct obj *p;
+       obj *p;
 
        k = n;
        for (i = 0; i < nobj; i++) {
 
        k = n;
        for (i = 0; i < nobj; i++) {
@@ -261,8 +357,8 @@ struct obj *getfirst(n, t)  /* find n-th occurrence of type t */
        return(NULL);
 }
 
        return(NULL);
 }
 
-struct obj *getblock(p, s)     /* find variable s in block p */
-       struct obj *p;
+obj *getblock(p, s)    /* find variable s in block p */
+       obj *p;
        char *s;
 {
        struct symtab *stp;
        char *s;
 {
        struct symtab *stp;
@@ -271,7 +367,7 @@ struct obj *getblock(p, s)  /* find variable s in block p */
                yyerror(".%s is not in that block", s);
                return(NULL);
        }
                yyerror(".%s is not in that block", s);
                return(NULL);
        }
-       for (stp = (struct symtab *) p->o_dotdash; stp != NULL; stp = stp->s_next)
+       for (stp = p->o_symtab; stp != NULL; stp = stp->s_next)
                if (strcmp(s, stp->s_name) == 0) {
                        dprintf("getblock found x,y= %g,%g\n",
                                (stp->s_val.o)->o_x, (stp->s_val.o)->o_y);
                if (strcmp(s, stp->s_name) == 0) {
                        dprintf("getblock found x,y= %g,%g\n",
                                (stp->s_val.o)->o_x, (stp->s_val.o)->o_y);
@@ -281,21 +377,36 @@ struct obj *getblock(p, s)        /* find variable s in block p */
        return(NULL);
 }
 
        return(NULL);
 }
 
-struct obj *fixpos(p, x, y)
-       struct obj *p;
+obj *fixpos(p, x, y)
+       obj *p;
        float x, y;
 {
        dprintf("fixpos returns %g %g\n", p->o_x + x, p->o_y + y);
        return makepos(p->o_x + x, p->o_y + y);
 }
 
        float x, y;
 {
        dprintf("fixpos returns %g %g\n", p->o_x + x, p->o_y + y);
        return makepos(p->o_x + x, p->o_y + y);
 }
 
-struct obj *makenode(type, n)
+obj *addpos(p, q)
+       obj *p, *q;
+{
+       dprintf("addpos returns %g %g\n", p->o_x+q->o_x, p->o_y+q->o_y);
+       return makepos(p->o_x+q->o_x, p->o_y+q->o_y);
+}
+
+obj *subpos(p, q)
+       obj *p, *q;
+{
+       dprintf("subpos returns %g %g\n", p->o_x-q->o_x, p->o_y-q->o_y);
+       return makepos(p->o_x-q->o_x, p->o_y-q->o_y);
+}
+
+obj *makenode(type, n)
        int type, n;
 {
        int type, n;
 {
-       struct obj *p;
+       obj *p;
        int i;
        int i;
+       extern char *calloc();
 
 
-       p = (struct obj *) malloc(sizeof(struct obj) + (n-1)*sizeof(float));
+       p = (obj *) calloc(1, sizeof(obj) + (n-1)*sizeof(float));
        if (p == NULL) {
                yyerror("out of space in makenode\n");
                exit(1);
        if (p == NULL) {
                yyerror("out of space in makenode\n");
                exit(1);
@@ -309,13 +420,9 @@ struct obj *makenode(type, n)
        p->o_nt1 = ntext1;
        p->o_nt2 = ntext;
        ntext1 = ntext; /* ready for next caller */
        p->o_nt1 = ntext1;
        p->o_nt2 = ntext;
        ntext1 = ntext; /* ready for next caller */
-       p->o_attr = p->o_dotdash = p->o_ddval = 0;
-       for (i = 0; i < n; i++)
-               p->o_val[i] = 0;
-       if (nobj >= MAXOBJ) {
-               yyerror("objlist overflow\n");
-               exit(1);
-       }
+       if (nobj >= nobjlist)
+               objlist = (obj **) grow(objlist, "objlist",
+                       nobjlist += 100, sizeof(obj *));
        objlist[nobj++] = p;
        return(p);
 }
        objlist[nobj++] = p;
        return(p);
 }
index e55cb74..aa56d0e 100644 (file)
@@ -1,28 +1,29 @@
 #ifndef lint
 #ifndef lint
-static char sccsid[] = "@(#)movegen.c  1.1 (CWI) 85/07/19";
+static char sccsid[] = "@(#)movegen.c  2.1 (CWI) 85/07/23";
 #endif lint
 #endif lint
-
 #include       <stdio.h>
 #include       "pic.h"
 #include       "y.tab.h"
 
 #include       <stdio.h>
 #include       "pic.h"
 #include       "y.tab.h"
 
-struct obj *movegen(type)
+obj *movegen(type)
 {
        static float prevdx, prevdy;
        int i, some;
        float defx, defy, dx, dy;
 {
        static float prevdx, prevdy;
        int i, some;
        float defx, defy, dx, dy;
-       struct obj *p;
-       struct obj *ppos;
+       obj *p;
+       obj *ppos;
        static int xtab[] = { 1, 0, -1, 0 };    /* R=0, U=1, L=2, D=3 */
        static int ytab[] = { 0, 1, 0, -1 };
        static int xtab[] = { 1, 0, -1, 0 };    /* R=0, U=1, L=2, D=3 */
        static int ytab[] = { 0, 1, 0, -1 };
+       Attr *ap;
 
        defx = getfval("movewid");
        defy = getfval("moveht");
        dx = dy = some = 0;
        for (i = 0; i < nattr; i++) {
 
        defx = getfval("movewid");
        defy = getfval("moveht");
        dx = dy = some = 0;
        for (i = 0; i < nattr; i++) {
-               switch (attr[i].a_type) {
-               case LJUST: case RJUST: case CENTER: case SPREAD: case FILL: case ABOVE: case BELOW:
-                       savetext(attr[i].a_type, attr[i].a_val.p);
+               ap = &attr[i];
+               switch (ap->a_type) {
+               case TEXTATTR:
+                       savetext(ap->a_sub, ap->a_val.p);
                        break;
                case SAME:
                        dx = prevdx;
                        break;
                case SAME:
                        dx = prevdx;
@@ -30,40 +31,40 @@ struct obj *movegen(type)
                        some++;
                        break;
                case LEFT:
                        some++;
                        break;
                case LEFT:
-                       dx -= (attr[i].a_val.f==0) ? defx : attr[i].a_val.f;
+                       dx -= (ap->a_sub==DEFAULT) ? defx : ap->a_val.f;
                        some++;
                        hvmode = L_DIR;
                        break;
                case RIGHT:
                        some++;
                        hvmode = L_DIR;
                        break;
                case RIGHT:
-                       dx += (attr[i].a_val.f==0) ? defx : attr[i].a_val.f;
+                       dx += (ap->a_sub==DEFAULT) ? defx : ap->a_val.f;
                        some++;
                        hvmode = R_DIR;
                        break;
                case UP:
                        some++;
                        hvmode = R_DIR;
                        break;
                case UP:
-                       dy += (attr[i].a_val.f==0) ? defy : attr[i].a_val.f;
+                       dy += (ap->a_sub==DEFAULT) ? defy : ap->a_val.f;
                        some++;
                        hvmode = U_DIR;
                        break;
                case DOWN:
                        some++;
                        hvmode = U_DIR;
                        break;
                case DOWN:
-                       dy -= (attr[i].a_val.f==0) ? defy : attr[i].a_val.f;
+                       dy -= (ap->a_sub==DEFAULT) ? defy : ap->a_val.f;
                        some++;
                        hvmode = D_DIR;
                        break;
                case TO:
                        some++;
                        hvmode = D_DIR;
                        break;
                case TO:
-                       ppos = attr[i].a_val.o;
+                       ppos = ap->a_val.o;
                        dx = ppos->o_x - curx;
                        dy = ppos->o_y - cury;
                        some++;
                        break;
                case BY:
                        dx = ppos->o_x - curx;
                        dy = ppos->o_y - cury;
                        some++;
                        break;
                case BY:
-                       ppos = attr[i].a_val.o;
+                       ppos = ap->a_val.o;
                        dx = ppos->o_x;
                        dy = ppos->o_y;
                        some++;
                        break;
                case FROM:
                case AT:
                        dx = ppos->o_x;
                        dy = ppos->o_y;
                        some++;
                        break;
                case FROM:
                case AT:
-                       ppos = attr[i].a_val.o;
+                       ppos = ap->a_val.o;
                        curx = ppos->o_x;
                        cury = ppos->o_y;
                        break;
                        curx = ppos->o_x;
                        cury = ppos->o_y;
                        break;
index 57da3f4..29a6eee 100644 (file)
@@ -1,16 +1,26 @@
-#ifndef lint
-static char sccsid[] = "@(#)pic.h      1.1 (CWI) 85/07/19";
-#endif lint
-
 #define        dprintf if(dbg)printf
 
 #define        dprintf if(dbg)printf
 
+#define        DEFAULT 0
+
 #define        HEAD1   1
 #define        HEAD2   2
 #define        HEAD12  (HEAD1+HEAD2)
 #define        INVIS   4
 #define        CW_ARC  8       /* clockwise arc */
 #define        HEAD1   1
 #define        HEAD2   2
 #define        HEAD12  (HEAD1+HEAD2)
 #define        INVIS   4
 #define        CW_ARC  8       /* clockwise arc */
+#ifndef PI
 #define        PI      3.141592654
 #define        PI      3.141592654
-#define        PI2     PI/2
+#endif
+#define        DOTBIT  16
+#define        DASHBIT 32
+
+#define        CENTER  01      /* text attributes */
+#define        LJUST   02
+#define        RJUST   04
+#define        ABOVE   010
+#define        BELOW   020
+#define        SPREAD  040
+#define        FILL    0100
+
 #define        SCALE   1.0     /* default scale: units/inch */
 #define        WID     0.75    /* default width for boxes and ellipses */
 #define        WID2    0.375
 #define        SCALE   1.0     /* default scale: units/inch */
 #define        WID     0.75    /* default width for boxes and ellipses */
 #define        WID2    0.375
@@ -19,16 +29,6 @@ static char sccsid[] = "@(#)pic.h    1.1 (CWI) 85/07/19";
 #define        HT5     0.1
 #define        HT10    0.05
 
 #define        HT5     0.1
 #define        HT10    0.05
 
-#define        MAXOBJ  1200
-#define        MAXTEXT 1200
-#define        SYMTAB  200
-#define        DEV202  1
-#define        DEVAPS  2
-#define        DEVCAT  3
-#define        DEV450  4
-#define        DEVVER  5
-#define        DEVHAR  6
-
 /* these have to be like so, so that we can write */
 /* things like R & V, etc. */
 #define        H       0
 /* these have to be like so, so that we can write */
 /* things like R & V, etc. */
 #define        H       0
@@ -44,35 +44,37 @@ static char sccsid[] = "@(#)pic.h   1.1 (CWI) 85/07/19";
 #define        isdown(n)       ((n) == D_DIR)
 #define        isup(n)         ((n) == U_DIR)
 
 #define        isdown(n)       ((n) == D_DIR)
 #define        isup(n)         ((n) == U_DIR)
 
-typedef union {                /* the yacc stack type */
-       int     i;
-       char    *p;
-       struct obj *o;
-       float   f;
-} YYSTYPE;
-
-extern YYSTYPE yylval, yyval;
-
-struct attr {  /* attribute of an object */
-       int     a_type;
-       YYSTYPE a_val;
+typedef struct Point {
+       float   x;
+       float   y;
 };
 
 };
 
-struct obj {   /* stores various things in variable length */
+typedef struct obj {   /* stores various things in variable length */
        int     o_type;
        int     o_count;        /* number of things */
        int     o_nobj;         /* index in objlist */
        int     o_mode;         /* hor or vert */
        int     o_type;
        int     o_count;        /* number of things */
        int     o_nobj;         /* index in objlist */
        int     o_mode;         /* hor or vert */
-       float   o_x;    /* coord of "center" */
+       float   o_x;            /* coord of "center" */
        float   o_y;
        float   o_y;
-       int     o_nt1;  /* 1st index in text[] for this object */
-       int     o_nt2;  /* 2nd; difference is #text strings */
-       int     o_attr; /* various attributes of interest */
-       int     o_dotdash;      /* kludge in a dot/dash mode */
+       int     o_nt1;          /* 1st index in text[] for this object */
+       int     o_nt2;          /* 2nd; difference is #text strings */
+       int     o_attr;         /* HEAD, CW, INVIS go here */
+       int     o_size;         /* linesize */
+       int     o_nhead;        /* arrowhead style */
+       struct symtab *o_symtab; /* symtab for [...] */
        float   o_ddval;        /* value of dot/dash expression */
        float   o_val[1];       /* actually this will be > 1 in general */
                                /* type is not always FLOAT!!!! */
        float   o_ddval;        /* value of dot/dash expression */
        float   o_val[1];       /* actually this will be > 1 in general */
                                /* type is not always FLOAT!!!! */
-};
+} obj;
+
+typedef union {                /* the yacc stack type */
+       int     i;
+       char    *p;
+       obj     *o;
+       float   f;
+} YYSTYPE;
+
+extern YYSTYPE yylval, yyval;
 
 struct symtab {
        char    *s_name;
 
 struct symtab {
        char    *s_name;
@@ -81,40 +83,75 @@ struct symtab {
        struct symtab *s_next;
 };
 
        struct symtab *s_next;
 };
 
-struct text {
-       int     t_type;
+typedef struct {       /* attribute of an object */
+       int     a_type;
+       int     a_sub;
+       YYSTYPE a_val;
+} Attr;
+
+typedef struct {
+       int     t_type;         /* CENTER, LJUST, etc. */
+       char    t_op;           /* optional sign for size changes */
+       char    t_size;         /* size, abs or rel */
        char    *t_val;
        char    *t_val;
-};
+} Text;
+
+#define        String  01
+#define        Macro   02
+#define        File    04
+#define        Char    010
+#define        Thru    020
+#define        Free    040
+
+typedef struct {       /* input source */
+       int     type;   /* Macro, String, File */
+       char    *sp;    /* if String or Macro */
+} Src;
+
+extern Src     src[], *srcp;   /* input source stack */
+
+typedef struct {
+       FILE    *fin;
+       char    *fname;
+       int     lineno;
+} Infile;
+
+extern Infile  infile[], *curfile;
+
+#define        MAXARGS 20
+typedef struct {       /* argument stack */
+       char    *argstk[MAXARGS];       /* pointers to args */
+       char    *argval;        /* points to space containing args */
+} Arg;
 
 extern int     dbg;
 
 extern int     dbg;
-extern struct  obj     *objlist[];
-extern int     nobj;
-extern struct  attr    attr[];
-extern int     nattr;
-extern struct  text    text[];
+extern obj     **objlist;
+extern int     nobj, nobjlist;
+extern Attr    *attr;
+extern int     nattr, nattrlist;
+extern Text    *text;
+extern int     ntextlist;
 extern int     ntext;
 extern int     ntext1;
 extern float   curx, cury;
 extern int     hvmode;
 extern int     codegen;
 extern int     ntext;
 extern int     ntext1;
 extern float   curx, cury;
 extern int     hvmode;
 extern int     codegen;
-extern char    *malloc(), *tostring();
+extern char    *malloc(), *realloc(), *tostring(), *grow();
 extern float   getfval(), getcomp();
 extern YYSTYPE getvar();
 extern struct symtab *lookup(), *makevar();
 extern float   getfval(), getcomp();
 extern YYSTYPE getvar();
 extern struct symtab *lookup(), *makevar();
+extern char    *ifstat(), *delimstr(), *sprintgen();
 
 extern float   deltx, delty;
 extern int     lineno;
 extern int     synerr;
 
 extern float   deltx, delty;
 extern int     lineno;
 extern int     synerr;
-extern int     crop;
-extern int     devtype, res, DX, DY;
 
 
-extern float   sxmin, sxmax, symin, symax;
 extern float   xmin, ymin, xmax, ymax;
 extern float   xmin, ymin, xmax, ymax;
-extern struct obj *leftthing(), *boxgen(), *circgen(), *arcgen();
-extern struct obj *linegen(), *splinegen(), *movegen(), *textgen();
-extern struct obj *troffgen(), *rightthing(), *blockgen();
-extern struct  obj *makenode(), *makepos(), *fixpos(), *makebetween();
-extern struct  obj *getpos(), *gethere(), *getfirst(), *getlast(), *getblock();
+extern obj     *leftthing(), *boxgen(), *circgen(), *arcgen();
+extern obj     *linegen(), *splinegen(), *movegen(), *textgen(), *plotgen();
+extern obj     *troffgen(), *rightthing(), *blockgen();
+extern obj     *makenode(), *makepos(), *fixpos(), *addpos(), *subpos(), *makebetween();
+extern obj     *getpos(), *gethere(), *getfirst(), *getlast(), *getblock();
 
 struct pushstack {
        float   p_x;
 
 struct pushstack {
        float   p_x;
@@ -128,6 +165,9 @@ struct pushstack {
 };
 extern struct pushstack stack[];
 extern int     nstack;
 };
 extern struct pushstack stack[];
 extern int     nstack;
-extern int cw;
+extern int     cw;
 
 
-extern float atof();
+extern double  errcheck();
+#define        Log10(x) errcheck(log10(x), "log")
+#define        Exp(x)  errcheck(exp(x), "exp")
+#define        Sqrt(x) errcheck(sqrt(x), "sqrt")
index 71f4628..0eaf73d 100644 (file)
@@ -1,14 +1,10 @@
-#ifndef lint
-static char sccsid[] = "@(#)picl.l     1.1 (CWI) 85/07/19";
-#endif lint
-
-%Start A str comment def sc br
-%e 1300
-%k 100
-%a 1400
-%o 1200
-%p 4000
-%n 600
+%Start A str def sc br thru sh
+%e 1700
+%k 120
+%a 1800
+%o 1500
+%p 5000
+%n 700
 
 %{
 #undef input
 
 %{
 #undef input
@@ -20,13 +16,13 @@ static char sccsid[] = "@(#)picl.l  1.1 (CWI) 85/07/19";
 
 extern float   atof();
 extern struct  symtab  symtab[];
 
 extern float   atof();
 extern struct  symtab  symtab[];
-extern char    *filename;
-extern int     synerr;
+extern char    *filename, *copythru();
 
 #define        CADD    cbuf[clen++]=yytext[0]; if(clen>=CBUFLEN-1) {yyerror("string too long", cbuf); BEGIN A;}
 
 #define        CADD    cbuf[clen++]=yytext[0]; if(clen>=CBUFLEN-1) {yyerror("string too long", cbuf); BEGIN A;}
-#define        CBUFLEN 150
+#define        CBUFLEN 500
 char   cbuf[CBUFLEN];
 char   cbuf[CBUFLEN];
-int    clen, cflag;
+int    c, clen, cflag, delim;
+int    ifsw    = 0;    /* 1 if if statement in progress */
 %}
 
 A      [a-zA-Z_]
 %}
 
 A      [a-zA-Z_]
@@ -54,14 +50,13 @@ WS  [ \t]
 <A>"}"         { BEGIN sc; return(ST); }
 <A>"]"         { BEGIN br; return(ST); }
 
 <A>"}"         { BEGIN sc; return(ST); }
 <A>"]"         { BEGIN br; return(ST); }
 
-<A>^".".*      { if (yytext[1] == 'P' && (yytext[2] == 'E' || yytext[2] == 'F')) {
+<A>^".PS".*    { if (curfile == infile) yyerror(".PS found inside .PS/.PE"); }
+<A>^"."P[EF].* { if (curfile == infile) {
                        yylval.i = yytext[2];
                        return(EOF);
                        yylval.i = yytext[2];
                        return(EOF);
-                 } else {
-                       yylval.p = tostring(yytext);
-                       return(TROFF);
                  }
                }
                  }
                }
+<A>^".".*      { yylval.p = tostring(yytext); return(TROFF); }
 
 <A>print       return(yylval.i = PRINT);
 <A>box         return(yylval.i = BOX);
 
 <A>print       return(yylval.i = PRINT);
 <A>box         return(yylval.i = BOX);
@@ -73,6 +68,8 @@ WS    [ \t]
 <A>line                return(yylval.i = LINE);
 <A>move                return(yylval.i = MOVE);
 <A>"[]"                return(yylval.i = BLOCK);
 <A>line                return(yylval.i = LINE);
 <A>move                return(yylval.i = MOVE);
 <A>"[]"                return(yylval.i = BLOCK);
+<A>reset       return(RESET);
+<A>sprintf     return(SPRINTF);
 
 <A>same                return(SAME);
 <A>between     return(BETWEEN);
 
 <A>same                return(SAME);
 <A>between     return(BETWEEN);
@@ -82,35 +79,21 @@ WS  [ \t]
 <A>the         ;
 <A>way         ;
 
 <A>the         ;
 <A>way         ;
 
-<A>".e"                { yylval.i = EAST; return(CORNER); }
-<A>".east"     { yylval.i = EAST; return(CORNER); }
-<A>".r"                { yylval.i = EAST; return(CORNER); }
-<A>".right"    { yylval.i = EAST; return(CORNER); }
-<A>".w"                { yylval.i = WEST; return(CORNER); }
-<A>".west"     { yylval.i = WEST; return(CORNER); }
-<A>".l"                { yylval.i = WEST; return(CORNER); }
-<A>".left"     { yylval.i = WEST; return(CORNER); }
-<A>".n"                { yylval.i = NORTH; return(CORNER); }
-<A>".north"    { yylval.i = NORTH; return(CORNER); }
-<A>".t"                { yylval.i = NORTH; return(CORNER); }
-<A>".top"      { yylval.i = NORTH; return(CORNER); }
-<A>".s"                { yylval.i = SOUTH; return(CORNER); }
-<A>".south"    { yylval.i = SOUTH; return(CORNER); }
-<A>".b"                { yylval.i = SOUTH; return(CORNER); }
-<A>".bot"      { yylval.i = SOUTH; return(CORNER); }
-<A>".bottom"   { yylval.i = SOUTH; return(CORNER); }
-<A>".c"                { yylval.i = CENTER; return(CORNER); }
-<A>".center"   { yylval.i = CENTER; return(CORNER); }
-<A>".start"    { yylval.i = START; return(CORNER); }
-<A>".end"      { yylval.i = END; return(CORNER); }
+<A>"."(e|east)         { yylval.i = EAST; return(CORNER); }
+<A>"."(r|right)                { yylval.i = EAST; return(CORNER); }
+<A>"."(w|west)         { yylval.i = WEST; return(CORNER); }
+<A>"."(l|left)         { yylval.i = WEST; return(CORNER); }
+<A>"."(n|north)                { yylval.i = NORTH; return(CORNER); }
+<A>"."(t|top)          { yylval.i = NORTH; return(CORNER); }
+<A>"."(s|south)                { yylval.i = SOUTH; return(CORNER); }
+<A>"."(b|bot|bottom)   { yylval.i = SOUTH; return(CORNER); }
+<A>"."(c|center)       { yylval.i = CENTER; return(CORNER); }
+<A>".start"            { yylval.i = START; return(CORNER); }
+<A>".end"              { yylval.i = END; return(CORNER); }
 <A>".ne"               { yylval.i = NE; return(CORNER); }
 <A>".ne"               { yylval.i = NE; return(CORNER); }
-<A>"."upper" "*right   { yylval.i = NE; return(CORNER); }
 <A>".se"               { yylval.i = SE; return(CORNER); }
 <A>".se"               { yylval.i = SE; return(CORNER); }
-<A>"."lower" "*right   { yylval.i = SE; return(CORNER); }
 <A>".nw"               { yylval.i = NW; return(CORNER); }
 <A>".nw"               { yylval.i = NW; return(CORNER); }
-<A>"."upper" "*left    { yylval.i = NW; return(CORNER); }
 <A>".sw"               { yylval.i = SW; return(CORNER); }
 <A>".sw"               { yylval.i = SW; return(CORNER); }
-<A>"."lower" "*left    { yylval.i = SW; return(CORNER); }
 
 <A>top" "+of           { yylval.i = NORTH; return(CORNER); }
 <A>north" "+of         { yylval.i = NORTH; return(CORNER); }
 
 <A>top" "+of           { yylval.i = NORTH; return(CORNER); }
 <A>north" "+of         { yylval.i = NORTH; return(CORNER); }
@@ -123,19 +106,11 @@ WS        [ \t]
 <A>center" "+of                { yylval.i = CENTER; return(CORNER); }
 <A>start" "+of         { yylval.i = START; return(CORNER); }
 <A>end" "+of           { yylval.i = END; return(CORNER); }
 <A>center" "+of                { yylval.i = CENTER; return(CORNER); }
 <A>start" "+of         { yylval.i = START; return(CORNER); }
 <A>end" "+of           { yylval.i = END; return(CORNER); }
-<A>upper" "+right" "+of        { yylval.i = NE; return(CORNER); }
-<A>upper" "+left" "+of { yylval.i = NW; return(CORNER); }
-<A>lower" "+right" "+of        { yylval.i = SE; return(CORNER); }
-<A>lower" "+left" "+of { yylval.i = SW; return(CORNER); }
-
-<A>height      { yylval.i = HEIGHT; return(ATTR); }
-<A>ht          { yylval.i = HEIGHT; return(ATTR); }
-<A>wid         { yylval.i = WIDTH; return(ATTR); }
-<A>width       { yylval.i = WIDTH; return(ATTR); }
-<A>rad         { yylval.i = RADIUS; return(ATTR); }
-<A>radius      { yylval.i = RADIUS; return(ATTR); }
-<A>diam                { yylval.i = DIAMETER; return(ATTR); }
-<A>diameter    { yylval.i = DIAMETER; return(ATTR); }
+
+<A>height|ht   { yylval.i = HEIGHT; return(ATTR); }
+<A>width|wid   { yylval.i = WIDTH; return(ATTR); }
+<A>radius|rad  { yylval.i = RADIUS; return(ATTR); }
+<A>diameter|diam { yylval.i = DIAMETER; return(ATTR); }
 <A>size                { yylval.i = SIZE; return(ATTR); }
 <A>left                { yylval.i = LEFT; return(DIR); }
 <A>right       { yylval.i = RIGHT; return(DIR); }
 <A>size                { yylval.i = SIZE; return(ATTR); }
 <A>left                { yylval.i = LEFT; return(DIR); }
 <A>right       { yylval.i = RIGHT; return(DIR); }
@@ -144,34 +119,28 @@ WS        [ \t]
 <A>cw          { yylval.i = CW; return(ATTR); }
 <A>clockwise   { yylval.i = CW; return(ATTR); }
 <A>ccw         { yylval.i = CCW; return(ATTR); }
 <A>cw          { yylval.i = CW; return(ATTR); }
 <A>clockwise   { yylval.i = CW; return(ATTR); }
 <A>ccw         { yylval.i = CCW; return(ATTR); }
-<A>then                { yylval.i = THEN; return(ATTR); }
-<A>invis       { yylval.i = INVIS; return(ATTR); }
-<A>invisible   { yylval.i = INVIS; return(ATTR); }
-<A>dot         return(yylval.i = DOT);
-<A>dotted      return(yylval.i = DOT);
-<A>dash                return(yylval.i = DASH);
-<A>dashed      return(yylval.i = DASH);
+<A>invis(ible)?        { yylval.i = INVIS; return(ATTR); }
+<A>dot(ted)?   return(yylval.i = DOT);
+<A>dash(ed)?   return(yylval.i = DASH);
 <A>chop                return(yylval.i = CHOP);
 
 <A>chop                return(yylval.i = CHOP);
 
-<A>spread      return(yylval.i = SPREAD);
-<A>fill                return(yylval.i = FILL);
-<A>ljust       return(yylval.i = LJUST);
-<A>rjust       return(yylval.i = RJUST);
-<A>above       return(yylval.i = ABOVE);
-<A>below       return(yylval.i = BELOW);
+<A>spread      { yylval.i = SPREAD; return TEXTATTR; }
+<A>fill                { yylval.i = FILL; return TEXTATTR; }
+<A>ljust       { yylval.i = LJUST; return TEXTATTR; }
+<A>rjust       { yylval.i = RJUST; return TEXTATTR; }
+<A>above       { yylval.i = ABOVE; return TEXTATTR; }
+<A>below       { yylval.i = BELOW; return TEXTATTR; }
+<A>center      { yylval.i = CENTER; return TEXTATTR; }
 
 <A>"<-"                { yylval.i = HEAD1; return(HEAD); }
 <A>"->"                { yylval.i = HEAD2; return(HEAD); }
 <A>"<->"       { yylval.i = HEAD12; return(HEAD); }
 
 
 <A>"<-"                { yylval.i = HEAD1; return(HEAD); }
 <A>"->"                { yylval.i = HEAD2; return(HEAD); }
 <A>"<->"       { yylval.i = HEAD12; return(HEAD); }
 
-<A>".x"                return(yylval.i = DOTX);
-<A>".y"                return(yylval.i = DOTY);
-<A>".ht"       return(yylval.i = DOTHT);
-<A>".height"   return(yylval.i = DOTHT);
-<A>".wid"      return(yylval.i = DOTWID);
-<A>".width"    return(yylval.i = DOTWID);
-<A>".rad"      return(yylval.i = DOTRAD);
-<A>".radius"   return(yylval.i = DOTRAD);
+<A>".x"                        return(yylval.i = DOTX);
+<A>".y"                        return(yylval.i = DOTY);
+<A>"."(ht|height)      return(yylval.i = DOTHT);
+<A>"."(wid|width)      return(yylval.i = DOTWID);
+<A>"."(rad|radius)     return(yylval.i = DOTRAD);
 
 <A>from                return(yylval.i = FROM);
 <A>to          return(yylval.i = TO);
 
 <A>from                return(yylval.i = FROM);
 <A>to          return(yylval.i = TO);
@@ -180,17 +149,81 @@ WS        [ \t]
 <A>with                return(yylval.i = WITH);
 <A>last                return(yylval.i = LAST);
 
 <A>with                return(yylval.i = WITH);
 <A>last                return(yylval.i = LAST);
 
+<A>log         return(LOG);
+<A>exp         return(EXP);
+<A>sin         return(SIN);
+<A>cos         return(COS);
+<A>atan2       return(ATAN2);
+<A>sqrt                return(SQRT);
+<A>rand                return(RAND);
+<A>max         return(MAX);
+<A>min         return(MIN);
+<A>int         return(INT);
+
+<A>"=="                return(EQ);
+<A>">="                return(GE);
+<A>"<="                return(LE);
+<A>"!="                return(NEQ);
+<A>">"         return(GT);
+<A>"<"         return(LT);
+<A>"&&"                return(ANDAND);
+<A>"||"                return(OROR);
+<A>"!"         return(NOT);    
+
 <A>Here                return(yylval.i = HERE);
 <A>Here                return(yylval.i = HERE);
-<A>define{WS}+ { BEGIN def; }
-<def>{A}{B}*   { definition(yytext); BEGIN A; }
+
+<A>for         return(FOR);
+<A>^Endfor\n   { endfor(); }
+<A>do          { yylval.p = delimstr("loop body"); return(DOSTR); }
+
+<A>copy|include                return(COPY);
+<A>(thru|through){WS}+ { BEGIN thru; return(THRU); }
+<thru>{A}{B}*|.                { yylval.p = copythru(yytext); BEGIN A; return(DEFNAME); }
+<A>until               return(UNTIL);
+
+<A>if          { ifsw = 1; return(IF); }
+<A>then                { if (!ifsw) { yylval.i = THEN; return(ATTR); }
+                 yylval.p = delimstr("then part"); ifsw = 0;
+                 return(THENSTR); }
+<A>else                { yylval.p = delimstr("else part"); return(ELSESTR); }
+
+<A>sh{WS}+     { BEGIN sh;
+                 if ((delim = input()) == '{') delim = '}';    /* no nested {} */
+                 shell_init(); }
+<sh>{A}{B}*    { struct symtab *p;
+                 if (yytext[0] == delim) {
+                       shell_exec();
+                       BEGIN A;
+                 } else {
+                       p = lookup(yytext, 0);
+                       if (p != NULL && p->s_type == DEFNAME) {
+                               c = input();
+                               unput(c);
+                               if (c == '(')
+                                       dodef(p);
+                               else
+                                       pbstr(p->s_val.p);
+                       } else
+                               shell_text(yytext);
+                 }
+               }
+<sh>.|\n       { if (yytext[0] == delim) {
+                       shell_exec();
+                       BEGIN A;
+                 } else
+                       shell_text(yytext);
+               }
+
+<A>define{WS}+         { BEGIN def; }
+<def>{A}{B}*           { definition(yytext); BEGIN A; }
+<A>undef(ine)?{WS}+{A}{B}*     { undefine(yytext); }
 
 <A>first               { yylval.i = 1; return(NTH); }
 <A>{D}+(th|nd|rd|st)   { yylval.i = atoi(yytext); return(NTH); }
 
 <A>first               { yylval.i = 1; return(NTH); }
 <A>{D}+(th|nd|rd|st)   { yylval.i = atoi(yytext); return(NTH); }
-<A>({D}+("."?){D}*|"."{D}+)i?  { yylval.f = atof(yytext); return(NUMBER); }
+<A>({D}+("."?){D}*|"."{D}+)((e|E)("+"|-)?{D}+)?i? {
+                       yylval.f = atof(yytext); return(NUMBER); }
 
 
-<A>{A}{B}* {
-               int c;
-               struct symtab *p;
+<A>{A}{B}* {   struct symtab *p;
                p = lookup(yytext);
                if (p != NULL && p->s_type == DEFNAME) {
                        c = input();
                p = lookup(yytext);
                if (p != NULL && p->s_type == DEFNAME) {
                        c = input();
@@ -211,18 +244,15 @@ WS        [ \t]
        }
 
 <A>\"          { BEGIN str; clen=0; }
        }
 
 <A>\"          { BEGIN str; clen=0; }
-
-<A>#           { BEGIN comment; }
-<comment>\n    { BEGIN A; return(ST); }
-<comment>.     ;
-
-<A>.           { yylval.i = yytext[0]; return(yytext[0]); }
-
-<str>\"                { BEGIN A; cbuf[clen]=0; yylval.p = tostring(cbuf); return(TEXT); }
+<str>\"                { cbuf[clen]=0; yylval.p = tostring(cbuf); BEGIN A; return(TEXT); }
 <str>\n                { yyerror("newline in string"); BEGIN A; return(ST); }
 <str>"\\\""    { cbuf[clen++]='"'; }
 <str>"\\"t     { cbuf[clen++]='\t'; }
 <str>"\\\\"    { cbuf[clen++]='\\'; }
 <str>.         { CADD; }
 
 <str>\n                { yyerror("newline in string"); BEGIN A; return(ST); }
 <str>"\\\""    { cbuf[clen++]='"'; }
 <str>"\\"t     { cbuf[clen++]='\t'; }
 <str>"\\\\"    { cbuf[clen++]='\\'; }
 <str>.         { CADD; }
 
+<A>#.*         ;
+
+<A>.           return(yylval.i = yytext[0]);
+
 %%
 %%
index d9b69a7..52ed143 100644 (file)
@@ -1,48 +1,56 @@
-#ifndef lint
-static char sccsid[] = "@(#)picy.y     1.1 (CWI) 85/07/19";
-#endif lint
-
 %{
 %{
-#include       <stdio.h>
-#include       "pic.h"
+#include <stdio.h>
+#include "pic.h"
+#include <math.h>
 YYSTYPE        y;
 %}
 
 YYSTYPE        y;
 %}
 
-%token <i>     BOX     1
-%token <i>     ARROW   2
-%token <i>     CIRCLE  3
-%token <i>     ARC     4
+%token <i>     BOX     1       /* DON'T CHANGE THESE! */
+%token <i>     LINE    2
+%token <i>     ARROW   3
+%token <i>     CIRCLE  4
 %token <i>     ELLIPSE 5
 %token <i>     ELLIPSE 5
-%token <i>     LINE    6
-%token <i>     MOVE    7
-%token <i>     TEXT    8
-%token <i>     TROFF   9
-%token <i>     SPLINE  10
-%token <i>     BLOCK   11
+%token <i>     ARC     6
+%token <i>     SPLINE  7
+%token <i>     BLOCK   8
+%token <p>     TEXT    9
+%token <i>     TROFF   10
+%token <i>     MOVE    11
 %token <i>     BLOCKEND 12
 %token <i>     BLOCKEND 12
-%token <i>     PRINT
 %token <i>     PLACE
 %token <i>     PLACE
-%token <i>     ATTR
-%token <i>     SPREAD FILL LJUST RJUST ABOVE BELOW
+%token <i>     PRINT RESET THRU UNTIL
+%token <o>     FOR IF COPY
+%token <p>     THENSTR ELSESTR DOSTR DEFNAME PLACENAME VARNAME SPRINTF
+%token <i>     ATTR TEXTATTR
 %token <i>     LEFT RIGHT UP DOWN FROM TO AT BY WITH HEAD CW CCW THEN
 %token <i>     HEIGHT WIDTH RADIUS DIAMETER LENGTH SIZE
 %token <i>     LEFT RIGHT UP DOWN FROM TO AT BY WITH HEAD CW CCW THEN
 %token <i>     HEIGHT WIDTH RADIUS DIAMETER LENGTH SIZE
-%token <i>     PLACENAME VARNAME DEFNAME CORNER HERE LAST NTH SAME BETWEEN AND
-%token <i>     EAST WEST NORTH SOUTH NE NW SE SW CENTER START END
+%token <i>     CORNER HERE LAST NTH SAME BETWEEN AND
+%token <i>     EAST WEST NORTH SOUTH NE NW SE SW START END
 %token <i>     DOTX DOTY DOTHT DOTWID DOTRAD
 %token <f>     NUMBER
 %token <i>     DOTX DOTY DOTHT DOTWID DOTRAD
 %token <f>     NUMBER
+%token <f>     LOG EXP SIN COS ATAN2 SQRT RAND MIN MAX INT
 %token <i>     DIR
 %token <i>     DOT DASH CHOP
 %token <o>     ST      /* statement terminator */
 
 %token <i>     DIR
 %token <i>     DOT DASH CHOP
 %token <o>     ST      /* statement terminator */
 
+%right <f>     '='
+%left  <f>     OROR
+%left  <f>     ANDAND
+%nonassoc <f>  GT LT LE GE EQ NEQ
 %left  <f>     '+' '-'
 %left  <f>     '*' '/' '%'
 %left  <f>     '+' '-'
 %left  <f>     '*' '/' '%'
-%right <f>     UMINUS
+%right <f>     UMINUS NOT
+
+%type  <f>     expr if_expr asgn
+%type  <p>     name text
+%type  <i>     optop exprlist
+%type  <o>     if for copy
 
 
-%type  <f>     expr opt_expr
+/* this is a lie:  picture and position are really the whole union */
 %type  <o>     leftbrace picture piclist position lbracket
 %type  <o>     prim place blockname
 %type  <o>     leftbrace picture piclist position lbracket
 %type  <o>     prim place blockname
-%type  <i>     textattr last type
-
+%type  <i>     textlist textattr       /* not a sensible value */
+%type  <i>     last type
 
 %%
 
 
 %%
 
@@ -58,18 +66,80 @@ piclist:
        ;
 
 picture:
        ;
 
 picture:
-         prim ST                       { codegen = 1; }
+         prim ST                       { codegen = 1; makeiattr(0, 0); }
        | leftbrace piclist '}'         { rightthing($1, '}'); $$ = $2; }
        | leftbrace piclist '}'         { rightthing($1, '}'); $$ = $2; }
-       | PLACENAME ':' picture         { makevar($1, PLACENAME, $3); $$ = $3; }
-       | PLACENAME ':' ST picture      { makevar($1, PLACENAME, $4); $$ = $4; }
-       | PLACENAME ':' position ST     { makevar($1, PLACENAME, $3); $$ = $3; }
-        | VARNAME '=' expr ST  { makevar($1, VARNAME, $3); checkscale($1); }
+       | PLACENAME ':' picture         { y.o=$3; makevar($1,PLACENAME,y); $$ = $3; }
+       | PLACENAME ':' ST picture      { y.o=$4; makevar($1,PLACENAME,y); $$ = $4; }
+       | PLACENAME ':' position ST     { y.o=$3; makevar($1,PLACENAME,y); $$ = $3; }
+       | asgn ST                       { y.f = $1; $$ = y.o; }
        | DIR                           { setdir($1); }
        | PRINT expr ST                 { printexpr($2); }
        | PRINT position ST             { printpos($2); }
        | DIR                           { setdir($1); }
        | PRINT expr ST                 { printexpr($2); }
        | PRINT position ST             { printpos($2); }
+       | PRINT text ST                 { printf("%s\n", $2); free($2); }
+       | RESET varlist ST              { resetvar(); makeiattr(0, 0); }
+       | copy
+       | for
+       | if
        | ST
        ;
 
        | ST
        ;
 
+varlist:
+         /* empty */
+       | VARNAME               { makevattr($1); }
+       | varlist VARNAME       { makevattr($2); }
+       | varlist ',' VARNAME   { makevattr($3); }
+       ;
+
+asgn:
+         VARNAME '=' expr      { $$=y.f=$3; makevar($1,VARNAME,y); checkscale($1); }
+       ;
+
+copy:
+         COPY copylist         { copy(); }
+       ;
+copylist:
+         copyattr
+       | copylist copyattr
+       ;
+copyattr:
+         text                  { copyfile($1); }
+       | THRU DEFNAME          { copydef($2); }
+       | UNTIL text            { copyuntil($2); }
+       ;
+
+for:
+         FOR name FROM expr TO expr BY optop expr DOSTR
+               { forloop($2, $4, $6, $8, $9, $10); }
+       | FOR name FROM expr TO expr DOSTR
+               { forloop($2, $4, $6, '+', 1.0, $7); }
+       | FOR name '=' expr TO expr BY optop expr DOSTR
+               { forloop($2, $4, $6, $8, $9, $10); }
+       | FOR name '=' expr TO expr DOSTR
+               { forloop($2, $4, $6, '+', 1.0, $7); }
+       ;
+
+if:
+         IF if_expr THENSTR ELSESTR    { ifstat($2, $3, $4); }
+       | IF if_expr THENSTR            { ifstat($2, $3, (char *) 0); }
+       ;
+if_expr:
+         expr
+       | text EQ text          { $$ = strcmp($1,$3) == 0; free($1); free($3); }
+       | text NEQ text         { $$ = strcmp($1,$3) != 0; free($1); free($3); }
+       ;
+
+name:
+         VARNAME       { y.f = 0; makevar($1, VARNAME, y); }
+       ;
+optop:
+         '+'           { $$ = '+'; }
+       | '-'           { $$ = '-'; }
+       | '*'           { $$ = '*'; }
+       | '/'           { $$ = '/'; }
+       | /* empty */   { $$ = ' '; }
+       ;
+
+
 leftbrace:
          '{'                   { $$ = leftthing('{'); }
        ;
 leftbrace:
          '{'                   { $$ = leftthing('{'); }
        ;
@@ -81,9 +151,9 @@ prim:
        | ARC attrlist          { $$ = arcgen($1); }
        | LINE attrlist         { $$ = linegen($1); }
        | ARROW attrlist        { $$ = linegen($1); }
        | ARC attrlist          { $$ = arcgen($1); }
        | LINE attrlist         { $$ = linegen($1); }
        | ARROW attrlist        { $$ = linegen($1); }
-       | SPLINE attrlist       { $$ = splinegen($1); }
+       | SPLINE attrlist       { $$ = linegen($1); }
        | MOVE attrlist         { $$ = movegen($1); }
        | MOVE attrlist         { $$ = movegen($1); }
-       | TEXT attrlist         { $$ = textgen($1); }
+       | textlist attrlist     { $$ = textgen($1); }
        | TROFF                 { $$ = troffgen($1); }
        | lbracket piclist ']' { $<o>$=rightthing($1,']'); } attrlist
                                { $$ = blockgen($1, $2, $<o>4); }
        | TROFF                 { $$ = troffgen($1); }
        | lbracket piclist ']' { $<o>$=rightthing($1,']'); } attrlist
                                { $$ = blockgen($1, $2, $<o>4); }
@@ -95,60 +165,66 @@ lbracket:
 
 attrlist:
          attrlist attr
 
 attrlist:
          attrlist attr
-       | /* empty */           { makeattr(0, 0); }
+       | /* empty */
        ;
 
 attr:
        ;
 
 attr:
-         ATTR opt_expr         { makeattr($1, $2); }
-       | DIR opt_expr          { makeattr($1, $2); }
-       | FROM position         { makeattr($1, $2); }
-       | TO position           { makeattr($1, $2); }
-       | AT position           { makeattr($1, $2); }
-       | BY position           { makeattr($1, $2); }
-       | WITH CORNER           { makeattr(WITH, $2); }
-       | WITH '.' PLACENAME    { makeattr(PLACE, getblock(getlast(1,BLOCK), $3)); }
-       | WITH position         { makeattr(PLACE, $2); }
-       | SAME                  { makeattr(SAME, $1); }
-       | textattr              { makeattr($1, 0); }
-       | HEAD                  { makeattr(HEAD, $1); }
-       | DOT opt_expr          { makeattr(DOT, $2); }
-       | DASH opt_expr         { makeattr(DASH, $2); }
-       | CHOP opt_expr         { makeattr(CHOP, $2); }
+         ATTR expr             { makefattr($1, !DEFAULT, $2); }
+       | ATTR                  { makefattr($1, DEFAULT, 0.0); }
+       | expr                  { makefattr(curdir(), !DEFAULT, $1); }
+       | DIR expr              { makefattr($1, !DEFAULT, $2); }
+       | DIR                   { makefattr($1, DEFAULT, 0.0); }
+       | FROM position         { makeoattr($1, $2); }
+       | TO position           { makeoattr($1, $2); }
+       | AT position           { makeoattr($1, $2); }
+       | BY position           { makeoattr($1, $2); }
+       | WITH CORNER           { makeiattr(WITH, $2); }
+       | WITH '.' PLACENAME    { makeoattr(PLACE, getblock(getlast(1,BLOCK), $3)); }
+       | WITH '.' PLACENAME CORNER
+               { makeoattr(PLACE, getpos(getblock(getlast(1,BLOCK), $3), $4)); }
+       | WITH position         { makeoattr(PLACE, $2); }
+       | SAME                  { makeiattr(SAME, $1); }
+       | TEXTATTR              { maketattr($1, 0); }
+       | HEAD                  { makeiattr(HEAD, $1); }
+       | DOT expr              { makefattr(DOT, !DEFAULT, $2); }
+       | DOT                   { makefattr(DOT, DEFAULT, 0.0); }
+       | DASH expr             { makefattr(DASH, !DEFAULT, $2); }
+       | DASH                  { makefattr(DASH, DEFAULT, 0.0); }
+       | CHOP expr             { makefattr(CHOP, !DEFAULT, $2); }
+       | CHOP                  { makefattr(CHOP, DEFAULT, 0.0); }
        | textlist
        ;
 
        | textlist
        ;
 
-opt_expr:
-         expr
-       | /* empty */           { $$ = 0; }
-       ;
-
 textlist:
 textlist:
-         TEXT                  { makeattr(CENTER, $1); }
-       | TEXT textattr         { makeattr($2, $1); }
-       | textlist TEXT         { makeattr(CENTER, $2); }
-       | textlist TEXT textattr { makeattr($3, $2); }
+         textattr
+       | textlist textattr
        ;
        ;
-
 textattr:
 textattr:
-         LJUST
-       | RJUST
-       | SPREAD
-       | FILL
-       | CENTER
-       | ABOVE
-       | BELOW
+         text                  { maketattr(CENTER, $1); }
+       | text TEXTATTR         { maketattr($2, $1); }
+       | textattr TEXTATTR     { addtattr($2); }
+       ;
+text:
+         TEXT
+       | SPRINTF '(' text ')'                  { $$ = sprintgen($3); }
+       | SPRINTF '(' text ',' exprlist ')'     { $$ = sprintgen($3); }
+       ;
+
+exprlist:
+         expr                  { exprsave($1); $$ = 0; }
+       | exprlist ',' expr     { exprsave($3); }
        ;
 
 position:              /* absolute, not relative */
          place
        ;
 
 position:              /* absolute, not relative */
          place
-       | expr ',' expr                 { $$ = makepos($1, $3); }
-       | position '+' expr ',' expr    { $$ = fixpos($1, $3, $5); }
-       | position '-' expr ',' expr    { $$ = fixpos($1, -$3, -$5); }
-       | '(' expr ',' expr ')'                 { $$ = makepos($2, $4); }
+       | '(' position ')'                      { $$ = $2; }
+       | expr ',' expr                         { $$ = makepos($1, $3); }
+       | position '+' expr ',' expr            { $$ = fixpos($1, $3, $5); }
+       | position '-' expr ',' expr            { $$ = fixpos($1, -$3, -$5); }
        | position '+' '(' expr ',' expr ')'    { $$ = fixpos($1, $4, $6); }
        | position '-' '(' expr ',' expr ')'    { $$ = fixpos($1, -$4, -$6); }
        | '(' place ',' place ')'       { $$ = makepos(getcomp($2,DOTX), getcomp($4,DOTY)); }
        | position '+' '(' expr ',' expr ')'    { $$ = fixpos($1, $4, $6); }
        | position '-' '(' expr ',' expr ')'    { $$ = fixpos($1, -$4, -$6); }
        | '(' place ',' place ')'       { $$ = makepos(getcomp($2,DOTX), getcomp($4,DOTY)); }
-       | expr '<' position ',' position '>'    { $$ = makebetween($1, $3, $5); }
+       | expr LT position ',' position GT      { $$ = makebetween($1, $3, $5); }
        | expr BETWEEN position AND position    { $$ = makebetween($1, $3, $5); }
        ;
 
        | expr BETWEEN position AND position    { $$ = makebetween($1, $3, $5); }
        ;
 
@@ -192,18 +268,42 @@ type:
        ;
 
 expr:
        ;
 
 expr:
-         expr '+' expr         { $$ = $1 + $3; }
+         NUMBER
+       | VARNAME               { $$ = getfval($1); }
+       | asgn
+       | expr '+' expr         { $$ = $1 + $3; }
        | expr '-' expr         { $$ = $1 - $3; }
        | expr '*' expr         { $$ = $1 * $3; }
        | expr '-' expr         { $$ = $1 - $3; }
        | expr '*' expr         { $$ = $1 * $3; }
-       | expr '/' expr         { $$ = $1 / $3; }
-       | expr '%' expr         { $$ = (long)$1 % (long)$3; }
+       | expr '/' expr         { if ($3 == 0.0) {
+                                       yyerror("division by 0"); $3 = 1; }
+                                 $$ = $1 / $3; }
+       | expr '%' expr         { if ((long)$3 == 0) {
+                                       yyerror("mod does division by 0"); $3 = 1; }
+                                 $$ = (long)$1 % (long)$3; }
        | '-' expr %prec UMINUS { $$ = -$2; }
        | '(' expr ')'          { $$ = $2; }
        | '-' expr %prec UMINUS { $$ = -$2; }
        | '(' expr ')'          { $$ = $2; }
-       | VARNAME               { $$ = getfval($1); }
-       | NUMBER
        | place DOTX            { $$ = getcomp($1, $2); }
        | place DOTY            { $$ = getcomp($1, $2); }
        | place DOTHT           { $$ = getcomp($1, $2); }
        | place DOTWID          { $$ = getcomp($1, $2); }
        | place DOTRAD          { $$ = getcomp($1, $2); }
        | place DOTX            { $$ = getcomp($1, $2); }
        | place DOTY            { $$ = getcomp($1, $2); }
        | place DOTHT           { $$ = getcomp($1, $2); }
        | place DOTWID          { $$ = getcomp($1, $2); }
        | place DOTRAD          { $$ = getcomp($1, $2); }
+       | expr GT expr          { $$ = $1 > $3; }
+       | expr LT expr          { $$ = $1 < $3; }
+       | expr LE expr          { $$ = $1 <= $3; }
+       | expr GE expr          { $$ = $1 >= $3; }
+       | expr EQ expr          { $$ = $1 == $3; }
+       | expr NEQ expr         { $$ = $1 != $3; }
+       | expr ANDAND expr      { $$ = $1 && $3; }
+       | expr OROR expr        { $$ = $1 || $3; }
+       | NOT expr              { $$ = !($2); }
+       | LOG '(' expr ')'              { $$ = Log10($3); }
+       | EXP '(' expr ')'              { $$ = Exp($3 * log(10.0)); }
+       | SIN '(' expr ')'              { $$ = sin($3); }
+       | COS '(' expr ')'              { $$ = cos($3); }
+       | ATAN2 '(' expr ',' expr ')'   { $$ = atan2($3, $5); }
+       | SQRT '(' expr ')'             { $$ = Sqrt($3); }
+       | RAND '(' ')'                  { $$ = (float)rand() / 32767.0; /* might be 2^31-1 */ }
+       | MAX '(' expr ',' expr ')'     { $$ = $3 >= $5 ? $3 : $5; }
+       | MIN '(' expr ',' expr ')'     { $$ = $3 <= $5 ? $3 : $5; }
+       | INT '(' expr ')'              { $$ = (long) $3; }
        ;
        ;
index f445d59..196e7ea 100644 (file)
@@ -1,62 +1,17 @@
 #ifndef lint
 #ifndef lint
-static char sccsid[] = "@(#)pltroff.c  1.1 (CWI) 85/07/19";
+static char sccsid[] = "@(#)pltroff.c  2.1 (CWI) 85/07/23";
 #endif lint
 #endif lint
-
-/*
- *     This version has code generators to drive the old-style troff
- *     that produces output for the Graphic Systems C/A/T.  
- *     Very few people actually have a C/A/T; they instead typically
- *     use some other typesetter that simulates it.  This is slow and
- *     rather silly, but compatibility with the past is important.
- *     Or so they say.  Anyway ...
-
- *     The code generator can be turned on to old-style troff by setting
- *     the constant OLDTROFF with a #define statement;  this will also
- *     have the effect of setting the default typesetter to the C/A/T
- *     in a consistent manner.
- */
-
 #include <stdio.h>
 #include <stdio.h>
-#include <ctype.h>
 #include <math.h>
 #include <math.h>
+#include "pic.h"
 extern int dbg;
 
 extern int dbg;
 
-/* this is the place to define OLDTROFF if you're going to */
-#ifdef OLDTROFF
-#      define  MAXY    8192
-#      define  MAXX    8192
-#      define  OLDSTYLE        1
-#else
-#      define  MAXY    32768
-#      define  MAXX    32768
-#      define  OLDSTYLE        0
-#endif
-
 #define        abs(n)  (n >= 0 ? n : -(n))
 #define        max(x,y)        ((x)>(y) ? (x) : (y))
 #define        abs(n)  (n >= 0 ? n : -(n))
 #define        max(x,y)        ((x)>(y) ? (x) : (y))
-#define        PI      3.141592654
-#define        PI2     PI/2
-
-extern int     res;
-extern int     DX;     /* step size in x */
-extern int     DY;     /* step size in y */
-
-#define        DEV202  1
-#define        DEVAPS  2
-#define        DEVCAT  3
-#define        DEV450  4
-extern int     devtype;
-int    minline = 245;  /* draw lines shorter than this with dots on 202 */
-               /* ought to be point-size dependent, but what's that? */
-               /* this is big enough to handle 202 up to 36 points */
-int    drawdot = '.';  /* character to use when drawing */
-
-int    useDline        = 0;    /* if set, produce \D for all lines */
-extern float   hshift; /* how much to move left by for text */
-extern float   vshift; /* how much down */
-
-/* scaling stuff, specific to typesetter */
-/* defined by s command as X0,Y0 to X1,Y1 */
+
+char   *textshift = "\\v'.2m'";        /* move text this far down */
+
+/* scaling stuff defined by s command as X0,Y0 to X1,Y1 */
 /* output dimensions set by -l,-w options to 0,0 to hmax, vmax */
 /* default output is 6x6 inches */
 
 /* output dimensions set by -l,-w options to 0,0 to hmax, vmax */
 /* default output is 6x6 inches */
 
@@ -64,22 +19,23 @@ extern      float   vshift; /* how much down */
 float  xscale;
 float  yscale;
 
 float  xscale;
 float  yscale;
 
-int    hpos    = 0;    /* current horizontal position in output coordinate system */
-int    vpos    = 0;    /* current vertical position; 0 is top of page */
+float  hpos    = 0;    /* current horizontal position in output coordinate system */
+float  vpos    = 0;    /* current vertical position; 0 is top of page */
 
 
-int    htrue   = 0;    /* where we really are */
-int    vtrue   = 0;
+float  htrue   = 0;    /* where we really are */
+float  vtrue   = 0;
 
 float  X0, Y0;         /* left bottom of input */
 float  X1, Y1;         /* right top of input */
 
 
 float  X0, Y0;         /* left bottom of input */
 float  X1, Y1;         /* right top of input */
 
-int    hmax;           /* right end of output */
-int    vmax;           /* top of output (down is positive) */
+float  hmax;           /* right end of output */
+float  vmax;           /* top of output (down is positive) */
 
 extern float   deltx;
 extern float   delty;
 
 extern float   deltx;
 extern float   delty;
-extern float   xmin, ymin, xmax, ymax, sxmin, symin, sxmax, symax;
-extern int     crop;
+extern float   xmin, ymin, xmax, ymax;
+
+float  xconv(), yconv(), xsc(), ysc();
 
 openpl(s)      /* initialize device */
        char *s;        /* residue of .PS invocation line */
 
 openpl(s)      /* initialize device */
        char *s;        /* residue of .PS invocation line */
@@ -87,49 +43,70 @@ openpl(s)   /* initialize device */
        float maxdelt;
 
        hpos = vpos = 0;
        float maxdelt;
 
        hpos = vpos = 0;
-       hmax = vmax = 6 * res;  /* default = 6 x 6 */
-       maxdelt = max(deltx, delty);
-       if (maxdelt > 8) {      /* 8 inches */
+       if (deltx > 8.5 || delty > 11) {        /* 8.5x11 inches max */
                fprintf(stderr, "pic: %g X %g picture shrunk to", deltx, delty);
                fprintf(stderr, "pic: %g X %g picture shrunk to", deltx, delty);
-               deltx *= 8/maxdelt;
-               delty *= 8/maxdelt;
+               maxdelt = max(deltx, delty);
+               deltx *= 7/maxdelt;
+               delty *= 7/maxdelt;
                fprintf(stderr, " %g X %g\n", deltx, delty);
        }
                fprintf(stderr, " %g X %g\n", deltx, delty);
        }
-       if (deltx > 0 && delty > 0) {   /* have to change default size */
-               hmax = res * deltx;
-               vmax = res * delty;
-       }
-       if (crop) {
-               if (xmax == xmin)
-                       space(xmin, ymin, xmin + ymax-ymin, ymax);
-               else
-                       space(xmin, ymin, xmax, ymin + xmax-xmin);      /* assumes 1:1 aspect ratio */
-       }
-       else
-               space(sxmin, symin, sxmax, symax);
-       printf("... %g %g %g %g %g %g %g %g\n",
-               xmin, ymin, xmax, ymax, sxmin, symin, sxmax, symax);
-       printf("... %du %du %du %du %du %du %du %du\n",
-               xconv(xmin), yconv(ymin), xconv(xmax), yconv(ymax),
-               xconv(sxmin), yconv(symin), xconv(sxmax), yconv(symax));
-       printf(".PS %d %d %s", yconv(ymin), xconv(xmax), s);
+       space(xmin, ymin, xmax, ymax);
+       printf("... %g %g %g %g\n", xmin, ymin, xmax, ymax);
+       printf("... %.3fi %.3fi %.3fi %.3fi\n",
+               xconv(xmin), yconv(ymin), xconv(xmax), yconv(ymax));
+       printf(".nr 00 \\n(.u\n");
+       printf(".nf\n");
+       printf(".PS %.3fi %.3fi %s", yconv(ymin), xconv(xmax), s);
                /* assumes \n comes as part of s */
                /* assumes \n comes as part of s */
-       if (xconv(xmax) >= MAXX || yconv(ymax) >= MAXY) {       /* internal troff limit: 13 bits for motion */
-               fprintf(stderr, "picture too high or wide");
-               exit(1);
-       }
-       printf(".br\n");
+}
+
+space(x0, y0, x1, y1)  /* set limits of page */
+       float x0, y0, x1, y1;
+{
+       X0 = x0;
+       Y0 = y0;
+       X1 = x1;
+       Y1 = y1;
+       xscale = deltx == 0.0 ? 1.0 : deltx / (X1-X0);
+       yscale = delty == 0.0 ? 1.0 : delty / (Y1-Y0);
+}
+
+float xconv(x) /* convert x from external to internal form */
+       float x;
+{
+       return (x-X0) * xscale;
+}
+
+float xsc(x)   /* convert x from external to internal form, scaling only */
+       float x;
+{
+
+       return (x) * xscale;
+}
+
+float yconv(y) /* convert y from external to internal form */
+       float y;
+{
+       return (Y1-y) * yscale;
+}
+
+float ysc(y)   /* convert y from external to internal form, scaling only */
+       float y;
+{
+       return (y) * yscale;
 }
 
 closepl(type)  /* clean up after finished */
 }
 
 closepl(type)  /* clean up after finished */
+       int type;
 {
 {
-       movehv(0, 0);   /* get back to where we started */
+       movehv(0.0, 0.0);       /* get back to where we started */
        if (type == 'F')
                printf(".PF\n");
        else {
        if (type == 'F')
                printf(".PF\n");
        else {
-               printf(".sp 1+%du\n", yconv(ymin));
+               printf(".sp 1+%.3fi\n", yconv(ymin));
                printf(".PE\n");
        }
                printf(".PE\n");
        }
+       printf(".if \\n(00 .fi\n");
 }
 
 move(x, y)     /* go to position x, y in external coords */
 }
 
 move(x, y)     /* go to position x, y in external coords */
@@ -140,30 +117,32 @@ move(x, y)        /* go to position x, y in external coords */
 }
 
 movehv(h, v)   /* go to internal position h, v */
 }
 
 movehv(h, v)   /* go to internal position h, v */
-       int h, v;
+       float h, v;
 {
        hgoto(h);
        vgoto(v);
 }
 
 hmot(n)        /* generate n units of horizontal motion */
 {
        hgoto(h);
        vgoto(v);
 }
 
 hmot(n)        /* generate n units of horizontal motion */
-       int n;
+       float n;
 {
        hpos += n;
 }
 
 vmot(n)        /* generate n units of vertical motion */
 {
        hpos += n;
 }
 
 vmot(n)        /* generate n units of vertical motion */
-       int n;
+       float n;
 {
        vpos += n;
 }
 
 hgoto(n)
 {
        vpos += n;
 }
 
 hgoto(n)
+       float n;
 {
        hpos = n;
 }
 
 vgoto(n)
 {
        hpos = n;
 }
 
 vgoto(n)
+       float n;
 {
        vpos = n;
 }
 {
        vpos = n;
 }
@@ -171,11 +150,11 @@ vgoto(n)
 hvflush()      /* get to proper point for output */
 {
        if (hpos != htrue) {
 hvflush()      /* get to proper point for output */
 {
        if (hpos != htrue) {
-               printf("\\h'%du'", hpos - htrue);
+               printf("\\h'%.3fi'", hpos - htrue);
                htrue = hpos;
        }
        if (vpos != vtrue) {
                htrue = hpos;
        }
        if (vpos != vtrue) {
-               printf("\\v'%du'", vpos - vtrue);
+               printf("\\v'%.3fi'", vpos - vtrue);
                vtrue = vpos;
        }
 }
                vtrue = vpos;
        }
 }
@@ -200,11 +179,11 @@ label(s, t, nh)   /* text s of type t nh half-lines up */
        char *p;
 
        hvflush();
        char *p;
 
        hvflush();
-       printf("\\h'-%.1fm'\\v'%.1fm'", hshift, vshift);        /* shift down and left */
-                       /*  .3 .3 is best for PO in circuit diagrams */
-       if (t == 'A')
+       dprintf("label: %s %o %d\n", s, t, nh);
+       printf("%s", textshift);        /* shift down and left */
+       if (t & ABOVE)
                nh++;
                nh++;
-       else if (t == 'B')
+       else if (t & BELOW)
                nh--;
        if (nh)
                printf("\\v'%du*\\n(.vu/2u'", -nh);
                nh--;
        if (nh)
                printf("\\v'%du*\\n(.vu/2u'", -nh);
@@ -215,27 +194,20 @@ label(s, t, nh)   /* text s of type t nh half-lines up */
                        q = 1;
                        break;
                }
                        q = 1;
                        break;
                }
-       switch (t) {
-       case 'L':
-       default:
+       t &= ~(ABOVE|BELOW);
+       if (t & LJUST) {
                printf("%s", s);
                printf("%s", s);
-               break;
-       case 'C':
-       case 'A':
-       case 'B':
-               if (q)
-                       printf("\\h\\(ts-\\w\\(ts%s\\(tsu/2u\\(ts%s\\h\\(ts-\\w\\(ts%s\\(tsu/2u\\(ts", s, s, s);
-               else
-                       printf("\\h'-\\w'%s'u/2u'%s\\h'-\\w'%s'u/2u'", s, s, s);
-               break;
-       case 'R':
+       } else if (t & RJUST) {
                if (q)
                        printf("\\h\\(ts-\\w\\(ts%s\\(tsu\\(ts%s", s, s);
                else
                        printf("\\h'-\\w'%s'u'%s", s, s);
                if (q)
                        printf("\\h\\(ts-\\w\\(ts%s\\(tsu\\(ts%s", s, s);
                else
                        printf("\\h'-\\w'%s'u'%s", s, s);
-               break;
+       } else {        /* CENTER */
+               if (q)
+                       printf("\\h\\(ts-\\w\\(ts%s\\(tsu/2u\\(ts%s\\h\\(ts-\\w\\(ts%s\\(tsu/2u\\(ts", s, s, s);
+               else
+                       printf("\\h'-\\w'%s'u/2u'%s\\h'-\\w'%s'u/2u'", s, s, s);
        }
        }
-       /* don't need these if flyback called immediately */
        printf("\n");
        flyback();
 }
        printf("\n");
        flyback();
 }
@@ -247,25 +219,27 @@ line(x0, y0, x1, y1)      /* draw line from x0,y0 to x1,y1 */
        cont(x1, y1);
 }
 
        cont(x1, y1);
 }
 
-arrow(x0, y0, x1, y1, w, h)    /* draw arrow (without line), head wid w & len h */
-       float x0, y0, x1, y1, w, h;
+arrow(x0, y0, x1, y1, w, h, ang, nhead)        /* draw arrow (without shaft) */
+       float x0, y0, x1, y1, w, h, ang;        /* head wid w, len h, rotated ang */
+       int nhead;                              /* and drawn with nhead lines */
 {
 {
-       double alpha, rot, hyp;
+       double alpha, rot, drot, hyp;
        float dx, dy;
        float dx, dy;
+       int i;
 
 
-       rot = atan2( w / 2, h );
+       rot = atan2(w / 2, h);
        hyp = sqrt(w/2 * w/2 + h * h);
        hyp = sqrt(w/2 * w/2 + h * h);
-       alpha = atan2(y1-y0, x1-x0);
-       if (dbg)
-               printf("rot=%f, hyp=%f, alpha=%f\n", rot, hyp, alpha);
-       dx = hyp * cos(alpha + PI + rot);
-       dy = hyp * sin(alpha + PI + rot);
-       if (dbg) printf("dx,dy = %g,%g\n", dx, dy);
-       line(x1+dx, y1+dy, x1, y1);
-       dx = hyp * cos(alpha + PI - rot);
-       dy = hyp * sin(alpha + PI - rot);
-       if (dbg) printf("dx,dy = %g,%g\n", dx, dy);
-       line(x1+dx, y1+dy, x1, y1);
+       alpha = atan2(y1-y0, x1-x0) + ang;
+       if (nhead < 2)
+               nhead = 2;
+       dprintf("rot=%g, hyp=%g, alpha=%g\n", rot, hyp, alpha);
+       for (i = nhead-1; i >= 0; i--) {
+               drot = 2 * rot / (float) (nhead-1) * (float) i;
+               dx = hyp * cos(alpha + PI - rot + drot);
+               dy = hyp * sin(alpha + PI - rot + drot);
+               dprintf("dx,dy = %g,%g\n", dx, dy);
+               line(x1+dx, y1+dy, x1, y1);
+       }
 }
 
 box(x0, y0, x1, y1)
 }
 
 box(x0, y0, x1, y1)
@@ -281,29 +255,15 @@ box(x0, y0, x1, y1)
 cont(x, y)     /* continue line from here to x,y */
        float x, y;
 {
 cont(x, y)     /* continue line from here to x,y */
        float x, y;
 {
-       int h1, v1;
-       int dh, dv;
+       float h1, v1;
+       float dh, dv;
 
        h1 = xconv(x);
        v1 = yconv(y);
        dh = h1 - hpos;
        dv = v1 - vpos;
 
        h1 = xconv(x);
        v1 = yconv(y);
        dh = h1 - hpos;
        dv = v1 - vpos;
-       downsize();
        hvflush();
        hvflush();
-       if (!useDline && dv == 0 && abs(dh) > minline)  /* horizontal */
-               printf("\\l'%du'\n", dh);
-       else if (!useDline && dh == 0 && abs(dv) > minline) {   /* vertical */
-               if (devtype == DEV202)
-                       printf("\\L'%du\\(vr'\n", dv);
-               else
-                       printf("\\v'-.25m'\\L'%du\\(br'\\v'.25m'\n", dv);       /* add -.25m correction if use \(br */
-       } else {
-               if (OLDSTYLE)
-                       drawline(dh, dv);
-               else
-                       printf("\\D'l%du %du'\n", dh, dv);
-       }
-       upsize();
+       printf("\\D'l%.3fi %.3fi'\n", dh, dv);
        flyback();      /* expensive */
        hpos = h1;
        vpos = v1;
        flyback();      /* expensive */
        hpos = h1;
        vpos = v1;
@@ -312,667 +272,65 @@ cont(x, y)       /* continue line from here to x,y */
 circle(x, y, r)
        float x, y, r;
 {
 circle(x, y, r)
        float x, y, r;
 {
-       int d;
-
-       downsize();
-       d = xsc(2 * r);
        move(x-r, y);
        hvflush();
        move(x-r, y);
        hvflush();
-       if (OLDSTYLE)
-               drawcircle(d);
-       else
-               printf("\\D'c%du'\n", d);
-       upsize();
+       printf("\\D'c%.3fi'\n", xsc(2 * r));
        flyback();
 }
 
 spline(x, y, n, p)
        float x, y, *p;
        flyback();
 }
 
 spline(x, y, n, p)
        float x, y, *p;
-       float n;
+       float n;        /* sic */
 {
 {
-       int i, j, dx, dy;
-       char temp[1000];
+       int i;
+       float dx, dy;
+       float xerr, yerr;
 
 
-       downsize();
        move(x, y);
        hvflush();
        move(x, y);
        hvflush();
-       if (OLDSTYLE) {
-               temp[0] = 0;
-               for (i = 0; i < 2 * n; i += 2) {
-                       dx = xsc(p[i]);
-                       dy = ysc(p[i+1]);
-                       sprintf(&temp[strlen(temp)], " %d %d", dx, dy);
-               }
-               drawspline(temp);
-       }
-       else {
-               printf("\\D'~");
-               for (i = 0; i < 2 * n; i += 2) {
-                       dx = xsc(p[i]);
-                       dy = ysc(p[i+1]);
-                       printf(" %du %du", dx, dy);
-               }
-               printf("'\n");
+       printf("\\D'~");
+       xerr = yerr = 0.0;
+       for (i = 0; i < 2 * n; i += 2) {
+               dx = xsc(xerr += p[i]);
+               xerr -= dx/xscale;
+               dy = ysc(yerr += p[i+1]);
+               yerr -= dy/yscale;
+               printf(" %.3fi %.3fi", dx, -dy);        /* WATCH SIGN */
        }
        }
-       upsize();
+       printf("'\n");
        flyback();
 }
 
 ellipse(x, y, r1, r2)
        float x, y, r1, r2;
 {
        flyback();
 }
 
 ellipse(x, y, r1, r2)
        float x, y, r1, r2;
 {
-       int ir1, ir2;
+       float ir1, ir2;
 
 
-       downsize();
        move(x-r1, y);
        hvflush();
        ir1 = xsc(r1);
        ir2 = ysc(r2);
        move(x-r1, y);
        hvflush();
        ir1 = xsc(r1);
        ir2 = ysc(r2);
-       if (OLDSTYLE)
-               drawellipse(2 * ir1, 2 * abs(ir2));
-       else
-               printf("\\D'e%du %du'\n", 2 * ir1, 2 * abs(ir2));
-       upsize();
+       printf("\\D'e%.3fi %.3fi'\n", 2 * ir1, 2 * abs(ir2));
        flyback();
 }
 
        flyback();
 }
 
-arc(x, y, x0, y0, x1, y1, r)   /* draw arc with center x,y */
-       float x, y, x0, y0, x1, y1, r;
+arc(x, y, x0, y0, x1, y1)      /* draw arc with center x,y */
+       float x, y, x0, y0, x1, y1;
 {
 
 {
 
-       downsize();
        move(x0, y0);
        hvflush();
        move(x0, y0);
        hvflush();
-       if (OLDSTYLE) {
-               drawarc(xsc(x1-x0), ysc(y1-y0), xsc(r));
-       } else {
-               printf("\\D'a%du %du %du %du'\n",
-                       xsc(x-x0), ysc(y-y0), xsc(x1-x), ysc(y1-y));
-       }
-       upsize();
+       printf("\\D'a%.3fi %.3fi %.3fi %.3fi'\n",
+               xsc(x-x0), -ysc(y-y0), xsc(x1-x), -ysc(y1-y));  /* WATCH SIGNS */
        flyback();
 }
 
        flyback();
 }
 
-erase()        /* get to bottom of frame */
-{
-       return; /* for now, ignore them */
-}
-
-point(x, y)    /* put point at x,y */
-       float x, y;
-{
-       static char *temp = ".";
-
-       move(x, y);
-       label(temp, 'L');
-}
-
-space(x0, y0, x1, y1)  /* set limits of page */
-       float x0, y0, x1, y1;
-{
-       if (x0 == x1)
-               x1 = x0 + 1;
-       if (y0 == y1)
-               y1 = y0 - 1;    /* kludge */
-       X0 = x0;
-       Y0 = y0;
-       X1 = x1;
-       Y1 = y1;
-       xscale = hmax / (X1-X0);
-       yscale = vmax / (Y0-Y1);
-}
-
-xconv(x)       /* convert x from external to internal form */
-       float x;
-{
-       int v;
-
-       v = (x-X0) * xscale + 0.5;
-       if (OLDSTYLE) {
-               v = (v + DX - 1) / DX;
-               v *= DX;
-       }
-       return v;
-}
-
-xsc(x) /* convert x from external to internal form, scaling only */
-       float x;
-{
-       int v;
-
-       v = (x) * xscale + 0.5;
-       if (OLDSTYLE) {
-               v = (v + DX - 1) / DX;
-               v *= DX;
-       }
-       return v;
-}
-
-yconv(y)       /* convert y from external to internal form */
-       float y;
-{
-       int v;
-
-       y += Y1 - ymax;
-       v = (y-Y1) * yscale + 0.5;
-       if (OLDSTYLE) {
-               v = (v + DY - 1) / DY;
-               v *= DY;
-       }
-       return v;
-}
-
-ysc(y) /* convert y from external to internal form, scaling only */
-       float y;
-{
-       int v;
-
-       v = (y) * yscale + 0.5;
-       if (OLDSTYLE) {
-               v = (v + DY - 1) / DY;
-               v *= DY;
-       }
-       return v;
-}
-
-linemod(s)
-       char *s;
-{
-}
-
 dot() {
        hvflush();
        /* what character to draw here depends on what's available. */
        /* on the 202, l. is good but small. */
 dot() {
        hvflush();
        /* what character to draw here depends on what's available. */
        /* on the 202, l. is good but small. */
-       /* on other typesetters, use a period and hope */
-       if (OLDSTYLE)
-               printf("\\&.\n");
-       else if (devtype == DEV202)
-               printf("\\z\\(l.\\(l.\\z\\(l.\\(l.\n");
-       else
-               printf("\\&.\n");
-       flyback();
-}
-
-#ifndef        OLDTROFF
-
-       /* satisfy the loader... */
-
-drawline(){;}
-drawcircle(){;}
-drawspline(){;}
-drawellipse(){;}
-drawarc(){;}
-upsize(){;}
-downsize(){;}
-
-#endif
-
-#ifdef OLDTROFF
-
-       /* these are for real */
-
-int    drawsize        = 2;    /* shrink point size by this factor */
-
-#define        sgn(n)  ((n > 0) ? 1 : ((n < 0) ? -1 : 0))
-#define        arcmove(x,y)    { hgoto(x); vmot(-vpos-(y)); }
-
-put1(c) /* output one character, usually a dot */
-{
-       static int nput = 0;
-
-       if (nput++ > 100) {     /* crude approx: troff input buffer ~ 400 */
-               nput = 0;
-               printf("\n");   /* someday this will give a spurious break */
-               flyback();
-               printf("\\\&");
-       }
-       hvflush();      /* crude! */
-       printf("\\z%c", c);
-}
+       /* in general, use a smaller, shifted period and hope */
 
 
-downsize()     /* set size lower to make it lighter */
-{
-       if (drawsize != 1) {
-               printf(".nr .. \\n(.s/%d\n", drawsize);
-               printf(".ps \\n(..\n");
-       }
-}
-
-upsize()       /* undo downsize */
-{
-       printf(".ps\n");        /* God help anyone who fiddles .ps */
-}
-
-drawline(dx, dy)       /* draw line from here to dx, dy */
-int dx, dy;
-{
-       int xd, yd;
-       float val, slope;
-       int i, numdots;
-       int dirmot, perp;
-       int motincr, perpincr;
-       int ohpos, ovpos, osize;
-       float incrway;
-
-        ohpos = hpos;
-       ovpos = vpos;
-       xd = dx / DX;
-       yd = dy / DX;
-       printf("\\\&");
-       put1(drawdot);
-       if (xd == 0) {
-               numdots = abs (yd);
-               motincr = DX * sgn (yd);
-               for (i = 0; i < numdots; i++) {
-                       vmot(motincr);
-                       put1(drawdot);
-               }
-               vgoto(ovpos + dy);
-               printf("\n");
-               return;
-       }
-       if (yd == 0) {
-               numdots = abs (xd);
-               motincr = DX * sgn (xd);
-               for (i = 0; i < numdots; i++) {
-                       hmot(motincr);
-                       put1(drawdot);
-               }
-               hgoto(ohpos + dx);
-               printf("\n");
-               return;
-       }
-       if (abs (xd) > abs (yd)) {
-               val = slope = (float) xd/yd;
-               numdots = abs (xd);
-               dirmot = 'h';
-               perp = 'v';
-               motincr = DX * sgn (xd);
-               perpincr = DX * sgn (yd);
-       }
-       else {
-               val = slope = (float) yd/xd;
-               numdots = abs (yd);
-               dirmot = 'v';
-               perp = 'h';
-               motincr = DX * sgn (yd);
-               perpincr = DX * sgn (xd);
-       }
-       incrway = sgn ((int) slope);
-       for (i = 0; i < numdots; i++) {
-               val -= incrway;
-               if (dirmot == 'h')
-                       hmot(motincr);
-               else
-                       vmot(motincr);
-               if (val * slope < 0) {
-                       if (perp == 'h')
-                               hmot(perpincr);
-                       else
-                               vmot(perpincr);
-                       val += slope;
-               }
-               put1(drawdot);
-       }
-       hgoto(ohpos + dx);
-       vgoto(ovpos + dy);
-       printf("\n");
-}
-
-drawspline(s)  /* draw spline curve */
-       char *s;
-{
-       int x[50], y[50], xp, yp, pxp, pyp;
-       float t1, t2, t3, w;
-       int i, j, steps, N, prevsteps;
-       register char *p;
-
-       N = 0;
-
-/* Weird...
-       N = sscanf(s, "%d %d  %d %d  %d %d  %d %d  %d %d  %d %d  %d %d  %d %d  %d %d  %d %d  %d %d  %d %d  %d %d  %d %d  %d %d  %d %d  %d %d  %d %d  %d %d  %d %d  %d %d  %d %d  %d %d  %d %d ",
-       &x[2], &y[2], &x[3], &y[3], &x[4], &y[4], &x[5], &y[5], &x[6], &y[6], &x[7], &y[7], &x[8], &y[8], &x[9], &y[9], &x[10], &y[10], &x[11], &y[11], &x[12], &y[12],
-&x[13], &y[13], &x[14], &y[14], &x[15], &y[15], &x[16], &y[16], &x[17], &y[17], &x[18], &y[18], &x[19], &y[19], &x[20], &y[20], &x[21], &y[21], &x[22], &y[22], &x[23], &y[23], &x[24], &y[24],
-&x[25], &y[25], &x[26], &y[26], &x[27], &y[27], &x[28], &y[28], &x[29], &y[29], &x[30], &y[30], &x[31], &y[31], &x[32], &y[32], &x[33], &y[33], &x[34], &y[34], &x[35], &y[35], &x[36], &y[36], 
-&x[37], &y[37]);
-*/
-       p = s;
-       for( i = 2; i <= 37; i++) {
-               j = sscanf(p, "%d%d", &x[i], &y[i]);
-               if( j == -1)
-                       break;
-               while( isspace(*p))
-                       p++;
-               while( isdigit(*p) || *p == '-')
-                       p++;
-               while( isspace(*p))
-                       p++;
-               while( isdigit(*p) || *p == '-')
-                       p++;
-               N += 2;
-       }
-
-       N = N/2 + 2;
-       x[0] = x[1] = hpos;
-       y[0] = y[1] = vpos;
-       for (i = 1; i < N; i++) {
-               x[i+1] += x[i];
-               y[i+1] += y[i];
-       }
-       x[N] = x[N-1];
-       y[N] = y[N-1];
-       prevsteps = 0;
-       pxp = pyp = -9999;
-       printf("\\\&");
-       for (i = 0; i < N-1; i++) {     /* interval */
-               steps = (dist(x[i],y[i], x[i+1],y[i+1]) + dist(x[i+1],y[i+1], x[i+2],y[i+2])) / 2;
-               steps /= DX;
-               for (j = 0; j < steps; j++) {   /* points within */
-                       w = (float) j / steps;
-                       t1 = 0.5 * w * w;
-                       w = w - 0.5;
-                       t2 = 0.75 - w * w;
-                       w = w - 0.5;
-                       t3 = 0.5 * w * w;
-                       xp = t1 * x[i+2] + t2 * x[i+1] + t3 * x[i] + 0.5;
-                       yp = t1 * y[i+2] + t2 * y[i+1] + t3 * y[i] + 0.5;
-                       xp = round(xp, DX);
-                       yp = round(yp, DY);
-                       if (xp != pxp || yp != pyp) {
-                               hgoto(xp);
-                               vgoto(yp);
-                               put1(drawdot);
-                               pxp = xp;
-                               pyp = yp;
-                       }
-               }
-       }
-       printf("\n");
-}
-
-drawcircle(d)
-{
-       int xc, yc;
-
-       xc = hpos;
-       yc = vpos;
-       printf("\\\&");
-       conicarc(hpos + d/2, -vpos, hpos, -vpos, hpos, -vpos, d/2, d/2);
-       hgoto(xc + d);  /* circle goes to right side */
-       vgoto(yc);
-       printf("\n");
-}
-
-dist(x1, y1, x2, y2)   /* integer distance from x1,y1 to x2,y2 */
-{
-       float dx, dy;
-
-       dx = x2 - x1;
-       dy = y2 - y1;
-       return sqrt(dx*dx + dy*dy) + 0.5;
-}
-
-drawarc(x, y, r)
-{
-       int x0, y0;
-       float dx, dy, phi, d, ht, ang;
-
-       if (r == 0)
-               r = 1;
-       if (r < 0)
-               ang = PI / 2;
-       else
-               ang = -(PI / 2);
-       dx = x / 2;
-       dy = y / 2;
-       phi = atan2(dy, dx) + ang;
-       while ((d = (float)r * r - (dx*dx + dy*dy)) < 0.0)
-               r *= 2;
-       ht = sqrt(d);
-       x0 = hpos + dx + ht * cos(phi) + 0.5;
-       y0 = vpos + dy + ht * sin(phi) + 0.5;
-       printf("\\\&");
-       conicarc(x0, -y0, hpos, -vpos, hpos+x, -vpos-y, r, r);
-       printf("\n");
-}
-
-drawellipse(a, b)
-{
-       int xc, yc;
-
-       xc = hpos;
-       yc = vpos;
-       printf("\\\&");
-       conicarc(hpos + a/2, -vpos, hpos, -vpos, hpos, -vpos, a/2, b/2);
-       hgoto(xc + a);
-       vgoto(yc);
-       printf("\n");
-}
-
-#define sqr(x) (long int)(x)*(x)
-
-conicarc(x, y, x0, y0, x1, y1, a, b)
-{
-       /* based on Bresenham, CACM, Feb 77, pp 102-3 */
-       /* by Chris Van Wyk */
-       /* capitalized vars are an internal reference frame */
-       long dotcount = 0;
-       int     xs, ys, xt, yt, Xs, Ys, qs, Xt, Yt, qt,
-       M1x, M1y, M2x, M2y, M3x, M3y,
-       Q, move, Xc, Yc;
-       int     delta;
-       float   xc, yc;
-       float   radius, slope;
-       float   xstep, ystep;
-       if (a != b)     /* an arc of an ellipse; internally, will still think of circle */
-               if (a > b) {
-                       xstep = (float)a / b;
-                       ystep = 1;
-                       radius = b;
-               } 
-               else
-                {
-                       xstep = 1;
-                       ystep = (float)b / a;
-                       radius = a;
-               } 
-       else    /* a circular arc; radius is computed from center and first point */     {
-               xstep = ystep = 1;
-               radius = sqrt((float)(sqr(x0 - x) + sqr(y0 - y)));
-       }
-
-
-       xc = x0;
-       yc = y0;
-       /* now, use start and end point locations to figure out
-   the angle at which start and end happen; use these
-   angles with known radius to figure out where start
-   and end should be */
-       slope = atan2((double)(y0 - y), (double)(x0 - x)
-           );
-       if ((slope == 0.0)
-            && (x0 < x)
-           )
-               slope = 3.14159265;
-       x0 = x + radius * cos(slope)
-        + 0.5;
-       y0 = y + radius * sin(slope)
-        + 0.5;
-       slope = atan2((double)(y1 - y), (double)(x1 - x)
-           );
-       if ((slope == 0.0)
-            && (x1 < x)
-           )
-               slope = 3.14159265;
-       x1 = x + radius * cos(slope)
-        + 0.5;
-       y1 = y + radius * sin(slope)
-        + 0.5;
-       /* step 2: translate to zero-centered circle */
-       xs = x0 - x;
-       ys = y0 - y;
-       xt = x1 - x;
-       yt = y1 - y;
-       /* step 3: normalize to first quadrant */
-       if (xs < 0)
-               if (ys < 0) {
-                       Xs = abs(ys);
-                       Ys = abs(xs);
-                       qs = 3;
-                       M1x = 0;
-                       M1y = -1;
-                       M2x = 1;
-                       M2y = -1;
-                       M3x = 1;
-                       M3y = 0;
-               } 
-               else {
-                       Xs = abs(xs);
-                       Ys = abs(ys);
-                       qs = 2;
-                       M1x = -1;
-                       M1y = 0;
-                       M2x = -1;
-                       M2y = -1;
-                       M3x = 0;
-                       M3y = -1;
-               } 
-       else if (ys < 0) {
-               Xs = abs(xs);
-               Ys = abs(ys);
-               qs = 0;
-               M1x = 1;
-               M1y = 0;
-               M2x = 1;
-               M2y = 1;
-               M3x = 0;
-               M3y = 1;
-       } else {
-               Xs = abs(ys);
-               Ys = abs(xs);
-               qs = 1;
-               M1x = 0;
-               M1y = 1;
-               M2x = -1;
-               M2y = 1;
-               M3x = -1;
-               M3y = 0;
-       }
-
-
-       Xc = Xs;
-       Yc = Ys;
-       if (xt < 0)
-               if (yt < 0) {
-                       Xt = abs(yt);
-                       Yt = abs(xt);
-                       qt = 3;
-               } 
-               else {
-                       Xt = abs(xt);
-                       Yt = abs(yt);
-                       qt = 2;
-               } 
-       else if (yt < 0) {
-               Xt = abs(xt);
-               Yt = abs(yt);
-               qt = 0;
-       } else {
-               Xt = abs(yt);
-               Yt = abs(xt);
-               qt = 1;
-       }
-
-
-       /* step 4: calculate number of quadrant crossings */
-       if (((4 + qt - qs)
-            % 4 == 0)
-            && (Xt <= Xs)
-            && (Yt >= Ys)
-           )
-               Q = 3;
-       else
-               Q = (4 + qt - qs) % 4 - 1;
-       /* step 5: calculate initial decision difference */
-       delta = sqr(Xs + 1)
-        + sqr(Ys - 1)
-       -sqr(xs)
-       -sqr(ys);
-       /* here begins the work of drawing
-   we hope it ends here too */
-       while ((Q >= 0)
-            || ((Q > -2)
-            && ((Xt > Xc)
-            || (Yt < Yc)
-           )
-           )
-           ) {
-               if (dotcount++ % DX == 0)
-                       putdot(round((int) xc, DX), round((int) yc, DY));
-               if (Yc < 0.5) {
-                       /* reinitialize */
-                       Xs = Xc = 0;
-                       Ys = Yc = sqrt((float)(sqr(xs) + sqr(ys)));
-                       delta = sqr(Xs + 1) + sqr(Ys - 1) - sqr(xs) - sqr(ys);
-                       Q--;
-                       M1x = M3x;
-                       M1y = M3y;
-                        {
-                               int     T;
-                               T = M2y;
-                               M2y = M2x;
-                               M2x = -T;
-                               T = M3y;
-                               M3y = M3x;
-                               M3x = -T;
-                       }
-               } else {
-                       if (delta <= 0)
-                               if (2 * delta + 2 * Yc - 1 <= 0)
-                                       move = 1;
-                               else
-                                       move = 2;
-                       else if (2 * delta - 2 * Xc - 1 <= 0)
-                               move = 2;
-                       else
-                               move = 3;
-                       switch (move) {
-                       case 1:
-                               Xc++;
-                               delta += 2 * Xc + 1;
-                               xc += M1x * xstep;
-                               yc += M1y * ystep;
-                               break;
-                       case 2:
-                               Xc++;
-                               Yc--;
-                               delta += 2 * Xc - 2 * Yc + 2;
-                               xc += M2x * xstep;
-                               yc += M2y * ystep;
-                               break;
-                       case 3:
-                               Yc--;
-                               delta -= 2 * Yc + 1;
-                               xc += M3x * xstep;
-                               yc += M3y * ystep;
-                               break;
-                       }
-               }
-       }
-
-
-}
-
-putdot(x, y)
-{
-       arcmove(x, y);
-       put1(drawdot);
-}
-
-round(x, dx)   /* round x relative to dx */
-{
-       x = (x + dx - 1) / dx;
-       return x * dx;
+       printf("\\&\\f1\\h'-.1m'\\v'.03m'\\s-3.\\s+3\\fP\n");
+       flyback();
 }
 }
-#endif
index d608e20..7352e95 100644 (file)
@@ -1,19 +1,16 @@
 #ifndef lint
 #ifndef lint
-static char sccsid[] = "@(#)print.c    1.1 (CWI) 85/07/19";
+static char sccsid[] = "@(#)print.c    2.1 (CWI) 85/07/23";
 #endif lint
 #endif lint
-
 #include       <stdio.h>
 #include       "pic.h"
 #include       "y.tab.h"
 #include       <stdio.h>
 #include       "pic.h"
 #include       "y.tab.h"
-int xxx;
 print()
 {
 print()
 {
-       struct obj *p;
-       int i, j, m;
+       obj *p;
+       int i, j, k, m;
        float x0, y0, x1, y1, ox, oy, dx, dy, ndx, ndy;
 
        for (i = 0; i < nobj; i++) {
        float x0, y0, x1, y1, ox, oy, dx, dy, ndx, ndy;
 
        for (i = 0; i < nobj; i++) {
-               xxx = i;
                p = objlist[i];
                ox = p->o_x;
                oy = p->o_y;
                p = objlist[i];
                ox = p->o_x;
                oy = p->o_y;
@@ -36,10 +33,10 @@ print()
                        y1 = oy + y1 / 2;
                        if (p->o_attr & INVIS || p->o_type == BLOCK)
                                ;       /* nothing at all */
                        y1 = oy + y1 / 2;
                        if (p->o_attr & INVIS || p->o_type == BLOCK)
                                ;       /* nothing at all */
-                       else if (p->o_dotdash == 0)
-                               box(x0, y0, x1, y1);
+                       else if (p->o_attr & (DOTBIT|DASHBIT))
+                               dotbox(x0, y0, x1, y1, p->o_attr, p->o_ddval);
                        else
                        else
-                               dotbox(x0, y0, x1, y1, p->o_dotdash, p->o_ddval);
+                               box(x0, y0, x1, y1);
                        if (ishor(m))
                                move(isright(m) ? x1 : x0, oy); /* right side */
                        else
                        if (ishor(m))
                                move(isright(m) ? x1 : x0, oy); /* right side */
                        else
@@ -47,15 +44,6 @@ print()
                        break;
                case BLOCKEND:
                        break;
                        break;
                case BLOCKEND:
                        break;
-                       x0 = ox - x1 / 2;
-                       y0 = oy - y1 / 2;
-                       x1 = ox + x1 / 2;
-                       y1 = oy + y1 / 2;
-                       if (ishor(m))
-                               move(isright(m) ? x1 : x0, oy); /* right side */
-                       else
-                               move(ox, isdown(m) ? y0 : y1);  /* bottom */
-                       break;
                case CIRCLE:
                        move(ox, oy);
                        dotext(p);
                case CIRCLE:
                        move(ox, oy);
                        dotext(p);
@@ -81,16 +69,15 @@ print()
                        dotext(p);
                        if (p->o_attr & HEAD1)
                                arrow(x1 - (y1 - oy), y1 + (x1 - ox),
                        dotext(p);
                        if (p->o_attr & HEAD1)
                                arrow(x1 - (y1 - oy), y1 + (x1 - ox),
-                                     x1, y1, p->o_val[4], p->o_val[5]);
+                                     x1, y1, p->o_val[4], p->o_val[5], p->o_val[5]/p->o_val[6]/2, p->o_nhead);
                         if (p->o_attr & INVIS)
                                 /* probably wrong when it's cw */
                                 move(x1, y1);
                         else
                         if (p->o_attr & INVIS)
                                 /* probably wrong when it's cw */
                                 move(x1, y1);
                         else
-                               arc(ox, oy, x1, y1, p->o_val[2], p->o_val[3], p->o_val[6]
-                                       ,(p->o_attr&CW_ARC));
+                               arc(ox, oy, x1, y1, p->o_val[2], p->o_val[3]);
                        if (p->o_attr & HEAD2)
                                arrow(p->o_val[2] + p->o_val[3] - oy, p->o_val[3] - (p->o_val[2] - ox),
                        if (p->o_attr & HEAD2)
                                arrow(p->o_val[2] + p->o_val[3] - oy, p->o_val[3] - (p->o_val[2] - ox),
-                                     p->o_val[2], p->o_val[3], p->o_val[4], p->o_val[5]);
+                                     p->o_val[2], p->o_val[3], p->o_val[4], p->o_val[5], -p->o_val[5]/p->o_val[6]/2, p->o_nhead);
                        if (p->o_attr & CW_ARC)
                                move(x1, y1);   /* because drawn backwards */
                        break;
                        if (p->o_attr & CW_ARC)
                                move(x1, y1);   /* because drawn backwards */
                        break;
@@ -100,45 +87,39 @@ print()
                        move((ox + x1)/2, (oy + y1)/2); /* center */
                        dotext(p);
                        if (p->o_attr & HEAD1)
                        move((ox + x1)/2, (oy + y1)/2); /* center */
                        dotext(p);
                        if (p->o_attr & HEAD1)
-                               arrow(ox + p->o_val[5], oy + p->o_val[6], ox, oy, p->o_val[2], p->o_val[3]);
+                               arrow(ox + p->o_val[5], oy + p->o_val[6], ox, oy, p->o_val[2], p->o_val[3], 0.0, p->o_nhead);
                         if (p->o_attr & INVIS)
                                 move(x1, y1);
                        else if (p->o_type == SPLINE)
                                spline(ox, oy, p->o_val[4], &p->o_val[5]);
                        else {
                         if (p->o_attr & INVIS)
                                 move(x1, y1);
                        else if (p->o_type == SPLINE)
                                spline(ox, oy, p->o_val[4], &p->o_val[5]);
                        else {
-                               int i, j;
                                dx = ox;
                                dy = oy;
                                dx = ox;
                                dy = oy;
-                               for (i=0, j=5; i < p->o_val[4]; i++, j += 2) {
+                               for (k=0, j=5; k < p->o_val[4]; k++, j += 2) {
                                        ndx = dx + p->o_val[j];
                                        ndy = dy + p->o_val[j+1];
                                        ndx = dx + p->o_val[j];
                                        ndy = dy + p->o_val[j+1];
-                                       if (p->o_dotdash == 0)
-                                               line(dx, dy, ndx, ndy);
+                                       if (p->o_attr & (DOTBIT|DASHBIT))
+                                               dotline(dx, dy, ndx, ndy, p->o_attr, p->o_ddval);
                                        else
                                        else
-                                               dotline(dx, dy, ndx, ndy, p->o_dotdash, p->o_ddval);
+                                               line(dx, dy, ndx, ndy);
                                        dx = ndx;
                                        dy = ndy;
                                }
                        }
                        if (p->o_attr & HEAD2) {
                                        dx = ndx;
                                        dy = ndy;
                                }
                        }
                        if (p->o_attr & HEAD2) {
-                               int i, j;
                                dx = ox;
                                dy = oy;
                                dx = ox;
                                dy = oy;
-                               for (i = 0, j = 5; i < p->o_val[4] - 1; i++, j += 2) {
+                               for (k = 0, j = 5; k < p->o_val[4] - 1; k++, j += 2) {
                                        dx += p->o_val[j];
                                        dy += p->o_val[j+1];
                                }
                                        dx += p->o_val[j];
                                        dy += p->o_val[j+1];
                                }
-                               arrow(dx, dy, x1, y1, p->o_val[2], p->o_val[3]);
+                               arrow(dx, dy, x1, y1, p->o_val[2], p->o_val[3], 0.0, p->o_nhead);
                        }
                        break;
                case MOVE:
                        }
                        break;
                case MOVE:
-                       move(ox, oy);
-                       dotext(p);
-                       break;
                case TEXT:
                        move(ox, oy);
                case TEXT:
                        move(ox, oy);
-                       label((char *)p->o_attr, p->o_dotdash, 0);      /* string in funny place */
-                       free((char *)p->o_attr);
+                       dotext(p);
                        break;
                }
        }
                        break;
                }
        }
@@ -159,7 +140,7 @@ dotline(x0, y0, x1, y1, ddtype, ddval) /* dotted line */
        /* don't save dot/dash value */
        dx = x1 - x0;
        dy = y1 - y0;
        /* don't save dot/dash value */
        dx = x1 - x0;
        dy = y1 - y0;
-       if (ddtype == DOT) {
+       if (ddtype & DOTBIT) {
                numdots = sqrt(dx*dx + dy*dy) / prevval + 0.5;
                if (numdots > 0)
                        for (i = 0; i <= numdots; i++) {
                numdots = sqrt(dx*dx + dy*dy) / prevval + 0.5;
                if (numdots > 0)
                        for (i = 0; i <= numdots; i++) {
@@ -167,7 +148,7 @@ dotline(x0, y0, x1, y1, ddtype, ddval) /* dotted line */
                                move(x0 + (a * dx), y0 + (a * dy));
                                dot();
                        }
                                move(x0 + (a * dx), y0 + (a * dy));
                                dot();
                        }
-       } else if (ddtype == DASH) {
+       } else if (ddtype & DASHBIT) {
                double d, dashsize, spacesize;
                d = sqrt(dx*dx + dy*dy);
                if (d <= 2 * prevval) {
                double d, dashsize, spacesize;
                d = sqrt(dx*dx + dy*dy);
                if (d <= 2 * prevval) {
@@ -202,7 +183,7 @@ dotbox(x0, y0, x1, y1, ddtype, ddval)       /* dotted or dashed box */
 }
 
 dotext(p)      /* print text strings of p in proper vertical spacing */
 }
 
 dotext(p)      /* print text strings of p in proper vertical spacing */
-       struct obj *p;
+       obj *p;
 {
        int i, nhalf;
 
 {
        int i, nhalf;
 
index e6f737f..ea76778 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef lint
 #ifndef lint
-static char sccsid[] = "@(#)symtab.c   1.1 (CWI) 85/07/19";
+static char sccsid[] = "@(#)symtab.c   2.1 (CWI) 85/07/23";
 #endif lint
 #endif lint
-
 #include       <stdio.h>
 #include       <ctype.h>
 #include       "pic.h"
 #include       <stdio.h>
 #include       <ctype.h>
 #include       "pic.h"
@@ -85,8 +84,34 @@ struct symtab *lookup(s)     /* find s in symtab */
 freesymtab(p)  /* free space used by symtab at p */
        struct symtab *p;
 {
 freesymtab(p)  /* free space used by symtab at p */
        struct symtab *p;
 {
-       for ( ; p != NULL; p = p->s_next) {
+       struct symtab *q;
+
+       for ( ; p != NULL; p = q) {
+               q = p->s_next;
                free(p->s_name);        /* assumes done with tostring */
                free(p);
        }
 }
                free(p->s_name);        /* assumes done with tostring */
                free(p);
        }
 }
+
+freedef(s)     /* free definition for string s */
+       char *s;
+{
+       struct symtab *p, *q, *op;
+
+       for (p = op = q = stack[nstack].p_symtab; p != NULL; p = p->s_next) {
+               if (strcmp(s, p->s_name) == 0) {        /* got it */
+                       if (p->s_type != DEFNAME)
+                               break;
+                       if (p == op)    /* 1st elem */
+                               stack[nstack].p_symtab = p->s_next;
+                       else
+                               q->s_next = p->s_next;
+                       free(p->s_name);
+                       free(p->s_val.p);
+                       free(p);
+                       return;
+               }
+               q = p;
+       }
+       yyerror("%s is not defined at this point", s);
+}
index 6c27dd1..f84d148 100644 (file)
 #ifndef lint
 #ifndef lint
-static char sccsid[] = "@(#)textgen.c  1.1 (CWI) 85/07/19";
+static char sccsid[] = "@(#)textgen.c  2.1 (CWI) 85/07/23";
 #endif lint
 #endif lint
-
 #include       <stdio.h>
 #include       "pic.h"
 #include       "y.tab.h"
 
 #include       <stdio.h>
 #include       "pic.h"
 #include       "y.tab.h"
 
-struct obj *textgen(s)
+obj *textgen()
 {
 {
-       int i, type;
-       float dx, dy;
-       struct obj *p, *ppos;
+       int i, type, sub, nstr, at, with, hset;
+       float xwith, ywith, h, w, x0, y0, x1, y1;
+       obj *p, *ppos;
+       static float prevh = 0;
+       static float prevw = 0;
+       Attr *ap;
 
 
-       type = 'C';
-       dx = dy = 0;
-       for (i = 0; i < nattr; i++)
-               switch (attr[i].a_type) {
-               case LEFT:
-                       dx -= attr[i].a_val.f;
-                       break;
-               case RIGHT:
-                       dx += attr[i].a_val.f;
+       sub = CENTER;
+       at = with = nstr = hset = 0;
+       h = getfval("textht");
+       w = getfval("textwid");
+       for (i = 0; i < nattr; i++) {
+               ap = &attr[i];
+               switch (ap->a_type) {
+               case HEIGHT:
+                       h = ap->a_val.f;
+                       hset++;
                        break;
                        break;
-               case UP:
-                       dy += attr[i].a_val.f;
+               case WIDTH:
+                       w = ap->a_val.f;
                        break;
                        break;
-               case DOWN:
-                       dy -= attr[i].a_val.f;
+               case WITH:
+                       with = ap->a_val.i;
                        break;
                case AT:
                        break;
                case AT:
-                       ppos = attr[i].a_val.o;
+                       ppos = ap->a_val.o;
                        curx = ppos->o_x;
                        cury = ppos->o_y;
                        curx = ppos->o_x;
                        cury = ppos->o_y;
+                       at++;
                        break;
                        break;
-               case LJUST:
-                       type = 'L';
-                       break;
-               case RJUST:
-                       type = 'R';
-                       break;
-               case SPREAD:
-                       type = 'S';
-                       break;
-               case FILL:
-                       type = 'F';
-                       break;
-               case ABOVE:
-                       type = 'A';
-                       break;
-               case BELOW:
-                       type = 'B';
+               case TEXTATTR:
+                       sub = ap->a_sub;
+                       if (ap->a_val.p == NULL)        /* an isolated modifier */
+                               text[ntext-1].t_type = sub;
+                       else {
+                               savetext(sub, ap->a_val.p);
+                               nstr++;
+                       }
                        break;
                }
                        break;
                }
-       dprintf("T %c %s\n", type, s);
-       extreme(curx, cury);
-       curx += dx;
-       cury += dy;
-       extreme(curx, cury);
+       }
+       if (hset == 0)          /* no explicit ht cmd */
+               h *= nstr;
+       if (with) {
+               xwith = ywith = 0.0;
+               switch (with) {
+               case NORTH:     ywith = -h / 2; break;
+               case SOUTH:     ywith = h / 2; break;
+               case EAST:      xwith = -w / 2; break;
+               case WEST:      xwith = w / 2; break;
+               case NE:        xwith = -w / 2; ywith = -h / 2; break;
+               case SE:        xwith = -w / 2; ywith = h / 2; break;
+               case NW:        xwith = w / 2; ywith = -h / 2; break;
+               case SW:        xwith = w / 2; ywith = h / 2; break;
+               }
+               curx += xwith;
+               cury += ywith;
+       }
+       if (!at) {
+               if (isright(hvmode))
+                       curx += w / 2;
+               else if (isleft(hvmode))
+                       curx -= w / 2;
+               else if (isup(hvmode))
+                       cury += h / 2;
+               else
+                       cury -= h / 2;
+       }
+       x0 = curx - w / 2;
+       y0 = cury - h / 2;
+       x1 = curx + w / 2;
+       y1 = cury + h / 2;
+       extreme(x0, y0);
+       extreme(x1, y1);
+       dprintf("Text h %g w %g at %g,%g\n", h, w, curx, cury);
        p = makenode(TEXT, 2);
        p = makenode(TEXT, 2);
-       p->o_val[0] = p->o_val[1] = 0;
-       p->o_attr = s;  /* kludge into funny place to avoid coercion */
-       p->o_dotdash = type;
+       p->o_val[0] = w;
+       p->o_val[1] = h;
+       if (isright(hvmode))
+               curx = x1;
+       else if (isleft(hvmode))
+               curx = x0;
+       else if (isup(hvmode))
+               cury = y1;
+       else
+               cury = y0;
+       prevh = h;
+       prevw = w;
        return(p);
 }
        return(p);
 }
+
+obj *troffgen(s)       /* save away a string of troff commands */
+       YYSTYPE s;
+{
+       savetext(CENTER, s.p);  /* use the existing text mechanism */
+       return makenode(TROFF, 0);
+}
+
+savetext(t, s) /* record text elements for current object */
+       int t;
+       char *s;
+{
+       if (ntext >= ntextlist)
+               text = (Text *) grow(text, "text", ntextlist += 200, sizeof(Text));
+       text[ntext].t_type = t;
+       text[ntext].t_val = s;
+       dprintf("saving %d text %s at %d\n", t, s, ntext);
+       ntext++;
+}