/*
 * Electric(tm) VLSI Design System
 *
 * File: vhdlals.c
 * ALS Code Generator for the VHDL front-end compiler
 * Written by: Andrew R. Kostiuk, Queen's University
 * Modified 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 VHDLTOOL

#include "global.h"
#include "vhdl.h"
#include "usr.h"

extern INTBIG		vhdl_externentities, vhdl_warnflag, vhdl_target;
extern DBUNITS		*vhdl_units;
extern SYMBOLLIST	*vhdl_gsymbols;
static IDENTTABLE	*vhdl_ident_ground, *vhdl_ident_power;

/* prototypes for local routines */
static BOOLEAN vhdl_addnetlist(LIBRARY*, char*);
static void    vhdl_genfunction(char*, BOOLEAN, BOOLEAN, INTBIG);
static void    vhdl_dumpfunction(char*, char**);
static void    vhdl_genals_interface(DBINTERFACE*, char*);
static void    vhdl_genals_aport(INTBIG*, DBNAME*);

/*
Module:  vhdl_genals
------------------------------------------------------------------------
Description:
	Generate ALS target output for the created database.  Assume
	database is semantically correct.
------------------------------------------------------------------------
Calling Sequence:  vhdl_genals(lib, basenp);
------------------------------------------------------------------------
*/
void vhdl_genals(LIBRARY *lib, NODEPROTO *basenp)
{
	char *gate;
	INTBIG total;
	DBINTERFACE *top_interface, *interfacef;
	UNRESLIST *ulist;
	static char *power[] =
	{
		"gate power(p)",
		"set p=H@3",
		"t: delta=0",
		0
	};
	static char *ground[] =
	{
		"gate ground(g)",
		"set g=L@3",
		"t: delta=0",
		0
	};
	static char *pMOStran[] =
	{
		"function PMOStran(g, a1, a2)",
		"i: g, a1, a2",
		"o: a1, a2",
		"t: delta=1e-8",
		0
	};
	static char *pMOStranWeak[] =
	{
		"function pMOStranWeak(g, a1, a2)",
		"i: g, a1, a2",
		"o: a1, a2",
		"t: delta=1e-8",
		0
	};
	static char *nMOStran[] =
	{
		"function nMOStran(g, a1, a2)",
		"i: g, a1, a2",
		"o: a1, a2",
		"t: delta=1e-8",
		0
	};
	static char *nMOStranWeak[] =
	{
		"function nMOStranWeak(g, a1, a2)",
		"i: g, a1, a2",
		"o: a1, a2",
		"t: delta=1e-8",
		0
	};
	static char *inverter[] =
	{
		"gate inverter(a,z)",
		"t: delta=1.33e-9",		/* T3=1.33 */
		"i: a=L o: z=H",
		"t: delta=1.07e-9",		/* T1=1.07 */
		"i: a=H o: z=L",
		"t: delta=0",
		"i: a=X o: z=X",
		"load: a=1.0",
		0
	};
	static char *buffer[] =
	{
		"gate buffer(in,out)",
		"t: delta=0.56e-9",		/* T4*Cin=0.56 */
		"i: in=H o: out=H",
		"t: delta=0.41e-9",		/* T2*Cin=0.41 */
		"i: in=L o: out=L",
		"t: delta=0",
		"i: in=X o: out=X",
		0
	};
	static char *xor2[] =
	{
		/* input a,b cap = 0.xx pF, Tphl = T1 + T2*Cin, Tplh = T3 + T4*Cin */
		"model xor2(a,b,z)",
		"g1: xor2fun(a,b,out)",
		"g2: xor2buf(out,z)",

		"gate xor2fun(a,b,out)",
		"t: delta=1.33e-9",		/* T3=1.33 */
		"i: a=L b=H o: out=H",
		"i: a=H b=L o: out=H",
		"t: delta=1.07e-9",		/* T1=1.07 */
		"i: a=L b=L o: out=L",
		"i: a=H b=H o: out=L",
		"t: delta=0",
		"i:         o: out=X",
		"load: a=1.0 b=1.0",

		"gate xor2buf(in,out)",
		"t: delta=0.56e-9",		/* T4*Cin=0.56 */
		"i: in=H    o: out=H",
		"t: delta=0.41e-9",		/* T2*Cin=0.41 */
		"i: in=L    o: out=L",
		"t: delta=0",
		"i: in=X    o: out=X",
		0
	};
	static char *JKFF[] =
	{
		"model jkff(j, k, clk, pr, clr, q, qbar)",
		"n: JKFFLOP(clk, j, k, q, qbar)",
		"function JKFFLOP(clk, j, k, q, qbar)",
		"i: clk, j, k",
		"o: q, qbar",
		"t: delta=1e-8",
		0
	};
	static char *DFF[] =
	{
		"model dsff(d, clk, pr, q)",
		"n: DFFLOP(d, clk, q)",
		"function DFFLOP(d, clk, q)",
		"i: d, clk",
		"o: q",
		"t: delta=1e-8",
		0
	};

	vhdl_freeunresolvedlist(&vhdl_unresolved_list);
	vhdl_ident_ground = vhdl_findidentkey("ground");
	vhdl_ident_power = vhdl_findidentkey("power");

	/* print file header */
	vhdl_printoneline("#*************************************************");
	vhdl_printoneline("#  ALS Netlist file");
	vhdl_printoneline("#");
	if ((us_useroptions&NODATEORVERSION) == 0)
	{
		vhdl_printoneline("#  File Creation:    %s", timetostring(getcurrenttime()));
	}
	vhdl_printoneline("#-------------------------------------------------");
	vhdl_print("");

	/* determine top level cell which must be renamed from "basenp" */
	top_interface = vhdl_findtopinterface(vhdl_units);
	if (top_interface == NULL)
	{
		ttyputmsg(_("ERROR - Cannot find interface to rename main."));
	} else
	{
		/* clear written flag on all interfaces */
		for (interfacef = vhdl_units->interfaces; interfacef != NULL; interfacef = interfacef->next)
		{
			interfacef->flags &= ~ENTITY_WRITTEN;
		}
		vhdl_genals_interface(top_interface, basenp->cell->cellname);
	}

	/* print closing line of output file */
	vhdl_printoneline("#********* End of netlist *******************");

	/* scan unresolved references for reality inside of Electric */
	total = 0;
	for (ulist = vhdl_unresolved_list; ulist != NULL; ulist = ulist->next)
	{
		total++;
		gate = ulist->interfacef->string;

		/* first see if this is a reference to a cell in the current library */
		if (vhdl_addnetlist(el_curlib, gate))
		{
			ulist->numref = 0;
			total--;
			continue;
		}

		/* next see if this is a reference to the behavior library */
		if (lib != NOLIBRARY && lib != el_curlib)
		{
			if (vhdl_addnetlist(lib, gate))
			{
				ulist->numref = 0;
				total--;
				continue;
			}
		}

		/* now see if this is a reference to a function primitive */
		if (strcmp(gate, "PMOStran") == 0)
		{
			vhdl_dumpfunction(gate, pMOStran);
			ulist->numref = 0;
			total--;
		} else if (strcmp(gate, "pMOStranWeak") == 0)
		{
			vhdl_dumpfunction(gate, pMOStranWeak);
			ulist->numref = 0;
			total--;
		} else if (strcmp(gate, "nMOStran") == 0)
		{
			vhdl_dumpfunction(gate, nMOStran);
			ulist->numref = 0;
			total--;
		} else if (strcmp(gate, "nMOStranWeak") == 0)
		{
			vhdl_dumpfunction(gate, nMOStranWeak);
			ulist->numref = 0;
			total--;
		} else if (strcmp(gate, "inverter") == 0)
		{
			vhdl_dumpfunction(gate, inverter);
			ulist->numref = 0;
			total--;
		} else if (strcmp(gate, "buffer") == 0)
		{
			vhdl_dumpfunction(gate, buffer);
			ulist->numref = 0;
			total--;
		} else if (strncmp(gate, "and", 3) == 0 && isdigit(gate[3]))
		{
			vhdl_genfunction("and", TRUE, FALSE, atoi(&gate[3]));
			ulist->numref = 0;
			total--;
		} else if (strncmp(gate, "nand", 4) == 0 && isdigit(gate[4]))
		{
			vhdl_genfunction("and", TRUE, TRUE, atoi(&gate[4]));
			ulist->numref = 0;
			total--;
		} else if (strncmp(gate, "or", 2) == 0 && isdigit(gate[2]))
		{
			vhdl_genfunction("or", FALSE, FALSE, atoi(&gate[2]));
			ulist->numref = 0;
			total--;
		} else if (strncmp(gate, "nor", 3) == 0 && isdigit(gate[3]))
		{
			vhdl_genfunction("or", FALSE, TRUE, atoi(&gate[3]));
			ulist->numref = 0;
			total--;
		} else if (strcmp(gate, "xor2") == 0)
		{
			vhdl_dumpfunction(gate, xor2);
			ulist->numref = 0;
			total--;
		} else if (strcmp(gate, "power") == 0)
		{
			vhdl_dumpfunction(gate, power);
			ulist->numref = 0;
			total--;
		} else if (strcmp(gate, "ground") == 0)
		{
			vhdl_dumpfunction(gate, ground);
			ulist->numref = 0;
			total--;
		} else if (strcmp(gate, "jkff") == 0)
		{
			vhdl_dumpfunction(gate, JKFF);
			ulist->numref = 0;
			total--;
		} else if (strcmp(gate, "dsff") == 0)
		{
			vhdl_dumpfunction(gate, DFF);
			ulist->numref = 0;
			total--;
		}
	}

	/* print unresolved reference list if not empty */
	if (total > 0)
	{
		ttyputmsg(_("*****  UNRESOLVED REFERENCES *****"));
		for (ulist = vhdl_unresolved_list; ulist != NULL; ulist = ulist->next)
			if (ulist->numref > 0)
				ttyputmsg(_("%s, %ld time(s)"), ulist->interfacef->string, ulist->numref);
	}
}

