/*******************************************************************************
* mbk : vti parser netlist view : hns & fne formats v7r5                       *
*                                                                              *
* Based upon material provided by Alain Greiner in 1990, in lex and yacc       *
*                                                                              *
* version 0.0 written by Hichang Li in june 1991 under the supervision of      *
*             Frederic Petrot                                                  *
* version n.x is a rewitting and update of version 0.0 written by Frederic     *
*             Petrot on september 1991                                         *
*                                                                              *
* New versions are mostly bug corrections, or standardization matters and are  *
* done by Frederic Petrot, since middle 1990.                                  *
*                                                                              *
* version : 4.04                                                               *
* date    : 03/08/92                                                           *
*******************************************************************************/

#ident "@(#)vti logical views parser version 4.04"

#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include MUT_H
#include MLO_H
#include MLU_H

#define LSIZE 16384 /* max line size for vfgets */

enum {SYNTAX_ERROR, NET_ERROR, OPEN_ERROR, PARSE_ERROR, CLOSE_ERROR,
		NAME_ERROR};

/*******************************************************************************
* hns_error : generic error routine for vtiloadlofig function                  *
*******************************************************************************/
static void hns_error(type, name, line, string, parameter)
int type;
long line, parameter;
char *name, *string;
{
	(void)fflush(stdout);
	(void)fprintf(stderr, "*** mbk error ***\n");
	switch (type) {
		case SYNTAX_ERROR :
			(void)fprintf(stderr, "syntax error");
			break;
		case NET_ERROR :
			(void)fprintf(stderr, "external connector %s on signal %ld",
								string, parameter);
			(void)fprintf(stderr, " is internally joined with an other");
			(void)fprintf(stderr, " external connector with an other name");
			break;
		case OPEN_ERROR :
			(void)fprintf(stderr, "can't open file : %s", name);
			break;
		case PARSE_ERROR :
			(void)fprintf(stderr, "abnormal parsing for : %s", name);
			break;
		case CLOSE_ERROR :
			(void)fprintf(stderr, "can't close file : %s", name);
			break;
		case NAME_ERROR :
			(void)fprintf(stderr, "name syntax error");
			break;
	}
	if (line)
		(void)fprintf(stderr, "\nvtiloadlofig : parsing file %s.%s line %d\n",
						name, IN_LO, line);
	else
		(void)fprintf(stderr, "\nvtiloadlofig : parsing file %s.%s\n",
						name, IN_LO);
	EXIT(1);
}

/*******************************************************************************
* vfgets: read a line of a file to a buffer, the line beeing size max or end   *
* with a \n. In order to properly treat vti line breaks, the -\n pattern is    *
* recognized and ignored                                                       *
*******************************************************************************/
static char *vfgets(str, size, iob)
char *str;
int size;
FILE *iob;
{
register char *cs;
register c;

	cs = str;
	while (--size > 0 && (c = getc(iob)) != EOF) {
		if ((*cs++ = c) == '-') {
			if ((c = getc(iob)) == '\n') {
				*cs--;
			} else
				(void)ungetc(c ,iob);
		} else if (c == '\n')
			break;
	}
	*cs = '\0';
	return (c == EOF && cs == str) ? (char *)NULL : str;
}

/*******************************************************************************
* shift : shift a float 3 times to give a long in ascii                        *
*******************************************************************************/
#define shift(pt) \
	if (*(pt + 1) == '\0') { \
		*pt = '0'; \
		*(pt + 1) = '0'; \
		*(pt + 2) = '0'; \
		*(pt + 3) = '\0'; \
	} else if (*(pt + 2) == '\0') { \
		*pt = *(pt + 1); \
		*(pt + 1) = '0'; \
		*(pt + 2) = '0'; \
		*(pt + 3) = '\0'; \
	} else if (*(pt + 3) == '\0') { \
		*pt = *(pt + 1); \
		*(pt + 1) = *(pt + 2); \
		*(pt + 2) = '0'; \
		*(pt + 3) = '\0'; \
	} else { \
		*pt = *(pt + 1); \
		*(pt + 1) = *(pt + 2); \
		*(pt + 2) = *(pt + 3); \
		*(pt + 3) = '\0'; \
	}

