/* yacc.y								   */
/*									   */
/* Copyright (C) 1989, 1991, Craig E. Kolb				   */
/* All rights reserved.							   */
/*									   */
/* This software may be freely copied, modified, and redistributed,	   */
/* provided that this copyright notice is preserved on all copies.	   */
/*									   */
/* You may not distribute this software, in whole or in part, as part of   */
/* any commercial product without the express consent of the authors.      */
/* 									   */
/* There is no warranty or other guarantee of fitness of this software	   */
/* for any purpose.  It is provided solely "as is".			   */
/* $Id$ */
%{
#include <stdio.h>
#include "libcommon/common.h"

/*#define NEWLINE()	WriteString("\n")*/
#define NEWLINE()
#define LIST	0
#define GRID	1
char yyfilename[BUFSIZ];
extern int yylineno;
%}
%union {
	char *c;
	int i;
	double d;
	Color col;
	Vector v;
};
%token <d> tFLOAT
%token <c> tSTRING
%token <i> tINT
%type <d> Fnumber sFnumber
%type <col> sColor;
%type <v> sVector;
%token tADAPTIVE tAPERTURE 
%token tBACKGROUND tBLOTCH tBOX tBUMP tCONE tCYL tDIRECTIONAL
%token tENDDEF tEXTENDED tEYEP tFBM tFBMBUMP tFOCALDIST tFOG tFOV tGLOSS tGRID
%token tHEIGHTFIELD tJITTERED tLIGHT tLIST tLOOKP tMARBLE tMAXDEPTH tMIST
%token tOBJECT tOUTFILE
%token tPLANE tPOINT tPOLY tROTATE tSAMPLES
%token tSCALE tSCREEN tSPHERE tSTARTDEF tSUPERQ tSURFACE tRESOLUTION
%token tTHRESH tTRANSLATE tTRANSFORM tTRIANGLE tUP tENDFILE
%token tTEXTURE tCHECKER tWOOD tCONTRAST tCUTOFF
%%
Items		: /* empty */
		| Items Item
		;
Item		: Eyep
		| Lookp
		| Up
		| Fov
		| Screen
		| Aperture
		| Focaldist
		| Maxdepth
		| Samples
		| Jittered
		| Adaptive
		| Contrast
		| Cutoff
		| Background
		| Light
		| Primitive
		| Child
		| Surface
		| Outfile
		| List
		| Grid
		| Object
		| Fog
		| Mist
		| ENDFILE		/* For backward compatibility */
		;
List		: LIST
		{
			NEWLINE();
		}
		;
Grid		: GRID
		{
			NEWLINE();
		}
		;
Primitive	: Prim Textures
		;
Prim		: Primtype Transforms
		;
		;
Primtype	: Plane
		| Sphere
		| Box
		| Triangle
		| Cylinder
		| Cone
		| Superq
		| Poly
		| HeightField
		;
Object		: Objectdef Textures
		{
			NEWLINE();
		}
		;
Objectdef	: Startdef Objdefs ENDDEF
		;
Startdef	: STARTDEF
		/*
		 * define <name>
		 */
		{
			NEWLINE();
		}
		;
Objdefs		: Objdefs Objdef
		|
		;
Objdef		: Primitive
		| Surface
		| Child
		| List
		| Grid
		| Object
		;
Textures	: Textures Texture
		|
		;
Texture		: TEXTURE Texturetype Transforms
		{
			NEWLINE();
		}
		;
Texturetype	: CHECKER String
		{
			NEWLINE();
		}
		| BLOTCH Fnumber String
		{
			NEWLINE();
		}
		| BUMP Fnumber
		{
			NEWLINE();
		}
		| MARBLE
		{
			NEWLINE();
		}
		| MARBLE String
		{
			NEWLINE();
		}
		| FBM Fnumber Fnumber Fnumber Fnumber Int Fnumber
		{
			NEWLINE();
		}
		| FBM Fnumber Fnumber Fnumber Fnumber Int Fnumber tSTRING
		{
			NEWLINE();
		}
		| FBMBUMP Fnumber Fnumber Fnumber Fnumber Int
		{
			NEWLINE();
		}
		| WOOD
		{
			NEWLINE();
		}
		| GLOSS Fnumber
		{
			NEWLINE();
		}
		;
Child		: Childdef Textures
		{
			NEWLINE();
		}
		;
Childdef	: OBJECT String Transforms
		{
			NEWLINE();
		}
		;
Transforms	: Transforms Transform
		| /* empty */
		;
