/****************************************************************************/
/*                                                                          */
/*                      Chaine de CAO & VLSI   Alliance                     */
/*                                                                          */
/*    Produit : Icon library                                                */
/*    Fichier : aiParse.c (Alliance icon parser)                            */
/*                                                                          */
/*    (c) copyright 1991 Laboratoire MASI equipe CAO & VLSI                 */
/*    Tous droits reserves                                                  */
/*    Support : e-mail cao-vlsi@masi.ibp.fr                                 */
/*                                                                          */
/*    Auteur(s) : Vincent POUILLEY                      le : 03/03/1993     */
/*                                                                          */
/*    Modifie par :                                     le : ../../....     */
/*    Modifie par :                                     le : ../../....     */
/*    Modifie par :                                     le : ../../....     */
/*                                                                          */
/*    $Id: aiParse.c,v 2.1.1.1 1993/09/23 16:04:30 sax Exp sax $                */
/*                                                                          */
/****************************************************************************/

#include <stdio.h>
#include <ctype.h>
#include <malloc.h>
#include <string.h>
#include "IconConst.h"
#include MUT_H
#include ICN_H
#include IAC_H
#include ICU_H
#include "ConvMacro.h"

#ident "@(#)Parser Alliance icon v2.00 06/08/93 by Vincent POUILLEY"

#ifdef __STDC__
char aiConvHAlign (char align)
#else
char aiConvHAlign (align)
char align;
#endif
{
    switch(align)
    {
		case 'R':
			return(SAX_RIGHT);
		case 'C' :
			return(SAX_CENTER);
		default  :
			return(SAX_LEFT);
    }
}

#ifdef __STDC__
char aiConvVAlign (char align)
#else
char aiConvVAlign (align)
char align;
#endif
{
    switch(align)
    {
		case 'U':
			return(SAX_UP);
		case 'C' :
			return(SAX_CENTER);
		default  :
			return(SAX_DOWN);
	}
}

#ifdef __STDC__
char aiConvDirection (char direction)
#else
char aiConvDirection (direction)
char direction;
#endif
{
    if (direction == 'H')
		return (SAX_HORIZONTAL);
    else
		return(SAX_VERTICAL);
}

#ifdef __STDC__
char aiConvSide (char side)
#else
char aiConvSide (side)
char side;
#endif
{
    switch(side)
    {
		case 'N':
			return(SAX_NORTH);
		case 'S' :
			return(SAX_SOUTH);
		case 'W' :
			return(SAX_WEST);
		default  :
			return(SAX_EAST);
	}
}

#ifdef __STDC__
char aiConvLoDir (char * dir)
#else
char aiConvLoDir (dir)
char * dir;
#endif
{
	switch (dir[2])
	{
		case 'O' :
			return 'B';
		case 'K' :
			return 'X';
		case 'I' :
			return 'Z';
		case 'A' :
			return 'T';
		default :
			return dir[0];
	}
}

#ifdef __STDC__
char aiConvType (char type)
#else
char aiConvType (type)
char type;
#endif
{
    switch(type)
    {
		case 'S':
			return(COMP_ISARCSTART);
		case 'E' :
			return(COMP_ISARCEND);
		case 'C' :
			return(COMP_ISARCCOMP);
		case 'A' :
			return(COMP_ISARCSTART | COMP_ISARCEND);
		default  :
			return(COMP_ISLINE);
	}
}

/*****************************************************************/
/*               read_ai_icon_* Functions.                          */
/*****************************************************************/

#ifdef __STDC__
int read_ai_icon_boundingbox (char * buf, IconGate_list * icon_gate)
#else
int read_ai_icon_boundingbox (buf, icon_gate)
char * buf;
IconGate_list * icon_gate;
#endif
{
	char * paux, *ptemp;
	
	if ((paux=(char *)strchr(buf,',')) == NULL)
		return PROBLEM;
	*paux='\0';
	ICONGATE_X(icon_gate) = atol(buf+2) * SCALE_X;
	ptemp = paux + 1;
	if ((paux=(char *)strchr(ptemp,',')) == NULL)
		return PROBLEM;
	*paux='\0';
	ICONGATE_Y(icon_gate) = atol(ptemp) * SCALE_X;
	ptemp = paux + 1;
	if ((paux=(char *)strchr(ptemp,',')) == NULL)
		return PROBLEM;
	*paux='\0';
	ICONGATE_WIDTH (icon_gate) = atol(ptemp) * SCALE_X;
	ptemp = paux + 1;
	ICONGATE_HEIGHT (icon_gate) = atol(ptemp) * SCALE_X;
	return OK;
}

