%{
#ifndef lint
static char *yrcs = "$Header: xxx.y,v 1.2 88/02/03 08:52:12 simpson Exp $";
#endif
/*
$Log:	xxx.y,v $
 * Revision 1.2  88/02/03  08:52:12  simpson
 * added tpic support
 * 
 * Revision 1.1  88/01/15  13:05:57  simpson
 * initial release
 * 
 * Revision 0.1  87/12/11  18:31:27  simpson
 * beta test
 * 
*/
#define	TPICRES		1000 		/* Tpic uses 1000 dots/inch */
static int	Coordinates[300][2];	/* Coordinates used by tpic */
static int	CoorCount;	        /* Count of # of coor in above array */
static int	PenWidth;
static int	GraphOrigin[2];
static double   Center[2], Cur[2], New[2];
static double   CurvePts[300][3], SplinePts[500][3];
static enum {none, white, shade, black} Color;
%}
%union {
    int	    i;
    double  f;
    char    s[81];
}
%token OVERLAY PENSIZE FLUSHPATH FLUSHDASHED FLUSHDOTTED ADDPATH DRAWARC
%token FLUSHSPLINE SHADELAST WHITENLAST BLACKENLAST TEXTURE
%token <s> STRING
%token <i> INTEGER
%token <f> FLOAT
%type <s> validfile
%%
keywords : 
    keyword ',' keywords
    | 
    keyword 
    |
    error ','
	{
	    yyerrok;
	}
    keywords
    ;