Transform	: TRANSLATE Vector
		{
			NEWLINE();
		}
		| ROTATE Vector Fnumber
		{
			NEWLINE();
		}
		| SCALE Fnumber Fnumber Fnumber
		{
			NEWLINE();
		}
		| TRANSFORM Fnumber Fnumber Fnumber
				Fnumber Fnumber Fnumber
				Fnumber Fnumber Fnumber
		{
			NEWLINE();
		}
		| TRANSFORM Fnumber Fnumber Fnumber
				Fnumber Fnumber Fnumber
				Fnumber Fnumber Fnumber
				Fnumber Fnumber Fnumber
		{
			NEWLINE();
		}
		;
Eyep		: EYEP Vector Transforms
		{
			NEWLINE();
		}
		;
Lookp		: LOOKP Vector
		{
			NEWLINE();
		}
		;
Up		: UP Vector
		{
			NEWLINE();
		}
		;
Fov		: FOV Fnumber Fnumber
		{
			NEWLINE();
		}
		| FOV Fnumber
		{
			NEWLINE();
		}
		;
Samples		: SAMPLES Int
		{
			NEWLINE();
		}
		;
Adaptive	: ADAPTIVE Int
		{
			NEWLINE();
		}
		;
Contrast	: CONTRAST Fnumber Fnumber Fnumber
		{
			NEWLINE();
		}
		;
Cutoff		: CUTOFF Fnumber
		{
			NEWLINE();
		}
		;
Jittered	: JITTERED
		{
			NEWLINE();
		}
		;
Screen		: SCREEN Int Int
		{
			NEWLINE();
		}
		| RESOLUTION Int Int
		{
			NEWLINE();
		}
		;
Aperture	: APERTURE Fnumber
		{
			NEWLINE();
		}
		;
Focaldist	: FOCALDIST Fnumber
		{
			NEWLINE();
		}
		;
Maxdepth	: MAXDEPTH Int
		{
			NEWLINE();
		}
		;
Background	: BACKGROUND Color
		{
			NEWLINE();
		}
		;
Light		: Lightdef POINT Vector
		{
			NEWLINE();
		}
		| Lightdef DIRECTIONAL Vector
		{
			NEWLINE();
		}
		| Lightdef EXTENDED sVector sFnumber
		{
			WriteFloat($4);
			WriteVector(&$3);
			NEWLINE();
		}
		;
Lightdef	: LIGHT Fnumber
		{
			NEWLINE();
		}
		| LIGHT Color
		{
			NEWLINE();
		}
		;
Surface		: SURFACE String
			sColor sColor sColor
			sFnumber sFnumber sFnumber sFnumber
		{
			if ($3.r || $3.g || $3.b) {
				WriteString("\tambient");
				WriteColor(&$3);
				WriteNewline();
			}
			if ($4.r || $4.g || $4.b) {
				WriteString("\tdiffuse");
				WriteColor(&$4);
				WriteNewline();
			}
			if ($5.r || $5.g || $5.b) {
				WriteString("\tspecular");
				WriteColor(&$5);
				WriteNewline();
				if ($6) {
					WriteString("\tspecpow");
					WriteFloat($6);
					WriteNewline();
				}
			}
			if ($7) {
				WriteString("\treflect");
				WriteFloat($7);
				WriteNewline();
			}
			if ($8) {
				WriteString("\ttransp");
				WriteFloat($8);
				WriteString("index");
				WriteFloat($9);
				WriteNewline();
			}
		}
		| SURFACE String sColor sColor sColor
			sFnumber sFnumber sFnumber sFnumber sFnumber sFnumber
		{
			if ($3.r || $3.g || $3.b) {
				WriteString("\tambient");
				WriteColor(&$3);
				WriteNewline();
			}
			if ($4.r || $4.g || $4.b) {
				WriteString("\tdiffuse");
				WriteColor(&$4);
				WriteNewline();
			}
			if ($5.r || $5.g || $5.b) {
				WriteString("\tspecular");
				WriteColor(&$5);
				WriteNewline();
				if ($6) {
					WriteString("\tspecpow");
					WriteFloat($6);
					WriteNewline();
				}
			}
			if ($7) {
				WriteString("\treflect");
				WriteFloat($7);
				WriteNewline();
			}
			if ($8) {
				WriteString("\ttransp");
				WriteFloat($8);
				WriteString("index");
				WriteFloat($9);
				WriteNewline();
			}
			if ($10) {
				WriteString("\ttranslu");
				WriteFloat($10);
				WriteFloat($11);
			}
		}
		;
HeightField	: HEIGHTFIELD String String
		{
			NEWLINE();
		}
		;
Poly		: POLY String Polypoints
		{
			NEWLINE();
		}
		;