#ifdef __STDC__
int read_ai_icon_model (char * buf, IconGate_list * icon_gate)
#else
int read_ai_icon_model (buf, icon_gate)
char * buf;
IconGate_list * icon_gate;
#endif
{
	char * paux, *ptemp;
	
	if ((paux=(char *)strchr(buf,',')) == NULL)
		return PROBLEM;
	*paux='\0';
	ICONGATE_X_MODELNAME(icon_gate) = atol(buf+2) * SCALE_X;
	ptemp = paux + 1;
	if ((paux=(char *)strchr(ptemp,',')) == NULL)
		return PROBLEM;
	*paux='\0';
	ICONGATE_Y_MODELNAME(icon_gate) = atol(ptemp) * SCALE_X;
	paux++;
	ICONGATE_HALIGN_MODELNAME(icon_gate) = aiConvHAlign(*paux++);
	ICONGATE_VALIGN_MODELNAME(icon_gate) = aiConvVAlign(*paux++);
	if (*paux++ != ',')
		return PROBLEM;
	ICONGATE_DIRECTION_MODELNAME(icon_gate) = aiConvDirection(*paux);
	return OK;
}

#ifdef __STDC__
int read_ai_icon_insname (char * buf, IconGate_list * icon_gate)
#else
int read_ai_icon_insname (buf, icon_gate)
char * buf;
IconGate_list * icon_gate;
#endif
{
	char * paux, *ptemp;
	
	if ((paux=(char *)strchr(buf,',')) == NULL)
		return PROBLEM;
	*paux='\0';
	ICONGATE_X_INSNAME(icon_gate) = atol(buf+2) * SCALE_X;
	ptemp = paux + 1;
	if ((paux=(char *)strchr(ptemp,',')) == NULL)
		return PROBLEM;
	*paux='\0';
	ICONGATE_Y_INSNAME(icon_gate) = atol(ptemp) * SCALE_X;
	paux++;
	ICONGATE_HALIGN_INSNAME(icon_gate) = aiConvHAlign(*paux++);
	ICONGATE_VALIGN_INSNAME(icon_gate) = aiConvVAlign(*paux++);
	if (*paux++ != ',')
		return PROBLEM;
	ICONGATE_DIRECTION_INSNAME(icon_gate) = aiConvDirection(*paux);
	return OK;
}

#ifdef __STDC__
int read_ai_icon_label (char * buf, IconGate_list * icon_gate)
#else
int read_ai_icon_label (buf, icon_gate)
char * buf;
IconGate_list * icon_gate;
#endif
{
	char * paux, *ptemp;
	
	if ((paux=(char *)strchr(buf,',')) == NULL)
		return PROBLEM;
	*paux='\0';
	ICONGATE_X_LABEL(icon_gate) = atol(buf+2) * SCALE_X;
	ptemp = paux + 1;
	if ((paux=(char *)strchr(ptemp,',')) == NULL)
		return PROBLEM;
	*paux='\0';
	ICONGATE_Y_LABEL(icon_gate) = atol(ptemp) * SCALE_X;
	paux++;
	ICONGATE_HALIGN_LABEL(icon_gate) = aiConvHAlign(*paux++);
	ICONGATE_VALIGN_LABEL(icon_gate) = aiConvVAlign(*paux++);
	if (*paux++ != ',')
		return PROBLEM;
	ICONGATE_DIRECTION_LABEL(icon_gate) = aiConvDirection(*paux);
	return OK;
}