/*******************************************************************************
* stol : convert a string to a long                                            *
*******************************************************************************/
static long	stol(token)
char	*token;
{
register char *pt;

	if ((pt = strchr(token, '.')) == (char *)NULL)
		return (long)(SCALE_X * atol(token));
	else {
		shift(pt);
		return (long)(SCALE_X * atol(token) / 1000);
	}
}

/*******************************************************************************
* checkname : check for busses                                                 *
*******************************************************************************/
static char *checkname(name)
char *name;
{
char *s, *t;

   s = t = name;
   while (*t) {
      if (*t == '[')
         *t = ' ';
      else if (*t == ']')
         if (*(++t) == '\0') /* ok, it's finished */
				goto end;
         else if (*t == '[') /* multiple array */
            continue;
      *s++ = *t++;
   }
end:
	*s = '\0';
	return name;
}

/*******************************************************************************
* function env()                                                               *
*******************************************************************************/
static void env(tn, tp)
char *tn, *tp;
{
char *s, *getenv();

	s = getenv("MBK_VTI_TN");
	*tn = s ? *s : 'e';
	if (islower(*tn))
		*tn = toupper(*tn);
	s = getenv("MBK_VTI_TP");
	*tp = s ? *s : 'p';
	if (islower(*tp))
		*tp = toupper(*tp);
}

/* erase or change model connector names :
   since some twice declared connectors are supposed to be merged or split,
   do it for fun, Fred! */
modelandinstanceconnectorcheck(fig)
lofig_list *fig;
{
loins_list *li;
locon_list *lci1, *lci2, **delete;
chain_list *pt;
long index;
#define TOBEINDEXED 0x1

	for (li = fig->LOINS; li; li = li->NEXT) {
		li->LOCON = (locon_list *)reverse((chain_list *)li->LOCON);
		for (lci1 = li->LOCON; lci1; lci1 = lci1->NEXT)
			lci1->USER = (ptype_list *)NULL;
		for (lci1 = li->LOCON; lci1; lci1 = lci1->NEXT) {
			if (lci1->NAME == (char *)NULL)
				continue;
			for (lci2 = lci1->NEXT; lci2; lci2 = lci2->NEXT) {
				/* different names, ok */
				if (lci1->NAME !=  lci2->NAME)
					continue;
				/* same name, same signal, lets delete the redundant one */
				if (lci1->SIG == lci2->SIG)
					lci2->NAME = (char *)NULL;
				else {
				/* that sucks :
				   the connectors should be indexed, with the same strategy than
				   the parser uses for figure. */
					lci1->USER = (ptype_list *)addchain((chain_list *)lci1->USER,
																		(void *)lci2);
					lci2->NAME = (char *)NULL;
					lci2->USER = (ptype_list *)TOBEINDEXED;
				}
			}
		}
		for (delete = &li->LOCON; *delete != NULL;) {
			if ((*delete)->NAME == NULL) {
				lci1 = (*delete)->NEXT;
				if ((*delete)->USER != (ptype_list *)TOBEINDEXED)
					mbkfree((void *)*delete);
				*delete = lci1;
			} else
				delete = &(*delete)->NEXT;
		}
		index = 0;
		li->LOCON = (locon_list *)reverse((chain_list *)li->LOCON);
		for (lci1 = li->LOCON; lci1; lci1 = lci1->NEXT) {
			for (pt = (chain_list *)lci1->USER; pt; pt = pt->NEXT) {
				lci2 = (locon_list *)pt->DATA;
				lci2->NAME = nameindex(lci1->NAME, ++index);
				lci2->NEXT = li->LOCON;
				lci2->USER = (ptype_list *)NULL;
				li->LOCON = lci2;
			}
			if ((chain_list *)lci1->USER) {
				lci1->NAME = nameindex(lci1->NAME, 0L);
				freechain((chain_list *)lci1->USER);
				lci1->USER = (ptype_list *)NULL;
			}
		}
	}
}