Polypoints	: /* empty */
		| Polypoints Polypoint
		;
Polypoint	: Vector
		{
			NEWLINE();
		}
		;
Cone		: CONE String sVector sVector sFnumber sFnumber
		{
			/* Radii now precede points */
			WriteFloat($5);
			WriteVector(&$3);
			WriteFloat($6);
			WriteVector(&$4);
			NEWLINE();
		}
		;
Cylinder	: CYL String sVector sVector sFnumber
		{
			/* Radius now goes first */
			WriteFloat($5);
			WriteVector(&$3);
			WriteVector(&$4);
			NEWLINE();
		}
		;
Sphere		: SPHERE String Fnumber Vector
		{
			NEWLINE();
		}
		;
Box		: BOX String
			sFnumber sFnumber sFnumber
			sFnumber sFnumber sFnumber
		{
			/* give box corners */
			WriteFloat($3 - $6);
			WriteFloat($4 - $7);
			WriteFloat($5 - $8);
			WriteFloat($3 + $6);
			WriteFloat($4 + $7);
			WriteFloat($5 + $8);
			NEWLINE();
		}
		;
Triangle	: TRIANGLE String Vector Vector Vector
		{
			NEWLINE();
		}
		| TRIANGLE String Vector Vector Vector Vector Vector Vector
		{
			NEWLINE();
		}
		;
Superq		: SUPERQ String
			Fnumber Fnumber Fnumber
			Fnumber Fnumber Fnumber
			Fnumber
		{
			NEWLINE();
		}
		;
Plane		: PLANE String sVector sVector
		{
			/* reverse order of point/normal */
			WriteVector(&$4);
			WriteVector(&$3);
			NEWLINE();
		}
		;
Outfile		: OUTFILE String
		{
			NEWLINE();
		}
		;
Mist		: MIST Color Color Fnumber Fnumber
		{
			NEWLINE();
		}
		;
Fog		: FOG Fnumber Color
		{
			NEWLINE();
		}
		;
Color		: Fnumber Fnumber Fnumber
		;
sColor		: sFnumber sFnumber sFnumber
		{
			$$.r = $1; $$.g = $2; $$.b = $3;
		}
		;
Vector		: Fnumber Fnumber Fnumber
		;
sVector		: sFnumber sFnumber sFnumber
		{
			$$.x = $1; $$.y = $2; $$.z = $3;
		}
		;
Fnumber		: tFLOAT
		{ WriteFloat($1); }
		| tINT
		{ WriteFloat((Float)$1); }
		;
Int		: tINT
		{ WriteFloat((Float)$1); };
sFnumber	: tFLOAT
		| tINT
		{ $$ = (double)$1; }
		;
String		: tSTRING
		{ WriteString($1); }
ADAPTIVE	: tADAPTIVE	{ WriteString("adaptive"); }
APERTURE	: tAPERTURE	{ WriteString("aperture"); }
BACKGROUND	: tBACKGROUND	{ WriteString("background"); }
BLOTCH		: tBLOTCH	{ WriteString("blotch"); }
BOX		: tBOX		{ WriteString("box"); }
BUMP		: tBUMP		{ WriteString("bump"); }
CONE		: tCONE		{ WriteString("cone"); }
CYL		: tCYL		{ WriteString("cylinder"); }
DIRECTIONAL	: tDIRECTIONAL	{ WriteString("directional"); }
ENDDEF		: tENDDEF	{ EndDefine(); }
EXTENDED	: tEXTENDED	{ WriteString("extended"); }
EYEP		: tEYEP		{ WriteString("eyep"); }
FBM		: tFBM		{ WriteString("fbm"); }
FBMBUMP		: tFBMBUMP	{ WriteString("fbmbump"); }
FOCALDIST	: tFOCALDIST	{ WriteString("focaldist"); }
FOG		: tFOG		{ WriteString("fog"); }
FOV		: tFOV		{ WriteString("fov"); }
GLOSS		: tGLOSS	{ WriteString("gloss"); }
GRID		: tGRID	tINT tINT tINT	{ SetTypeGrid($2,$3,$4); }
HEIGHTFIELD	: tHEIGHTFIELD	{ WriteString("heightfield"); }
JITTERED	: tJITTERED	{ WriteString("jittered"); }
LIGHT		: tLIGHT	{ WriteString("light"); }
LIST		: tLIST		{ SetTypeList(); }
LOOKP		: tLOOKP	{ WriteString("lookp"); }
MARBLE		: tMARBLE	{ WriteString("marble"); }
MAXDEPTH	: tMAXDEPTH	{ WriteString("maxdepth"); }
MIST		: tMIST		{ WriteString("mist"); }
OBJECT		: tOBJECT	{ WriteString("object"); }
OUTFILE		: tOUTFILE	{ WriteString("outfile"); }
PLANE		: tPLANE	{ WriteString("plane"); }
POINT		: tPOINT	{ WriteString("point"); }
POLY		: tPOLY		{ WriteString("poly"); }
ROTATE		: tROTATE	{ WriteString("rotate"); }
SAMPLES		: tSAMPLES	{ WriteString("samples"); }
SCALE		: tSCALE	{ WriteString("scale"); }
SCREEN		: tSCREEN	{ WriteString("screen"); }
SPHERE		: tSPHERE	{ WriteString("sphere"); }
STARTDEF	: tSTARTDEF tSTRING	{ StartDefine($2); }
SUPERQ		: tSUPERQ	{ WriteString("superq"); }
SURFACE		: tSURFACE	{ WriteString("surface"); }
RESOLUTION	: tRESOLUTION	{ WriteString("resolution"); }
TRANSLATE	: tTRANSLATE	{ WriteString("translate"); }
TRANSFORM	: tTRANSFORM	{ WriteString("transform"); }
TRIANGLE	: tTRIANGLE	{ WriteString("triangle"); }
UP		: tUP		{ WriteString("up"); }
ENDFILE		: tENDFILE	{ WriteString("endfile"); }
TEXTURE		: tTEXTURE	{ WriteString("texture"); }
CHECKER		: tCHECKER	{ WriteString("checker"); }
WOOD		: tWOOD		{ WriteString("wood"); }
CONTRAST	: tCONTRAST	{ WriteString("contrast"); }
CUTOFF		: tCUTOFF	{ WriteString("cutoff"); }
%%