#ifdef __STDC__
int read_ai_icon_connector (char * buf, IconGate_list * icon_gate)
#else
int read_ai_icon_connector (buf, icon_gate)
char * buf;
IconGate_list * icon_gate;
#endif
{
	char * paux, *ptemp;
	long x, y, xname, yname;
	char * name;
	char side, lodir, halign, valign, direction;
	IconCon_list*	icon_con;
	
	if ((paux=(char *)strchr(buf,',')) == NULL)
		return PROBLEM;
	*paux='\0';
	x = atol(buf+2) * SCALE_X;
	ptemp = paux + 1;
	if ((paux=(char *)strchr(ptemp,',')) == NULL)
		return PROBLEM;
	*paux='\0';
	y = atol(ptemp) * SCALE_X;
	paux++;
	side = aiConvSide(*paux++);
	ptemp = paux + 1;
	if ((paux=(char *)strchr(ptemp,',')) == NULL)
		return PROBLEM;
	*paux='\0';
	lodir = aiConvLoDir(ptemp);
	name = paux + 1;
	if ((paux=(char *)strchr(name,',')) == NULL)
		return PROBLEM;
	*paux='\0';
	ptemp = paux + 1;
	if ((paux=(char *)strchr(ptemp,',')) == NULL)
		return PROBLEM;
	*paux='\0';
	xname = atol(ptemp) * SCALE_X;
	ptemp = paux + 1;
	if ((paux=(char *)strchr(ptemp,',')) == NULL)
		return PROBLEM;
	*paux='\0';
	yname = atol(ptemp) * SCALE_X;
	paux++;
	halign = aiConvHAlign(*paux++);
	valign = aiConvVAlign(*paux++);
	if (*paux++ != ',')
		return PROBLEM;
	direction = aiConvDirection(*paux);

	icon_con = addiconcon(icon_gate, name, x, y, side, lodir, halign, valign, direction, xname, yname);
	
	if (icon_con == NULL)
		return PROBLEM;
	else
		return OK;
}

#ifdef __STDC__
int read_ai_icon_line (char * buf, IconGate_list * icon_gate)
#else
int read_ai_icon_line (buf, icon_gate)
char * buf;
IconGate_list * icon_gate;
#endif
{
	char * paux, *ptemp;
	long x1, x2, y1, y2;
	IconLine_list*	icon_line;
	
	if ((paux=(char *)strchr(buf,',')) == NULL)
		return PROBLEM;
	*paux='\0';
	x1 = atol(buf+2) * SCALE_X;
	ptemp = paux + 1;
	if ((paux=(char *)strchr(ptemp,',')) == NULL)
		return PROBLEM;
	*paux='\0';
	y1 = atol(ptemp) * SCALE_X;
	ptemp = paux + 1;
	if ((paux=(char *)strchr(ptemp,',')) == NULL)
		return PROBLEM;
	*paux='\0';
	x2 = atol(ptemp) * SCALE_X;
	ptemp = paux + 1;
	y2 = atol(ptemp) * SCALE_X;

	icon_line = addiconline(icon_gate, x1, y1, x2, y2);

	if (icon_line == NULL)
		return PROBLEM;
	else
		return OK;
}

#ifdef __STDC__
int read_ai_icon_shape (FILE * in, char * buf, int * i, IconGate_list * icon_gate)
#else
int read_ai_icon_shape (in, buf, i, icon_gate)
FILE * in;
char * buf;
int * i;
IconGate_list * icon_gate;
#endif
{
	char * paux, *ptemp;
	int nbcomp, q;
	long x, y;
	char type;
	IconShape_list*	icon_shape = NULL;
	IconComp_list*	comp = NULL, *ctmp;

/* read number of components */
	nbcomp = atoi(buf+2);
/* read components */
	for (q = 0; q < nbcomp; q++)
	{
		if (fgets(buf, ICON_BUFSIZE, in) == NULL)
			return PROBLEM;
		(*i) ++;

		if (buf[0] != 'P')
		{
			fprintf(stderr, "\n*** Icon Error *** loadicon (ai) impossible : Invalid number of components, line : %d\n", *i);
			while(comp != NULL)
			{
				ctmp = comp;
				comp = ICONSHAPE_NEXTCOMP(comp);
				free(ctmp);
			}
			return PROBLEM;
		}

		if ((paux=(char *)strchr(buf,',')) == NULL)
			return PROBLEM;
		*paux='\0';
		x = atol(buf+2) * SCALE_X;
		ptemp = paux + 1;
		if ((paux=(char *)strchr(ptemp,',')) == NULL)
			return PROBLEM;
		*paux='\0';
		y = atol(ptemp) * SCALE_X;
		paux++;
		type = aiConvType(*paux);
		
		comp = addiconcomp(comp, type, x, y);
		if (comp == NULL)
			return PROBLEM;
	}

	comp = (IconComp_list *)reverse((chain_list *)comp);
	icon_shape = addiconshape(icon_gate, comp);
	
	if (icon_shape == NULL)
		return PROBLEM;
	else
		return OK;
}