/*******************************************************************************
*        logical parser : vti2mbk                                              *
*******************************************************************************/
static int parse(fig, mode, in, fname)
lofig_list *fig;
char mode;
FILE *in;
char *fname;
{
char line[LSIZE+1];
char *t1, *t2, *t3, *t4, *t5;             /* pointers to token on a line */
char *t6, *t7, *t8, *t9, *t10;      /* of vti file */
char s[100];  /* intermediate string to process tokens */
long l1, l2, l3, l4;  /* results from strtol */
float f; /* only used for capacitances */
chain_list *join = (chain_list *)NULL; /* must be initialized */
lofig_list *model = (lofig_list *)NULL; /* must be initialized */
num_list *ylist = (num_list *)NULL; /* must be initialized */
long i = 1L; /* line number */
static char tn, tp;

	if (!tn) /* or tp, who cares? */
		env(&tn, &tp);

	while (1) {
		i++;
		if (vfgets(line, LSIZE, in) == (char *)NULL)
			hns_error((int)SYNTAX_ERROR, fname, (long)i, (char *)NULL, 0L);
		switch (line[0]) {
			case '#' : /* comment */
			case '\{' : /* comment */
			case ' ' : /* empty line in vti file */
			case ';' : /* empty line in vti file */
			case 'A' :
			case 'B' :
				break;
			case 'C' : /* C INT NOP NOP cap INT INT ; */
				if (mode != 'P') {
					t1 = strtok(line + 2, " \n\t\"");
					l1 = atol(t1);
					t2 = strtok((char *)NULL, " \n\t\"");
					t3 = strtok((char *)NULL, " \n\t\"");
					t4 = strtok((char *)NULL, " \n\t\"");
					(void)strcpy(s, t4);
					f = atof(s);
					t5 = strtok((char *)NULL, " \n\t\"");
					l3 = atol(t5);
					t6 = strtok((char *)NULL, " \n\t\"");
					l4 = atol(t6);
					/* capacitance :
					   units are picofarads inside vti logical formats.
					   add capacitance on both signals.
						0 is a linear, wire, capacitance,
						1 is a grid capacitance,
					   2-5 are sidewall and surface diffusion capacitances
					   6 is diaphonic capacitances. */
					if (l1 != 1) {
						addcapa(givelosig(fig, (long)l3), f);
						addcapa(givelosig(fig, (long)l4), f);
					}
				}
				break;
			case 'E': /* E ; */
				{
				long	index;
				loins_list *ptins;
				losig_list *ptsig1, *ptsig2;
				chain_list *pt1, *pt2;
				locon_list *ptcon, *c1, *c2, *next, **delete;
				lotrs_list *pttrs;
				num_list *pn;

				/* actually processes the joins statments */
				for (pt1 = join; pt1; pt1 = pt1->NEXT) {
					ptsig1 = (losig_list *)((chain_list *)pt1->DATA)->DATA;
					for (pt2 = (chain_list *)((chain_list *)pt1->DATA)->NEXT; pt2;
							pt2 = pt2->NEXT) {
						ptsig2 = (losig_list *)pt2->DATA;
						for (ptcon = fig->LOCON; ptcon; ptcon = ptcon->NEXT) {
							if (ptcon->SIG == ptsig2) {
								ptcon->SIG = ptsig1;
								/* flag :
								   either two external connectors with different names
								   are on the same net or a join with a signal of 
								   a user linked connector takes place. */
								ptcon->ROOT = (void *)NULL;
							}
							for (c1 = (locon_list *)ptcon->USER; c1; c1 = c1->NEXT)
								if (c1->SIG == ptsig2)
									c1->SIG = ptsig1;
						}
						for (ptins = fig->LOINS; ptins; ptins = ptins->NEXT)
							for (ptcon = ptins->LOCON; ptcon; ptcon = ptcon->NEXT)
								if (ptcon->SIG == ptsig2)
									ptcon->SIG = ptsig1;
						for (pttrs = fig->LOTRS; pttrs; pttrs = pttrs->NEXT) {
							if (pttrs->GRID->SIG == ptsig2)
								pttrs->GRID->SIG = ptsig1;
							if (pttrs->DRAIN->SIG == ptsig2)
								pttrs->DRAIN->SIG = ptsig1;
							if (pttrs->SOURCE->SIG == ptsig2)
								pttrs->SOURCE->SIG = ptsig1;
						}
						(void)addcapa(ptsig1, ptsig2->CAPA);
						(void)dellosig(fig, ptsig2->INDEX);
					}
				}
				/* changes a ptcon->ROOT to the figure value if it is a single
				   external connector on the net.
				   the order of the joins implies this verification, since I shall
				   no erase a unique external connector. */
				for (c1 = fig->LOCON; c1; c1 = c1->NEXT) {
					if (c1->ROOT == (void *)NULL) {
						for (c2 = c1->NEXT; c2; c2 = c2->NEXT)
							/* is c1 on a net used by an other connector ? */
							if (c2->SIG == c1->SIG)
								break;
						if (!c2)
							c1->ROOT = (void *)fig;
					}
				}
				for (pt1 = join; pt1; pt1 = pt1->NEXT)
					freechain((chain_list *)(pt1->DATA));
				freechain((chain_list *)pt1);
	
				/* connectors with same names */
				for (ptcon = fig->LOCON; ptcon; ptcon = ptcon->NEXT) {
					if (ptcon->USER != (ptype_list *)NULL) {
						for (c1 = (locon_list *)ptcon->USER; c1->NEXT; c1 = c1->NEXT)
							for (c2 = c1->NEXT; c2; c2 = c2->NEXT)
								if (c1->SIG == c2->SIG)
									c2->NAME = NULL; /* to be deleted */
						for (delete = (locon_list **)&ptcon->USER; *delete != NULL;)
							if ((*delete)->NAME == NULL) {
								c1 = (*delete)->NEXT;
								mbkfree((void *)*delete);
								*delete = c1;
							} else
								delete = &(*delete)->NEXT;
						index = 0;
						for (c1 = (locon_list *)ptcon->USER; c1; c1 = next) {
							if (ptcon->SIG != c1->SIG) {
								next = c1->NEXT;
								c1->NAME = nameindex(ptcon->NAME, ++index);
								c1->NEXT = fig->LOCON;
								fig->LOCON = c1;
							} else {
								next = c1->NEXT;
								mbkfree((void *)c1);
							}
						}
						if (index)
							ptcon->NAME = nameindex(ptcon->NAME, 0L);
						ptcon->USER = (ptype_list *)NULL;
					}
				}

				/* destroy the trhu routes connectors and signals */
				for (pn = ylist; pn; pn = pn->NEXT)
					for (delete = &fig->LOCON; *delete != NULL;)
						if ((*delete)->SIG->INDEX == pn->DATA) {
							c1 = (*delete)->NEXT;
							mbkfree((void *)*delete);
							*delete = c1;
						} else
							delete = &(*delete)->NEXT;
				for (pn = ylist; pn; pn = pn->NEXT)
					(void)dellosig(fig, pn->DATA);
				freenum(ylist);

				for (ptcon = fig->LOCON; ptcon; ptcon = next)
					if (ptcon->ROOT != (void *)NULL)
						next = ptcon->NEXT;
					else { /* let's delete the connector */
						/* if one wants a warning only, later on ??? */
						/*
						fputs("*** mbk warning *** in vti logical parser\n", stderr);
						fprintf(stderr, "deleted external connector %s on signal %ld",
									ptcon->NAME, ptcon->SIG->INDEX);
						fprintf(stderr, " in figure %s\n", fig->NAME);
						fputs("because two external connectors can't be", stderr);
						fputs(" on the same net\n", stderr);
						if (ptcon == fig->LOCON)
							next = fig->LOCON = ptcon->NEXT;
						else
							next = ptcon->NEXT;
						mbkfree((void *)ptcon);
						*/
						/* expected to fail now. let's see tomorrow */
						hns_error((int)NET_ERROR, fname, (long)i, ptcon->NAME,
										ptcon->SIG->INDEX);
					}

				/* for Marc & Payam :
				   since some guys use strange stuff uncompatible with mbk,
				   I must as usual transform all that bullshit into mbk. */
				modelandinstanceconnectorcheck(fig);
				/*  suppress phantoms of figures */
				freelomodel(model);

				/* successfull exit */
				return 0;
				}
			case 'G' : /* G INT name ; */
				if (mode != 'P') {
				losig_list *ptsig;
					t1 = strtok(line + 2, " \n\t\"@");
					l1 = atol(t1);
					t2 = strtok((char *)NULL, " \n\t\"@;");
					for (ptsig = fig->LOSIG; ptsig; ptsig = ptsig->NEXT)
						if (ptsig->INDEX == (long)l1) {
							ptsig->NAMECHAIN = addchain(ptsig->NAMECHAIN,
					     									(void *)namealloc(checkname(t2)));
							break;
						}
					if (ptsig == (losig_list *)NULL) 
						(void)addlosig(fig, (long)l1, addchain((chain_list *)NULL,
											(void *)t2), INTERNAL, 0.0);
				}
				break;
			case 'H' : /* H INT ; */
				break;
			case 'I' : /* I name name name | numlist | numlist ; */
				if (mode != 'P') {
				num_list *pnlist1 = (num_list *)NULL, *pnlist2 = (num_list *)NULL;
				char s2[100];
				char s3[100];

					if (strchr(line + 2, ';') != (char *)NULL) {
						t1 = strtok(line + 2, " \n\t\"@");
						t2 = strtok((char *)NULL, " \n\t\"@");
						(void)strcpy(s2, t2);
						t3 = strtok((char *)NULL, " \n\t\"@");
						(void)strcpy(s3, t3);
						t4 = strtok((char *)NULL, " \n\t\"@");
						t5 = strtok((char *)NULL, " \n\t\"@");
						if (*t5 == '|')
							pnlist1 = (num_list *)NULL;
						else {
							if (*t5 == '*')
								pnlist1 = addnum((num_list *)NULL, 0L);
							else
								pnlist1 = addnum((num_list *)NULL, atol(t5));
							while (*(t5 = strtok((char *)NULL, " \n\t\"@")) != '|') {
								if (*t5 == '*')
									pnlist1 = addnum(pnlist1, 0L);
								else
									pnlist1 = addnum(pnlist1, atol(t5));
							}
						}
						t6 = strtok((char *)NULL, " \n\t\"@;");
						if (t6 == (char *)NULL)
							pnlist2 = (num_list *)NULL;
						else {
							if (*t6 == '*')
								pnlist2 = addnum((num_list *)NULL, 0L);
							else
								pnlist2 = addnum((num_list *)NULL, atol(t6));
							while ((t6 = strtok((char *)NULL, " \n\t\"@;"))
									!= (char *)NULL) {
								if (*t6 == '*')
									pnlist2 = addnum(pnlist2, 0L);
								else
									pnlist2 = addnum(pnlist2, atol(t6));
							}
						}
					} else
						hns_error((int)SYNTAX_ERROR, fname, (long)i, (char *)NULL, 0L);
					{
					chain_list *ptchain = (chain_list *)NULL;
					losig_list *ptsig   = (losig_list *)NULL;
					num_list   *ptnum   = (num_list *)NULL;
					for (ptnum = pnlist2; ptnum; ptnum = ptnum->NEXT) {
						ptsig = givelosig(fig, ptnum->DATA);
						ptchain = addchain(ptchain, (void *)ptsig);
					}
					ptchain = reverse(ptchain);
					freenum(pnlist2);
					freenum(pnlist1); /* no more parameters */
					(void)addloins(fig, s3, getlomodel(model, s2), ptchain);
					}
				}
				break;
			case 'J' : /* J INT INT ; */
				{
				losig_list *ptsig1, *ptsig2;
				chain_list *pt, *merge, *data;
				char merged = 0; /* avoid a goto, is it necessary? */
				t1 = strtok(line + 2, " \n\t\"@");
				l1 = atol(t1);
				t2 = strtok((char *)NULL, " \n\t\"@;");
				l2 = atol(t2);
				ptsig1 = givelosig(fig, (long)l1);
				ptsig2 = givelosig(fig, (long)l2);
				/* by construction it may only merge once */
				for (merge = join; merge && !merged; merge = merge->NEXT)
					for (data = (chain_list *)merge->DATA; data && !merged;
								data = data->NEXT)
						if (data->DATA == (void *)ptsig1) {
							merge->DATA = (void *)append(merge->DATA,
											addchain((chain_list *)NULL, (void *)ptsig2));
							merged = 1;
						} else if (data->DATA == (void *)ptsig2) {
							merge->DATA = (void *)append(merge->DATA,
											addchain((chain_list *)NULL, (void *)ptsig1));
							merged = 1;
						}
				if (!merged) {
					pt = addchain((chain_list *)NULL, (void *)ptsig1);
					pt = addchain(pt, (void *)ptsig2);
					join = addchain(join, (void *)pt);
				}
				}
				break;
			case 'M' : /* M name name | strlist | strlist | numlist ; */
				if (mode != 'P') {
				chain_list *slist2 = (chain_list *)NULL, *pt;

					t1 = strtok(line + 2, " \n\t\"@");
					t2 = strtok((char *)NULL, " \n\t\"@");
					(void)strcpy(s, t2);
					t3 = strtok((char *)NULL, " \n\t\"@");     /* the seperator | */
					if (*t3 != '|')
						hns_error((int)SYNTAX_ERROR, fname, (long)i, (char *)NULL, 0L);
					/* the first strlist is to be skipped */
					do {
						t4 = strtok((char *)NULL, " \n\t\"@");
						if (t4 == (char *)NULL)
							hns_error((int)SYNTAX_ERROR, fname,
											(long)i, (char *)NULL, 0L);
					} while(*t4 != '|');
					/* the second one contains the connectors name and order */
					t4 = strtok((char *)NULL, " \n\t\"@");
					while(*t4 != '|') {
						if (t4 == (char *)NULL)
							hns_error((int)SYNTAX_ERROR, fname,
											(long)i, (char *)NULL, 0L);
						slist2 = addchain(slist2, (void *)namealloc(checkname(t4)));
						t4 = strtok((char *)NULL, " \n\t\"@");
					}

					model = addlomodel(model, s);
					slist2 = reverse(slist2);
					for (pt = slist2; pt; pt = pt->NEXT)
						(void)addlocon(model, (char *)pt->DATA,
											(losig_list *)NULL, 'X');
					freechain(slist2);
				}
				break;
			case 'N' : /* N INT name ; */
				if (mode != 'P') {
				losig_list *ptsig;
					t1 = strtok(line + 2, " \n\t\"@");
					l1 = atol(t1);
					t2 = strtok((char *)NULL, " \n\t\"@;");
					ptsig = givelosig(fig, (long)l1);
					ptsig->NAMECHAIN = addchain(ptsig->NAMECHAIN,
													     (void *)namealloc(checkname(t2)));
				}
				break;
			case 'P' : /* P INT name num ; */
				if (mode != 'C') {
					t1 = strtok(line + 2, " \n\t\"@");
					t2 = strtok((char *)NULL, " \n\t\"@");
					t3 = strtok((char *)NULL, " \n\t\"@;");
					/* let's keep it, just in case ... */
				}
				break;
			case 'T' : /* T name name name num num cap INT INT INT INT ; */
				if (mode != 'P') {
				char type;
					t1 = strtok(line + 2, " \n\t\"@");
					t2 = strtok((char *)NULL, " \n\t\"@[");
					t3 = strtok((char *)NULL, " \n\t\"@[,");
					t4 = strtok((char *)NULL, " \n\t\"@,]");
					t5 = strtok((char *)NULL, " \n\t\"@]");
					t6 = strtok((char *)NULL, " \n\t\"@");
					t7 = strtok((char *)NULL, " \n\t\"@");
					t8 = strtok((char *)NULL, " \n\t\"@");
					t9 = strtok((char *)NULL, " \n\t\"@");
					if (islower(*t1))
						*t1 = toupper(*t1);
					type = (*t1 == tn) ? TRANSN : TRANSP;
					(void)strcpy(s, t3);
					l1 = stol(s);
					(void)strcpy(s, t4);
					l2 = stol(s);
					if ((t10 = strtok((char *)NULL, " \n\t\"@;"))
							== (char *)NULL) {
					losig_list *ptgrid;
						ptgrid = givelosig(fig, atol(t6));
						(void)addlotrs(fig, type, 0L, 0L,
											(unsigned short)l1, (unsigned short)l2,
											0, 0, 0, 0,
											ptgrid, givelosig(fig, atol(t7)),
											givelosig(fig, atol(t8)));
						/* do not add grid capacatance anymore
						(void)addcapa(ptgrid, atof(t5));
						*/
					} else { /* T name name [num,num] num num cap INT INT INT INT; */
					losig_list *ptgrid;
						/* t11 = strtok((char *)NULL, " \n\t\"@;"); */
						ptgrid = givelosig(fig, atol(t8));
						(void)strcpy(s, t5);
						l3 = stol(s);
						(void)strcpy(s, t6);
						l4 = stol(s);
						(void)addlotrs(fig, type, l1, l2,
									(unsigned short)l3, (unsigned short)l4,
									0, 0, 0, 0,
									ptgrid, givelosig(fig, atol(t9)),
									givelosig(fig, atol(t10)));
						/* do not add grid capacatance anymore
						(void)addcapa(ptgrid, atof(t7));
						*/
					}
				}
				break;
			case 'X' : /* X INT bof name ; */
				if (mode != 'C') {
				locon_list *ptsav, *ptcon;
				losig_list *ptsig;
				char *conname;
					t1 = strtok(line + 2, " \n\t\"@");
					l1 = atol(t1);
					t2 = strtok((char *)NULL, " \n\t\"@");
					t3 = strtok((char *)NULL, " \n\t\"@;");
					while ((t4 = strtok((char *)NULL, " \n\t\"@;"))
								!= (char *)NULL)
						t3 = t4;
					conname = namealloc(checkname(t3));
					ptsig = addlosig(fig, (long)l1, addchain((chain_list *)NULL,
											(void *)conname), EXTERNAL, 0.0);
					for (ptsav = fig->LOCON; ptsav; ptsav = ptsav->NEXT)
						if (ptsav->NAME == conname)
							break;

					if (ptsav == (locon_list *)NULL)
						(void)addlocon(fig, conname, ptsig, 'X');
					 else { /* two connectors with same name  */
						ptcon = (locon_list *)mbkalloc(sizeof(locon_list));
						ptcon->SIG = ptsig;
						ptcon->ROOT = (void *)fig;
						ptcon->TYPE = EXTERNAL;
						ptcon->DIRECTION = 'X';
						ptcon->NAME = conname;
						ptcon->NEXT = (locon_list *)ptsav->USER;
						ptsav->USER = (ptype_list *)ptcon;
					}
				}
				break;
			case 'Y' : /* Y INT INT [ num , num ] [ num , num ] ; */
				t1 = strtok(line + 2, " \n\t\"@");
				t2 = strtok((char *)NULL, " \n\t\"@;");
				l2 = atol(t2);
				ylist = addnum(ylist, l2); /* create a list of thru routes */
				break;
			case 'Z' : /* Z INT name INT cap INT num num ; */
				break;
			default :
				hns_error((int)SYNTAX_ERROR, fname, (long)i, (char *)NULL, 0L);
				break;
		}
	}
}

/*******************************************************************************
* unique function accesible from this file                                     *
*******************************************************************************/
void vtiloadlofig(ptfig, figname, mode)
lofig_list *ptfig;
char *figname;
char mode;
{
FILE *in;

	/* opening file */
	if ((in = mbkfopen(figname, IN_LO, READ_TEXT)) == (FILE *)NULL)
		hns_error((int)OPEN_ERROR, figname, 0L, (char *)NULL, 0L);

	if (TRACE_MODE == 'Y')
		(void)printf("\n--- mbk --- parsing file : %s.%s in mode %c\n",
		     		figname, IN_LO, mode);

	/* parsing */
	if (parse(ptfig, mode, in, figname))
		hns_error((int)PARSE_ERROR, figname, 0L, (char *)NULL, 0L);

	if (fclose(in))
		hns_error((int)CLOSE_ERROR, figname, 0L, (char *)NULL, 0L);

	(void)strcpy(PARSER_INFO, "@(#)vti logical views parser version 4.04");
}
