/*
 * Electric(tm) VLSI Design System
 *
 * File: iovhdl.c
 * Input/output aid: VHDL input
 * Written by: Steven M. Rubin, Static Free Software
 *
 * Copyright (c) 2000 Static Free Software.
 *
 * Electric(tm) is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * Electric(tm) is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Electric(tm); see the file COPYING.  If not, write to
 * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
 * Boston, Mass 02111-1307, USA.
 *
 * Static Free Software
 * 4119 Alpine Road
 * Portola Valley, California 94028
 * info@staticfreesoft.com
 */

#include "config.h"
#if VHDLAID

#include "global.h"
#include "eio.h"
#include "edialogs.h"

#define MAXCHARS 300

INTBIG io_vhdllength;
INTBIG io_vhdlcurline;

void io_vhdlreadfile(LIBRARY *lib, FILE *io);

/*
 * Routine to read the VHDL file into library "lib".  Returns nonzero on error.
 */
INTSML io_readvhdllibrary(LIBRARY *lib)
{
	REGISTER FILE *io;
	char *pt;
	extern DIALOG us_progressdialog;

	/* get the VHDL file */
	if ((io = xopen(lib->libfile, FILETYPEVHDL, "", &pt)) == NULL)
	{
		ttyputerr("File %s not found", lib->libfile);
		return(1);
	}

	/* determine file length */
	io_vhdllength = filesize(io);
	if (io_verbose < 0 && io_vhdllength > 0)
	{
		if (DiaInitDialog(&us_progressdialog) != 0)
		{
			xclose(io);
			return(1);
		}
		DiaPercent(1, 0);
	}

	io_vhdlreadfile(lib, io);

	xclose(io);
	if (io_verbose < 0 && io_vhdllength > 0)
	{
		DiaPercent(1, 100);
		DiaDoneDialog();
	}
	return(0);
}

void io_vhdlreadfile(LIBRARY *lib, FILE *io)
{
	char *pt, *start, text[MAXCHARS], facetname[256], endtag[256];
	REGISTER INTSML save, sectionnamelen;
	enum {SECTIONNONE, SECTIONCOMPONENT, SECTIONENTITY, SECTIONARCHITECTURE} sectiontype;
	REGISTER INTBIG i, len, curLength;
	REGISTER NODEPROTO *storagefacet;
	void *stringarray;
	REGISTER VARIABLE *var;

	/* read the file */
	io_vhdlcurline = 0;
	storagefacet = NONODEPROTO;
	for(;;)
	{
		if (stopping("VHDL")) break;
		if (xfgets(text, MAXCHARS, io) != 0) break;
		io_vhdlcurline++;
		if ((io_vhdlcurline % 100) == 0)
		{
			curLength = xtell(io);
			DiaPercent(1, curLength * 100L / io_vhdllength);
		}

		if (storagefacet == NONODEPROTO)
		{
			/* scan for start of facet */
			pt = text;
			while (*pt == ' ' || *pt == '\t') pt++;
			sectiontype = SECTIONNONE;
			if (strncmp(pt, "component", (sectionnamelen = 9)) == 0)
				sectiontype = SECTIONCOMPONENT;
			else if (strncmp(pt, "entity", (sectionnamelen = 6)) == 0)
				sectiontype = SECTIONENTITY;
			else if (strncmp(pt, "architecture", (sectionnamelen = 12)) == 0)
				sectiontype = SECTIONARCHITECTURE;
			if (sectiontype != SECTIONNONE)
			{
				pt += sectionnamelen;
				if (*pt == ' ' || *pt == '\t')
				{
					while (*pt == ' ' || *pt == '\t') pt++;
					start = pt;
					while (*pt != 0 && *pt != ' ' && *pt != '\t') pt++;
					save = *pt;
					*pt = 0;
					strcpy(endtag, start);
					strcpy(facetname, start);
					*pt = (char)save;

					if (sectiontype == SECTIONARCHITECTURE)
					{
						while (*pt == ' ' || *pt == '\t') pt++;
						if (strncmp(pt, "of", 2) == 0)
						{
							pt += 2;
							while (*pt == ' ' || *pt == '\t') pt++;
							start = pt;
							while (*pt != 0 && *pt != ' ' && *pt != '\t') pt++;
							save = *pt;
							*pt = 0;
							strcpy(facetname, start);
							*pt = (char)save;
						}
					}

					for(storagefacet = lib->firstnodeproto; storagefacet != NONODEPROTO;
						storagefacet = storagefacet->nextnodeproto)
							if (namesame(facetname, storagefacet->cell->cellname) == 0 &&
								storagefacet->cellview == el_vhdlview) break;

					/* see if the facet already exists */
					if (storagefacet != NONODEPROTO)
					{
						/* already there: start with the existing VHDL */
						stringarray = newstringarray(io_aid->cluster);
						var = getvalkey((INTBIG)storagefacet, VNODEPROTO, VSTRING|VISARRAY,
							el_facet_message);
						if (var != NOVARIABLE)
						{
							len = getlength(var);
							for(i=0; i<len; i++)
								addtostringarray(stringarray, ((char **)var->addr)[i]);
							addtostringarray(stringarray, "");
						}
					} else
					{
						strcat(facetname, "{vhdl}");
						storagefacet = newnodeproto(facetname, lib);
						if (storagefacet == NONODEPROTO)
						{
							ttyputerr("Could not create facet %s", facetname);
							return;
						}
						stringarray = newstringarray(io_aid->cluster);
					}
				}
			}
			if (storagefacet == NONODEPROTO) continue;
		}

		/* save this line in the facet */
		addtostringarray(stringarray, text);

		/* see if this is the last line */
		pt = text;
		while (*pt == ' ' || *pt == '\t') pt++;
		if (strncmp(pt, "end", 3) == 0)
		{
			pt += 3;
			if (*pt == ' ' || *pt == '\t')
			{
				while (*pt == ' ' || *pt == '\t') pt++;
				switch (sectiontype)
				{
					case SECTIONCOMPONENT:
						if (strncmp(pt, "component", 9) == 0)
						{
							stringarraytotextfacet(stringarray, storagefacet, 1);
							killstringarray(stringarray);
							storagefacet = NONODEPROTO;
						}
						break;
					case SECTIONENTITY:
					case SECTIONARCHITECTURE:
						start = pt;
						while (*pt != ';' && *pt != ' ' && *pt != '\t' && *pt != 0) pt++;
						save = *pt;   *pt = 0;
						if (namesame(start, endtag) == 0)
						{
							stringarraytotextfacet(stringarray, storagefacet, 1);
							killstringarray(stringarray);
							storagefacet = NONODEPROTO;
						}
						*pt = (char)save;
						break;
					default:
						break;
				}
			}
		}
	}
}

#endif  /* VHDLAID - at top */