keyword : 
    OVERLAY 
    '('
    validfile
	{
	    FILE    *f;
	    char    filename[81], *expandtilde(), *strcpy();
	    int	    c;

	    (void)strcpy(filename, $3);
            (void)expandtilde(filename);
	    if (f = fopen(filename, "r")) {
		while ((c = getc(f)) != EOF)
		    (void)putchar(c);
		(void)fclose(f);
	    }
	}
    ')'
    |
    PENSIZE
    INTEGER
	{
	    /* A pen command designates the start of a new graph */
	    PenWidth = ROUND($2 / 1000.0 * RESOLUTION);
	    GraphOrigin[0] = Origin[0], GraphOrigin[1] = Origin[1];
	    CoorCount = 0;
	    Color = none;
	}
    |
    FLUSHPATH
	{
    	    if (CoorCount > 1) {
		int i;

		fputs(VECTORON, stdout);
		printf("%s%05d:%05d", PENUP, 
		ROUND((GraphOrigin[0]/(double)RESOLUTION+Coordinates[0][0]/(double)TPICRES)*1000),
		ROUND((GraphOrigin[1]/(double)RESOLUTION+Coordinates[0][1]/(double)TPICRES)*1000));
		printf("%s%02d", PENWIDTH, PenWidth);
		for (i = 1; i < CoorCount; i++)
		    printf("%s%05d:%05d", PENDOWN,
		    ROUND((GraphOrigin[0]/(double)RESOLUTION+Coordinates[i][0]/(double)TPICRES)*1000),
		    ROUND((GraphOrigin[1]/(double)RESOLUTION+Coordinates[i][1]/(double)TPICRES)*1000));
		fputs(VECTOROFF, stdout);
	    }
	    if (CoorCount >=4 && Color != none) {
		/* Find midpoint of diagonal */
		Center[0] = ((GraphOrigin[0]/(double)RESOLUTION+
		Coordinates[0][0]/(double)TPICRES)+(GraphOrigin[0]/
		(double)RESOLUTION+Coordinates[2][0]/(double)TPICRES))/2.0;
		Center[1] = ((GraphOrigin[1]/(double)RESOLUTION+
		Coordinates[0][1]/(double)TPICRES)+(GraphOrigin[1]/
		(double)RESOLUTION+Coordinates[2][1]/(double)TPICRES))/2.0;
		printf("%s%05d%05d", AREAFILL,
		ROUND(Center[0]*1000),ROUND(Center[1]*1000));
		switch (Color) {
		case white:
		    printf("%02d", 0);
		    break;
		case shade:
		    printf("%02d", 19);
		    break;
		case black:
		    printf("%02d", 20);
		    break;
		}
		printf("%s", ENDCMD);
	    }
	    CoorCount = 0;
	    Color = none;
	}
    |
    FLUSHDASHED
    FLOAT
	{
    	    if (CoorCount > 1) {
		int i;

		fputs(VECTORON, stdout);
		printf("%s%05d:%05d", PENUP, 
		ROUND((GraphOrigin[0]/(double)RESOLUTION+Coordinates[0][0]/(double)TPICRES)*1000),
		ROUND((GraphOrigin[1]/(double)RESOLUTION+Coordinates[0][1]/(double)TPICRES)*1000));
		printf("%s%02d", PENWIDTH, PenWidth);
		printf("%s%d", "^V", 4);
		for (i = 1; i < CoorCount; i++)
		    printf("%s%05d:%05d", PENDOWN,
		    ROUND((GraphOrigin[0]/(double)RESOLUTION+Coordinates[i][0]/(double)TPICRES)*1000),
		    ROUND((GraphOrigin[1]/(double)RESOLUTION+Coordinates[i][1]/(double)TPICRES)*1000));
		fputs(VECTOROFF, stdout);
	    }
	    CoorCount = 0;
	    Color = none;
	}
    |
    FLUSHDOTTED
    FLOAT
	{
    	    if (CoorCount > 1) {
		int i;

		fputs(VECTORON, stdout);
		printf("%s%05d:%05d", PENUP, 
		ROUND((GraphOrigin[0]/(double)RESOLUTION+Coordinates[0][0]/(double)TPICRES)*1000),
		ROUND((GraphOrigin[1]/(double)RESOLUTION+Coordinates[0][1]/(double)TPICRES)*1000));
		printf("%s%02d", PENWIDTH, PenWidth);
		printf("%s%d", "^V", 2);
		for (i = 1; i < CoorCount; i++)
		    printf("%s%05d:%05d", PENDOWN,
		    ROUND((GraphOrigin[0]/(double)RESOLUTION+Coordinates[i][0]/(double)TPICRES)*1000),
		    ROUND((GraphOrigin[1]/(double)RESOLUTION+Coordinates[i][1]/(double)TPICRES)*1000));
		fputs(VECTOROFF, stdout);
	    }
	    CoorCount = 0;
	    Color = none;
	}
    |
    ADDPATH
    INTEGER
    INTEGER
	{
	    Coordinates[CoorCount][0] = $2, Coordinates[CoorCount++][1] = $3;
	}
    |
    DRAWARC
    INTEGER
    INTEGER
    INTEGER
    INTEGER
    FLOAT
    FLOAT
	{
	    Center[0] = GraphOrigin[0] / (double)RESOLUTION + $2 /
	    (double)TPICRES,
	    Center[1] = GraphOrigin[1] / (double)RESOLUTION + $3 /
	    (double)TPICRES;
    	    if ($4 != $5) {	/* Ellipse */
		int i;

		/* Ellipses satisfy the equation (x^2)/(a^2)+(y^2)/(b^2)=1
		 * where 'a' is the length of the semimajor axis and 'b'
		 * is the length of the semiminor axis.  We divide each
		 * quadrant into 200 line segments and connect the line
		 * segments.
		 */
		/* Cur and New are relative to the origin */
		Cur[0] = $4 / (double)TPICRES, Cur[1] = 0.0;
		fputs(VECTORON, stdout);
		printf("%s%02d", PENWIDTH, PenWidth);
		for (i = 1; i <= 200; i++, Cur[0] = New[0], Cur[1] = New[1]) {
		    New[0] = ($4/(double)TPICRES)*cos((i/200.0)*(PI/2.0)),
		    New[1] = ($5/(double)TPICRES)*sin((i/200.0)*(PI/2.0));
		    /* First quadrant */
		    printf("%s%05d:%05d", PENUP,
		    ROUND((Center[0]+Cur[0])*1000.0),
		    ROUND((Center[1]+Cur[1])*1000.0));
		    printf("%s%05d:%05d", PENDOWN,
		    ROUND((Center[0]+New[0])*1000.0),
		    ROUND((Center[1]+New[1])*1000.0));
		    /* Second quadrant */
		    printf("%s%05d:%05d", PENUP,
		    ROUND((Center[0]-Cur[0])*1000.0),
		    ROUND((Center[1]+Cur[1])*1000.0));
		    printf("%s%05d:%05d", PENDOWN,
		    ROUND((Center[0]-New[0])*1000.0),
		    ROUND((Center[1]+New[1])*1000.0));
		    /* Third quadrant */
		    printf("%s%05d:%05d", PENUP,
		    ROUND((Center[0]-Cur[0])*1000.0),
		    ROUND((Center[1]-Cur[1])*1000.0));
		    printf("%s%05d:%05d", PENDOWN,
		    ROUND((Center[0]-New[0])*1000.0),
		    ROUND((Center[1]-New[1])*1000.0));
		    /* Fourth quadrant */
		    printf("%s%05d:%05d", PENUP,
		    ROUND((Center[0]+Cur[0])*1000.0),
		    ROUND((Center[1]-Cur[1])*1000.0));
		    printf("%s%05d:%05d", PENDOWN,
		    ROUND((Center[0]+New[0])*1000.0),
		    ROUND((Center[1]-New[1])*1000.0));
		    if (Color != none) {
			printf("%s%05d%05d", AREAFILL,
			ROUND(Center[0]*1000),ROUND(Center[1]*1000));
			switch (Color) {
			case white:
			    printf("%02d", 0);
			    break;
			case shade:
			    printf("%02d", 19);
			    break;
			case black:
			    printf("%02d", 20);
			    break;
			}
			printf("%s", ENDCMD);
			Color = none;
		    }
		}
		fputs(VECTOROFF, stdout);
	    } else {	/* Arc */
		printf("%s%c%05d%c%05d%05d%03d%03d%02d%s", DECIMALARC,
		Center[0]>0?'+':'-',
		Center[0]>0?ROUND(Center[0]*1000):
		ROUND(-Center[0]*1000),Center[1]>0?'+':'-',
		Center[1]>0?ROUND(Center[1]*1000):
		ROUND(-Center[1]*1000),$4,ROUND($6/PI*500.0)>999?999:
		ROUND($6/PI*500.0),ROUND($7/PI*500.0)>999?999:
		ROUND($7/PI*500.0), PenWidth, ENDCMD);
		if ($6 == 0 && ABS($7-2*PI) < 0.01)
		    if (Color != none) {
			printf("%s%05d%05d", AREAFILL,
			ROUND(Center[0]*1000),ROUND(Center[1]*1000));
			switch (Color) {
			case white:
			    printf("%02d", 0);
			    break;
			case shade:
			    printf("%02d", 19);
			    break;
			case black:
			    printf("%02d", 20);
			    break;
			}
			printf("%s", ENDCMD);
			Color = none;
		    }
	    }
	}
								  
    |
    FLUSHSPLINE
	{
	    if (CoorCount > 1) {
		int i;

		for (i = 0; i < CoorCount; i++) {
		    CurvePts[i][0] = Coordinates[i][0] / (double)TPICRES;
		    CurvePts[i][1] = Coordinates[i][1] / (double)TPICRES;
		    CurvePts[i][2] = 0.0;	/* z-axis not used */
		}
		spline(CurvePts,CoorCount-1,SplinePts,499,3); /* 2nd degree */
		fputs(VECTORON, stdout);
		printf("%s%05d:%05d", PENUP,
		ROUND((GraphOrigin[0]/(double)RESOLUTION+SplinePts[0][0])*1000),
		ROUND((GraphOrigin[1]/(double)RESOLUTION+SplinePts[0][1])*1000));
		printf("%s%02d", PENWIDTH, PenWidth);
		for (i = 1; i < 500; i++)
		    printf("%s%05d:%05d", PENDOWN,
		    ROUND((GraphOrigin[0]/(double)RESOLUTION+SplinePts[i][0])*1000),
		    ROUND((GraphOrigin[1]/(double)RESOLUTION+SplinePts[i][1])*1000));
		fputs(VECTOROFF, stdout);
	    }
	    CoorCount = 0;
	}
    |
    TEXTURE
    textureargs		/* Ignore - Imagen only */
    |
    SHADELAST
	{
	    Color = shade;
	}
    |
    WHITENLAST
	{
	    Color = white;
	}
    |
    BLACKENLAST
	{
	    Color = black;
	}
    ;