#define STARTBUFSIZ	(1 << 18)

typedef struct db {
	int bufsiz, curpos;
	int type, x, y, z;
	char *name;
	struct db *next;
	char *memory;
} DefBuf;

DefBuf *defbuf = NULL;

yyerror(s)
{
	fprintf(stderr,"yyerror: %s\n",s);
}

StartDefine(name)
char *name;
{
	DefBuf *new;
	/*
	 * Push new buffer onto define stack.
	 */
	new = (DefBuf *)Malloc(sizeof(DefBuf));
	new->bufsiz = STARTBUFSIZ;
	new->curpos = 0;
	new->name = name;
	new->memory = (char *)Calloc(new->bufsiz, sizeof(char));
	new->next = defbuf;
	defbuf = new;
}

EndDefine()
{
	char buf[BUFSIZ];
	DefBuf *old;

	old = defbuf;
	defbuf = defbuf->next;
	if (old->type == LIST) {
		sprintf(buf, "name %s list", old->name);
	} else {
		sprintf(buf, "name %s grid %d %d %d", old->name,
				old->x, old->y, old->z);
	}
	/*
	 * dump goodies
	 */
	WriteVerbatim(buf);
	WriteVerbatim(old->memory);
	WriteVerbatim("end");
	free((voidstar)old->memory);
	free((voidstar)old);
	
}

WriteString(str)
char *str;
{
	WriteVerbatim(str);
	WriteChar(' ');
}

WriteVerbatim(str)
char *str;
{
	int n;

	for (n = strlen(str); n; n--)
		WriteChar(*(str++));
}

WriteChar(c)
char c;
{
	if (defbuf) {
		if (defbuf->curpos == defbuf->bufsiz) {
			defbuf->bufsiz *= 2;
			defbuf->memory = (char *)realloc(defbuf->memory,
				defbuf->bufsiz * sizeof(char));
		}
		defbuf->memory[defbuf->curpos++] = c;
		defbuf->memory[defbuf->curpos] = (char)NULL;
	} else
		putchar(c);
}

WriteVector(v)
Vector *v;
{
	WriteFloat(v->x);
	WriteFloat(v->y);
	WriteFloat(v->z);
}

WriteFloat(x)
Float x;
{
	char buf[BUFSIZ];
	sprintf(buf, "%g ", x);
	WriteVerbatim(buf);
}

WriteNewline()
{
	WriteVerbatim("\n");
}

SetTypeList()
{
	if (defbuf)
		defbuf->type = LIST;
	/* else set world type */
}

SetTypeGrid(x,y,z)
int x, y, z;
{
	if (defbuf) {
		defbuf->type = GRID;
		defbuf->x = x; defbuf->y = y; defbuf->z = z;
	} /* else set world type */
}

WriteColor(c)
Color *c;
{
	WriteFloat(c->r);
	WriteFloat(c->g);
	WriteFloat(c->b);
}