#ifdef __STDC__
int read_ai_icon_circle (char * buf, IconGate_list * icon_gate)
#else
int read_ai_icon_circle (buf, icon_gate)
char * buf;
IconGate_list * icon_gate;
#endif
{
	char * paux, *ptemp;
	long x, y, width, height;
	IconCircle_list*	icon_circle;
	
	if ((paux=(char *)strchr(buf,',')) == NULL)
		return PROBLEM;
	*paux='\0';
	x = atol(buf+2) * SCALE_X;
	ptemp = paux + 1;
	if ((paux=(char *)strchr(ptemp,',')) == NULL)
		return PROBLEM;
	*paux='\0';
	y = atol(ptemp) * SCALE_X;
	ptemp = paux + 1;
	if ((paux=(char *)strchr(ptemp,',')) == NULL)
		return PROBLEM;
	*paux='\0';
	width = atol(ptemp) * SCALE_X;
	ptemp = paux + 1;
	height = atol(ptemp) * SCALE_X;

	icon_circle = addiconcircle(icon_gate, x, y, width, height);

	if (icon_circle == NULL)
		return PROBLEM;
	else
		return OK;
}

#ifdef __STDC__
int read_ai_icon_arc (char * buf, IconGate_list * icon_gate)
#else
int read_ai_icon_arc (buf, icon_gate)
char * buf;
IconGate_list * icon_gate;
#endif
{
	char * paux, *ptemp;
	long x, y, width, height, angle1, angle2;
	IconArc_list*	icon_arc;
	
	if ((paux=(char *)strchr(buf,',')) == NULL)
		return PROBLEM;
	*paux='\0';
	x = atol(buf+2) * SCALE_X;
	ptemp = paux + 1;
	if ((paux=(char *)strchr(ptemp,',')) == NULL)
		return PROBLEM;
	*paux='\0';
	y = atol(ptemp) * SCALE_X;
	ptemp = paux + 1;
	if ((paux=(char *)strchr(ptemp,',')) == NULL)
		return PROBLEM;
	*paux='\0';
	width = atol(ptemp) * SCALE_X;
	ptemp = paux + 1;
	if ((paux=(char *)strchr(ptemp,',')) == NULL)
		return PROBLEM;
	*paux='\0';
	height = atol(ptemp) * SCALE_X;
	ptemp = paux + 1;
	if ((paux=(char *)strchr(ptemp,',')) == NULL)
		return PROBLEM;
	*paux='\0';
	angle1 = atol(ptemp) * SCALE_X;
	ptemp = paux + 1;
	angle2 = atol(ptemp) * SCALE_X;

	icon_arc = addiconarc(icon_gate, x, y, width, height, angle1, angle2);

	if (icon_arc == NULL)
		return PROBLEM;
	else
		return OK;
}

/*****************************************************************/
/*               IconGate.                                       */
/*****************************************************************/

