1 /* -*- tab-width: 4 -*-
2  *
3  * Electric(tm) VLSI Design System
4  *
5  * File: iocifin.c
6  * Input/output tool: CIF input
7  * Written by: Robert Winstanley, University of Calgary
8  *
9  * Copyright (c) 2000 Static Free Software.
10  *
11  * Electric(tm) is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  *
16  * Electric(tm) is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with Electric(tm); see the file COPYING.  If not, write to
23  * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
24  * Boston, Mass 02111-1307, USA.
25  *
26  * Static Free Software
27  * 4119 Alpine Road
28  * Portola Valley, California 94028
29  * info@staticfreesoft.com
30  */
31 
32 #include "config.h"
33 #include "global.h"
34 #include "database.h"
35 #include "eio.h"
36 #include "usr.h"
37 #include "iocifpars.h"
38 #include "edialogs.h"
39 #include <math.h>
40 
41 #define RTOD (45. / atan(1.))
42 
43 /**************************** CIF CELLS ****************************/
44 
45 #define NOCIFCELL ((CIFCELL *) -1)
46 
47 typedef struct Icifcell
48 {
49 	INTBIG           cindex;		/* cell index given in the define statement */
50 	INTBIG           l, r, t, b;	/* bounding box of cell */
51 	NODEPROTO       *addr;			/* the address of the cif cell */
52 } CIFCELL;
53 
54 static CIFCELL **io_cifcells = (CIFCELL **)NOSTRING; /* hash table of 'cifcells' */
55 static INTBIG    io_cifcells_size = 0; 	/* allocated size of io_cifcells */
56 static INTBIG    io_cifcells_num = 0;	/* number of used entries in io_cifcells */
57 static CIFCELL  *io_curcell;			/* the current cell */
58 static BOOLEAN   io_cifroundwires;		/* nonzero if wires should be rounded */
59 
60 /**************************** CIF LISTS ****************************/
61 
62 #define NOCIFLIST ((CIFLIST *) -1)
63 
64 /* values for CIFLIST->identity */
65 #define C_START		0
66 #define C_END		1
67 #define C_WIRE		2
68 #define C_FLASH		3
69 #define C_BOX		4
70 #define C_POLY		5
71 #define C_COMMAND	6
72 #define C_GNAME		7
73 #define C_LABEL		8
74 #define C_CALL		9
75 
76 typedef struct Iciflist
77 {
78 	INTBIG           identity;		/* specifies the nature of the entry */
79 	CHAR            *member;		/* will point to member's structure */
80 	struct Iciflist *next;			/* next entry in list */
81 } CIFLIST;
82 
83 static CIFLIST *io_ciflist = NOCIFLIST;	/* head of the list */
84 static CIFLIST *io_curlist;				/* current location in list */
85 
86 /**************************** MEMBER STRUCTURES ****************************/
87 
88 typedef struct Icfstart
89 {
90 	INTBIG cindex;					/* cell index */
91 	CHAR  *name;					/* cell name */
92 	INTBIG l, r, t, b;				/* bounding box of cell */
93 } CFSTART;
94 
95 typedef struct Icbox
96 {
97 	INTBIG lay;						/* the corresponding layer number */
98 	INTBIG length, width;			/* dimensions of box */
99 	INTBIG cenx, ceny;				/* center point of box */
100 	INTBIG xrot, yrot;				/* box direction */
101 } CBOX;
102 
103 typedef struct Icpolygon
104 {
105 	INTBIG  lay;					/* the corresponding layer number */
106 	INTBIG *x, *y;					/* list of points */
107 	INTBIG  lim;					/* number of points in list */
108 } CPOLY;
109 
110 typedef struct Icgeoname
111 {
112 	INTBIG lay;						/* the corresponding layer number */
113 	INTBIG x, y;					/* location of name */
114 	CHAR  *geoname;					/* the geo name */
115 } CGNAME;
116 
117 typedef struct Iclabel
118 {
119 	INTBIG x, y;					/* location of label */
120 	CHAR  *label;					/* the label */
121 } CLABEL;
122 
123 typedef struct Iccall
124 {
125 	INTBIG          cindex;			/* index of cell called */
126 	CHAR           *name;			/* name of cell called */
127 	struct Ictrans *list;			/* list of transformations */
128 } CCALL;
129 
130 /* values for the transformation type */
131 #define MIRX	1					/* mirror in x */
132 #define MIRY	2					/* mirror in y */
133 #define TRANS	3					/* translation */
134 #define ROT		4					/* rotation */
135 
136 #define NOCTRANS ((CTRANS *) -1)
137 
138 typedef struct Ictrans
139 {
140 	INTBIG          type;			/* type of transformation */
141 	INTBIG          x, y;			/* not required for the mirror types */
142 	struct Ictrans *next;			/* next element in list */
143 } CTRANS;
144 
145 static CTRANS *io_curctrans;				/* current transformation description */
146 
147 /**************************** MISCELLANEOUS ****************************/
148 
149 static CHAR       *io_curnodeprotoname;		/* name of the current cell */
150 static NODEPROTO  *io_incell;				/* address of cell being defined */
151 static NODEPROTO **io_cifnodes = 0;			/* nodeprotos associated with CIF names */
152 static INTBIG      io_varlength;			/* the length of all attribute arrays */
153 static VARIABLE   *io_cifnames;				/* cif names for the current technology */
154 static INTBIG      io_cifnotfoundcount;		/* number of unknown layer names */
155 static CHAR      **io_cifnotfoundlist;		/* unknown layer name list */
156 static INTBIG      io_cifnotfoundlimit = 0;	/* size of unknown layer name list */
157 
158 /* prototypes for local routines */
159 static BOOLEAN    io_interpret(FILE*);
160 static BOOLEAN    io_listtonodes(LIBRARY*);
161 static NODEPROTO *io_nodes_start(LIBRARY*, void*);
162 static BOOLEAN    io_nodes_box(void);
163 static BOOLEAN    io_nodes_poly(void);
164 static BOOLEAN    io_nodes_call(void);
165 static void       io_rotatelayer(INTBIG*, INTBIG*, INTBIG);
166 static BOOLEAN    io_initfind(void);
167 static NODEPROTO *io_findprotonode(INTBIG);
168 static CIFCELL   *io_findcifcell(INTBIG);
169 static void       io_insertcifcell(CIFCELL *cifcell);
170 static CIFCELL   *io_newcifcell(INTBIG);
171 static CIFLIST   *io_newciflist(INTBIG);
172 static void       io_placeciflist(INTBIG);
173 static CTRANS    *io_newctrans(void);
174 static void       io_ciffreeciflist(void);
175 static void       io_ciffreecifcells(void);
176 
177 /*
178  * Routine to free all memory associated with this module.
179  */
io_freecifinmemory(void)180 void io_freecifinmemory(void)
181 {
182 	io_ciffreeciflist();
183 	io_ciffreecifcells();
184 	if (io_cifnodes != 0) efree((CHAR *)io_cifnodes);
185 }
186 
io_readciflibrary(LIBRARY * lib)187 BOOLEAN io_readciflibrary(LIBRARY *lib)
188 {
189 	REGISTER FILE *f;
190 	CHAR *filename;
191 	REGISTER INTBIG i, *curstate;
192 
193 	curstate = io_getstatebits();
194 	if ((curstate[0]&CIFINSQUARE) != 0) io_cifroundwires = FALSE;
195 		else io_cifroundwires = TRUE;
196 
197 	/* initialize all lists and the searching routines */
198 	io_ciffreecifcells();
199 	io_ciffreeciflist();
200 
201 	if (io_initfind()) return(TRUE);
202 
203 	/* get the cif file */
204 	f = xopen(lib->libfile, io_filetypecif, x_(""), &filename);
205 	if (f == NULL)
206 	{
207 		ttyputerr(_("File %s not found"), lib->libfile);
208 		return(TRUE);
209 	}
210 
211 	if (setjmp(io_filerror))
212 	{
213 		ttyputerr(_("Error reading CIF"));
214 		return(TRUE);
215 	}
216 
217 	/* initialize list of not-found layers */
218 	io_cifnotfoundcount = 0;
219 
220 	/* parse the cif and create a listing */
221 	if (io_interpret(f)) return(TRUE);
222 
223 	/* instantiate the cif as nodes */
224 	if (io_listtonodes(lib)) return(TRUE);
225 
226 	/* clean up */
227 	(void)io_doneinterpreter();
228 	for(i=0; i<io_cifnotfoundcount; i++) efree((CHAR *)io_cifnotfoundlist[i]);
229 
230 	return(FALSE);
231 }
232 
io_interpret(FILE * file)233 BOOLEAN io_interpret(FILE *file)
234 {
235 	INTBIG comcount, left, right, bottom, top;
236 
237 	if (io_initparser())
238 	{
239 		ttyputerr(_("Error initializing parser"));
240 		return(TRUE);
241 	}
242 	if (io_initinterpreter())
243 	{
244 		ttyputerr(_("Error initializing interpreter"));
245 		return(TRUE);
246 	}
247 	if (io_infromfile(file)) return(TRUE);
248 	comcount = io_parsefile();		/* read in the cif */
249 	(void)io_doneparser();
250 	if (stopping(STOPREASONCIF)) return(TRUE);
251 	ttyputverbose(M_("Total CIF commands: %ld"), comcount);
252 
253 	if (io_fatalerrors() > 0) return(TRUE);
254 
255 	io_iboundbox(&left, &right, &bottom, &top);
256 
257 	/* construct a list: first step in the conversion */
258 	(void)io_createlist();
259 	return(FALSE);
260 }
261 
262 /**************************** NODE CONVERSION ****************************/
263 
io_listtonodes(LIBRARY * lib)264 BOOLEAN io_listtonodes(LIBRARY *lib)
265 {
266 	REGISTER void *dia;
267 
268 	if (io_verbose < 0)
269 	{
270 		dia = DiaInitProgress(0, 0);
271 		if (dia == 0) return(TRUE);
272 		DiaSetProgress(dia, 999, 1000);
273 	}
274 	io_incell = NONODEPROTO;
275 	for(io_curlist = io_ciflist; io_curlist != NOCIFLIST; io_curlist = io_curlist->next)
276 	{
277 		if (stopping(STOPREASONCIF))
278 		{
279 			if (io_verbose < 0) DiaDoneDialog(dia);
280 			return(TRUE);
281 		}
282 		if (io_incell != NONODEPROTO || io_curlist->identity == C_START)
283 			switch (io_curlist->identity)
284 		{
285 			case C_START:
286 				io_incell = io_nodes_start(lib, dia);
287 				if (io_incell == NONODEPROTO)
288 				{
289 					if (io_verbose < 0) DiaDoneProgress(dia);
290 					return(TRUE);
291 				}
292 				break;
293 			case C_END:
294 				/* make cell size right */
295 				db_boundcell(io_incell, &io_incell->lowx, &io_incell->highx,
296 					&io_incell->lowy, &io_incell->highy);
297 				lib->curnodeproto = io_incell;
298 				io_incell = NONODEPROTO;
299 				break;
300 			case C_BOX:
301 				if (io_nodes_box())
302 				{
303 					if (io_verbose < 0) DiaDoneProgress(dia);
304 					return(TRUE);
305 				}
306 				break;
307 			case C_POLY:
308 				if (io_nodes_poly())
309 				{
310 					if (io_verbose < 0) DiaDoneProgress(dia);
311 					return(TRUE);
312 				}
313 				break;
314 			case C_CALL:
315 				if (io_nodes_call())
316 				{
317 					if (io_verbose < 0) DiaDoneProgress(dia);
318 					return(TRUE);
319 				}
320 				break;
321 		}
322 	}
323 	if (io_verbose < 0) DiaDoneProgress(dia);
324 	return(FALSE);
325 }
326 
io_nodes_start(LIBRARY * lib,void * dia)327 NODEPROTO *io_nodes_start(LIBRARY *lib, void *dia)
328 {
329 	CIFCELL *cifcell;
330 	CFSTART *cs;
331 	CHAR *opt;
332 	REGISTER void *infstr;
333 
334 	cs = (CFSTART *)io_curlist->member;
335 	if ((cifcell = io_newcifcell(cs->cindex)) == NOCIFCELL) return(NONODEPROTO);
336 	cifcell->l = cs->l;   cifcell->r = cs->r;
337 	cifcell->b = cs->b;   cifcell->t = cs->t;
338 	io_curnodeprotoname = cs->name;
339 
340 	/* remove illegal characters */
341 	for(opt = io_curnodeprotoname; *opt != 0; opt++)
342 		if (*opt <= ' ' || *opt == ':' || *opt == ';' || *opt >= 0177)
343 			*opt = 'X';
344 	cifcell->addr = us_newnodeproto(io_curnodeprotoname, lib);
345 	if (cifcell->addr == NONODEPROTO)
346 	{
347 		ttyputerr(_("Cannot create the cell %s"), io_curnodeprotoname);
348 		return(NONODEPROTO);
349 	}
350 
351 	if (io_verbose < 0)
352 	{
353 		infstr = initinfstr();
354 		formatinfstr(infstr, _("Reading %s"), io_curnodeprotoname);
355 		DiaSetTextProgress(dia, returninfstr(infstr));
356 	} else if (io_verbose > 0) ttyputmsg(_("Reading %s"), io_curnodeprotoname);
357 	return(cifcell->addr);
358 }
359 
io_nodes_box(void)360 BOOLEAN io_nodes_box(void)
361 {
362 	NODEPROTO *node;
363 	CBOX *cb;
364 	CHAR *layname;
365 	INTBIG l, w, lx, ly, hx, hy, r;
366 
367 	cb = (CBOX *)io_curlist->member;
368 	node = io_findprotonode(cb->lay);
369 	if (node == NONODEPROTO)
370 	{
371 		layname = layername(el_curtech, cb->lay);
372 		ttyputerr(_("Cannot find primitive to use for layer '%s' (number %ld)"),
373 			layname, cb->lay);
374 		return(TRUE);
375 	}
376 	l = cb->length;        w = cb->width;
377 	lx = cb->cenx - l/2;   ly = cb->ceny - w/2;
378 	hx = cb->cenx + l/2;   hy = cb->ceny + w/2;
379 	r = figureangle(0, 0, (INTBIG)cb->xrot, (INTBIG)cb->yrot);
380 	if (newnodeinst(node, scalefromdispunit((float)lx, DISPUNITCMIC),
381 		scalefromdispunit((float)hx, DISPUNITCMIC), scalefromdispunit((float)ly, DISPUNITCMIC),
382 		scalefromdispunit((float)hy, DISPUNITCMIC), 0, r, io_curcell->addr) == NONODEINST)
383 	{
384 		layname = layername(el_curtech, cb->lay);
385 		ttyputerr(_("Problems creating a box on layer %s in cell %s"), layname,
386 			describenodeproto(io_curcell->addr));
387 		return(TRUE);
388 	}
389 	return(FALSE);
390 }
391 
io_nodes_poly(void)392 BOOLEAN io_nodes_poly(void)
393 {
394 	REGISTER INTBIG lx, ly, hx, hy, i, *trace, cx, cy, *pt;
395 	REGISTER NODEPROTO *np;
396 	REGISTER NODEINST *newni;
397 	REGISTER CPOLY *cp;
398 
399 	cp = (CPOLY *)io_curlist->member;
400 	if (cp->lim == 0) return(FALSE);
401 	np = io_findprotonode(cp->lay);
402 	lx = hx = cp->x[0];   ly = hy = cp->y[0];
403 	for(i=1; i<cp->lim; i++)
404 	{
405 		if (cp->x[i] < lx) lx = cp->x[i];
406 		if (cp->x[i] > hx) hx = cp->x[i];
407 		if (cp->y[i] < ly) ly = cp->y[i];
408 		if (cp->y[i] > hy) hy = cp->y[i];
409 	}
410 	newni = newnodeinst(np, scalefromdispunit((float)lx, DISPUNITCMIC),
411 		scalefromdispunit((float)hx, DISPUNITCMIC), scalefromdispunit((float)ly, DISPUNITCMIC),
412 			scalefromdispunit((float)hy, DISPUNITCMIC), 0, 0, io_curcell->addr);
413 	if (newni == NONODEINST)
414 	{
415 		ttyputerr(_("Problems creating a polygon on layer %ld in cell %s"), cp->lay,
416 			describenodeproto(io_curcell->addr));
417 		return(TRUE);
418 	}
419 
420 	/* store the trace information */
421 	pt = trace = emalloc((cp->lim*2*SIZEOFINTBIG), io_tool->cluster);
422 	if (trace == 0) return(TRUE);
423 	cx = (hx + lx) / 2;   cy = (hy + ly) / 2;
424 	for(i=0; i<cp->lim; i++)
425 	{
426 		*pt++ = scalefromdispunit((float)(cp->x[i] - cx), DISPUNITCMIC);
427 		*pt++ = scalefromdispunit((float)(cp->y[i] - cy), DISPUNITCMIC);
428 	}
429 
430 	/* store the trace information */
431 	(void)setvalkey((INTBIG)newni, VNODEINST, el_trace_key, (INTBIG)trace,
432 		VINTEGER|VISARRAY|((cp->lim*2)<<VLENGTHSH));
433 
434 	/* free the polygon memory */
435 	efree((CHAR *)trace);
436 	efree((CHAR *)cp->x);   efree((CHAR *)cp->y);
437 	cp->lim = 0;
438 	return(FALSE);
439 }
440 
io_nodes_call(void)441 BOOLEAN io_nodes_call(void)
442 {
443 	CIFCELL *cell;
444 	CCALL *cc;
445 	CTRANS *ctrans;
446 	INTBIG l, r, t, b, rot, trans, hlen, hwid, cenx, ceny, temp;
447 	INTBIG deg;
448 
449 	cc = (CCALL *)io_curlist->member;
450 	if ((cell = io_findcifcell(cc->cindex)) == NOCIFCELL)
451 	{
452 		ttyputerr(_("Referencing an undefined cell"));
453 		return(TRUE);
454 	}
455 	rot = trans = 0;
456 	l = cell->l;    r = cell->r;    b = cell->b;    t = cell->t;
457 	for(ctrans = cc->list; ctrans != NOCTRANS; ctrans = ctrans->next)
458 		switch (ctrans->type)
459 	{
460 		case MIRX:
461 			temp = l;   l = -r;   r = -temp;
462 			rot = (trans) ? ((rot+2700) % 3600) : ((rot+900) % 3600);
463 			trans = 1 - trans;
464 			break;
465 		case MIRY:
466 			temp = t;   t = -b;   b = -temp;
467 			rot = (trans) ? ((rot+900) % 3600) : ((rot+2700) % 3600);
468 			trans = 1 - trans;
469 			break;
470 		case TRANS:
471 			l += ctrans->x;   r += ctrans->x;
472 			b += ctrans->y;   t += ctrans->y;
473 			break;
474 		case ROT:
475 			deg = figureangle(0L, 0L, ctrans->x, ctrans->y);
476 			if (deg != 0)
477 			{
478 				hlen = abs(((l-r)/2));   hwid = abs(((b-t)/2));
479 				cenx = (l+r)/2;   ceny = (b+t)/2;
480 				io_rotatelayer(&cenx, &ceny, deg);
481 				l = cenx - hlen;   r = cenx + hlen;
482 				b = ceny - hwid;   t = ceny + hwid;
483 				rot += ((trans) ? -deg : deg);
484 			}
485 	}
486 	while(rot >= 3600) rot -= 3600;
487 	while(rot < 0) rot += 3600;
488 	if (newnodeinst((NODEPROTO *)(cell->addr), scalefromdispunit((float)l, DISPUNITCMIC),
489 		scalefromdispunit((float)r, DISPUNITCMIC), scalefromdispunit((float)b, DISPUNITCMIC),
490 			scalefromdispunit((float)t, DISPUNITCMIC), trans, rot, io_curcell->addr) ==
491 				NONODEINST)
492 	{
493 		ttyputerr(_("Problems creating an instance of cell %s in cell %s"),
494 			describenodeproto(cell->addr), describenodeproto(io_curcell->addr));
495 		return(TRUE);
496 	}
497 	return(FALSE);
498 }
499 
io_rotatelayer(INTBIG * cenx,INTBIG * ceny,INTBIG deg)500 void io_rotatelayer(INTBIG *cenx, INTBIG *ceny, INTBIG deg)
501 {
502 	double vlen, vang, fx, fy, factx, facty, fact;
503 	INTBIG temp;
504 
505 	/* trivial test to prevent atan2 domain errors */
506 	if (*cenx == 0 && *ceny == 0) return;
507 	switch (deg)	/* do the manhattan cases directly (SRP)*/
508 	{
509 		case 0:
510 		case 3600:	/* just in case */
511 			break;
512 		case 900:
513 			temp = *cenx;   *cenx = -*ceny;   *ceny = temp;
514 			break;
515 		case 1800:
516 			*cenx = -*cenx;   *ceny = -*ceny;
517 			break;
518 		case 2700:
519 			temp = *cenx;   *cenx = *ceny;   *ceny = -temp;
520 			break;
521 		default: /* this old code only permits rotation by integer angles (SRP)*/
522 			for(factx=1.; fabs((*cenx/factx)) > 1000; factx *= 10.) ;
523 			for(facty=1.; fabs((*ceny/facty)) > 1000; facty *= 10.) ;
524 			fact = (factx > facty) ? facty : factx;
525 			fx = *cenx / fact;		  fy = *ceny / fact;
526 			vlen = fact * sqrt((double)(fx*fx + fy*fy));
527 			vang = (deg + figureangle(0L,0L,*cenx, *ceny)) / 10.0 / RTOD;
528 			*cenx = (INTBIG)(vlen * cos(vang));
529 			*ceny = (INTBIG)(vlen * sin(vang));
530 			break;
531 	}
532 }
533 
534 /**************************** SEARCHING ROUTINES ****************************/
535 
io_initfind(void)536 BOOLEAN io_initfind(void)
537 {
538 	REGISTER CHAR *ch, *ch2;
539 	REGISTER NODEPROTO *np;
540 	REGISTER NODEINST *ni;
541 	NODEINST nodeinst;
542 	REGISTER INTBIG total, i, j, k;
543 	static POLYGON *poly = NOPOLYGON;
544 
545 	/* get the array of CIF names */
546 	io_cifnames = getval((INTBIG)el_curtech, VTECHNOLOGY, VSTRING|VISARRAY, x_("IO_cif_layer_names"));
547 	if (io_cifnames == NOVARIABLE)
548 	{
549 		ttyputerr(_("There are no CIF layer names assigned in the %s technology"),
550 			el_curtech->techname);
551 		return(TRUE);
552 	}
553 	io_varlength = getlength(io_cifnames);
554 	if (io_varlength < el_curtech->layercount)
555 	{
556 		ttyputerr(_("Warning: CIF layer information is bad for technology %s.  Use 'CIF Options' to fix it"),
557 			el_curtech->techname);
558 		return(TRUE);
559 	}
560 
561 	/* create the array of nodes associated with the array of CIF names */
562 	total = el_curtech->layercount;
563 	if (io_cifnodes != 0) efree((CHAR *)io_cifnodes);
564 	io_cifnodes = (NODEPROTO **)emalloc((total * (sizeof (NODEPROTO *))), io_tool->cluster);
565 	if (io_cifnodes == 0) return(TRUE);
566 	for(i=0; i<total; i++) io_cifnodes[i] = NONODEPROTO;
567 
568 	/* create the polygon */
569 	(void)needstaticpolygon(&poly, 4, io_tool->cluster);
570 
571 	/* run through the node prototypes in this technology */
572 	for(np = el_curtech->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
573 	{
574 		ni = &nodeinst;   initdummynode(ni);
575 		ni->proto = np;
576 		ni->lowx  = np->lowx;
577 		ni->highx = np->highx;
578 		ni->lowy  = np->lowy;
579 		ni->highy = np->highy;
580 		i = nodepolys(ni, 0, NOWINDOWPART);
581 		if (i != 1) continue;
582 		shapenodepoly(ni, 0, poly);
583 		if (poly->layer < 0) continue;
584 		ch = ((CHAR **)io_cifnames->addr)[poly->layer];
585 		if (*ch != 0) io_cifnodes[poly->layer] = np;
586 	}
587 
588 	/* make sure every CIF string has an equivalent node */
589 	for(i=0; i<total; i++)
590 	{
591 		ch = ((CHAR **)io_cifnames->addr)[i];
592 		if (*ch == 0) continue;
593 		if (io_cifnodes[i] != NONODEPROTO) continue;
594 
595 		/* first look for a layer with the same CIF name */
596 		for (k=0; k<total; k++)
597 		{
598 			np = io_cifnodes[k];
599 			if (np == NONODEPROTO) continue;
600 			ni = &nodeinst;   initdummynode(ni);
601 			ni->proto = np;
602 			ni->lowx  = np->lowx;
603 			ni->highx = np->highx;
604 			ni->lowy  = np->lowy;
605 			ni->highy = np->highy;
606 			(void)nodepolys(ni, 0, NOWINDOWPART);
607 			shapenodepoly(ni, 0, poly);
608 			ch2 = ((CHAR **)io_cifnames->addr)[poly->layer];
609 			if (estrcmp(ch, ch2) != 0) continue;
610 			io_cifnodes[i] = np;
611 			break;
612 		}
613 		if (k < total) continue;
614 
615 		/* search for ANY node with this layer */
616 		for(np = el_curtech->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
617 		{
618 			ni = &nodeinst;   initdummynode(ni);
619 			ni->proto = np;
620 			ni->lowx  = np->lowx;
621 			ni->highx = np->highx;
622 			ni->lowy  = np->lowy;
623 			ni->highy = np->highy;
624 			j = nodepolys(ni, 0, NOWINDOWPART);
625 			for(k=0; k<j; k++)
626 			{
627 				shapenodepoly(ni, 0, poly);
628 				if (poly->layer == i) break;
629 			}
630 			if (k >= j) continue;
631 			io_cifnodes[i] = np;
632 			break;
633 		}
634 	}
635 
636 	return(FALSE);
637 }
638 
io_findlayernum(CHAR * name)639 INTBIG io_findlayernum(CHAR *name)
640 {
641 	REGISTER INTBIG i, newlimit;
642 	REGISTER CHAR **newlist;
643 
644 	for(i=0; i<io_varlength; i++)
645 		if (estrcmp(name, ((CHAR **)io_cifnames->addr)[i]) == 0) return(i);
646 
647 	/* CIF name not found: see if it is in the list of unfound layers */
648 	for(i=0; i<io_cifnotfoundcount; i++)
649 		if (estrcmp(name, io_cifnotfoundlist[i]) == 0) return(-1);
650 
651 	/* add to the list */
652 	if (io_cifnotfoundcount >= io_cifnotfoundlimit)
653 	{
654 		newlimit = io_cifnotfoundlimit * 2;
655 		if (newlimit <= 0) newlimit = 10;
656 		if (newlimit < io_cifnotfoundcount) newlimit = io_cifnotfoundcount;
657 		newlist = (CHAR **)emalloc(newlimit * (sizeof (CHAR *)), io_tool->cluster);
658 		if (newlist == 0) return(-1);
659 		for(i=0; i<io_cifnotfoundcount; i++)
660 			newlist[i] = io_cifnotfoundlist[i];
661 		if (io_cifnotfoundlimit > 0) efree((CHAR *)io_cifnotfoundlist);
662 		io_cifnotfoundlist = newlist;
663 		io_cifnotfoundlimit = newlimit;
664 	}
665 	(void)allocstring(&io_cifnotfoundlist[io_cifnotfoundcount], name, io_tool->cluster);
666 	io_cifnotfoundcount++;
667 	ttyputmsg(_("Layer %s not found"), name);
668 	return(-1);
669 }
670 
io_findprotonode(INTBIG num)671 NODEPROTO *io_findprotonode(INTBIG num)
672 {
673 	return(io_cifnodes[num]);
674 }
675 
io_findcifcell(INTBIG cindex)676 CIFCELL *io_findcifcell(INTBIG cindex)
677 {
678 	CIFCELL *cifcell;
679 	REGISTER INTBIG i, j;
680 
681 	i = cindex % io_cifcells_size;
682 	for(j=1; j<=io_cifcells_size; j += 2)
683 	{
684 		cifcell = io_cifcells[i];
685 		if (cifcell == NOCIFCELL) break;
686 		if (cindex == cifcell->cindex) return(cifcell);
687 		i += j;
688 		if (i >= io_cifcells_size) i -= io_cifcells_size;
689 	}
690 	return(NOCIFCELL);
691 }
692 
io_insertcifcell(CIFCELL * cifcell)693 void io_insertcifcell(CIFCELL *cifcell)
694 {
695 	REGISTER INTBIG i, j;
696 
697 	i = cifcell->cindex % io_cifcells_size;
698 	for(j=1; j<=io_cifcells_size; j += 2)
699 	{
700 		if (io_cifcells[i] == NOCIFCELL)
701 		{
702 			io_cifcells[i] = cifcell;
703 			break;
704 		}
705 		i += j;
706 		if (i >= io_cifcells_size) i -= io_cifcells_size;
707 	}
708 }
709 
io_newcifcell(INTBIG cindex)710 CIFCELL *io_newcifcell(INTBIG cindex)
711 {
712 	CIFCELL *newcc, *cc;
713 	CIFCELL **old_cifcells;
714 	INTBIG old_cifcells_size;
715 	INTBIG new_cifcells_size;
716 	INTBIG i;
717 
718 	newcc = (CIFCELL *)emalloc((sizeof (CIFCELL)), io_tool->cluster);
719 	if (newcc == (CIFCELL *) 0)
720 	{
721 		ttyputerr(_("Not enough memory allocated for CIFCELL"));
722 		return(NOCIFCELL);
723 	}
724 	io_cifcells_num++;
725 	if (io_cifcells_num >= io_cifcells_size/2)
726 	{
727 		old_cifcells = io_cifcells;
728 		old_cifcells_size = io_cifcells_size;
729 		new_cifcells_size = pickprime(io_cifcells_num * 4);
730 		io_cifcells = (CIFCELL **)emalloc(new_cifcells_size * (sizeof (CIFCELL *)), io_tool->cluster);
731 		if (io_cifcells == (CIFCELL **) 0)
732 		{
733 			ttyputerr(_("Not enough memory allocated for CIFCELL"));
734 			return(NOCIFCELL);
735 		}
736 		for (i = 0; i < new_cifcells_size; i++) io_cifcells[i] = NOCIFCELL;
737 		io_cifcells_size = new_cifcells_size;
738 		for (i = 0; i < old_cifcells_size; i++)
739 		{
740 			cc = old_cifcells[i];
741 			if (cc != NOCIFCELL) io_insertcifcell(cc);
742 		}
743 		if (old_cifcells_size > 0) efree((CHAR *) old_cifcells);
744 	}
745 	newcc->addr = NONODEPROTO;
746 	newcc->cindex = cindex;
747 	io_insertcifcell(newcc);
748 
749 	io_curcell = newcc;
750 	return(newcc);
751 }
752 
io_ciffreecifcells(void)753 void io_ciffreecifcells(void)
754 {
755 	CIFCELL *cc;
756 	INTBIG i;
757 
758 	for (i = 0; i < io_cifcells_size; i++)
759 	{
760 		cc = io_cifcells[i];
761 		if (cc != NOCIFCELL)
762 			efree((CHAR *)cc);
763 	}
764 	if (io_cifcells_size > 0) efree((CHAR *)io_cifcells);
765 	io_cifcells_size = 0;
766 	io_cifcells_num = 0;
767 	io_cifcells = (CIFCELL **)NOSTRING;
768 }
769 
io_newciflist(INTBIG id)770 CIFLIST *io_newciflist(INTBIG id)
771 {
772 	CIFLIST *newcl;
773 	CCALL *cc;
774 	CFSTART *cs;
775 
776 	newcl = (CIFLIST *)emalloc((sizeof (CIFLIST)), io_tool->cluster);
777 	if (newcl == (CIFLIST *) 0)
778 	{
779 		ttyputerr(_("Not enough memory allocated for CIFLIST"));
780 		return(NOCIFLIST);
781 	}
782 	newcl->next = NOCIFLIST;
783 	newcl->identity = id;
784 	switch (id)
785 	{
786 		case C_START:
787 			cs = (CFSTART *)emalloc((sizeof (CFSTART)), io_tool->cluster);
788 			if (cs == 0) return(NOCIFLIST);
789 			newcl->member = (CHAR *)cs;
790 			cs->name = 0;
791 			break;
792 		case C_BOX:
793 			newcl->member = (CHAR *)emalloc((sizeof (CBOX)), io_tool->cluster);
794 			if (newcl->member == (CHAR *) 0) return(NOCIFLIST);
795 			break;
796 		case C_POLY:
797 			newcl->member = (CHAR *)emalloc((sizeof (CPOLY)), io_tool->cluster);
798 			if (newcl->member == (CHAR *) 0) return(NOCIFLIST);
799 			break;
800 		case C_GNAME:
801 			newcl->member = (CHAR *)emalloc((sizeof (CGNAME)), io_tool->cluster);
802 			if (newcl->member == (CHAR *) 0) return(NOCIFLIST);
803 			break;
804 		case C_LABEL:
805 			newcl->member = (CHAR *)emalloc((sizeof (CLABEL)), io_tool->cluster);
806 			if (newcl->member == (CHAR *) 0) return(NOCIFLIST);
807 			break;
808 		case C_CALL:
809 			cc = (CCALL *)emalloc((sizeof (CCALL)), io_tool->cluster);
810 			if (cc == 0) return(NOCIFLIST);
811 			newcl->member = (CHAR *)cc;
812 			cc->name = 0;
813 			break;
814 	}
815 	return(newcl);
816 }
817 
io_ciffreeciflist(void)818 void io_ciffreeciflist(void)
819 {
820 	REGISTER CIFLIST *cl;
821 	REGISTER CCALL *cc;
822 	REGISTER CTRANS *cct;
823 	REGISTER CFSTART *cs;
824 
825 	while (io_ciflist != NOCIFLIST)
826 	{
827 		cl = io_ciflist;
828 		io_ciflist = io_ciflist->next;
829 		switch (cl->identity)
830 		{
831 			case C_CALL:
832 				cc = (CCALL *)cl->member;
833 				while (cc->list != NOCTRANS)
834 				{
835 					cct = cc->list;
836 					cc->list = cc->list->next;
837 					efree((CHAR *)cct);
838 				}
839 				if (cc->name != 0) efree((CHAR *)cc->name);
840 				efree((CHAR *)cc);
841 				break;
842 			case C_START:
843 				cs = (CFSTART *)cl->member;
844 				if (cs->name != 0) efree((CHAR *)cs->name);
845 				efree((CHAR *)cs);
846 				break;
847 			case C_BOX:
848 			case C_POLY:
849 			case C_GNAME:
850 			case C_LABEL:
851 				efree((CHAR *)cl->member);
852 				break;
853 		}
854 		efree((CHAR *)cl);
855 	}
856 }
857 
io_placeciflist(INTBIG id)858 void io_placeciflist(INTBIG id)
859 {
860 	CIFLIST *cl;
861 
862 	if ((cl = io_newciflist(id)) == NOCIFLIST) return;
863 	if (io_ciflist == NOCIFLIST) io_ciflist = io_curlist = cl; else
864 	{
865 		while(io_curlist->next != NOCIFLIST)
866 			io_curlist = io_curlist->next;
867 		io_curlist->next = cl;
868 		io_curlist = io_curlist->next;
869 	}
870 }
871 
io_newctrans(void)872 CTRANS *io_newctrans(void)
873 {
874 	CTRANS *newct;
875 	CCALL *cc;
876 
877 	newct = (CTRANS *)emalloc((sizeof (CTRANS)), io_tool->cluster);
878 	if (newct == (CTRANS *) 0)
879 	{
880 		ttyputerr(_("Not enough memory allocated for CTRANS"));
881 		return(NOCTRANS);
882 	}
883 	newct->next = NOCTRANS;
884 	cc = (CCALL *)io_curlist->member;
885 	if (cc->list == NOCTRANS) cc->list = newct; else
886 		io_curctrans->next = newct;
887 	io_curctrans = newct;
888 	return(newct);
889 }
890 
io_outputwire(INTBIG lay,INTBIG width,CHAR * wpath)891 void io_outputwire(INTBIG lay, INTBIG width, CHAR *wpath)
892 {
893 	/* convert wires to boxes and flashes  */
894 	INTBIG i;
895 	INTBIG llt, lrt, lbm, ltp, lim;
896 	point prev, curr;
897 
898 	lim = io_pathlength((path)wpath);
899 	prev = io_removepoint((path)wpath);
900 
901 	/* do not use roundflashes with zero-width wires */
902 	if (width != 0 && io_cifroundwires)
903 	{
904 		io_bbflash(lay, width, prev, &llt, &lrt, &lbm, &ltp);
905 		io_outputflash(lay, width, prev);
906 	}
907 	for (i = 1; i < lim; i++)
908 	{
909 		INTBIG len;
910 		INTBIG xr, yr;
911 		point center;
912 
913 		curr = io_removepoint((path)wpath);
914 
915 		/* do not use roundflashes with zero-width wires */
916 		if (width != 0 && io_cifroundwires)
917 		{
918 			io_bbflash(lay, width, curr, &llt, &lrt, &lbm, &ltp);
919 			io_outputflash(lay, width, curr);
920 		}
921 		xr = curr.x-prev.x;   yr = curr.y-prev.y;
922 		len = computedistance(0, 0, xr, yr);
923 		if (!io_cifroundwires) len += width;
924 		center.x = (curr.x+prev.x)/2;   center.y = (curr.y+prev.y)/2;
925 		io_bbbox(lay, len, width, center, xr, yr, &llt, &lrt, &lbm, &ltp);
926 		io_outputbox(lay, len, width, center, xr, yr);
927 		prev = curr;
928 	}
929 }
930 
io_outputflash(INTBIG lay,INTBIG diameter,point center)931 void io_outputflash(INTBIG lay, INTBIG diameter, point center)
932 {
933 	/* flash approximated by an octagon */
934 	INTBIG radius = diameter/2;
935 	float fcx = (float)center.x;
936 	float fcy = (float)center.y;
937 	float offset = (((float)diameter)/2.0f)*0.414213f;
938 	CHAR *fpath = io_makepath();
939 	point temp;
940 
941 	temp.x = center.x-radius;
942 	temp.y = roundfloat(fcy+offset);
943 	if (io_appendpoint((path)fpath, temp)) return;
944 	temp.y = roundfloat(fcy-offset);
945 	if (io_appendpoint((path)fpath, temp)) return;
946 	temp.x = roundfloat(fcx-offset);
947 	temp.y = center.y-radius;
948 	if (io_appendpoint((path)fpath, temp)) return;
949 	temp.x = roundfloat(fcx+offset);
950 	if (io_appendpoint((path)fpath, temp)) return;
951 	temp.x = center.x+radius;
952 	temp.y = roundfloat(fcy-offset);
953 	if (io_appendpoint((path)fpath, temp)) return;
954 	temp.y = roundfloat(fcy+offset);
955 	if (io_appendpoint((path)fpath, temp)) return;
956 	temp.x = roundfloat(fcx+offset);
957 	temp.y = center.y+radius;
958 	if (io_appendpoint((path)fpath, temp)) return;
959 	temp.x = roundfloat(fcx-offset);
960 	if (io_appendpoint((path)fpath, temp)) return;
961 
962 	io_outputpolygon(lay, fpath);
963 	io_freepath((path)fpath);
964 }
965 
io_outputbox(INTBIG lay,INTBIG length,INTBIG width,point center,INTBIG xrotation,INTBIG yrotation)966 void io_outputbox(INTBIG lay, INTBIG length, INTBIG width, point center,
967 	INTBIG xrotation, INTBIG yrotation)
968 {
969 	CBOX *cb;
970 
971 	if (length == 0 && width == 0) return;	/* ignore null boxes */
972 	io_placeciflist(C_BOX);
973 	cb = (CBOX *)io_curlist->member;
974 	cb->lay = lay;
975 	cb->length = length;	cb->width = width;
976 	cb->cenx = center.x;	cb->ceny = center.y;
977 	cb->xrot = xrotation;	cb->yrot = yrotation;
978 }
979 
io_outputpolygon(INTBIG lay,CHAR * ppath)980 void io_outputpolygon(INTBIG lay, CHAR *ppath)
981 {
982 	INTBIG i;
983 	INTBIG lim;
984 	CPOLY *cp;
985 	point temp;
986 
987 	lim = io_pathlength((path)ppath);
988 	if (lim < 3) return;
989 
990 	io_placeciflist(C_POLY);
991 	cp = (CPOLY *)io_curlist->member;
992 	cp->lay = lay;
993 	cp->x = emalloc((lim * SIZEOFINTBIG), io_tool->cluster);
994 	if (cp->x == 0)
995 	{
996 		ttyputnomemory();
997 		cp->lim = 0;
998 		return;
999 	}
1000 	cp->y = emalloc((lim * SIZEOFINTBIG), io_tool->cluster);
1001 	if (cp->y == 0)
1002 	{
1003 		ttyputnomemory();
1004 		cp->lim = 0;
1005 		return;
1006 	}
1007 
1008 	cp->lim = lim;
1009 	for (i = 0; i < lim; i++)
1010 	{
1011 		temp = io_removepoint((path)ppath);
1012 		cp->x[i] = temp.x;
1013 		cp->y[i] = temp.y;
1014 	}
1015 }
1016 
io_outputusercommand(INTBIG command,CHAR * text)1017 void io_outputusercommand(INTBIG command, CHAR *text)
1018 {
1019 }
1020 
io_outputgeoname(CHAR * name,point pt,INTBIG lay)1021 void io_outputgeoname(CHAR *name, point pt, INTBIG lay)
1022 {
1023 	CGNAME *cg;
1024 
1025 	io_placeciflist(C_GNAME);
1026 	cg = (CGNAME *)io_curlist->member;
1027 	cg->lay = lay;
1028 	(void)allocstring(&cg->geoname, name, io_tool->cluster);
1029 	cg->x = pt.x;   cg->y = pt.y;
1030 }
1031 
io_outputlabel(CHAR * name,point pt)1032 void io_outputlabel(CHAR *name, point pt)
1033 {
1034 	CLABEL *cl;
1035 
1036 	io_placeciflist(C_LABEL);
1037 	cl = (CLABEL *)io_curlist->member;
1038 	(void)allocstring(&cl->label, name, io_tool->cluster);
1039 	cl->x = pt.x;   cl->y = pt.y;
1040 }
1041 
io_outputcall(INTBIG number,CHAR * name,CHAR * list)1042 void io_outputcall(INTBIG number, CHAR *name, CHAR *list)
1043 {
1044 	CCALL *cc;
1045 	tentry temp;
1046 	INTBIG i;
1047 
1048 	io_placeciflist(C_CALL);
1049 	cc = (CCALL *)io_curlist->member;
1050 	cc->cindex = number;
1051 	(void)allocstring(&cc->name, name, io_tool->cluster);
1052 	cc->list = io_curctrans = NOCTRANS;
1053 	for(i = io_tlistlength((tlist)list); i>0; i--)
1054 	{
1055 		if (io_newctrans() == NOCTRANS) return;
1056 		temp = io_removetentry((tlist)list);
1057 		switch (temp.kind)
1058 		{
1059 			case MIRROR:
1060 				if (temp.guts.mi.xcoord) io_curctrans->type = MIRX; else
1061 					io_curctrans->type = MIRY;
1062 				break;
1063 			case TRANSLATE:
1064 				io_curctrans->type = TRANS;
1065 				io_curctrans->x = temp.guts.tr.xt;
1066 				io_curctrans->y = temp.guts.tr.yt;
1067 				break;
1068 			case ROTATE:
1069 				io_curctrans->type = ROT;
1070 				io_curctrans->x = temp.guts.ro.xrot;
1071 				io_curctrans->y = temp.guts.ro.yrot;
1072 				break;
1073 		}
1074 	}
1075 }
1076 
io_outputds(INTBIG number,CHAR * name,INTBIG l,INTBIG r,INTBIG b,INTBIG t)1077 void io_outputds(INTBIG number, CHAR *name, INTBIG l, INTBIG r, INTBIG b, INTBIG t)
1078 {
1079 	CFSTART *cs;
1080 
1081 	io_placeciflist(C_START);
1082 	cs = (CFSTART *)io_curlist->member;
1083 	cs->cindex = number;
1084 	(void)allocstring(&cs->name, name, io_tool->cluster);
1085 	cs->l = l;   cs->r = r;
1086 	cs->b = b;   cs->t = t;
1087 }
1088 
io_outputdf(void)1089 void io_outputdf(void)
1090 {
1091 	io_placeciflist(C_END);
1092 }
1093