/*
 * routine to search library "lib" for a netlist that matches "name".  If found,
 * add it to the current output netlist and return nonzero.  If not found, return false.
 */
BOOLEAN vhdl_addnetlist(LIBRARY *lib, char *name)
{
	REGISTER NODEPROTO *np;
	REGISTER char *pn, *key;
	REGISTER VARIABLE *var;
	REGISTER INTBIG len, i;

	for(np = lib->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
	{
		if (np->cellview != el_netlistalsview) continue;
		(void)initinfstr();
		for(pn = np->cell->cellname; *pn != 0; pn++)
			if (isalnum(*pn)) (void)addtoinfstr(*pn); else
				(void)addtoinfstr('_');
		key = returninfstr();
		if (namesame(name, key) != 0) continue;

		/* add it to the netlist */
		var = getvalkey((INTBIG)np, VNODEPROTO, VSTRING|VISARRAY, el_facet_message_key);
		if (var == NOVARIABLE) continue;
		len = getlength(var);
		vhdl_print("");
		for(i=0; i<len; i++) vhdl_printoneline(((char **)var->addr)[i]);
		return(TRUE);
	}
	return(FALSE);
}

/*
 * inputs cap = 0.xx pF, Tphl = T1 + T2*Cin, Tplh = T3 + T4*Cin
 */
void vhdl_genfunction(char *name, BOOLEAN isand, BOOLEAN isneg, INTBIG inputs)
{
	char modelname[20], line[20];
	REGISTER INTBIG i;

	/* generate model name */
	if (!isneg) modelname[0] = 0; else (void)strcpy(modelname, "n");
	if (isand) (void)strcat(modelname, "and"); else (void)strcat(modelname, "or");
	(void)sprintf(line, "%ld", inputs);
	(void)strcat(modelname, line);

	vhdl_print("");
	(void)initinfstr();
	(void)addstringtoinfstr("# Built-in model for ");
	(void)addstringtoinfstr(modelname);
	vhdl_printoneline(returninfstr());

	/* write header line */
	(void)initinfstr();
	(void)addstringtoinfstr("model ");
	(void)addstringtoinfstr(modelname);
	(void)addstringtoinfstr("(");
	for(i=1; i<=inputs; i++)
	{
		if (i > 1) (void)addstringtoinfstr(",");
		(void)sprintf(line, "a%ld", i);
		(void)addstringtoinfstr(line);
	}
	(void)addstringtoinfstr(",z)");
	vhdl_print(returninfstr());

	/* write function line */
	(void)initinfstr();
	(void)addstringtoinfstr("g1: ");
	(void)addstringtoinfstr(modelname);
	(void)addstringtoinfstr("fun(");
	for(i=1; i<=inputs; i++)
	{
		if (i > 1) (void)addstringtoinfstr(",");
		(void)sprintf(line, "a%ld", i);
		(void)addstringtoinfstr(line);
	}
	if (!isneg) (void)addstringtoinfstr(",out)"); else
		(void)addstringtoinfstr(",z)");
	vhdl_print(returninfstr());

	/* write buffer line if not negated */
	if (!isneg)
	{
		(void)initinfstr();
		(void)addstringtoinfstr("g2: ");
		(void)addstringtoinfstr(modelname);
		(void)addstringtoinfstr("buf(out,z)");
		vhdl_print(returninfstr());
	}

	/* write function header */
	(void)initinfstr();
	(void)addstringtoinfstr("gate ");
	(void)addstringtoinfstr(modelname);
	(void)addstringtoinfstr("fun(");
	for(i=1; i<=inputs; i++)
	{
		if (i > 1) (void)addstringtoinfstr(",");
		(void)sprintf(line, "a%ld", i);
		(void)addstringtoinfstr(line);
	}
	(void)addstringtoinfstr(",z)");
	vhdl_print(returninfstr());
	vhdl_print("t: delta=1.33e-9");		/* T3=1.33 */
	for(i=1; i<=inputs; i++)
	{
		(void)initinfstr();
		(void)sprintf(line, "i: a%ld", i);
		(void)addstringtoinfstr(line);
		if (isand) (void)addstringtoinfstr("=L o: z=H"); else
			(void)addstringtoinfstr("=H o: z=L");
		vhdl_print(returninfstr());
	}
	vhdl_print("t: delta=1.07e-9");		/* T1=1.07 */
	(void)initinfstr();
	(void)addstringtoinfstr("i:");
	for(i=1; i<=inputs; i++)
	{
		if (isand) (void)sprintf(line, " a%ld=H", i); else
			(void)sprintf(line, " a%ld=L", i);
		(void)addstringtoinfstr(line);
	}
	if (isand)  (void)addstringtoinfstr(" o: z=L"); else
		(void)addstringtoinfstr(" o: z=H");
	vhdl_print(returninfstr());
	vhdl_print("t: delta=0");
	vhdl_print("i: o: z=X");

	(void)initinfstr();
	(void)addstringtoinfstr("load:");
	for(i=1; i<=inputs; i++)
	{
		(void)sprintf(line, " a%ld=1.0", i);
		(void)addstringtoinfstr(line);
	}
	vhdl_print(returninfstr());

	/* write buffer gate if not negated */
	if (!isneg)
	{
		(void)initinfstr();
		(void)addstringtoinfstr("gate ");
		(void)addstringtoinfstr(modelname);
		(void)addstringtoinfstr("buf(in,out)");
		vhdl_print(returninfstr());
		vhdl_print("t: delta=0.56e-9");		/* T4*Cin=0.56 */
		vhdl_print("i: in=H    o: out=L");
		vhdl_print("t: delta=0.41e-9");		/* T2*Cin=0.41 */
		vhdl_print("i: in=L    o: out=H");
		vhdl_print("t: delta=0");
		vhdl_print("i: in=X    o: out=X");
	}
}

void vhdl_dumpfunction(char *name, char **model)
{
	REGISTER INTBIG i;

	vhdl_print("");
	(void)initinfstr();
	(void)addstringtoinfstr("# Built-in model for ");
	(void)addstringtoinfstr(name);
	vhdl_printoneline(returninfstr());
	for(i=0; model[i] != 0; i++) vhdl_printoneline(model[i]);
}

/*
Module:  vhdl_genals_interface
------------------------------------------------------------------------
Description:
	Recursively generate the ALS description for the specified model
	by first generating the lowest interface instantiation and working
	back to the top (i.e. bottom up).
------------------------------------------------------------------------
Calling Sequence:  vhdl_genals_interface(interfacef, name);

Name		Type			Description
----		----			-----------
interfacef	*DBINTERFACE	Pointer to interface.
name		*char			Pointer to string name of interface.
------------------------------------------------------------------------
*/
void vhdl_genals_interface(DBINTERFACE *interfacef, char *name)
{
	DBINSTANCE *inst;
	SYMBOLTREE *symbol;
	DBPORTLIST *port;
	DBAPORTLIST *aport;
	INTBIG first, generic, power_flag, ground_flag, i;
	char temp[30], *pt;
	IDENTTABLE *ident;
	DBINDEXRANGE *irange;
	DBDISCRETERANGE *drange;
	DBNAMELIST *cat;

	/* go through interface's architectural body and call generate interfaces*/
	/* for any interface called by an instance which has not been already */
	/* generated */

	/* check written flag */
	if (interfacef->flags & ENTITY_WRITTEN) return;

	/* set written flag */
	interfacef->flags |= ENTITY_WRITTEN;

	/* check all instants of corresponding architectural body */
	/* and write if non-primitive instances */
	if (interfacef->bodies && interfacef->bodies->statements)
	{
		for (inst = interfacef->bodies->statements->instances; inst != NULL; inst = inst->next)
		{
			symbol = vhdl_searchsymbol(inst->compo->name, vhdl_gsymbols);
			if (symbol == NULL)
			{
				if (vhdl_externentities)
				{
					if (vhdl_warnflag)
						ttyputmsg(_("WARNING - interface %s not found, assumed external."),
							inst->compo->name->string);
					vhdl_unresolved(inst->compo->name, &vhdl_unresolved_list);
				} else
				{
					ttyputmsg(_("ERROR - interface %s not found."), inst->compo->name->string);
				}
				continue;
			} else if (symbol->pointer == NULL)
			{
				/* Should have gate entity */
				/* should be automatically added at end of .net file */
				/* EMPTY */ 
			} else
			{
				vhdl_genals_interface((DBINTERFACE *)symbol->pointer, inst->compo->name->string);
			}
		}
	}

	/* write this interface */
	generic = 0;
	power_flag = ground_flag = FALSE;
	(void)initinfstr();
	(void)addstringtoinfstr("model ");
	for(pt = name; *pt != 0; pt++)
		if (isalnum(*pt)) (void)addtoinfstr(*pt); else
	{
		(void)addtoinfstr('_');
	}
	(void)addstringtoinfstr("(");

	/* write port list of interface */
	first = TRUE;
	for (port = interfacef->ports; port != NULL; port = port->next)
	{
		if (port->type == NULL || port->type->type == DBTYPE_SINGLE)
		{
			if (!first) (void)addstringtoinfstr(", ");
			(void)addstringtoinfstr(port->name->string);
			first = FALSE;
		} else
		{
			irange = (DBINDEXRANGE *)port->type->pointer;
			drange = irange->drange;
			if (drange->start > drange->end)
			{
				for (i = drange->start; i >= drange->end; i--)
				{
					if (!first) (void)addstringtoinfstr(", ");
					(void)addstringtoinfstr(port->name->string);
					(void)sprintf(temp, "[%ld]", i);
					(void)addstringtoinfstr(temp);
					first = FALSE;
				}
			} else
			{
				for (i = drange->start; i <= drange->end; i++)
				{
					if (!first) (void)addstringtoinfstr(", ");
					(void)addstringtoinfstr(port->name->string);
					(void)sprintf(temp, "[%ld]", i);
					(void)addstringtoinfstr(temp);
					first = FALSE;
				}
			}
		}
	}
	(void)addstringtoinfstr(")");
	vhdl_print(returninfstr());

	/* write all instances */
	if (interfacef->bodies && interfacef->bodies->statements)
	{
		for (inst = interfacef->bodies->statements->instances; inst != NULL;
			inst = inst->next)
		{
			(void)initinfstr();
			(void)addstringtoinfstr(inst->name->string);
			(void)addstringtoinfstr(": ");
			(void)addstringtoinfstr(inst->compo->name->string);
			(void)addstringtoinfstr("(");

			/* print instance port list */
			first = TRUE;
			for (aport = inst->ports; aport != NULL; aport = aport->next)
			{
				if (aport->name)
				{
					if (aport->name->type == DBNAME_CONCATENATED)
					{
						/* concatenated name */
						for (cat = (DBNAMELIST *)aport->name->pointer; cat; cat = cat->next)
						{
							ident = cat->name->name;
							if (ident == vhdl_ident_power) power_flag = TRUE; else
								if (ident == vhdl_ident_ground) ground_flag = TRUE;
							vhdl_genals_aport((INTBIG *)&first, cat->name);
						}
					} else
					{
						ident = aport->name->name;
						if (ident == vhdl_ident_power) power_flag = TRUE; else
							if (ident == vhdl_ident_ground) ground_flag = TRUE;
						vhdl_genals_aport((INTBIG *)&first, aport->name);
					}
				} else
				{
					/* check if formal port is of array type */
					if (aport->port->type && aport->port->type->type == DBTYPE_ARRAY)
					{
						irange = (DBINDEXRANGE *)aport->port->type->pointer;
						drange = irange->drange;
						if (drange->start > drange->end)
						{
							for (i = drange->start; i >= drange->end; i--)
							{
								if (!first) (void)addstringtoinfstr(", ");
								(void)sprintf(temp, "n%ld", generic++);
								(void)addstringtoinfstr(temp);
								first = FALSE;
							}
						} else
						{
							for (i = drange->start; i <= drange->end; i++)
							{
								if (!first) (void)addstringtoinfstr(", ");
								(void)sprintf(temp, "n%ld", generic++);
								(void)addstringtoinfstr(temp);
								first = FALSE;
							}
						}
					} else
					{
						if (!first) (void)addstringtoinfstr(", ");
						(void)sprintf(temp, "n%ld", generic++);
						(void)addstringtoinfstr(temp);
						first = FALSE;
					}
				}
			}
			(void)addstringtoinfstr(")");
			vhdl_print(returninfstr());
		}
	}

	/* check for power and ground flags */
	if (power_flag) vhdl_print("set power = H@3");
		else if (ground_flag) vhdl_print("set ground = L@3");
	vhdl_print("");
}

/*
Module:  vhdl_genals_aport
------------------------------------------------------------------------
Description:
	Add the actual port for a single name to the infinite string.
------------------------------------------------------------------------
Calling Sequence:  vhdl_genals_aport(first, name);

Name		Type		Description
----		----		-----------
first		*INTBIG		Addres of first flag.
name		*DBNAME		Pointer to single name.
------------------------------------------------------------------------
*/
void vhdl_genals_aport(INTBIG *first, DBNAME *name)
{
	DBINDEXRANGE *irange;
	DBDISCRETERANGE *drange;
	INTBIG i;
	char temp[30];

	if (name->type == DBNAME_INDEXED)
	{
		if (!(*first)) (void)addstringtoinfstr(", ");
		(void)addstringtoinfstr(name->name->string);
		(void)sprintf(temp, "[%ld]", ((DBEXPRLIST *)(name->pointer))->value);
		(void)addstringtoinfstr(temp);
		*first = FALSE;
	} else
	{
		if (name->dbtype && name->dbtype->type == DBTYPE_ARRAY)
		{
			irange = (DBINDEXRANGE *)name->dbtype->pointer;
			drange = irange->drange;
			if (drange->start > drange->end)
			{
				for (i = drange->start; i >= drange->end; i--)
				{
					if (!(*first)) (void)addstringtoinfstr(", ");
					(void)addstringtoinfstr(name->name->string);
					(void)sprintf(temp, "[%ld]", i);
					(void)addstringtoinfstr(temp);
					*first = FALSE;
				}
			} else
			{
				for (i = drange->start; i <= drange->end; i++)
				{
					if (!(*first)) (void)addstringtoinfstr(", ");
					(void)addstringtoinfstr(name->name->string);
					(void)sprintf(temp, "[%ld]", i);
					(void)addstringtoinfstr(temp);
					*first = FALSE;
				}
			}
		} else
		{
			if (!(*first)) (void)addstringtoinfstr(", ");
			(void)addstringtoinfstr(name->name->string);
			*first = FALSE;
		}
	}
}

#endif  /* VHDLTOOL - at top */