#ifdef __STDC__
int read_ai_icon (char * name, IconGate_list * icon_gate)
#else
int read_ai_icon (name, icon_gate)
char * name;
IconGate_list * icon_gate;
#endif
{
	FILE * input_file = NULL;
	char buf[ICON_BUFSIZE];
	char * paux;
	int i, status = OK, error = OK;

	ICONGATE_ISDEFAULT(icon_gate) = 0; /* This icon is not a default icon. */
	ICONGATE_SCALE(icon_gate) = 1.;
	ICONGATE_BITMAP(icon_gate) = (char *) 0;
	ICONGATE_NEXT (icon_gate) = (IconGate_list*) 0;
	ICONGATE_USER (icon_gate) = (struct ptype*) 0;
	ICONGATE_MODELNAME (icon_gate) = (char *) 0;
	ICONGATE_CONNECTORS (icon_gate) = (IconCon_list*) 0;
	ICONGATE_LINES(icon_gate) = (IconLine_list*) 0;
	ICONGATE_SHAPES(icon_gate) = (IconShape_list*) 0;
	ICONGATE_CIRCLES(icon_gate) = (IconCircle_list*) 0;
	ICONGATE_ARCS(icon_gate) = (IconArc_list*) 0;

	if ((input_file = mbkfopen(name, ICON_IN, READ_TEXT)) == NULL)
	{
		(void)fprintf(stderr,"\n*** Icon Error *** loadicon (ai) impossible : Unable to load file %s.%s\n",
					  name, ICON_IN);
		return PROBLEM;
	}
	

/* Read V header */
	(void)fgets(buf,ICON_BUFSIZE,input_file);
	i=0;
	(void)sscanf(buf,"V ALLIANCE : %d",&i);
	if (i!=2)
		{
		(void)fprintf(stderr,"\n*** Icon Error *** loadicon (ai) impossible : Unable to load file %s.%s, too old version\n",
					  name, ICON_IN);
		fclose (input_file);
		return PROBLEM;
		}
/* Read H header */
	(void)fgets(buf,ICON_BUFSIZE,input_file);
	if (buf[0]!='H')
		{
		(void)fprintf(stderr,"\n*** Icon Error *** loadicon (ai) impossible : Line 2 unexpected, header needed\n");
		fclose (input_file);
		return PROBLEM;
		}
	if ((paux=(char *)strchr(buf,',')) == NULL)
		{
		(void)fprintf(stderr,"\n*** Icon Error *** loadicon (ai) impossible : Syntax error line 2\n");
		fclose (input_file);
		return PROBLEM;
		}
	*paux='\0';
/* control the name */
	if (strcmp(buf+2,name)!=0)
		{
		(void)fprintf(stderr,"\n*** Icon Error *** loadicon (ai) impossible : Invalid name, line : 2\n");
		fclose (input_file);
		return PROBLEM;
		}
	paux++;
/* control file type */
	if (*paux!='I')
		{
		(void)fprintf(stderr,"\n*** Icon Error *** loadicon (ai) impossible : Bad file type\n");
		fclose (input_file);
		return PROBLEM;
		}

	for (i = 3;; i++)
	{
		if (fgets(buf, ICON_BUFSIZE, input_file) == NULL)
		{
			fprintf(stderr, "\n*** Icon Error *** loadicon (ai) impossible : Syntax error line %d\n", i);
			fclose (input_file);
			return PROBLEM;
		}
		/* skip comments */
		if (buf[0] == '#')
			continue;
		/* End of file */
		if (strncmp(buf, "EOF", 3) == 0)
			break;
		/* analyse other ligne */
		switch (buf[0])
		{
			case 'B' :
				if (read_ai_icon_boundingbox(buf, icon_gate) == PROBLEM)
					error = PROBLEM;
				break;
			case 'M' :
				if (read_ai_icon_model(buf, icon_gate) == PROBLEM)
					error = PROBLEM;
				break;
			case 'I' :
				if (read_ai_icon_insname(buf, icon_gate) == PROBLEM)
					error = PROBLEM;
				break;
			case 'T' :
				if (read_ai_icon_label(buf, icon_gate) == PROBLEM)
					error = PROBLEM;
				break;
			case 'C' :
				if (read_ai_icon_connector(buf, icon_gate) == PROBLEM)
					error = PROBLEM;
				break;
			case 'L' :
				if (read_ai_icon_line(buf, icon_gate) == PROBLEM)
					error = PROBLEM;
				break;
			case 'S' :
				if (read_ai_icon_shape(input_file, buf, &i, icon_gate) == PROBLEM)
					error = PROBLEM;
				break;
			case 'R' :
				if (read_ai_icon_circle(buf, icon_gate) == PROBLEM)
					error = PROBLEM;
				break;
			case 'A' :
				if (read_ai_icon_arc(buf, icon_gate) == PROBLEM)
					error = PROBLEM;
				break;
			case 'P' :
				fprintf(stderr, "\n*** Icon Error *** loadicon (ai) impossible : Invalid number of components, line : %d\n", i);
				status = PROBLEM;
				break;
			default :
				error = PROBLEM;
				break;
		}
		if (error == PROBLEM)
		{
			fprintf (stderr, "\n*** Icon Error *** loadicon (ai) impossible : Syntax error line %d\n", i);
			error = OK;
			status = PROBLEM;
		}
	}
	
	ICONGATE_MODELNAME (icon_gate) = name;
	fclose (input_file);
  
	return status;
}