validfile :
    STRING
	{
	    (void)strcpy($$, $1);
	}
    |
    OVERLAY
	{
	    (void)strcpy($$, "overlay");
	}
    |
    PENSIZE
	{
	    (void)strcpy($$, "pn");
	}
    | 
    FLUSHPATH
	{
	    (void)strcpy($$, "fp");
	}
    |
    FLUSHDASHED
	{
	    (void)strcpy($$, "da");
	}
    |
    FLUSHDOTTED
	{
	    (void)strcpy($$, "dt");
	}
    |
    ADDPATH
	{
	    (void)strcpy($$, "pa");
	}
    |
    DRAWARC
	{
	    (void)strcpy($$, "ar");
	}
    |
    FLUSHSPLINE
	{
	    (void)strcpy($$, "sp");
	}
    |
    SHADELAST
	{
	    (void)strcpy($$, "sh");
	}
    |
    WHITENLAST
	{
	    (void)strcpy($$, "wh");
	}
    |
    BLACKENLAST
	{
	    (void)strcpy($$, "bk");
	}
    |
    TEXTURE
	{
	    (void)strcpy($$, "tx");
	}
    |
    INTEGER
	{
	    (void)sprintf($$, "%d", $1);
	}
/*  |		Unfortunately this won't work since the lexeme
    FLOAT	of a float has been lost when we converted it to a 
        {	real number.
 	    (void)sprintf($$, "%f", $1);
	}
*/
    ;

textureargs : texturearg textureargs | /* epsilon */ ;

texturearg : STRING | INTEGER  ;
%%
#include "xxxlex.c"

yyerror(s)
char *s;
{
    return;
}