#ifdef __STDC__
IconGate_list * loadaiicon(char * name)
#else
IconGate_list * loadaiicon(name)
char * name;
#endif
{
	IconGate_list * newicon;
	char * iconname;
	
	/* verify if icon allready exist */
	iconname = namealloc(name);
	if (iconname == NULL)
	{
		fprintf(stderr, "*** Icon Error *** loadicon (ai) impossible : Unable to allocate icon name \"%s\"\n", name);
		return NULL;
	}
	for(newicon = HEAD_ICON; newicon; newicon = ICONGATE_NEXT(newicon))
		if (iconname == ICONGATE_MODELNAME(newicon))
			return NULL;
	
	/* create icon */
	newicon = (IconGate_list*)malloc(sizeof(IconGate_list));
	if (newicon == NULL)
	{
		fprintf(stderr, "*** Icon Error *** loadicon (ai) impossible : Unable to allocate icon \"%s\"\n", name);
		return NULL;
	}
	if (read_ai_icon(iconname, newicon) == PROBLEM)
	{
		IconCon_list * iconcon;
		IconLine_list * iconline;
		IconShape_list * iconshape;
		IconComp_list * iconcomp;
		IconCircle_list * iconcircle;
		IconArc_list * iconarc;

		while (ICONGATE_CONNECTORS(newicon))
		{
			iconcon = ICONGATE_CONNECTORS(newicon);
			ICONGATE_CONNECTORS(newicon) = ICONCON_NEXT(iconcon);
			free(iconcon);
		}
		while (ICONGATE_LINES(newicon))
		{
			iconline = ICONGATE_LINES(newicon);
			ICONGATE_LINES(newicon) = ICONLINE_NEXT(iconline);
			free(iconline);
		}
		while (ICONGATE_SHAPES(newicon))
		{
			iconshape = ICONGATE_SHAPES(newicon);
			ICONGATE_SHAPES(newicon) = ICONSHAPE_NEXT(iconshape);
			while(ICONSHAPE_FIRSTCOMP(iconshape))
			{
				iconcomp = ICONSHAPE_FIRSTCOMP(iconshape);
				ICONSHAPE_FIRSTCOMP(iconshape) = ICONSHAPE_NEXTCOMP(iconcomp);
				free(iconcomp);
			}
			free(iconshape);
		}
		while (ICONGATE_CIRCLES(newicon))
		{
			iconcircle = ICONGATE_CIRCLES(newicon);
			ICONGATE_CIRCLES(newicon) = ICONCIRCLE_NEXT(iconcircle);
			free(iconcircle);
		}
		while (ICONGATE_ARCS(newicon))
		{
			iconarc = ICONGATE_ARCS(newicon);
			ICONGATE_ARCS(newicon) = ICONARC_NEXT(iconarc);
			free(iconarc);
		}
		free(newicon);
		return NULL;
	}
	
	ICONGATE_NEXT(newicon) = HEAD_ICON;
	HEAD_ICON = newicon;
	return newicon;
}
