1 /* -*- tab-width: 4 -*-
2  *
3  * Electric(tm) VLSI Design System
4  *
5  * File: dbvars.c
6  * Database object variables module
7  * Written by: Steven M. Rubin, Static Free Software
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 "global.h"
33 #include "database.h"
34 #include "egraphics.h"
35 #include "edialogs.h"
36 #include "usr.h"
37 #include "drc.h"
38 #include "erc.h"
39 #include "rout.h"
40 #include "network.h"
41 #include "logeffort.h"
42 #include "sim.h"
43 #include "simirsim.h"
44 #include "eio.h"
45 #include "tecart.h"
46 #include "tecmocmos.h"
47 #include "tecmocmossub.h"
48 #include "tecschem.h"
49 
50 /***** option saving structures *****/
51 
52 /* this define should match the one in "usrdiacom.c" */
53 #define SAVEDBITWORDS 2
54 
55 typedef struct
56 {
57 	BOOLEAN   dirty;
58 	INTBIG    saveflag;
59 	INTBIG   *addr;
60 	INTBIG    type;
61 	INTBIG    partial;
62 	CHAR     *variablename;
63 	UINTBIG   initialbits1, initialbits2;
64 	UINTBIG   maskbits1, maskbits2;
65 	CHAR     *meaning;
66 } OPTIONVARPROTO;
67 
68 typedef struct
69 {
70 	UINTBIG         bits[SAVEDBITWORDS];
71 	CHAR           *command;
72 	OPTIONVARPROTO *variables;
73 } OPTIONVARCOMS;
74 
75 typedef struct
76 {
77 	INTBIG    addr;
78 	INTBIG    type;
79 	CHAR     *variablename;
80 	INTBIG    oldtype;
81 } OPTIONVARCACHE;
82 
83 static OPTIONVARCACHE *db_optionvarcache;
84 static INTBIG          db_optionvarcachecount = 0;
85 
86 /***** for parameterized cells *****/
87 
88 #define NOPARCELL      ((PARCELL *)-1)
89 
90 typedef struct Iparcell
91 {
92 	NODEPROTO       *cell;
93 	CHAR            *parname;
94 	CHAR            *shortname;
95 	struct Iparcell *nextparcell;
96 } PARCELL;
97 
98 static PARCELL *db_parcellfree = NOPARCELL;
99 static PARCELL *db_firstparcell = NOPARCELL;
100 
101        BOOLEAN db_onanobject = FALSE;	/* TRUE if code evaluation is "on an object" (getval, etc.) */
102        INTBIG  db_onobjectaddr;			/* the address of the first object that we are on */
103        INTBIG  db_onobjecttype;			/* the type of the first object that we are on */
104 	   WINDOWPART *db_onobjectwin;		/* the window of the first object that we are on */
105        INTBIG  db_lastonobjectaddr;		/* the address of the last object that we were on */
106        INTBIG  db_lastonobjecttype;		/* the type of the last object that we were on */
107 
108 /***** for finding variables on objects *****/
109 
110 #define SPECNAME  0		/* look for special names in structure */
111 #define VARNAME   1		/* look for variable names in structure */
112 #define PORTCNAME 2		/* look for port names on nodeproto */
113 #define ARCINAME  3		/* look for nodeinst/arcinst names in cell */
114 #define NODEINAME 4		/* look for nodeinst/arcinst names in cell */
115 #define PORTANAME 5		/* look for port arc names on nodeinst */
116 #define PORTENAME 6		/* look for export names on nodeinst */
117 #define ARCNAME   7		/* look for arcproto names in technology */
118 #define NODENAME  8		/* look for nodeproto names in technology */
119 #define NULLNAME  9		/* no more names in structure */
120 
121 typedef struct
122 {
123 	CHAR   *name;
124 	UINTBIG type;
125 	INTBIG *ptr;
126 } NAMEVARS;
127 
128 #define MAXAPACK	5				/* maximum nested attribute searches */
129 static struct attrsearch
130 {
131 	INTSML      *numvar;			/* address of object variable count */
132 	VARIABLE   **firstvar;			/* address of object variable list */
133 	NAMEVARS    *vars;				/* special names in this object */
134 	INTBIG       proto;				/* address of object prototype */
135 	INTBIG       object;			/* address of this object */
136 	INTBIG       state;				/* current name type under test */
137 	INTBIG       varindex;			/* current index for variable search */
138 	INTBIG       specindex;			/* current index for name search */
139 	NODEPROTO   *nodeprotoname;		/* current cell object */
140 	ARCPROTO    *arcprotoname;		/* current arcproto object */
141 	PORTARCINST *portarcinstname;	/* current portarcinst object */
142 	PORTEXPINST *portexpinstname;	/* current portexpinst object */
143 	PORTPROTO   *portprotoname;		/* current portproto object */
144 	ARCINST     *arciname;			/* current arcinst object */
145 	NODEINST    *nodeiname;			/* current nodeinst object */
146 } db_attrpacket[MAXAPACK];
147 static INTBIG db_apackindex = 0;
148 static struct attrsearch *db_thisapack;
149 static INTBIG db_realaddress;
150 
151 /* prototypes for local routines */
152 static PARCELL  *db_allocparcell(void);
153 static INTBIG    db_assignvalue(void *loc, INTBIG datasize);
154 static INTBIG    db_binarysearch(INTSML, VARIABLE*, INTBIG);
155 static BOOLEAN   db_delindvar(INTBIG, INTBIG, VARIABLE*, INTBIG);
156 static CHAR     *db_describetype(INTBIG type);
157 static void      db_freeparcell(PARCELL *pc);
158 static INTBIG    db_getdatasize(INTBIG);
159 static BOOLEAN   db_getindvar(VARIABLE*, INTBIG, INTBIG*);
160 static INTBIG    db_getkey(CHAR*);
161 static void      db_initarcinstlist(ARCINST*);
162 static void      db_initarcprotolist(ARCPROTO*);
163 static void      db_initconstraintlist(CONSTRAINT*);
164 static void      db_initgeomlist(GEOM*);
165 static void      db_initgraphicslist(GRAPHICS*);
166 static void      db_initliblist(LIBRARY*);
167 static void      db_initnetworklist(NETWORK*);
168 static void      db_initnodeinstlist(NODEINST*);
169 static void      db_initnodeprotolist(NODEPROTO*);
170 static void      db_initpolygonlist(POLYGON*);
171 static void      db_initportarcinstlist(PORTARCINST*);
172 static void      db_initportexpinstlist(PORTEXPINST*);
173 static void      db_initportprotolist(PORTPROTO*);
174 static void      db_initrtnodelist(RTNODE*);
175 static void      db_inittechlist(TECHNOLOGY*);
176 static void      db_inittoollist(TOOL*);
177 static void      db_initviewlist(VIEW*);
178 static void      db_initwindowframelist(WINDOWFRAME*);
179 static void      db_initwindowlist(WINDOWPART*);
180 static BOOLEAN   db_insindvar(INTBIG, INTBIG, VARIABLE*, INTBIG, INTBIG);
181 #ifdef DEBUGMEMORY
182   static BOOLEAN db_setindvar(INTBIG, INTBIG, VARIABLE*, INTBIG, INTBIG, CHAR*, INTBIG);
183   static BOOLEAN db_setval(UCHAR1*, UCHAR1*, INTBIG, CLUSTER*, CHAR*, INTBIG);
184   static BOOLEAN db_setvalkey(INTSML*, VARIABLE**, INTBIG, INTBIG, INTBIG, INTBIG, CLUSTER*, CHAR*, INTBIG);
185   static BOOLEAN db_setvalvar(VARIABLE*, INTBIG, INTBIG, CLUSTER*, CHAR*, INTBIG);
186 #else
187   static BOOLEAN db_setindvar(INTBIG, INTBIG, VARIABLE*, INTBIG, INTBIG);
188   static BOOLEAN db_setval(UCHAR1*, UCHAR1*, INTBIG, CLUSTER*);
189   static BOOLEAN db_setvalkey(INTSML*, VARIABLE**, INTBIG, INTBIG, INTBIG, INTBIG, CLUSTER*);
190   static BOOLEAN db_setvalvar(VARIABLE*, INTBIG, INTBIG, CLUSTER*);
191 #endif
192 static void      db_makefontassociationdescript(UINTBIG *descript, INTBIG *fontusage, INTBIG numfonts);
193 static void      db_makefontassociationvar(INTSML numvar, VARIABLE *firstvar, INTBIG *fontusage, INTBIG numfonts);
194 static void      db_makefontassociations(LIBRARY *lib);
195 static void      db_renamevar(INTSML, VARIABLE*, INTBIG, INTBIG);
196 static CLUSTER  *db_whichcluster(INTBIG, INTBIG);
197 
198 /*
199  * Routine to free all memory associated with this module.
200  */
db_freevariablememory(void)201 void db_freevariablememory(void)
202 {
203 	REGISTER INTBIG i;
204 	REGISTER PARCELL *pc;
205 
206 	for(i=0; i<el_numnames; i++) efree((CHAR *)el_namespace[i]);
207 	if (el_numnames != 0) efree((CHAR *)el_namespace);
208 	if (db_optionvarcachecount > 0) efree((CHAR *)db_optionvarcache);
209 
210 	while (db_firstparcell != NOPARCELL)
211 	{
212 		pc = db_firstparcell;
213 		db_firstparcell = pc->nextparcell;
214 		efree((CHAR *)pc->parname);
215 		efree((CHAR *)pc->shortname);
216 		db_freeparcell(pc);
217 	}
218 	while (db_parcellfree != NOPARCELL)
219 	{
220 		pc = db_parcellfree;
221 		db_parcellfree = pc->nextparcell;
222 		efree((CHAR *)pc);
223 	}
224 }
225 
226 /************************* ACCESSING VARIABLES *************************/
227 
228 /*
229  * routine to find the variable with name "name", which must be of type
230  * "want", on the object whose address is "addr" and type is "type".  If
231  * "want" is -1 then any type will do.  If the variable does not exist or
232  * is the wrong type, NOVARIABLE is returned.  If the variable is code, it
233  * will be evaluated and a pseudo-variable will be returned that holds the
234  * value.
235  */
getval(INTBIG addr,INTBIG type,INTBIG want,CHAR * name)236 VARIABLE *getval(INTBIG addr, INTBIG type, INTBIG want, CHAR *name)
237 {
238 	VARIABLE *var;
239 	REGISTER VARIABLE *retvar;
240 	REGISTER CHAR *pp;
241 	REGISTER INTBIG search;
242 	REGISTER BOOLEAN oldonobjectstate;
243 
244 	/* accumulate the object that the "getval" is on (should use mutex) */
245 	oldonobjectstate = db_onanobject;
246 	if (!db_onanobject)
247 	{
248 		db_onanobject = TRUE;
249 		db_onobjectaddr = addr;
250 		db_onobjecttype = type;
251 	}
252 	db_lastonobjectaddr = addr;
253 	db_lastonobjecttype = type;
254 
255 	retvar = NOVARIABLE;
256 	search = initobjlist(addr, type, FALSE);
257 	if (search != 0)
258 	{
259 		for(;;)
260 		{
261 			pp = nextobjectlist(&var, search);
262 			if (pp == 0) break;
263 			if (namesame(pp, name) == 0)
264 			{
265 				/* variable found: make sure it is right type */
266 				if (want == -1 || ((INTBIG)(var->type & (VTYPE|VISARRAY))) == want)
267 				{
268 					retvar = evalvar(var, addr, type);
269 					if (retvar != var && retvar != NOVARIABLE)
270 					{
271 						/* check the type again */
272 						if (want != -1 && ((INTBIG)(retvar->type & (VTYPE|VISARRAY))) != want)
273 							retvar = NOVARIABLE;
274 					}
275 				}
276 				break;
277 			}
278 		}
279 	}
280 
281 	/* complete the accumulation of the "getval" object (should use mutex) */
282 	db_onanobject = oldonobjectstate;
283 
284 	/* return the result */
285 	return(retvar);
286 }
287 
288 /*
289  * routine to find the variable with name "name", which must be of type
290  * "want", on the object whose address is "addr" and type is "type".  If
291  * "want" is -1 then any type will do.  If the variable does not exist or
292  * is the wrong type, NOVARIABLE is returned.  If the variable is code, it
293  * will not be evaluated.
294  */
getvalnoeval(INTBIG addr,INTBIG type,INTBIG want,CHAR * name)295 VARIABLE *getvalnoeval(INTBIG addr, INTBIG type, INTBIG want, CHAR *name)
296 {
297 	VARIABLE *var;
298 	REGISTER VARIABLE *retvar;
299 	REGISTER CHAR *pp;
300 	REGISTER INTBIG search;
301 	REGISTER BOOLEAN oldonobjectstate;
302 
303 	/* accumulate the object that the "getval" is on (should use mutex) */
304 	oldonobjectstate = db_onanobject;
305 	if (!db_onanobject)
306 	{
307 		db_onanobject = TRUE;
308 		db_onobjectaddr = addr;
309 		db_onobjecttype = type;
310 	}
311 	db_lastonobjectaddr = addr;
312 	db_lastonobjecttype = type;
313 
314 	retvar = NOVARIABLE;
315 	search = initobjlist(addr, type, FALSE);
316 	if (search != 0)
317 	{
318 		for(;;)
319 		{
320 			pp = nextobjectlist(&var, search);
321 			if (pp == 0) break;
322 			if (namesame(pp, name) == 0)
323 			{
324 				/* variable found: make sure it is right type */
325 				if (want == -1 || ((INTBIG)(var->type & (VTYPE|VISARRAY))) == want)
326 					retvar = var;
327 				break;
328 			}
329 		}
330 	}
331 
332 	/* complete the accumulation of the "getval" object (should use mutex) */
333 	db_onanobject = oldonobjectstate;
334 
335 	/* return the result */
336 	return(retvar);
337 }
338 
339 /*
340  * routine to find the variable with key "key", which must be of type "want",
341  * on the object whose address is "addr" and type is "type".  If the
342  * variable does not exist or is the wrong type, NOVARIABLE is returned.
343  * If the variable is code, it will be evaluated and a pseudo-variable
344  * will be returned that holds the value.
345  */
getvalkey(INTBIG addr,INTBIG type,INTBIG want,INTBIG key)346 VARIABLE *getvalkey(INTBIG addr, INTBIG type, INTBIG want, INTBIG key)
347 {
348 	REGISTER INTBIG med;
349 	INTSML *mynumvar;
350 	REGISTER VARIABLE *var, *retvar;
351 	VARIABLE **myfirstvar;
352 	REGISTER BOOLEAN oldonobjectstate;
353 
354 	/* accumulate the object that the "getval" is on (should use mutex) */
355 	oldonobjectstate = db_onanobject;
356 	if (!db_onanobject)
357 	{
358 		db_onanobject = TRUE;
359 		db_onobjectaddr = addr;
360 		db_onobjecttype = type;
361 	}
362 	db_lastonobjectaddr = addr;
363 	db_lastonobjecttype = type;
364 
365 	/* get the firstvar/numvar into the globals */
366 	retvar = NOVARIABLE;
367 	if (!db_getvarptr(addr, type, &myfirstvar, &mynumvar))
368 	{
369 		/* binary search variable space for the key */
370 		med = db_binarysearch(*mynumvar, *myfirstvar, key);
371 		if (med >= 0)
372 		{
373 			/* get the variable */
374 			var = &(*myfirstvar)[med];
375 
376 			/* make sure it is right type if a type was specified */
377 			if (want == -1 || ((INTBIG)(var->type & (VTYPE|VISARRAY))) == want)
378 			{
379 				retvar = evalvar(var, addr, type);
380 				if (retvar != var && retvar != NOVARIABLE)
381 				{
382 					/* check the type again */
383 					if (want != -1 && ((INTBIG)(retvar->type & (VTYPE|VISARRAY))) != want)
384 						retvar = NOVARIABLE;
385 				}
386 			}
387 		}
388 	}
389 
390 	/* complete the accumulation of the "getval" object (should use mutex) */
391 	db_onanobject = oldonobjectstate;
392 
393 	/* return the result */
394 	return(retvar);
395 }
396 
397 /*
398  * routine to find the variable with key "key", which must be of type "want",
399  * on the object whose address is "addr" and type is "type".  If the
400  * variable does not exist or is the wrong type, NOVARIABLE is returned.
401  * If the variable is code, it will not be evaluated.
402  */
getvalkeynoeval(INTBIG addr,INTBIG type,INTBIG want,INTBIG key)403 VARIABLE *getvalkeynoeval(INTBIG addr, INTBIG type, INTBIG want, INTBIG key)
404 {
405 	REGISTER INTBIG med;
406 	INTSML *mynumvar;
407 	REGISTER VARIABLE *var, *retvar;
408 	VARIABLE **myfirstvar;
409 	REGISTER BOOLEAN oldonobjectstate;
410 
411 	/* accumulate the object that the "getval" is on (should use mutex) */
412 	oldonobjectstate = db_onanobject;
413 	if (!db_onanobject)
414 	{
415 		db_onanobject = TRUE;
416 		db_onobjectaddr = addr;
417 		db_onobjecttype = type;
418 	}
419 	db_lastonobjectaddr = addr;
420 	db_lastonobjecttype = type;
421 
422 	/* get the firstvar/numvar into the globals */
423 	retvar = NOVARIABLE;
424 	if (!db_getvarptr(addr, type, &myfirstvar, &mynumvar))
425 	{
426 		/* binary search variable space for the key */
427 		med = db_binarysearch(*mynumvar, *myfirstvar, key);
428 		if (med >= 0)
429 		{
430 			/* get the variable */
431 			var = &(*myfirstvar)[med];
432 
433 			/* make sure it is right type if a type was specified */
434 			if (want == -1 || ((INTBIG)(var->type & (VTYPE|VISARRAY))) == want)
435 				retvar = var;
436 		}
437 	}
438 
439 	/* complete the accumulation of the "getval" object (should use mutex) */
440 	db_onanobject = oldonobjectstate;
441 
442 	/* return the result */
443 	return(retvar);
444 }
445 
446 /*
447  * Routine to set the current window to use when examining the value of variables.
448  * Returns the previous value of the default window.
449  */
setvariablewindow(WINDOWPART * win)450 WINDOWPART *setvariablewindow(WINDOWPART *win)
451 {
452 	REGISTER WINDOWPART *lastwin;
453 
454 	lastwin = db_onobjectwin;
455 	db_onobjectwin = win;
456 	return(lastwin);
457 }
458 
459 /*
460  * Routine to return the address and type of the current object that is being querried with
461  * "getval()", "getvalkey()", "getvalnoeval()", or "getvalkeynoeval()".
462  * Returns TRUE if there is a valid object, FALSE if not.
463  */
getcurrentvariableenvironment(INTBIG * addr,INTBIG * type,WINDOWPART ** win)464 BOOLEAN getcurrentvariableenvironment(INTBIG *addr, INTBIG *type, WINDOWPART **win)
465 {
466 	if (db_onanobject)
467 	{
468 		*addr = db_onobjectaddr;
469 		*type = db_onobjecttype;
470 		*win = db_onobjectwin;
471 		return(db_onanobject);
472 	}
473 	return(FALSE);
474 }
475 
476 /*
477  * Routine to return the last address and type of the object from which a "getval()",
478  * "getvalkey()", "getvalnoeval()", or "getvalkeynoeval()" was called.
479  * Returns TRUE if there is a valid object, FALSE if not.
480  */
getlastvariableobject(INTBIG * addr,INTBIG * type)481 BOOLEAN getlastvariableobject(INTBIG *addr, INTBIG *type)
482 {
483 	if (db_onanobject)
484 	{
485 		*addr = db_lastonobjectaddr;
486 		*type = db_lastonobjecttype;
487 		return(db_onanobject);
488 	}
489 	return(FALSE);
490 }
491 
492 #define NUMEVALS 100
493 
494 /*
495  * Routine to return a VARIABLE that can be used as a placeholder for a real one.
496  * This is needed when a VARIABLE is code (a dummy one must be created to hold the
497  * evaluation).  It is also needed when generating VARIABLEs for objects that are part
498  * of the fixed C structures.
499  */
db_dummyvariable(void)500 VARIABLE *db_dummyvariable(void)
501 {
502 	REGISTER VARIABLE *var;
503 	static INTBIG evalnum = 0;
504 	static VARIABLE retvar[NUMEVALS];
505 
506 	/* code cannot be called by multiple procesors: uses globals */
507 	NOT_REENTRANT;
508 
509 	/* prepare to evaluate the variable */
510 	evalnum++;
511 	if (evalnum >= NUMEVALS) evalnum = 0;
512 	var = &retvar[evalnum];
513 	return(var);
514 }
515 
516 /*
517  * routine to evaluate variable "var" and replace it with its true value if it is code
518  */
evalvar(VARIABLE * var,INTBIG addr,INTBIG type)519 VARIABLE *evalvar(VARIABLE *var, INTBIG addr, INTBIG type)
520 {
521 	REGISTER INTBIG language;
522 	REGISTER VARIABLE *thevar;
523 
524 	/* if this isn't code or even a variable, just return the input */
525 	if (var == NOVARIABLE) return(var);
526 	language = var->type & (VCODE1|VCODE2);
527 	if (language == 0) return(var);
528 
529 	/* set the environment */
530 	if (addr == 0) db_onanobject = FALSE; else
531 	{
532 		db_onanobject = TRUE;
533 		db_lastonobjectaddr = db_onobjectaddr = addr;
534 		db_lastonobjecttype = db_onobjecttype = type;
535 	}
536 
537 	/* evaluate the variable */
538 	thevar = doquerry((CHAR *)var->addr, language, var->type & ~(VCODE1|VCODE2));
539 
540 	/* remove the environment */
541 	db_onanobject = FALSE;
542 
543 	if (thevar == NOVARIABLE) return(var);
544 	thevar->key = var->key;
545 	TDCOPY(thevar->textdescript, var->textdescript);
546 	return(thevar);
547 }
548 
549 /*
550  * routine to get an entry in the array variable "name" in object "addr"
551  * which is of type "type".  Entry "aindex" is placed into "value".  Returns
552  * true on error.
553  */
getind(INTBIG addr,INTBIG type,CHAR * name,INTBIG aindex,INTBIG * value)554 BOOLEAN getind(INTBIG addr, INTBIG type, CHAR *name, INTBIG aindex, INTBIG *value)
555 {
556 	VARIABLE *var;
557 	REGISTER CHAR *pp;
558 	REGISTER INTBIG search;
559 
560 	search = initobjlist(addr, type, FALSE);
561 	if (search == 0) return(TRUE);
562 	for(;;)
563 	{
564 		pp = nextobjectlist(&var, search);
565 		if (pp == 0) break;
566 		if (namesame(pp, name) == 0) break;
567 	}
568 
569 	/* variable must exist */
570 	if (pp == 0) return(TRUE);
571 
572 	if ((var->type&VCANTSET) != 0) return(TRUE);
573 
574 	return(db_getindvar(var, aindex, value));
575 }
576 
577 /*
578  * routine to get an entry in the array variable whose key is "key" in object
579  * "addr" which is of type "type".  Entry "aindex" is placed in "value".
580  * The routine returns true upon error.
581  */
getindkey(INTBIG addr,INTBIG type,INTBIG key,INTBIG aindex,INTBIG * value)582 BOOLEAN getindkey(INTBIG addr, INTBIG type, INTBIG key, INTBIG aindex, INTBIG *value)
583 {
584 	VARIABLE **myfirstvar;
585 	INTSML *mynumvar;
586 	REGISTER INTBIG med;
587 
588 	/* get the attribute list into the globals */
589 	if (db_getvarptr(addr, type, &myfirstvar, &mynumvar)) return(TRUE);
590 
591 	/* binary search variable space for the key */
592 	med = db_binarysearch(*mynumvar, *myfirstvar, key);
593 
594 	/* variable must exist */
595 	if (med < 0) return(TRUE);
596 
597 	if (((*myfirstvar)[med].type&VCANTSET) != 0) return(TRUE);
598 
599 	/* get the variable */
600 	return(db_getindvar(&(*myfirstvar)[med], aindex, value));
601 }
602 
603 BOOLEAN db_parentvaldefaulted = FALSE;
604 
605 /*
606  * Routine to examine the hierarchy and find the variable "name".
607  * Looks as many as "height" levels up the hierarchy (arbitrary if zero).
608  * Returns the variable if found.
609  */
getparentval(CHAR * name,INTBIG height)610 VARIABLE *getparentval(CHAR *name, INTBIG height)
611 {
612 	REGISTER INTBIG key;
613 
614 	key = makekey(name);
615 	return(getparentvalkey(key, height));
616 }
617 
618 /*
619  * Routine to examine the hierarchy and find the variable with key "key".
620  * Looks as many as "height" levels up the hierarchy (arbitrary if zero).
621  * Returns the variable if found.
622  */
getparentvalkey(INTBIG key,INTBIG height)623 VARIABLE *getparentvalkey(INTBIG key, INTBIG height)
624 {
625 	NODEINST **localnilist;
626 	INTBIG localdepth, *localindexlist, oldclimb;
627 	REGISTER NODEINST *ni;
628 	REGISTER INTBIG i, climbed;
629 	REGISTER VARIABLE *var, *varne;
630 
631 	/* search hierarchical path */
632 	gettraversalpath(el_curlib->curnodeproto, db_onobjectwin, &localnilist, &localindexlist, &localdepth, height);
633 	climbed = 0;
634 	oldclimb = getpopouthierarchy();
635 
636 	for(i = localdepth - 1; i >= 0; i--)
637 	{
638 		ni = localnilist[i];
639 
640 		/*
641 		 * because evaluation of this variable may involve examination of the
642 		 * hierarchy, the hierarchy stack must get shortened
643 		 */
644 		climbed++;
645 		popouthierarchy(oldclimb+climbed);
646 
647 		/* look for the variable on the instance up the hierarchy */
648 		var = getvalkey((INTBIG)ni, VNODEINST, -1, key);
649 
650 		/* restore hierarchy stack */
651 		popouthierarchy(oldclimb);
652 
653 		/* return value if found */
654 		if (var != NOVARIABLE)
655 		{
656 			/* make sure the variable is of type "parameter" */
657 			if (TDGETISPARAM(var->textdescript) == 0)
658 			{
659 				ttyputmsg(_("Warning: Cell %s, node %s has attribute %s used as a parameter"),
660 					describenodeproto(ni->parent), describenodeinst(ni), truevariablename(var));
661 
662 				/* repair the bit */
663 				popouthierarchy(climbed);
664 				varne = getvalkeynoeval((INTBIG)ni, VNODEINST, -1, key);
665 				popouthierarchy(0);
666 				if (varne != NOVARIABLE)
667 				{
668 					TDSETISPARAM(varne->textdescript, VTISPARAMETER);
669 					ni->parent->lib->userbits |= LIBCHANGEDMINOR;
670 				}
671 			}
672 			return(var);
673 		}
674 
675 		/* stop climbing hierarchy if limited */
676 		if (height != 0)
677 		{
678 			height--;
679 			if (height <= 0) break;
680 		}
681 	}
682 	db_parentvaldefaulted = TRUE;
683 	return(NOVARIABLE);
684 }
685 
686 /*
687  * Routine to return TRUE if the any call to "getparentval()" or "getparentvalkey()" returned
688  * a default value.  Resets the flag at each call.
689  */
parentvaldefaulted(void)690 BOOLEAN parentvaldefaulted(void)
691 {
692 	REGISTER BOOLEAN retval;
693 
694 	retval = db_parentvaldefaulted;
695 	db_parentvaldefaulted = FALSE;
696 	return(retval);
697 }
698 
699 /*
700  * routine to modify the text descriptor on variable "var", which resides on
701  * object "addr" of type "type".  The new descriptor is set to "newdescript"
702  */
modifydescript(INTBIG addr,INTBIG type,VARIABLE * var,UINTBIG * newdescript)703 void modifydescript(INTBIG addr, INTBIG type, VARIABLE *var, UINTBIG *newdescript)
704 {
705 	UINTBIG olddescript[TEXTDESCRIPTSIZE];
706 
707 	if (var != NOVARIABLE)
708 	{
709 		TDCOPY(olddescript, var->textdescript);
710 		TDCOPY(var->textdescript, newdescript);
711 	}
712 
713 	/* handle change control, constraint, and broadcast */
714 	if (!db_donextchangequietly && !db_dochangesquietly)
715 	{
716 		/* tell constraint system about killed variable */
717 		(*el_curconstraint->modifydescript)(addr, type, var->key, olddescript);
718 
719 		db_setchangecell(db_whichnodeproto(addr, type));
720 
721 		/* record the change */
722 		(void)db_change(addr, DESCRIPTMOD, type, var->key, var->type, olddescript[0],
723 			olddescript[1], 0);
724 	}
725 	db_donextchangequietly = FALSE;
726 
727 	/* mark a change to the database */
728 	db_changetimestamp++;
729 }
730 
731 /*
732  * routine to return the length of the array in variable "var".  If it is not
733  * an array, the value -1 is returned.
734  */
getlength(VARIABLE * var)735 INTBIG getlength(VARIABLE *var)
736 {
737 	REGISTER INTBIG len;
738 
739 	if ((var->type&VISARRAY) == 0) return(-1);
740 	len = (var->type&VLENGTH) >> VLENGTHSH;
741 	if (len != 0) return(len);
742 
743 	if ((var->type&VTYPE) == VCHAR)
744 	{
745 		for(len=0; ((((CHAR *)var->addr)[len])&0377) != 0377; len++) ;
746 	} else if ((var->type&VTYPE) == VFLOAT)
747 	{
748 		for(len=0; ((float *)var->addr)[len] != -1; len++) ;
749 	} else if ((var->type&VTYPE) == VDOUBLE)
750 	{
751 		for(len=0; ((double *)var->addr)[len] != -1; len++) ;
752 	} else if ((var->type&VTYPE) == VSHORT)
753 	{
754 		for(len=0; ((INTSML *)var->addr)[len] != -1; len++) ;
755 	} else
756 	{
757 		for(len=0; ((INTBIG *)var->addr)[len] != -1; len++) ;
758 	}
759 	return(len);
760 }
761 
762 /*
763  * routine to convert a variable name in "name" to a key and return it.
764  * If an error is detected, the routine returns -1.
765  */
makekey(CHAR * name)766 INTBIG makekey(CHAR *name)
767 {
768 	REGISTER CHAR **newname;
769 	REGISTER INTBIG med, i;
770 
771 	/* search namespace for this name */
772 	med = db_getkey(name);
773 	if (med >= 0) return((INTBIG)el_namespace[med]);
774 
775 	/* convert return value to proper index for new name */
776 	med = -med-1;
777 
778 	/* make sure the name is valid */
779 	for(i=0; name[i] != 0; i++) if (name[i] == ' ' || name[i] == '\t')
780 		return(db_error(DBBADNAME|DBMAKEKEY));
781 
782 	/* allocate space for new list */
783 	newname = (CHAR **)emalloc(((el_numnames+1)*(sizeof (CHAR *))), db_cluster);
784 	if (newname == 0) return(db_error(DBNOMEM|DBMAKEKEY));
785 
786 	/* copy old list up to the new entry */
787 	for(i=0; i<med; i++) newname[i] = el_namespace[i];
788 
789 	/* add the new entry */
790 	if (allocstring(&newname[med], name, db_cluster)) return(-1);
791 
792 	/* copy old list after the new entry */
793 	for(i=med; i<el_numnames; i++) newname[i+1] = el_namespace[i];
794 
795 	/* clean-up */
796 	if (el_numnames != 0) efree((CHAR *)el_namespace);
797 	el_namespace = newname;
798 	el_numnames++;
799 	return((INTBIG)el_namespace[med]);
800 }
801 
802 /*
803  * routine to convert a variable key in "key" to a name and return it.
804  * Because of the techniques used, this is trivial.
805  */
makename(INTBIG key)806 CHAR *makename(INTBIG key)
807 {
808 	return((CHAR *)key);
809 }
810 
811 /*
812  * routine to initialize a search of the variable names on object "addr"
813  * of type "type".  Subsequent calls to "nextobjectlist" will return
814  * variable names and fill the parameter with the variable addresses.
815  * If "restrictdirect" is nonzero, only list those attributes directly on the
816  * object (and not those in linked lists).  The routine returns zero upon
817  * error, and otherwise returns a value that must be passed to the subsequent
818  * "nextobjectlist" calls
819  */
initobjlist(INTBIG addr,INTBIG type,BOOLEAN restrictdirect)820 INTBIG initobjlist(INTBIG addr, INTBIG type, BOOLEAN restrictdirect)
821 {
822 	/* code cannot be called by multiple procesors: uses globals */
823 	NOT_REENTRANT;
824 
825 	db_thisapack = &db_attrpacket[db_apackindex++];
826 	if (db_apackindex >= MAXAPACK) db_apackindex = 0;
827 	switch (type&VTYPE)
828 	{
829 		case VNODEINST:    db_initnodeinstlist((NODEINST *)addr);       break;
830 		case VNODEPROTO:   db_initnodeprotolist((NODEPROTO *)addr);     break;
831 		case VPORTARCINST: db_initportarcinstlist((PORTARCINST *)addr); break;
832 		case VPORTEXPINST: db_initportexpinstlist((PORTEXPINST *)addr); break;
833 		case VPORTPROTO:   db_initportprotolist((PORTPROTO *)addr);     break;
834 		case VARCINST:     db_initarcinstlist((ARCINST *)addr);         break;
835 		case VARCPROTO:    db_initarcprotolist((ARCPROTO *)addr);       break;
836 		case VGEOM:        db_initgeomlist((GEOM *)addr);               break;
837 		case VLIBRARY:     db_initliblist((LIBRARY *)addr);             break;
838 		case VTECHNOLOGY:  db_inittechlist((TECHNOLOGY *)addr);         break;
839 		case VTOOL:        db_inittoollist((TOOL *)addr);               break;
840 		case VRTNODE:      db_initrtnodelist((RTNODE *)addr);           break;
841 		case VNETWORK:     db_initnetworklist((NETWORK *)addr);         break;
842 		case VVIEW:        db_initviewlist((VIEW *)addr);               break;
843 		case VWINDOWPART:  db_initwindowlist((WINDOWPART *)addr);       break;
844 		case VGRAPHICS:    db_initgraphicslist((GRAPHICS *)addr);       break;
845 		case VCONSTRAINT:  db_initconstraintlist((CONSTRAINT *)addr);   break;
846 		case VWINDOWFRAME: db_initwindowframelist((WINDOWFRAME *)addr); break;
847 		case VPOLYGON:     db_initpolygonlist((POLYGON *)addr);         break;
848 		default:
849 			(void)db_error(DBBADOBJECT|DBINITOBJLIST);
850 			return(0);
851 	}
852 	if (restrictdirect)
853 		if (db_thisapack->state != NULLNAME) db_thisapack->state = SPECNAME;
854 	return((INTBIG)db_thisapack);
855 }
856 
857 /*
858  * routine to return the next name in the list (and the associated variable)
859  */
nextobjectlist(VARIABLE ** actualvar,INTBIG ain)860 CHAR *nextobjectlist(VARIABLE **actualvar, INTBIG ain)
861 {
862 	struct attrsearch *apack;
863 	REGISTER INTBIG datasize;
864 	REGISTER BOOLEAN indir;
865 	REGISTER CHAR *retval;
866 	REGISTER NODEINST *ni;
867 	REGISTER ARCINST *ai;
868 	static CHAR line[50];
869 	REGISTER VARIABLE *var, *nvar;
870 
871 	apack = (struct attrsearch *)ain;
872 	for(;;) switch (apack->state)
873 	{
874 		case SPECNAME:	/* looking for special names in object structure */
875 			if (apack->vars[apack->specindex].name != 0)
876 			{
877 				/* get next special name */
878 				*actualvar = var = db_dummyvariable();
879 				var->key = apack->specindex;
880 				var->type = apack->vars[apack->specindex].type;
881 				TDCLEAR(var->textdescript);
882 				TDSETSIZE(var->textdescript, TXTSETQLAMBDA(4));
883 				var->addr = (INTBIG)apack->vars[apack->specindex].ptr - apack->proto + apack->object;
884 				db_realaddress = var->addr;
885 				indir = FALSE;
886 				if ((var->type&VISARRAY) == 0) indir = TRUE; else
887 					if ((var->type&VCREF) == 0) indir = TRUE;
888 				if (indir)
889 				{
890 					datasize = db_getdatasize(var->type);
891 					var->addr = db_assignvalue((void *)var->addr, datasize);
892 				}
893 				var->type |= VCREF;
894 				return(apack->vars[apack->specindex++].name);
895 			}
896 			/* no more special names, go to next case */
897 			apack->state = VARNAME;
898 			break;
899 		case VARNAME:	/* looking for variable names in object */
900 			if (apack->varindex < *apack->numvar)
901 			{
902 				/* get next variable name */
903 				*actualvar = &(*apack->firstvar)[apack->varindex];
904 				return((CHAR *)(*apack->firstvar)[apack->varindex++].key);
905 			}
906 			/* no more variable names, go to terminal case */
907 			apack->state = NULLNAME;
908 			break;
909 		case ARCINAME:	/* looking for arcs in the nodeproto */
910 			if (apack->arciname != NOARCINST)
911 			{
912 				/* get next arcinst name */
913 				ai = apack->arciname;
914 				apack->arciname = apack->arciname->nextarcinst;
915 				*actualvar = var = db_dummyvariable();
916 				var->key = -1;
917 				var->type = VARCINST;
918 				TDCLEAR(var->textdescript);
919 				TDSETSIZE(var->textdescript, TXTSETQLAMBDA(4));
920 				var->addr = (INTBIG)ai;
921 				nvar = getvalkey((INTBIG)ai, VARCINST, VSTRING, el_arc_name_key);
922 				if (nvar != NOVARIABLE) return((CHAR *)nvar->addr);
923 				(void)esnprintf(line, 50, x_("arc%ld"), (INTBIG)ai);
924 				return(line);
925 			}
926 			apack->state = NODEINAME;
927 			break;
928 		case NODEINAME:	/* looking for nodes in the nodeproto */
929 			if (apack->nodeiname != NONODEINST)
930 			{
931 				/* get next nodeinst name */
932 				ni = apack->nodeiname;
933 				apack->nodeiname = apack->nodeiname->nextnodeinst;
934 				*actualvar = var = db_dummyvariable();
935 				var->key = -1;
936 				var->type = VNODEINST;
937 				TDCLEAR(var->textdescript);
938 				TDSETSIZE(var->textdescript, TXTSETQLAMBDA(4));
939 				var->addr = (INTBIG)ni;
940 				nvar = getvalkey((INTBIG)ni, VNODEINST, VSTRING, el_node_name_key);
941 				if (nvar != NOVARIABLE) return((CHAR *)nvar->addr);
942 				(void)esnprintf(line, 50, x_("node%ld"), (INTBIG)ni);
943 				return(line);
944 			}
945 			/* no more nodeinst names, go to next case */
946 			apack->state = PORTCNAME;
947 			break;
948 		case PORTCNAME:	/* looking for port names on nodeproto */
949 			if (apack->portprotoname != NOPORTPROTO)
950 			{
951 				/* get next port name */
952 				*actualvar = var = db_dummyvariable();
953 				var->key = -1;
954 				TDCLEAR(var->textdescript);
955 				TDSETSIZE(var->textdescript, TXTSETQLAMBDA(4));
956 				var->type = VPORTPROTO;   var->addr = (INTBIG)apack->portprotoname;
957 				retval = apack->portprotoname->protoname;
958 				apack->portprotoname = apack->portprotoname->nextportproto;
959 				return(retval);
960 			}
961 			/* no more port names, go to next case */
962 			apack->state = SPECNAME;
963 			break;
964 		case PORTANAME:	/* looking for portarcinst names on nodeinst */
965 			if (apack->portarcinstname != NOPORTARCINST)
966 			{
967 				/* get next portarcinst name */
968 				*actualvar = var = db_dummyvariable();
969 				var->key = -1;
970 				var->type = VPORTARCINST;
971 				TDCLEAR(var->textdescript);
972 				TDSETSIZE(var->textdescript, TXTSETQLAMBDA(4));
973 				var->addr = (INTBIG)apack->portarcinstname;
974 				retval = apack->portarcinstname->proto->protoname;
975 				apack->portarcinstname = apack->portarcinstname->nextportarcinst;
976 				return(retval);
977 			}
978 			/* no more portarcinst names, go to next case */
979 			apack->state = PORTENAME;
980 			break;
981 		case PORTENAME:	/* looking for portexpinst names on nodeinst */
982 			if (apack->portexpinstname != NOPORTEXPINST)
983 			{
984 				/* get next portexpinst name */
985 				*actualvar = var = db_dummyvariable();
986 				var->key = -1;
987 				var->type = VPORTEXPINST;
988 				TDCLEAR(var->textdescript);
989 				TDSETSIZE(var->textdescript, TXTSETQLAMBDA(4));
990 				var->addr = (INTBIG)apack->portexpinstname;
991 				retval = apack->portexpinstname->proto->protoname;
992 				apack->portexpinstname = apack->portexpinstname->nextportexpinst;
993 				return(retval);
994 			}
995 			/* no more portexpinst names, go to next case */
996 			apack->state = SPECNAME;
997 			break;
998 		case ARCNAME:	/* looking for arcs in the technology */
999 			if (apack->arcprotoname != NOARCPROTO)
1000 			{
1001 				/* get next arcproto name */
1002 				*actualvar = var = db_dummyvariable();
1003 				var->key = -1;
1004 				TDCLEAR(var->textdescript);
1005 				TDSETSIZE(var->textdescript, TXTSETQLAMBDA(4));
1006 				var->type = VARCPROTO;   var->addr = (INTBIG)apack->arcprotoname;
1007 				retval = apack->arcprotoname->protoname;
1008 				apack->arcprotoname = apack->arcprotoname->nextarcproto;
1009 				return(retval);
1010 			}
1011 			/* no more arcproto names, go to next case */
1012 			apack->state = NODENAME;
1013 			break;
1014 		case NODENAME:	/* looking for cells in the tech/lib */
1015 			if (apack->nodeprotoname != NONODEPROTO)
1016 			{
1017 				/* get next cell name */
1018 				*actualvar = var = db_dummyvariable();
1019 				var->key = -1;
1020 				TDCLEAR(var->textdescript);
1021 				TDSETSIZE(var->textdescript, TXTSETQLAMBDA(4));
1022 				var->type = VNODEPROTO;   var->addr = (INTBIG)apack->nodeprotoname;
1023 				retval = describenodeproto(apack->nodeprotoname);
1024 				apack->nodeprotoname = apack->nodeprotoname->nextnodeproto;
1025 				return(retval);
1026 			}
1027 			/* no more nodeproto names, go to next case */
1028 			apack->state = SPECNAME;
1029 			break;
1030 		case NULLNAME:
1031 			*actualvar = NOVARIABLE;
1032 			return(0);
1033 	}
1034 }
1035 
1036 /********************** DELETING AND RENAMING VARIABLES *********************/
1037 
1038 /*
1039  * delete the variable "name" from object whose address is "addr" and type
1040  * is "type".  Returns true if there is an error.
1041  */
delval(INTBIG addr,INTBIG type,CHAR * name)1042 BOOLEAN delval(INTBIG addr, INTBIG type, CHAR *name)
1043 {
1044 	REGISTER INTBIG key;
1045 
1046 	key = makekey(name);
1047 	if (key == -1)
1048 	{
1049 		db_donextchangequietly = FALSE;
1050 		return(TRUE);
1051 	}
1052 
1053 	return(delvalkey(addr, type, key));
1054 }
1055 
1056 /*
1057  * delete the variable with the key "key" from object whose address is
1058  * "addr" and type is "type".  Returns true if there is an error.
1059  */
delvalkey(INTBIG addr,INTBIG type,INTBIG key)1060 BOOLEAN delvalkey(INTBIG addr, INTBIG type, INTBIG key)
1061 {
1062 	REGISTER VARIABLE *var;
1063 	REGISTER CHAR *varname;
1064 	VARIABLE **myfirstvar;
1065 	INTSML *mynumvar;
1066 	REGISTER INTSML i, j;
1067 	REGISTER INTBIG oldaddr, oldtype;
1068 	UINTBIG olddescript[TEXTDESCRIPTSIZE];
1069 
1070 	/* get the firstvar/numvar pointers */
1071 	if (db_getvarptr(addr, type, &myfirstvar, &mynumvar))
1072 	{
1073 		db_donextchangequietly = FALSE;
1074 		return(TRUE);
1075 	}
1076 
1077 	/* search for the variable in the list */
1078 	for(i=0; i<*mynumvar; i++)
1079 		if ((*myfirstvar)[i].key == key) break;
1080 	if (i >= *mynumvar)
1081 	{
1082 		if (key != -1) varname = makename(key); else
1083 			varname = _("FIXED VARIABLE");
1084 		ttyputmsg(_("Internal error: tried to delete %s on object of type %s.  No worry."),
1085 			varname, db_describetype(type));
1086 		db_donextchangequietly = FALSE;
1087 		(void)db_error(DBNOVAR|DBDELVALKEY);
1088 		return(TRUE);
1089 	}
1090 
1091 	/* delete the variable */
1092 	var = &(*myfirstvar)[i];
1093 	oldaddr = var->addr;
1094 	oldtype = var->type;
1095 	TDCOPY(olddescript, var->textdescript);
1096 
1097 	/* delete the entry in the variable list */
1098 	(*mynumvar)--;
1099 	for(j = i; j < *mynumvar; j++)
1100 	{
1101 		(*myfirstvar)[j].key  = (*myfirstvar)[j+1].key;
1102 		(*myfirstvar)[j].type = (*myfirstvar)[j+1].type;
1103 		TDCOPY((*myfirstvar)[j].textdescript, (*myfirstvar)[j+1].textdescript);
1104 		(*myfirstvar)[j].addr = (*myfirstvar)[j+1].addr;
1105 	}
1106 	if (*mynumvar == 0) efree((CHAR *)*myfirstvar);
1107 
1108 	/* handle change control, constraint, and broadcast */
1109 	if (!db_donextchangequietly && !db_dochangesquietly)
1110 	{
1111 		/* tell constraint system about killed variable */
1112 		(*el_curconstraint->killvariable)(addr, type, key, oldaddr, oldtype, olddescript);
1113 
1114 		/* record the change */
1115 		(void)db_change((INTBIG)addr, VARIABLEKILL, type, key, oldaddr, oldtype, olddescript[0],
1116 			olddescript[1]);
1117 	} else
1118 	{
1119 		/* not going through change control, so delete the memory now */
1120 		db_freevar(oldaddr, oldtype);
1121 	}
1122 	db_donextchangequietly = FALSE;
1123 
1124 	/* mark a change to the database */
1125 	if (type != VTOOL || addr != (INTBIG)us_tool) db_changetimestamp++;
1126 	return(FALSE);
1127 }
1128 
1129 /*
1130  * routine to rename variable "oldname" to "newname" everywhere in the
1131  * database.
1132  * This routine does not delete the old name from the namespace but it does
1133  * rename the variable wherever it exists, so the old name is no longer
1134  * in use.  NOTE: this does not check variables on R-tree nodes.
1135  */
renameval(CHAR * oldname,CHAR * newname)1136 void renameval(CHAR *oldname, CHAR *newname)
1137 {
1138 	REGISTER INTBIG oldkey, newkey;
1139 	REGISTER INTSML i;
1140 	REGISTER NODEPROTO *np;
1141 	REGISTER ARCPROTO *ap;
1142 	REGISTER PORTPROTO *pp;
1143 	REGISTER NETWORK *net;
1144 	REGISTER VIEW *v;
1145 	REGISTER NODEINST *ni;
1146 	REGISTER ARCINST *ai;
1147 	REGISTER LIBRARY *lib;
1148 	REGISTER TECHNOLOGY *tech;
1149 
1150 	/* get key of old name */
1151 	oldkey = db_getkey(oldname);
1152 	if (oldkey < 0) return;
1153 	oldkey = (INTBIG)el_namespace[oldkey];
1154 
1155 	/* make sure new name is different */
1156 	if (namesame(oldname, newname) == 0) return;
1157 
1158 	/* make new name key */
1159 	newkey = makekey(newname);
1160 	if (newkey < 0) return;
1161 
1162 	/* search the libraries */
1163 	for(lib = el_curlib; lib != NOLIBRARY; lib = lib->nextlibrary)
1164 	{
1165 		db_renamevar(lib->numvar, lib->firstvar, oldkey, newkey);
1166 		for(np = lib->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
1167 		{
1168 			db_renamevar(np->numvar, np->firstvar, oldkey, newkey);
1169 			for(pp = np->firstportproto; pp != NOPORTPROTO; pp = pp->nextportproto)
1170 			{
1171 				db_renamevar(pp->numvar, pp->firstvar, oldkey, newkey);
1172 				db_renamevar(pp->subportexpinst->numvar,
1173 					pp->subportexpinst->firstvar, oldkey, newkey);
1174 			}
1175 			for(ni = np->firstnodeinst; ni != NONODEINST; ni = ni->nextnodeinst)
1176 			{
1177 				db_renamevar(ni->numvar, ni->firstvar, oldkey, newkey);
1178 				db_renamevar(ni->geom->numvar, ni->geom->firstvar, oldkey, newkey);
1179 			}
1180 			for(ai = np->firstarcinst; ai != NOARCINST; ai = ai->nextarcinst)
1181 			{
1182 				db_renamevar(ai->numvar, ai->firstvar, oldkey, newkey);
1183 				db_renamevar(ai->geom->numvar, ai->geom->firstvar, oldkey, newkey);
1184 				db_renamevar(ai->end[0].portarcinst->numvar,
1185 					ai->end[0].portarcinst->firstvar, oldkey, newkey);
1186 				db_renamevar(ai->end[1].portarcinst->numvar,
1187 					ai->end[1].portarcinst->firstvar, oldkey, newkey);
1188 			}
1189 			for(net = np->firstnetwork; net != NONETWORK; net = net->nextnetwork)
1190 				db_renamevar(net->numvar, net->firstvar, oldkey, newkey);
1191 		}
1192 	}
1193 
1194 	/* search the tools */
1195 	for(i=0; i<el_maxtools; i++)
1196 		db_renamevar(el_tools[i].numvar, el_tools[i].firstvar, oldkey, newkey);
1197 
1198 	/* search the views */
1199 	for(v = el_views; v != NOVIEW; v = v->nextview)
1200 		db_renamevar(v->numvar, v->firstvar, oldkey, newkey);
1201 
1202 	/* search the technologies */
1203 	for(tech = el_technologies; tech != NOTECHNOLOGY; tech = tech->nexttechnology)
1204 	{
1205 		db_renamevar(tech->numvar, tech->firstvar, oldkey, newkey);
1206 		for(ap = tech->firstarcproto; ap != NOARCPROTO; ap = ap->nextarcproto)
1207 			db_renamevar(ap->numvar, ap->firstvar, oldkey, newkey);
1208 		for(np = tech->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
1209 			db_renamevar(np->numvar, np->firstvar, oldkey, newkey);
1210 	}
1211 
1212 	/* mark a change to the database */
1213 	db_changetimestamp++;
1214 }
1215 
1216 /************************* SETTING ENTIRE VARIABLES *************************/
1217 
1218 /*
1219  * routine to set the value of entry "name" in object "addr" which is of
1220  * type "type".  The entry is set to "newaddr" which has type "newtype".
1221  * The routine returns the variable address (NOVARIABLE on error).
1222  */
1223 #ifdef DEBUGMEMORY
_setval(INTBIG addr,INTBIG type,CHAR * name,INTBIG newaddr,INTBIG newtype,CHAR * module,INTBIG line)1224 VARIABLE *_setval(INTBIG addr, INTBIG type, CHAR *name, INTBIG newaddr, INTBIG newtype,
1225 	CHAR *module, INTBIG line)
1226 #else
1227 VARIABLE *setval(INTBIG addr, INTBIG type, CHAR *name, INTBIG newaddr, INTBIG newtype)
1228 #endif
1229 {
1230 	VARIABLE *var;
1231 	REGISTER CHAR *pp;
1232 	REGISTER INTBIG key, search;
1233 
1234 	/* look for an attribute that already has this name */
1235 	search = initobjlist(addr, type, FALSE);
1236 	if (search == 0)
1237 	{
1238 		db_donextchangequietly = FALSE;
1239 		return(NOVARIABLE);
1240 	}
1241 	for(;;)
1242 	{
1243 		pp = nextobjectlist(&var, search);
1244 		if (pp == 0) break;
1245 		if (namesame(pp, name) == 0) break;
1246 	}
1247 
1248 	/* if the attribute exists, change its value */
1249 	if (pp != 0)
1250 	{
1251 		if ((var->type&VCANTSET) != 0)
1252 		{
1253 			db_donextchangequietly = FALSE;
1254 			return((VARIABLE *)db_error(DBVARFIXED|DBSETVAL));
1255 		}
1256 
1257 		/* handle change control, constraint, and broadcast */
1258 		if (!db_donextchangequietly && !db_dochangesquietly)
1259 		{
1260 			/* tell constraint system about killed variable */
1261 			(*el_curconstraint->killvariable)(addr, type, var->key, var->addr, var->type, var->textdescript);
1262 
1263 			/* record a change for removal of the old variable */
1264 			(void)db_change((INTBIG)addr, VARIABLEKILL, type, var->key,
1265 				var->addr, var->type, var->textdescript[0], var->textdescript[1]);
1266 		}
1267 
1268 #ifdef DEBUGMEMORY
1269 		if (db_setvalvar(var, newaddr, newtype, db_whichcluster(addr, type), module, line))
1270 #else
1271 		if (db_setvalvar(var, newaddr, newtype, db_whichcluster(addr, type)))
1272 #endif
1273 		{
1274 			db_donextchangequietly = FALSE;
1275 			return((VARIABLE *)db_error(DBNOMEM|DBSETVAL));
1276 		}
1277 
1278 		/* handle change control, constraint, and broadcast */
1279 		if (!db_donextchangequietly && !db_dochangesquietly)
1280 		{
1281 			/* tell constraint system about new variable */
1282 			(*el_curconstraint->newvariable)(addr, type, var->key, var->type);
1283 
1284 			(void)db_change((INTBIG)addr, VARIABLENEW, type, var->key, var->type, 0, 0, 0);
1285 		}
1286 		db_donextchangequietly = FALSE;
1287 
1288 		/* if nodeproto name changed, rebuild hash table of nodeproto names */
1289 		if (type == VNODEPROTO && namesame(name, x_("protoname")) == 0)
1290 			db_buildnodeprotohashtable(((NODEPROTO *)addr)->lib);
1291 
1292 		/* if portproto name changed, rebuild hash table of portproto names */
1293 		if (type == VPORTPROTO && namesame(name, x_("protoname")) == 0)
1294 			db_buildportprotohashtable(((PORTPROTO *)addr)->parent);
1295 
1296 		/* mark a change to the database */
1297 		if (type != VTOOL || addr != (INTBIG)us_tool) db_changetimestamp++;
1298 		return(var);
1299 	}
1300 
1301 	/* create new variable: first ensure the name starts with a letter */
1302 	if (!isalpha(*name))
1303 	{
1304 		db_donextchangequietly = FALSE;
1305 		return((VARIABLE *)db_error(DBBADNAME|DBSETVAL));
1306 	}
1307 
1308 	/* get the key of the new name */
1309 	key = makekey(name);
1310 	if (key == -1)
1311 	{
1312 		db_donextchangequietly = FALSE;
1313 		return(NOVARIABLE);
1314 	}
1315 
1316 	/* set the variable by its key */
1317 #ifdef DEBUGMEMORY
1318 	return(_setvalkey(addr, type, key, newaddr, newtype, module, line));
1319 #else
1320 	return(setvalkey(addr, type, key, newaddr, newtype));
1321 #endif
1322 }
1323 
1324 /*
1325  * routine to set the variable on the object whose address is "addr", type
1326  * is "type", and key is "key".  The variable is set to "newaddr" with type
1327  * "newtype".  The routine returns the variable address (NOVARIABLE on error).
1328  */
1329 #ifdef DEBUGMEMORY
_setvalkey(INTBIG addr,INTBIG type,INTBIG key,INTBIG newaddr,INTBIG newtype,CHAR * module,INTBIG line)1330 VARIABLE *_setvalkey(INTBIG addr, INTBIG type, INTBIG key, INTBIG newaddr,
1331 	INTBIG newtype, CHAR *module, INTBIG line)
1332 #else
1333 VARIABLE *setvalkey(INTBIG addr, INTBIG type, INTBIG key, INTBIG newaddr,
1334 	INTBIG newtype)
1335 #endif
1336 {
1337 	REGISTER INTBIG med;
1338 	VARIABLE **myfirstvar;
1339 	INTSML *mynumvar;
1340 
1341 	/* get the attribute list pointers */
1342 	if (db_getvarptr(addr, type, &myfirstvar, &mynumvar))
1343 	{
1344 		db_donextchangequietly = FALSE;
1345 		return(NOVARIABLE);
1346 	}
1347 
1348 	/* binary search variable space for the key */
1349 	med = db_binarysearch(*mynumvar, *myfirstvar, key);
1350 	if (med >= 0)
1351 	{
1352 		if (((*myfirstvar)[med].type&VCANTSET) != 0)
1353 		{
1354 			db_donextchangequietly = FALSE;
1355 			return((VARIABLE *)db_error(DBVARFIXED|DBSETVALKEY));
1356 		}
1357 
1358 		/* handle change control, constraint, and broadcast */
1359 		if (!db_donextchangequietly && !db_dochangesquietly)
1360 		{
1361 			/* tell constraint system about killed variable */
1362 			(*el_curconstraint->killvariable)(addr, type, key,
1363 				(*myfirstvar)[med].addr, (*myfirstvar)[med].type, (*myfirstvar)[med].textdescript);
1364 
1365 			/* record a change for removal of the old variable */
1366 			(void)db_change((INTBIG)addr, VARIABLEKILL, type, key,
1367 				(*myfirstvar)[med].addr, (*myfirstvar)[med].type, (*myfirstvar)[med].textdescript[0],
1368 					(*myfirstvar)[med].textdescript[1]);
1369 		}
1370 	}
1371 
1372 	/* set the new variable */
1373 #ifdef DEBUGMEMORY
1374 	if (db_setvalkey(mynumvar, myfirstvar, med, key, newaddr, newtype, db_whichcluster(addr, type),
1375 		module, line))
1376 #else
1377 	if (db_setvalkey(mynumvar, myfirstvar, med, key, newaddr, newtype,
1378 		db_whichcluster(addr, type)))
1379 #endif
1380 	{
1381 		db_donextchangequietly = FALSE;
1382 		return((VARIABLE *)db_error(DBNOMEM|DBSETVALKEY));
1383 	}
1384 
1385 	/* handle change control, constraint, and broadcast */
1386 	if (!db_donextchangequietly && !db_dochangesquietly)
1387 	{
1388 		/* tell constraint system about new variable */
1389 		(*el_curconstraint->newvariable)(addr, type, key, newtype);
1390 
1391 		/* record the change */
1392 		(void)db_change((INTBIG)addr, VARIABLENEW, type, key, newtype, 0, 0, 0);
1393 	}
1394 	db_donextchangequietly = FALSE;
1395 	if (med < 0) med = -1 - med;
1396 
1397 	/* mark a change to the database */
1398 	if (type != VTOOL || addr != (INTBIG)us_tool) db_changetimestamp++;
1399 	return(&(*myfirstvar)[med]);
1400 }
1401 
1402 /*
1403  * routine to copy the variables from object "fromaddr" (which has type
1404  * "fromtype") to object "toaddr" (which has type "totype").  Returns true
1405  * on error.  If "uniquenames" is true, make sure nodes and arcs have unique names.
1406  */
copyvars(INTBIG fromaddr,INTBIG fromtype,INTBIG toaddr,INTBIG totype,BOOLEAN uniquenames)1407 BOOLEAN copyvars(INTBIG fromaddr, INTBIG fromtype, INTBIG toaddr, INTBIG totype, BOOLEAN uniquenames)
1408 {
1409 	REGISTER INTSML i;
1410 	REGISTER INTBIG key, addr, type;
1411 	INTBIG lx, hx, ly, hy;
1412 	REGISTER CHAR *objname, *newname;
1413 	REGISTER GEOM *geom;
1414 	REGISTER NODEPROTO *np;
1415 	REGISTER NODEINST *ni;
1416 	REGISTER ARCINST *ai;
1417 	INTSML *numvar;
1418 	VARIABLE **firstvar;
1419 	REGISTER VARIABLE *var;
1420 
1421 	if (db_getvarptr(fromaddr, fromtype, &firstvar, &numvar)) return(TRUE);
1422 
1423 	for(i=0; i<(*numvar); i++)
1424 	{
1425 		key = (*firstvar)[i].key;
1426 		addr = (*firstvar)[i].addr;
1427 		type = (*firstvar)[i].type;
1428 		if (uniquenames)
1429 		{
1430 			if (totype == VNODEINST && key == el_node_name_key)
1431 			{
1432 				/* if the node name wasn't displayable, do not copy */
1433 				if ((type&VDISPLAY) == 0) continue;
1434 
1435 				/* find a unique node name */
1436 				ni = (NODEINST *)toaddr;
1437 				objname = (CHAR *)addr;
1438 				newname = us_uniqueobjectname(objname, ni->parent, VNODEINST, ni);
1439 				if (namesame(newname, objname) != 0) addr = (INTBIG)newname;
1440 			} else if (totype == VARCINST && key == el_arc_name_key)
1441 			{
1442 				/* if the arc name wasn't displayable, do not copy */
1443 				if ((type&VDISPLAY) == 0) continue;
1444 
1445 				/* find a unique node name */
1446 				ai = (ARCINST *)toaddr;
1447 				objname = (CHAR *)addr;
1448 				newname = us_uniqueobjectname(objname, ai->parent, VARCINST, ai);
1449 				if (namesame(newname, objname) != 0) addr = (INTBIG)newname;
1450 			}
1451 		}
1452 
1453 		var = setvalkey(toaddr, totype, key, addr, type);
1454 		if (var == NOVARIABLE) return(TRUE);
1455 		TDCOPY(var->textdescript, (*firstvar)[i].textdescript);
1456 	}
1457 
1458 	/* variables may affect geometry size */
1459 	if (totype == VNODEINST || totype == VARCINST)
1460 	{
1461 		if (totype == VNODEINST)
1462 		{
1463 			ni = (NODEINST *)toaddr;
1464 			geom = ni->geom;
1465 			np = ni->parent;
1466 		} else
1467 		{
1468 			ai = (ARCINST *)toaddr;
1469 			geom = ai->geom;
1470 			np = ai->parent;
1471 		}
1472 		boundobj(geom, &lx, &hx, &ly, &hy);
1473 		if (lx != geom->lowx || hx != geom->highx ||
1474 			ly != geom->lowy || hy != geom->highy)
1475 				updategeom(geom, np);
1476 	}
1477 	return(FALSE);
1478 }
1479 
1480 /*********************** SETTING ENTRIES IN VARIABLES ***********************/
1481 
1482 /*
1483  * routine to set an entry in the array variable "name" in object "addr"
1484  * which is of type "type".  Entry "aindex" is set to "newaddr".
1485  * The routine returns true upon error.
1486  */
1487 #ifdef DEBUGMEMORY
_setind(INTBIG addr,INTBIG type,CHAR * name,INTBIG aindex,INTBIG newaddr,CHAR * module,INTBIG line)1488 BOOLEAN _setind(INTBIG addr, INTBIG type, CHAR *name, INTBIG aindex, INTBIG newaddr,
1489 	CHAR *module, INTBIG line)
1490 #else
1491 BOOLEAN setind(INTBIG addr, INTBIG type, CHAR *name, INTBIG aindex, INTBIG newaddr)
1492 #endif
1493 {
1494 	VARIABLE *var;
1495 	REGISTER CHAR *pp;
1496 	REGISTER INTBIG search;
1497 	REGISTER BOOLEAN retval;
1498 
1499 	search = initobjlist(addr, type, FALSE);
1500 	if (search == 0)
1501 	{
1502 		db_donextchangequietly = FALSE;
1503 		return(TRUE);
1504 	}
1505 	for(;;)
1506 	{
1507 		pp = nextobjectlist(&var, search);
1508 		if (pp == 0) break;
1509 		if (namesame(pp, name) == 0) break;
1510 	}
1511 
1512 	/* variable must exist */
1513 	if (pp == 0)
1514 	{
1515 		db_donextchangequietly = FALSE;
1516 		(void)db_error(DBNOVAR|DBSETIND);
1517 		return(TRUE);
1518 	}
1519 
1520 	if ((var->type&VCANTSET) != 0)
1521 	{
1522 		db_donextchangequietly = FALSE;
1523 		(void)db_error(DBVARFIXED|DBSETIND);
1524 		return(TRUE);
1525 	}
1526 
1527 #ifdef DEBUGMEMORY
1528 	retval = db_setindvar(addr, type, var, aindex, newaddr, module, line);
1529 #else
1530 	retval = db_setindvar(addr, type, var, aindex, newaddr);
1531 #endif
1532 	db_donextchangequietly = FALSE;
1533 	if (retval)
1534 	{
1535 		(void)db_error(DBNOMEM|DBSETIND);
1536 		return(TRUE);
1537 	}
1538 
1539 	/* mark a change to the database */
1540 	db_changetimestamp++;
1541 	return(FALSE);
1542 }
1543 
1544 /*
1545  * routine to set an entry in the array variable whose key is "key" in object
1546  * "addr" which is of type "type".  Entry "aindex" is set to "newaddr".
1547  * The routine returns nonzero upon error.
1548  */
1549 #ifdef DEBUGMEMORY
_setindkey(INTBIG addr,INTBIG type,INTBIG key,INTBIG aindex,INTBIG newaddr,CHAR * module,INTBIG line)1550 BOOLEAN _setindkey(INTBIG addr, INTBIG type, INTBIG key, INTBIG aindex, INTBIG newaddr,
1551 	CHAR *module, INTBIG line)
1552 #else
1553 BOOLEAN setindkey(INTBIG addr, INTBIG type, INTBIG key, INTBIG aindex, INTBIG newaddr)
1554 #endif
1555 {
1556 	VARIABLE **myfirstvar;
1557 	INTSML *mynumvar;
1558 	REGISTER INTBIG med;
1559 	REGISTER BOOLEAN retval;
1560 
1561 	/* get the attribute list into the globals */
1562 	if (db_getvarptr(addr, type, &myfirstvar, &mynumvar))
1563 	{
1564 		db_donextchangequietly = FALSE;
1565 		return(TRUE);
1566 	}
1567 
1568 	/* binary search variable space for the key */
1569 	med = db_binarysearch(*mynumvar, *myfirstvar, key);
1570 
1571 	/* variable must exist */
1572 	if (med < 0)
1573 	{
1574 		db_donextchangequietly = FALSE;
1575 		(void)db_error(DBNOVAR|DBSETINDKEY);
1576 		return(TRUE);
1577 	}
1578 
1579 	if (((*myfirstvar)[med].type&VCANTSET) != 0)
1580 	{
1581 		db_donextchangequietly = FALSE;
1582 		(void)db_error(DBVARFIXED|DBSETINDKEY);
1583 		return(TRUE);
1584 	}
1585 
1586 	/* set the variable */
1587 #ifdef DEBUGMEMORY
1588 	retval = db_setindvar(addr, type, &(*myfirstvar)[med], aindex, newaddr, module, line);
1589 #else
1590 	retval = db_setindvar(addr, type, &(*myfirstvar)[med], aindex, newaddr);
1591 #endif
1592 	db_donextchangequietly = FALSE;
1593 	if (retval != 0)
1594 	{
1595 		(void)db_error(DBNOMEM|DBSETINDKEY);
1596 		return(TRUE);
1597 	}
1598 
1599 	/* mark a change to the database */
1600 	db_changetimestamp++;
1601 	return(FALSE);
1602 }
1603 
1604 /*
1605  * routine to insert an entry in the array variable "name" in object "addr"
1606  * which is of type "type".  Entry "aindex" is set to "newaddr" and all entries
1607  * equal to or greater than "aindex" are moved up (i.e. "newaddr" is inserted
1608  * before entry "aindex").  The routine returns true upon error.
1609  */
insind(INTBIG addr,INTBIG type,CHAR * name,INTBIG aindex,INTBIG newaddr)1610 BOOLEAN insind(INTBIG addr, INTBIG type, CHAR *name, INTBIG aindex, INTBIG newaddr)
1611 {
1612 	VARIABLE *var;
1613 	REGISTER CHAR *pp;
1614 	REGISTER INTBIG search;
1615 	REGISTER BOOLEAN retval;
1616 
1617 	search = initobjlist(addr, type, FALSE);
1618 	if (search == 0)
1619 	{
1620 		db_donextchangequietly = FALSE;
1621 		return(TRUE);
1622 	}
1623 	for(;;)
1624 	{
1625 		pp = nextobjectlist(&var, search);
1626 		if (pp == 0) break;
1627 		if (namesame(pp, name) == 0) break;
1628 	}
1629 
1630 	/* variable must exist */
1631 	if (pp == 0)
1632 	{
1633 		db_donextchangequietly = FALSE;
1634 		(void)db_error(DBNOVAR|DBINSIND);
1635 		return(TRUE);
1636 	}
1637 
1638 	/* cannot insert if variable is frozen or is in C data structures */
1639 	if ((var->type&VCANTSET) != 0 || (var->type&VCREF) != 0)
1640 	{
1641 		db_donextchangequietly = FALSE;
1642 		(void)db_error(DBVARFIXED|DBINSIND);
1643 		return(TRUE);
1644 	}
1645 
1646 	retval = db_insindvar(addr, type, var, aindex, newaddr);
1647 	db_donextchangequietly = FALSE;
1648 	if (retval != 0)
1649 	{
1650 		(void)db_error(DBNOMEM|DBINSIND);
1651 		return(TRUE);
1652 	}
1653 
1654 	/* mark a change to the database */
1655 	db_changetimestamp++;
1656 	return(FALSE);
1657 }
1658 
1659 /*
1660  * routine to insert an entry in the array variable whose key is "key" in object
1661  * "addr" which is of type "type".  Entry "aindex" is set to "newaddr" and all entries
1662  * equal to or greater than "aindex" are moved up (i.e. "newaddr" is inserted
1663  * before entry "aindex").  The routine returns true upon error.
1664  */
insindkey(INTBIG addr,INTBIG type,INTBIG key,INTBIG aindex,INTBIG newaddr)1665 BOOLEAN insindkey(INTBIG addr, INTBIG type, INTBIG key, INTBIG aindex, INTBIG newaddr)
1666 {
1667 	VARIABLE **myfirstvar;
1668 	INTSML *mynumvar;
1669 	REGISTER INTBIG med;
1670 	REGISTER BOOLEAN retval;
1671 
1672 	/* get the attribute list into the globals */
1673 	if (db_getvarptr(addr, type, &myfirstvar, &mynumvar))
1674 	{
1675 		db_donextchangequietly = FALSE;
1676 		return(TRUE);
1677 	}
1678 
1679 	/* binary search variable space for the key */
1680 	med = db_binarysearch(*mynumvar, *myfirstvar, key);
1681 
1682 	/* variable must exist */
1683 	if (med < 0)
1684 	{
1685 		db_donextchangequietly = FALSE;
1686 		(void)db_error(DBNOVAR|DBINSINDKEY);
1687 		return(TRUE);
1688 	}
1689 
1690 	/* cannot insert if variable is frozen or is in C data structures */
1691 	if (((*myfirstvar)[med].type&VCANTSET) != 0 || ((*myfirstvar)[med].type&VCREF) != 0)
1692 	{
1693 		db_donextchangequietly = FALSE;
1694 		(void)db_error(DBVARFIXED|DBINSINDKEY);
1695 		return(TRUE);
1696 	}
1697 
1698 	/* set the variable */
1699 	retval = db_insindvar(addr, type, &(*myfirstvar)[med], aindex, newaddr);
1700 	db_donextchangequietly = FALSE;
1701 	if (retval != 0)
1702 	{
1703 		(void)db_error(DBNOMEM|DBINSINDKEY);
1704 		return(TRUE);
1705 	}
1706 
1707 	/* mark a change to the database */
1708 	db_changetimestamp++;
1709 	return(FALSE);
1710 }
1711 
1712 /*
1713  * routine to delete entry "aindex" in the array variable "name" in object "addr"
1714  * which is of type "type".  The routine returns true upon error.
1715  */
delind(INTBIG addr,INTBIG type,CHAR * name,INTBIG aindex)1716 BOOLEAN delind(INTBIG addr, INTBIG type, CHAR *name, INTBIG aindex)
1717 {
1718 	VARIABLE *var;
1719 	REGISTER CHAR *pp;
1720 	REGISTER INTBIG search;
1721 	REGISTER BOOLEAN retval;
1722 
1723 	search = initobjlist(addr, type, FALSE);
1724 	if (search == 0)
1725 	{
1726 		db_donextchangequietly = FALSE;
1727 		return(TRUE);
1728 	}
1729 	for(;;)
1730 	{
1731 		pp = nextobjectlist(&var, search);
1732 		if (pp == 0) break;
1733 		if (namesame(pp, name) == 0) break;
1734 	}
1735 
1736 	/* variable must exist */
1737 	if (pp == 0)
1738 	{
1739 		db_donextchangequietly = FALSE;
1740 		(void)db_error(DBNOVAR|DBDELIND);
1741 		return(TRUE);
1742 	}
1743 
1744 	if ((var->type&VCANTSET) != 0)
1745 	{
1746 		db_donextchangequietly = FALSE;
1747 		(void)db_error(DBVARFIXED|DBDELIND);
1748 		return(TRUE);
1749 	}
1750 
1751 	retval = db_delindvar(addr, type, var, aindex);
1752 	db_donextchangequietly = FALSE;
1753 	if (retval)
1754 	{
1755 		(void)db_error(DBNOMEM|DBDELIND);
1756 		return(TRUE);
1757 	}
1758 
1759 	/* mark a change to the database */
1760 	db_changetimestamp++;
1761 	return(FALSE);
1762 }
1763 
1764 /*
1765  * routine to delete entry "aindex" in the array variable whose key is "key" in object
1766  * "addr" which is of type "type".  The routine returns true upon error.
1767  */
delindkey(INTBIG addr,INTBIG type,INTBIG key,INTBIG aindex)1768 BOOLEAN delindkey(INTBIG addr, INTBIG type, INTBIG key, INTBIG aindex)
1769 {
1770 	VARIABLE **myfirstvar;
1771 	INTSML *mynumvar;
1772 	REGISTER INTBIG med;
1773 	REGISTER BOOLEAN retval;
1774 
1775 	/* get the attribute list into the globals */
1776 	if (db_getvarptr(addr, type, &myfirstvar, &mynumvar))
1777 	{
1778 		db_donextchangequietly = FALSE;
1779 		return(TRUE);
1780 	}
1781 
1782 	/* binary search variable space for the key */
1783 	med = db_binarysearch(*mynumvar, *myfirstvar, key);
1784 
1785 	/* variable must exist */
1786 	if (med < 0)
1787 	{
1788 		db_donextchangequietly = FALSE;
1789 		(void)db_error(DBNOVAR|DBDELINDKEY);
1790 		return(TRUE);
1791 	}
1792 
1793 	if (((*myfirstvar)[med].type&VCANTSET) != 0)
1794 	{
1795 		db_donextchangequietly = FALSE;
1796 		(void)db_error(DBVARFIXED|DBDELINDKEY);
1797 		return(TRUE);
1798 	}
1799 
1800 	/* set the variable */
1801 	retval = db_delindvar(addr, type, &(*myfirstvar)[med], aindex);
1802 	db_donextchangequietly = FALSE;
1803 	if (retval != 0)
1804 	{
1805 		(void)db_error(DBNOMEM|DBDELINDKEY);
1806 		return(TRUE);
1807 	}
1808 
1809 	/* mark a change to the database */
1810 	db_changetimestamp++;
1811 	return(FALSE);
1812 }
1813 
1814 /************************* OPTION VARIABLES *************************/
1815 
1816 /*
1817  * Many user-settable options are stored in variables.  When libraries are saved,
1818  * these variables are saved, unless they are marked "VDONTSAVE".  To handle this
1819  * situation properly, the library "options" is saved with all option variables
1820  * intact, but all other libraries are saved with the option variables removed.
1821  * The routines below "remove" the option variables (by marking them VDONTSAVE)
1822  * and restore them after the library is written.
1823  */
1824 
1825 #if COMTOOL
1826   extern TOOL *com_tool;
1827 #endif
1828 #if DRCTOOL
1829   extern TOOL *dr_tool;
1830 #endif
1831 #if ERCTOOL
1832   extern TOOL *erc_tool;
1833 #endif
1834 #if LOGEFFTOOL
1835   extern TOOL *le_tool;
1836 #endif
1837 #if ROUTTOOL
1838   extern TOOL *ro_tool;
1839 #endif
1840 #if SCTOOL
1841   extern TOOL *sc_tool;
1842 #endif
1843 #if SIMTOOL
1844   extern TOOL *sim_tool;
1845 #endif
1846 #if VHDLTOOL
1847   extern TOOL *vhdl_tool;
1848 #endif
1849 
1850 static OPTIONVARPROTO db_ovpcopyright[] =			/* FILE: IO Options: Library Options */
1851 {
1852 	{0, 0, (INTBIG*)&us_tool,  VTOOL,       0, x_("USER_copyright_file"), 0, 0, 0, 0, N_("Copyright file")},
1853 	{0, 0, 0,                  0,           0, 0, 0, 0, 0, 0, x_("")}
1854 };
1855 static OPTIONVARPROTO db_ovpforeignfilelibrary[] =	/* FILE: IO Options: Copyright Options */
1856 {
1857 	{0, 0, (INTBIG*)&io_tool,  VTOOL,       0, x_("IO_state"), 0, 0, BINOUTBACKUP, 0, N_("Library file backup")},
1858 	{0, 0, (INTBIG*)&io_tool,  VTOOL,       0, x_("IO_state"), 0, 0, CHECKATWRITE, 0, N_("Check database after write")},
1859 	{0, 0, 0,                  0,           0, 0, 0, 0, 0, 0, x_("")}
1860 };
1861 static OPTIONVARPROTO db_ovpforeignfilecif[] =		/* FILE: IO Options: CIF Options */
1862 {
1863 	{0, 0, (INTBIG*)&io_tool,  VTOOL,       0, x_("IO_state"), 0, 0, CIFOUTEXACT, 0, N_("Output mimics display")},
1864 	{0, 0, (INTBIG*)&io_tool,  VTOOL,       0, x_("IO_state"), 0, 0, CIFOUTMERGE, 0, N_("Output merges boxes")},
1865 	{0, 0, (INTBIG*)&io_tool,  VTOOL,       0, x_("IO_state"), 0, 0, CIFINSQUARE, 0, N_("Input squares wires")},
1866 	{0, 0, (INTBIG*)&io_tool,  VTOOL,       0, x_("IO_state"), 0, 0, CIFOUTNOTOPCALL, 0, N_("Output Instantiates top level")},
1867 	{0, 0, (INTBIG*)&io_tool,  VTOOL,       0, x_("IO_state"), 0, 0, CIFOUTNORMALIZE, 0, N_("Normalize coordinates")},
1868 	{0, 0, (INTBIG*)&io_tool,  VTOOL,       0, x_("IO_state"), 0, 0, 0, CIFRESHIGH, N_("Resolution check")},
1869 	{0, 0, 0,                  VTECHNOLOGY, 0, x_("IO_cif_layer_names"), 0, 0, 0, 0, N_("CIF layers")},
1870 	{0, 0, 0,                  VTECHNOLOGY, 0, x_("IO_cif_resolution"), 0, 0, 0, 0, N_("CIF resolution")},
1871 	{0, 0, 0,                  0,           0, 0, 0, 0, 0, 0, x_("")}
1872 };
1873 static OPTIONVARPROTO db_ovpforeignfilegds[] =		/* FILE: IO Options: GDS Options */
1874 {
1875 	{0, 0, (INTBIG*)&io_tool,  VTOOL,       0, x_("IO_state"), 0, 0, GDSINTEXT, 0, N_("Input includes text")},
1876 	{0, 0, (INTBIG*)&io_tool,  VTOOL,       0, x_("IO_state"), 0, 0, GDSINEXPAND, 0, N_("Input expands cells")},
1877 	{0, 0, (INTBIG*)&io_tool,  VTOOL,       0, x_("IO_state"), 0, 0, GDSINARRAYS, 0, N_("Input instantiates arrays")},
1878 	{0, 0, (INTBIG*)&io_tool,  VTOOL,       0, x_("IO_state"), 0, 0, GDSOUTMERGE, 0, N_("Output merges boxes")},
1879 	{0, 0, (INTBIG*)&io_tool,  VTOOL,       0, x_("IO_state"), 0, 0, GDSINIGNOREUKN, 0, N_("Input ignores unknown layers")},
1880 	{0, 0, (INTBIG*)&io_tool,  VTOOL,       0, x_("IO_state"), 0, 0, 0, GDSOUTPINS, N_("Output generates pins at exports")},
1881 	{0, 0, (INTBIG*)&io_tool,  VTOOL,       0, x_("IO_state"), 0, 0, 0, GDSOUTUC, N_("Output All Upper Case")},
1882 	{0, 0, 0,                  VTECHNOLOGY, 0, x_("IO_gds_layer_numbers"), 0, 0, 0, 0, N_("GDS layers")},
1883 	{0, 0, 0,                  VTECHNOLOGY, 0, x_("IO_gds_export_layer"), 0, 0, 0, 0, N_("Output export layer")},
1884 	{0, 0, (INTBIG*)&io_tool,  VTOOL,       0, x_("IO_curve_resolution"), 0, 0, 0, 0, N_("Maximum arc angle")},
1885 	{0, 0, (INTBIG*)&io_tool,  VTOOL,       0, x_("IO_curve_sag"), 0, 0, 0, 0, N_("Maximum arc sag")},
1886 	{0, 0, 0,                  0,           0, 0, 0, 0, 0, 0, x_("")}
1887 };
1888 static OPTIONVARPROTO db_ovpforeignfiledxf[] =		/* FILE: IO Options: DXF Options */
1889 {
1890 	{0, 0, (INTBIG*)&io_tool,  VTOOL,       0, x_("IO_state"), 0, 0, DXFFLATTENINPUT, 0, N_("Input flattens hierarchy")},
1891 	{0, 0, (INTBIG*)&io_tool,  VTOOL,       0, x_("IO_state"), 0, 0, DXFALLLAYERS, 0, N_("Input reads all layers")},
1892 	{0, 0, (INTBIG*)&io_tool,  VTOOL,       0, x_("IO_dxf_units"), 0, 0, 0, 0, N_("DXF scale")},
1893 	{0, 0, 0,                  VTECHNOLOGY, 0, x_("IO_dxf_layer_names"), 0, 0, 0, 0, N_("DXF layers")},
1894 	{0, 0, 0,                  0,           0, 0, 0, 0, 0, 0, x_("")}
1895 };
1896 static OPTIONVARPROTO db_ovpforeignfileedif[] =		/* FILE: IO Options: EDIF Options */
1897 {
1898 	{0, 0, (INTBIG*)&io_tool,  VTOOL,       0, x_("IO_state"), 0, 0, EDIFSCHEMATIC, 0, N_("Use schematic view")},
1899 	{0, 0, (INTBIG*)&io_tool,  VTOOL,       0, x_("IO_edif_input_scale"), 0, 0, 0, 0, N_("Input scale")},
1900 	{0, 0, 0,                  0,           0, 0, 0, 0, 0, 0, x_("")}
1901 };
1902 #ifdef FORCECADENCE
1903 static OPTIONVARPROTO db_ovpforeignfileskill[] =	/* FILE: IO Options: SKILL Options */
1904 {
1905 	{0, 0, (INTBIG*)&io_tool,  VTOOL,       0, x_("IO_state"), 0, 0, SKILLNOHIER, 0, N_("Do not include subcells")},
1906 	{0, 0, (INTBIG*)&io_tool,  VTOOL,       0, x_("IO_state"), 0, 0, 0, SKILLFLATHIER, N_("Flatten hierarchy")},
1907 	{0, 0, 0,                  VTECHNOLOGY, 0, x_("IO_skill_layer_names"), 0, 0, 0, 0, N_("SKILL layers")},
1908 	{0, 0, 0,                  0,           0, 0, 0, 0, 0, 0, x_("")}
1909 };
1910 #endif
1911 static OPTIONVARPROTO db_ovpforeignfilecdl[] =	/* FILE: IO Options: CDL Options */
1912 {
1913 	{0, 0, (INTBIG*)&io_tool,  VTOOL,       0, x_("IO_cdl_library_name"), 0, 0, 0, 0, N_("Cadence Library Name")},
1914 	{0, 0, (INTBIG*)&io_tool,  VTOOL,       0, x_("IO_cdl_library_path"), 0, 0, 0, 0, N_("Cadence Library Path")},
1915 	{0, 0, (INTBIG*)&io_tool,  VTOOL,       0, x_("IO_state"), 0, 0, 0, CDLNOBRACKETS, N_("Convert brackets")},
1916 	{0, 0, 0,                  0,           0, 0, 0, 0, 0, 0, x_("")}
1917 };
1918 static OPTIONVARPROTO db_ovpforeignfiledef[] =		/* FILE: IO Options: DEF Options */
1919 {
1920 	{0, 0, (INTBIG*)&io_tool,  VTOOL,       0, x_("IO_state"), 0, 0, DEFNOLOGICAL, 0, N_("Place logical interconnect")},
1921 	{0, 0, (INTBIG*)&io_tool,  VTOOL,       0, x_("IO_state"), 0, 0, DEFNOPHYSICAL, 0, N_("Place physical interconnect")},
1922 	{0, 0, 0,                  0,           0, 0, 0, 0, 0, 0, x_("")}
1923 };
1924 static OPTIONVARPROTO db_ovpforeignfilesue[] =	/* FILE: IO Options: Sue Options */
1925 {
1926 	{0, 0, (INTBIG*)&io_tool,  VTOOL,       0, x_("IO_state"), 0, 0, 0, SUEUSE4PORTTRANS, N_("Make 4-port transistors")},
1927 	{0, 0, 0,                  0,           0, 0, 0, 0, 0, 0, x_("")}
1928 };
1929 
1930 static OPTIONVARPROTO db_ovpprint[] =				/* FILE: Print Options */
1931 {
1932 /*	{0, 0, 0,                  VNODEPROTO,  0, "IO_postscript_EPS_scale", 0, 0, 0, 0, N_("")},  *** cell specific ***/
1933 /*	{0, 0, 0,                  VNODEPROTO,  0, "IO_postscript_filename", 0, 0, 0, 0, N_("")},  *** cell specific ***/
1934 	{0, 0, (INTBIG*)&io_tool,  VTOOL,       0, x_("IO_state"), 0, 0, PLOTFOCUS|PLOTFOCUSDPY, 0, N_("Area to plot")},
1935 	{0, 0, (INTBIG*)&io_tool,  VTOOL,       0, x_("IO_state"), 0, 0, PLOTDATES, 0, N_("Plot date in corner")},
1936 	{0, 0, (INTBIG*)&io_tool,  VTOOL,       0, x_("IO_state"), 0, 0, EPSPSCRIPT, 0, N_("Encapsulated PostScript")},
1937 	{0, 0, (INTBIG*)&io_tool,  VTOOL,       0, x_("IO_state"), 0, 0, HPGL2, 0, N_("Write HPGL/2")},
1938 	{0, 0, (INTBIG*)&io_tool,  VTOOL,       0, x_("IO_state"), 0, 0, PSCOLOR1|PSCOLOR2, 0, N_("Color PostScript")},
1939 	{0, 0, (INTBIG*)&io_tool,  VTOOL,       0, x_("IO_state"), 0, 0, PSPLOTTER, 0, N_("Printer/plotter")},
1940 	{0, 0, (INTBIG*)&io_tool,  VTOOL,       0, x_("IO_state"), 0, 0, PSROTATE, 0, N_("Rotate plot 90 degrees")},
1941 	{0, 0, (INTBIG*)&io_tool,  VTOOL,       0, x_("IO_state"), 0, 0, 0, PSAUTOROTATE, N_("Auto-rotate plot to fit")},
1942 	{0, 0, (INTBIG*)&io_tool,  VTOOL,       0, x_("IO_postscript_width"), 0, 0, 0, 0, N_("Page width")},
1943 	{0, 0, (INTBIG*)&io_tool,  VTOOL,       0, x_("IO_postscript_height"), 0, 0, 0, 0, N_("Page height")},
1944 	{0, 0, (INTBIG*)&io_tool,  VTOOL,       0, x_("IO_postscript_margin"), 0, 0, 0, 0, N_("Page margin")},
1945 	{0, 0, (INTBIG*)&io_tool,  VTOOL,       0, x_("IO_print_resolution_scale"), 0, 0, 0, 0, N_("Print and Copy resolution factor")},
1946 	{0, 0, (INTBIG*)&io_tool,  VTOOL,       0, x_("IO_hpgl2_scale"), 0, 0, 0, 0, N_("HPGL/2 units per pixel")},
1947 	{0, 0, (INTBIG*)&io_tool,  VTOOL,       0, x_("IO_default_printer"), 0, 0, 0, 0, N_("Default printer")},
1948 	{0, 0, 0,                  0,           0, 0, 0, 0, 0, 0, x_("")}
1949 };
1950 static OPTIONVARPROTO db_ovpnewnode[] =				/* EDIT: New Node Options */
1951 {
1952 /*	{0, 0, 0,                  VNODEPROTO,  0, "userbits", 0, 0, 0, 0, N_("")},  *** cell specific ***/
1953 	{0, 0, (INTBIG*)&us_tool,  VTOOL,       0, x_("USER_optionflags"), 0, 0, NOPRIMCHANGES, 0, N_("Disallow modification of locked primitives")},
1954 	{0, 0, (INTBIG*)&us_tool,  VTOOL,       0, x_("USER_optionflags"), 0, 0, NOMOVEAFTERDUP, 0, N_("Move after duplicate")},
1955 	{0, 0, (INTBIG*)&us_tool,  VTOOL,       0, x_("USER_optionflags"), 0, 0, DUPCOPIESPORTS, 0, N_("Duplicate/array/extract copies exports")},
1956 	{0, 0, 0,                  VNODEPROTO,  0, x_("NODE_size_default"), 0, 0, 0, 0, N_("Size of new primitives")},
1957 	{0, 0, 0,                  VNODEPROTO,  0, x_("USER_placement_angle"), 0, 0, 0, 0, N_("Rotation of new nodes")},
1958 	{0, 0, (INTBIG*)&us_tool,  VTOOL,       0, x_("USER_placement_angle"), 0, 0, 0, 0, N_("Rotation of new nodes")},
1959 	{0, 0, (INTBIG*)&net_tool, VTOOL,       0, x_("NET_node_abbreviations"), 0, 0, 0, 0, N_("Primitive function abbreviations")},
1960 	{0, 0, (INTBIG*)&net_tool, VTOOL,       0, x_("NET_node_abbreviation_length"), 0, 0, 0, 0, N_("Length of cell abbreviations")},
1961 	{0, 0, 0,                  0,           0, 0, 0, 0, 0, 0, x_("")}
1962 };
1963 static OPTIONVARPROTO db_ovpselect[] =				/* EDIT: Selection: Selection Options */
1964 {
1965 	{0, 0, (INTBIG*)&us_tool,  VTOOL,       0, x_("USER_optionflags"), 0, 0, NOINSTANCESELECT, 0, N_("Easy selection of cell instances")},
1966 	{0, 0, (INTBIG*)&us_tool,  VTOOL,       0, x_("USER_optionflags"), 0, 0, NOTEXTSELECT, 0, N_("Easy selection of annotation text")},
1967 	{0, 0, (INTBIG*)&us_tool,  VTOOL,       0, x_("USER_optionflags"), 0, 0, CENTEREDPRIMITIVES, 0, N_("Center-based primitives")},
1968 	{0, 0, (INTBIG*)&us_tool,  VTOOL,       0, x_("USER_optionflags"), 0, 0, MUSTENCLOSEALL, 0, N_("Dragging must enclose entire object")},
1969 	{0, 0, 0,                  0,           0, 0, 0, 0, 0, 0, x_("")}
1970 };
1971 static OPTIONVARPROTO db_ovpcell[] =				/* CELLS: Cell Options */
1972 {
1973 /*	{0, 0, 0,                  VNODEPROTO,  0, "userbits", 0, 0, 0, 0},  *** cell specific ***/
1974 	{0, 0, (INTBIG*)&us_tool,  VTOOL,       0, x_("USER_optionflags"), 0, 0, DRAWTINYCELLS, 0, N_("Tiny cell instances hashed out")},
1975 	{0, 0, (INTBIG*)&us_tool,  VTOOL,       0, x_("USER_optionflags"), 0, 0, CHECKDATE, 0, N_("Check cell dates during creation")},
1976 	{0, 0, (INTBIG*)&us_tool,  VTOOL,       0, x_("USER_optionflags"), 0, 0, AUTOSWITCHTECHNOLOGY, 0, N_("Switch technology to match current cell")},
1977 	{0, 0, (INTBIG*)&us_tool,  VTOOL,       0, x_("USER_optionflags"), 0, 0, CELLCENTERALWAYS, 0, N_("Place cell center in new cells")},
1978 	{0, 0, (INTBIG*)&us_tool,  VTOOL,       0, x_("USER_tiny_lambda_per_pixel"), 0, 0, 0, 0, N_("Hash out scale")},
1979 	{0, 0, (INTBIG*)&us_tool,  VTOOL,       0, x_("USER_facet_explorer_textsize"), 0, 0, 0, 0, N_("Cell explorer text size")},
1980 	{0, 0, 0,                  0,           0, 0, 0, 0, 0, 0, x_("")}
1981 };
1982 static OPTIONVARPROTO db_ovpframe[] =				/* VIEW: Frame Options */
1983 {
1984 /*	{0, 0, 0,                  VNODEPROTO,  0, "FACET_schematic_page_size", 0, 0, 0, 0, N_("")},  *** cell specific ***/
1985 	{0, 0, (INTBIG*)&us_tool,  VTOOL,       0, x_("USER_drawing_company_name"), 0, 0, 0, 0, N_("Company name")},
1986 	{0, 0, (INTBIG*)&us_tool,  VTOOL,       0, x_("USER_drawing_designer_name"), 0, 0, 0, 0, N_("Designer name")},
1987 	{0, 0, (INTBIG*)&us_tool,  VTOOL,       0, x_("USER_drawing_project_name"), 0, 0, 0, 0, N_("Project name")},
1988 	{0, 0, 0,                  0,           0, 0, 0, 0, 0, 0, x_("")}
1989 };
1990 static OPTIONVARPROTO db_ovpicon[] =				/* VIEW: Icon Options */
1991 {
1992 	{0, 0, (INTBIG*)&us_tool,  VTOOL,       0, x_("USER_icon_style"), 0, 0, ICONSTYLESIDEIN, 0, N_("Inputs on which side")},
1993 	{0, 0, (INTBIG*)&us_tool,  VTOOL,       0, x_("USER_icon_style"), 0, 0, ICONSTYLESIDEOUT, 0, N_("Outputs on which side")},
1994 	{0, 0, (INTBIG*)&us_tool,  VTOOL,       0, x_("USER_icon_style"), 0, 0, ICONSTYLESIDEBIDIR, 0, N_("Bidir. on which side")},
1995 	{0, 0, (INTBIG*)&us_tool,  VTOOL,       0, x_("USER_icon_style"), 0, 0, ICONSTYLESIDEPOWER, 0, N_("Power on which side")},
1996 	{0, 0, (INTBIG*)&us_tool,  VTOOL,       0, x_("USER_icon_style"), 0, 0, ICONSTYLESIDEGROUND, 0, N_("Ground on which side")},
1997 	{0, 0, (INTBIG*)&us_tool,  VTOOL,       0, x_("USER_icon_style"), 0, 0, ICONSTYLESIDECLOCK, 0, N_("Clock on which side")},
1998 	{0, 0, (INTBIG*)&us_tool,  VTOOL,       0, x_("USER_icon_style"), 0, 0, ICONSTYLEPORTLOC, 0, N_("Export location")},
1999 	{0, 0, (INTBIG*)&us_tool,  VTOOL,       0, x_("USER_icon_style"), 0, 0, ICONSTYLEPORTSTYLE, 0, N_("Export style")},
2000 	{0, 0, (INTBIG*)&us_tool,  VTOOL,       0, x_("USER_icon_style"), 0, 0, ICONSTYLETECH, 0, N_("Export technology")},
2001 	{0, 0, (INTBIG*)&us_tool,  VTOOL,       0, x_("USER_icon_style"), 0, 0, ICONSTYLEDRAWNOLEADS, 0, N_("Draw leads")},
2002 	{0, 0, (INTBIG*)&us_tool,  VTOOL,       0, x_("USER_icon_style"), 0, 0, ICONSTYLEDRAWNOBODY, 0, N_("Draw body")},
2003 	{0, 0, (INTBIG*)&us_tool,  VTOOL,       0, x_("USER_icon_style"), 0, 0, ICONSTYLEREVEXPORT, 0, N_("Reverse export order")},
2004 	{0, 0, (INTBIG*)&us_tool,  VTOOL,       0, x_("USER_icon_style"), 0, 0, ICONINSTLOC, 0, N_("Instance location")},
2005 	{0, 0, (INTBIG*)&us_tool,  VTOOL,       0, x_("USER_icon_lead_length"), 0, 0, 0, 0, N_("Lead length")},
2006 	{0, 0, (INTBIG*)&us_tool,  VTOOL,       0, x_("USER_icon_lead_spacing"), 0, 0, 0, 0, N_("Lead spacing")},
2007 	{0, 0, 0,                  0,           0, 0, 0, 0, 0, 0, x_("")}
2008 };
2009 static OPTIONVARPROTO db_ovpnewarc[] =				/* ARC: New Arc Options */
2010 {
2011 	{0, 0, 0,                  VARCPROTO,   0, x_("ARC_width_default"), 0, 0, 0, 0, N_("Width")},
2012 	{0, 0, (INTBIG*)&us_tool,  VTOOL,       0, x_("USER_arc_style"), 0, 0, WANTFIX, 0, N_("All rigid")},
2013 	{0, 0, (INTBIG*)&us_tool,  VTOOL,       0, x_("USER_arc_style"), 0, 0, WANTFIXANG, 0, N_("All fixed angle")},
2014 	{0, 0, (INTBIG*)&us_tool,  VTOOL,       0, x_("USER_arc_style"), 0, 0, WANTCANTSLIDE, 0, N_("All slidable")},
2015 	{0, 0, (INTBIG*)&us_tool,  VTOOL,       0, x_("USER_arc_style"), 0, 0, WANTNEGATED, 0, N_("All negated")},
2016 	{0, 0, (INTBIG*)&us_tool,  VTOOL,       0, x_("USER_arc_style"), 0, 0, WANTNOEXTEND, 0, N_("All ends extended")},
2017 	{0, 0, (INTBIG*)&us_tool,  VTOOL,       0, x_("USER_arc_style"), 0, 0, WANTDIRECTIONAL, 0, N_("All directional")},
2018 	{0, 0, (INTBIG*)&us_tool,  VTOOL,       0, x_("USER_arc_style"), 0, 0, AANGLEINC, 0, N_("All angle")},
2019 	{0, 0, 0,                  VARCPROTO,   0, x_("USER_arc_style"), 0, 0, WANTFIX, 0, N_("Arc rigid")},
2020 	{0, 0, 0,                  VARCPROTO,   0, x_("USER_arc_style"), 0, 0, WANTFIXANG, 0, N_("Arc fixed angle")},
2021 	{0, 0, 0,                  VARCPROTO,   0, x_("USER_arc_style"), 0, 0, WANTCANTSLIDE, 0, N_("Arc slidable")},
2022 	{0, 0, 0,                  VARCPROTO,   0, x_("USER_arc_style"), 0, 0, WANTNEGATED, 0, N_("Arc negated")},
2023 	{0, 0, 0,                  VARCPROTO,   0, x_("USER_arc_style"), 0, 0, WANTNOEXTEND, 0, N_("Arc ends extended")},
2024 	{0, 0, 0,                  VARCPROTO,   0, x_("USER_arc_style"), 0, 0, WANTDIRECTIONAL, 0, N_("Arc directional")},
2025 	{0, 0, 0,                  VARCPROTO,   0, x_("USER_arc_style"), 0, 0, AANGLEINC, 0, N_("Arc angle")},
2026 	{0, 0, 0,                  VARCPROTO,   0, x_("ARC_Default_Pin"), 0, 0, 0, 0, N_("Pin")},
2027 	{0, 0, 0,                  0,           0, 0, 0, 0, 0, 0, x_("")}
2028 };
2029 
2030 static OPTIONVARPROTO db_ovpgrid[] =				/* WINDOWS: Grid Options */
2031 {
2032 	{0, 0, (INTBIG*)&us_tool,  VTOOL,       0, x_("USER_default_grid"), 0, 0, 0, 0, N_("Default grid spacing")},
2033 	{0, 0, (INTBIG*)&us_tool,  VTOOL,       0, x_("USER_grid_bold_spacing"), 0, 0, 0, 0, N_("Distance between bold dots")},
2034 	{0, 0, (INTBIG*)&us_tool,  VTOOL,       0, x_("USER_grid_floats"), 0, 0, 0, 0, N_("Align grid with circuit")},
2035 	{0, 0, 0,                  0,           0, 0, 0, 0, 0, 0, x_("")}
2036 };
2037 static OPTIONVARPROTO db_ovpalign[] =				/* WINDOWS: Alignment Options */
2038 {
2039 	{0, 0, (INTBIG*)&us_tool,  VTOOL,       0, x_("USER_alignment_ratio"), 0, 0, 0, 0, N_("Alignment of cursor to grid")},
2040 	{0, 0, (INTBIG*)&us_tool,  VTOOL,       0, x_("USER_alignment_edge_ratio"), 0, 0, 0, 0, N_("Alignment of edges to grid")},
2041 	{0, 0, 0,                  0,           0, 0, 0, 0, 0, 0, x_("")}
2042 };
2043 static OPTIONVARPROTO db_ovplayvis[] =				/* WINDOWS: Layer Visibility Options */
2044 {
2045 	{0, 0, (INTBIG*)&us_tool,  VTOOL,       0, x_("USER_optionflags"), 0, 0, HIDETXTNODE, 0, N_("Node text")},
2046 	{0, 0, (INTBIG*)&us_tool,  VTOOL,       0, x_("USER_optionflags"), 0, 0, HIDETXTARC, 0, N_("Arc text")},
2047 	{0, 0, (INTBIG*)&us_tool,  VTOOL,       0, x_("USER_optionflags"), 0, 0, HIDETXTPORT, 0, N_("Port text")},
2048 	{0, 0, (INTBIG*)&us_tool,  VTOOL,       0, x_("USER_optionflags"), 0, 0, HIDETXTEXPORT, 0, N_("Export text")},
2049 	{0, 0, (INTBIG*)&us_tool,  VTOOL,       0, x_("USER_optionflags"), 0, 0, HIDETXTNONLAY, 0, N_("Nonlayout text")},
2050 	{0, 0, (INTBIG*)&us_tool,  VTOOL,       0, x_("USER_optionflags"), 0, 0, HIDETXTINSTNAME, 0, N_("Instance names")},
2051 	{0, 0, (INTBIG*)&us_tool,  VTOOL,       0, x_("USER_optionflags"), 0, 0, HIDETXTCELL, 0, N_("Cell text")},
2052 	{0, 0, 0,                  0,           0, 0, 0, 0, 0, 0, x_("")}
2053 };
2054 static OPTIONVARPROTO db_ovplaypat[] =				/* WINDOWS: Layer Display Options */
2055 {
2056 	{0, 0, 0,                  VTECHNOLOGY, 1, x_("TECH_layer_pattern_"), 0, 0, 0, 0, N_("Layer pattern/color")},
2057 	{0, 0, 0,                  0,           0, 0, 0, 0, 0, 0, x_("")}
2058 };
2059 static OPTIONVARPROTO db_ovpcolor[] =				/* WINDOWS: Color Options */
2060 {
2061 	{0, 0, 0,                  VTECHNOLOGY, 0, x_("USER_print_colors"), 0, 0, 0, 0, N_("Print colors")},
2062 	{0, 0, (INTBIG*)&us_tool,  VTOOL,       0, x_("USER_colormap_red"), 0, 0, 0, 0, N_("Red colormap")},
2063 	{0, 0, (INTBIG*)&us_tool,  VTOOL,       0, x_("USER_colormap_green"), 0, 0, 0, 0, N_("Green colormap")},
2064 	{0, 0, (INTBIG*)&us_tool,  VTOOL,       0, x_("USER_colormap_blue"), 0, 0, 0, 0, N_("Blue colormap")},
2065 	{0, 0, 0,                  0,           0, 0, 0, 0, 0, 0, x_("")}
2066 };
2067 static OPTIONVARPROTO db_ovpport[] =				/* WINDOWS: Port and Export Options */
2068 {
2069 	{0, 0, (INTBIG*)&us_tool,  VTOOL,       0, x_("USER_optionflags"), 0, 0, PORTLABELS, 0, N_("Ports (on instances)")},
2070 	{0, 0, (INTBIG*)&us_tool,  VTOOL,       0, x_("USER_optionflags"), 0, 0, EXPORTLABELS, 0, N_("Exports (in cells)")},
2071 	{0, 0, (INTBIG*)&us_tool,  VTOOL,       0, x_("USER_optionflags"), 0, 0, MOVENODEWITHEXPORT, 0, N_("Move node with export name")},
2072 	{0, 0, 0,                  0,           0, 0, 0, 0, 0, 0, x_("")}
2073 };
2074 static OPTIONVARPROTO db_ovptext[] =				/* WINDOWS: Text Options */
2075 {
2076 	{0, 0, (INTBIG*)&us_tool,  VTOOL,       0, x_("USER_default_text_style"), 0, 0, 0, 0, N_("Text corner")},
2077 	{0, 0, (INTBIG*)&us_tool,  VTOOL,       0, x_("USER_default_text_smart_style"), 0, 0, 0, 0, N_("Smart placement")},
2078 	{0, 0, (INTBIG*)&us_tool,  VTOOL,       0, x_("USER_default_node_text_size"), 0, 0, 0, 0, N_("Node style")},
2079 	{0, 0, (INTBIG*)&us_tool,  VTOOL,       0, x_("USER_default_arc_text_size"), 0, 0, 0, 0, N_("Arc style")},
2080 	{0, 0, (INTBIG*)&us_tool,  VTOOL,       0, x_("USER_default_export_text_size"), 0, 0, 0, 0, N_("Export style")},
2081 	{0, 0, (INTBIG*)&us_tool,  VTOOL,       0, x_("USER_default_nonlayout_text_size"), 0, 0, 0, 0, N_("Nonlayout style")},
2082 	{0, 0, (INTBIG*)&us_tool,  VTOOL,       0, x_("USER_default_instance_text_size"), 0, 0, 0, 0, N_("Instance style")},
2083 	{0, 0, (INTBIG*)&us_tool,  VTOOL,       0, x_("USER_default_facet_text_size"), 0, 0, 0, 0, N_("Cell style")},
2084 	{0, 0, (INTBIG*)&us_tool,  VTOOL,       0, x_("USER_text_editor"), 0, 0, 0, 0, N_("Text editor")},
2085 	{0, 0, 0,                  0,           0, 0, 0, 0, 0, 0, x_("")}
2086 };
2087 static OPTIONVARPROTO db_ovp3d[] =					/* WINDOWS: 3D Options */
2088 {
2089 	{0, 0, (INTBIG*)&us_tool,  VTOOL,       0, x_("USER_optionflags"), 0, 0, NO3DPERSPECTIVE, 0, N_("Use perspective")},
2090 	{0, 0, 0,                  VTECHNOLOGY, 0, x_("TECH_layer_3dheight"), 0, 0, 0, 0, N_("Height")},
2091 	{0, 0, 0,                  VTECHNOLOGY, 0, x_("TECH_layer_3dthickness"), 0, 0, 0, 0, N_("Thickness")},
2092 	{0, 0, 0,                  0,           0, 0, 0, 0, 0, 0, x_("")}
2093 };
2094 static OPTIONVARPROTO db_ovpmsgloc[] =				/* WINDOWS: Save Messages Location */
2095 {
2096 	{0, 0, (INTBIG*)&us_tool,  VTOOL,       0, x_("USER_messages_position"), 0, 0, 0, 0, N_("Messages window location")},
2097 	{0, 0, 0,                  0,           0, 0, 0, 0, 0, 0, x_("")}
2098 };
2099 static OPTIONVARPROTO db_ovpgeneral[] =				/* INFO: General Options */
2100 {
2101 	{0, 0, (INTBIG*)&us_tool,  VTOOL,       0, x_("USER_optionflags"), 0, 0, NODATEORVERSION, 0, N_("Include date and version in output files")},
2102 	{0, 0, (INTBIG*)&us_tool,  VTOOL,       0, x_("USER_optionflags"), 0, 0, NOPROMPTBEFOREWRITE, 0, N_("Show file-selection dialog before writing netlists")},
2103 	{0, 0, (INTBIG*)&us_tool,  VTOOL,       0, x_("USER_optionflags"), 0, 0, BEEPAFTERLONGJOB, 0, N_("Beep after long jobs")},
2104 	{0, 0, (INTBIG*)&us_tool,  VTOOL,       0, x_("USER_optionflags"), 0, 0, EXPANDEDDIALOGSDEF, 0, N_("Expandable dialogs default to fullsize")},
2105 	{0, 0, (INTBIG*)&us_tool,  VTOOL,       0, x_("USER_optionflags"), 0, 0, NOEXTRASOUND, 0, N_("Click sounds when arcs are created")},
2106 	{0, 0, (INTBIG*)&us_tool,  VTOOL,       0, x_("USER_maximum_errors"), 0, 0, 0, 0, N_("Maximum errors to report")},
2107 	{0, 0, (INTBIG*)&us_tool,  VTOOL,       0, x_("USER_motion_delay"), 0, 0, 0, 0, N_("Motion delay after selection")},
2108 	{0, 0, 0,                  0,           0, 0, 0, 0, 0, 0, x_("")}
2109 };
2110 static OPTIONVARPROTO db_ovpquickkey[] =			/* INFO: Quick Key Options */
2111 {
2112 	{0, 0, (INTBIG*)&us_tool,  VTOOL,       0, x_("USER_quick_keys"), 0, 0, 0, 0, N_("Quick keys")},
2113 	{0, 0, 0,                  0,           0, 0, 0, 0, 0, 0, x_("")}
2114 };
2115 static OPTIONVARPROTO db_ovptechopt[] =				/* TECHNOLOGY: Technology Options */
2116 {
2117 	{0, 0, (INTBIG*)&mocmossub_tech,VTECHNOLOGY, 0, x_("TECH_state"), 0, 0, MOCMOSSUBMETALS, 0, N_("mocmossub number of metal layers")},
2118 	{0, 0, (INTBIG*)&mocmossub_tech,VTECHNOLOGY, 0, x_("TECH_state"), 0, 0, MOCMOSSUBNOCONV, 0, N_("mocmossub converts to mocmos")},
2119 	{0, 0, (INTBIG*)&mocmos_tech,VTECHNOLOGY, 0, x_("TECH_state"), 0, 0, MOCMOSMETALS, 0, N_("mocmos number of metal layers")},
2120 	{0, 0, (INTBIG*)&mocmos_tech,VTECHNOLOGY, 0, x_("TECH_state"), 0, 0, MOCMOSSTICKFIGURE, 0, N_("mocmos stick figure")},
2121 	{0, 0, (INTBIG*)&mocmos_tech,VTECHNOLOGY, 0, x_("TECH_state"), 0, 0, MOCMOSNOSTACKEDVIAS, 0, N_("mocmos stacked vias")},
2122 	{0, 0, (INTBIG*)&mocmos_tech,VTECHNOLOGY, 0, x_("TECH_state"), 0, 0, MOCMOSALTAPRULES, 0, N_("mocmos alternate contact rules")},
2123 	{0, 0, (INTBIG*)&mocmos_tech,VTECHNOLOGY, 0, x_("TECH_state"), 0, 0, MOCMOSTWOPOLY, 0, N_("mocmos number of polysilicon layers")},
2124 	{0, 0, (INTBIG*)&mocmos_tech,VTECHNOLOGY, 0, x_("TECH_state"), 0, 0, MOCMOSSPECIALTRAN, 0, N_("mocmos shows special transistors")},
2125 	{0, 0, (INTBIG*)&mocmos_tech,VTECHNOLOGY, 0, x_("TECH_state"), 0, 0, MOCMOSRULESET, 0, N_("mocmos rule set")},
2126 	{0, 0, (INTBIG*)&art_tech, VTECHNOLOGY, 0, x_("TECH_state"), 0, 0, ARTWORKFILLARROWHEADS, 0, N_("artwork fills arrowheads")},
2127 	{0, 0, (INTBIG*)&sch_tech, VTECHNOLOGY, 0, x_("TECH_layout_technology"), 0, 0, 0, 0, N_("Technology to use for schematics")},
2128 	{0, 0, 0,                  0,           0, 0, 0, 0, 0, 0, x_("")}
2129 };
2130 static OPTIONVARPROTO db_ovptechunits[] =			/* TECHNOLOGY: Units */
2131 {
2132 	{0, 0, (INTBIG*)&us_tool,  VTOOL,       0, x_("USER_display_units"), 0, 0, DISPLAYUNITS, 0, N_("Display units")},
2133 	{0, 0, (INTBIG*)&us_tool,  VTOOL,       0, x_("USER_display_units"), 0, 0, INTERNALUNITS, 0, N_("Internal units")},
2134 	{0, 0, (INTBIG*)&us_tool,  VTOOL,       0, x_("USER_electrical_units"), 0, 0, 0, 0, N_("Electrical units")},
2135 	{0, 0, 0,                  0,           0, 0, 0, 0, 0, 0, x_("")}
2136 };
2137 #if DRCTOOL
2138 static OPTIONVARPROTO db_ovpdrc[] =					/* TOOLS: DRC: DRC Options */
2139 {
2140 	{0, 0, (INTBIG*)&dr_tool,  VTOOL,       0, x_("DRC_pointout"), 0, 0, 0, 0, N_("Incremental DRC highlights errors")},
2141 	{0, 0, (INTBIG*)&dr_tool,  VTOOL,       0, x_("DRC_options"), 0, 0, DRCFIRSTERROR, 0, N_("Just 1 error per cell")},
2142 	{0, 0, (INTBIG*)&dr_tool,  VTOOL,       0, x_("DRC_options"), 0, 0, DRCREASONABLE, 0, N_("Ignore center cuts in large contacts")},
2143 	{0, 0, (INTBIG*)&dr_tool,  VTOOL,       0, x_("DRC_options"), 0, 0, DRCMULTIPROC|DRCNUMPROC, 0, N_("Use multiple processors")},
2144 	{0, 0, (INTBIG*)&dr_tool,  VTOOL,       0, x_("DRC_incrementalon"), 0, 0, 0, 0, N_("Incremental DRC on")},
2145 	{0, 0, 0,                  VTECHNOLOGY, 0, x_("DRC_ecad_deck"), 0, 0, 0, 0, N_("Dracula rules deck")},
2146 	{0, 0, 0,                  0,           0, 0, 0, 0, 0, 0, x_("")}
2147 };
2148 static OPTIONVARPROTO db_ovpdrcr[] =				/* TOOLS: DRC: DRC Rules */
2149 {
2150 	{0, 0, 0,                  VTECHNOLOGY, 0, x_("DRC_wide_limit"), 0, 0, 0, 0, N_("Wide rule size")},
2151 	{0, 0, 0,                  VTECHNOLOGY, 0, x_("DRC_min_width"), 0, 0, 0, 0, N_("Minimum width distance")},
2152 	{0, 0, 0,                  VTECHNOLOGY, 0, x_("DRC_min_width_rule"), 0, 0, 0, 0, N_("Minimum width rule")},
2153 	{0, 0, 0,                  VTECHNOLOGY, 0, x_("DRC_min_connected_distances"), 0, 0, 0, 0, N_("Normal connected distance")},
2154 	{0, 0, 0,                  VTECHNOLOGY, 0, x_("DRC_min_connected_distances_rule"), 0, 0, 0, 0, N_("Normal connected rule")},
2155 	{0, 0, 0,                  VTECHNOLOGY, 0, x_("DRC_min_unconnected_distances"), 0, 0, 0, 0, N_("Normal not-connected distance")},
2156 	{0, 0, 0,                  VTECHNOLOGY, 0, x_("DRC_min_unconnected_distances_rule"), 0, 0, 0, 0, N_("Normal not-connected rule")},
2157 	{0, 0, 0,                  VTECHNOLOGY, 0, x_("DRC_min_connected_distances_wide"), 0, 0, 0, 0, N_("Wide connected distance")},
2158 	{0, 0, 0,                  VTECHNOLOGY, 0, x_("DRC_min_connected_distances_wide_rule"), 0, 0, 0, 0, N_("Wide connected rule")},
2159 	{0, 0, 0,                  VTECHNOLOGY, 0, x_("DRC_min_unconnected_distances_wide"), 0, 0, 0, 0, N_("Wide not-connected spacing")},
2160 	{0, 0, 0,                  VTECHNOLOGY, 0, x_("DRC_min_unconnected_distances_wide_rule"), 0, 0, 0, 0, N_("Wide not-connected rule")},
2161 	{0, 0, 0,                  VTECHNOLOGY, 0, x_("DRC_min_connected_distances_multi"), 0, 0, 0, 0, N_("Multiple cuts connected distance")},
2162 	{0, 0, 0,                  VTECHNOLOGY, 0, x_("DRC_min_connected_distances_multi_rule"), 0, 0, 0, 0, N_("Multiple cuts connected rule")},
2163 	{0, 0, 0,                  VTECHNOLOGY, 0, x_("DRC_min_unconnected_distances_multi"), 0, 0, 0, 0, N_("Multiple cuts not-connected distance")},
2164 	{0, 0, 0,                  VTECHNOLOGY, 0, x_("DRC_min_unconnected_distances_multi_rule"), 0, 0, 0, 0, N_("Multiple cuts not-connected rule")},
2165 	{0, 0, 0,                  VTECHNOLOGY, 0, x_("DRC_min_edge_distances"), 0, 0, 0, 0, N_("Edge distance")},
2166 	{0, 0, 0,                  VTECHNOLOGY, 0, x_("DRC_min_edge_distances_rule"), 0, 0, 0, 0, N_("Edge rule")},
2167 	{0, 0, 0,                  VTECHNOLOGY, 0, x_("DRC_min_node_size"), 0, 0, 0, 0, N_("Minimum node size")},
2168 	{0, 0, 0,                  VTECHNOLOGY, 0, x_("DRC_min_node_size_rule"), 0, 0, 0, 0, N_("Minimum node size rule")},
2169 	{0, 0, 0,                  0,           0, 0, 0, 0, 0, 0, x_("")}
2170 };
2171 #endif
2172 #if SIMTOOL
2173 static OPTIONVARPROTO db_ovpsimulation[] =			/* TOOLS: Simulation: Simulation Options */
2174 {
2175 	{0, 0, (INTBIG*)&sim_tool, VTOOL,       0, x_("SIM_als_no_update"), 0, 0, 0, 0, N_("Resimulate each change")},
2176 	{0, 0, (INTBIG*)&sim_tool, VTOOL,       0, x_("SIM_als_num_events"), 0, 0, 0, 0, N_("ALS: maximum events")},
2177 	{0, 0, (INTBIG*)&sim_tool, VTOOL,       0, x_("SIM_window_state"), 0, 0, ADVANCETIME, 0, N_("Auto advance time")},
2178 	{0, 0, (INTBIG*)&sim_tool, VTOOL,       0, x_("SIM_window_state"), 0, 0, BUSBASEBITS, 0, N_("Base for bus values")},
2179 	{0, 0, (INTBIG*)&sim_tool, VTOOL,       0, x_("SIM_window_state"), 0, 0, SIMENGINE, 0, N_("Simulation engine")},
2180 	{0, 0, (INTBIG*)&sim_tool, VTOOL,       0, x_("SIM_window_state"), 0, 0, SHOWWAVEFORM, 0, N_("Show waveform window")},
2181 	{0, 0, (INTBIG*)&sim_tool, VTOOL,       0, x_("SIM_window_state"), 0, 0, WAVEPLACE, 0, N_("Place waveform window")},
2182 	{0, 0, (INTBIG*)&sim_tool, VTOOL,       0, x_("SIM_window_state"), 0, 0, FULLSTATE, 0, N_("Multistate display")},
2183 	{0, 0, (INTBIG*)&sim_tool, VTOOL,       0, x_("SIM_irsim_state"), 0, 0, IRSIMPARASITICS, 0, N_("IRSIM parasitics")},
2184 	{0, 0, (INTBIG*)&sim_tool, VTOOL,       0, x_("SIM_irsim_state"), 0, 0, IRSIMSHOWCOMMANDS, 0, N_("IRSIM show commands")},
2185 	{0, 0, (INTBIG*)&sim_tool, VTOOL,       0, x_("SIM_irsim_parameter_file"), 0, 0, 0, 0, N_("IRSIM parameter file")},
2186 	{0, 0, (INTBIG*)&sim_tool, VTOOL,       0, x_("SIM_window_color_str0"), 0, 0, 0, 0, N_("Strength 0 (off) color")},
2187 	{0, 0, (INTBIG*)&sim_tool, VTOOL,       0, x_("SIM_window_color_str1"), 0, 0, 0, 0, N_("Strength 1 (node) color")},
2188 	{0, 0, (INTBIG*)&sim_tool, VTOOL,       0, x_("SIM_window_color_str2"), 0, 0, 0, 0, N_("Strength 2 (gate) color")},
2189 	{0, 0, (INTBIG*)&sim_tool, VTOOL,       0, x_("SIM_window_color_str3"), 0, 0, 0, 0, N_("Strength 3 (power) color")},
2190 	{0, 0, (INTBIG*)&sim_tool, VTOOL,       0, x_("SIM_window_color_low"), 0, 0, 0, 0, N_("Low color")},
2191 	{0, 0, (INTBIG*)&sim_tool, VTOOL,       0, x_("SIM_window_color_high"), 0, 0, 0, 0, N_("High color")},
2192 	{0, 0, (INTBIG*)&sim_tool, VTOOL,       0, x_("SIM_window_color_X"), 0, 0, 0, 0, N_("Undefined (X) color")},
2193 	{0, 0, (INTBIG*)&sim_tool, VTOOL,       0, x_("SIM_window_color_Z"), 0, 0, 0, 0, N_("Floating (Z) color")},
2194 	{0, 0, 0,                  0,           0, 0, 0, 0, 0, 0, x_("")}
2195 };
2196 static OPTIONVARPROTO db_ovpsimspice[] =			/* TOOLS: Simulation Interface: Spice Options */
2197 {
2198 /*	{0, 0, 0,                  VNODEPROTO,  0, "SIM_spice_behave_file", 0, 0, 0, 0, N_("")},  *** cell specific ***/
2199 	{0, 0, (INTBIG*)&sim_tool, VTOOL,       0, x_("SIM_dontrun"), 0, 0, 0, 0, N_("Running SPICE")},
2200 	{0, 0, (INTBIG*)&sim_tool, VTOOL,       0, x_("SIM_spice_level"), 0, 0, 0, 0, N_("SPICE level")},
2201 	{0, 0, (INTBIG*)&sim_tool, VTOOL,       0, x_("SIM_spice_state"), 0, 0, SPICETYPE, 0, N_("SPICE engine")},
2202 	{0, 0, (INTBIG*)&sim_tool, VTOOL,       0, x_("SIM_spice_state"), 0, 0, SPICEOUTPUT, 0, N_("SPICE output format")},
2203 	{0, 0, (INTBIG*)&sim_tool, VTOOL,       0, x_("SIM_spice_state"), 0, 0, SPICEGLOBALPG, 0, N_("Force global VDD/GND")},
2204 	{0, 0, (INTBIG*)&sim_tool, VTOOL,       0, x_("SIM_spice_state"), 0, 0, SPICEUSELAMBDAS, 0, N_("Write sizes in lambda")},
2205 	{0, 0, (INTBIG*)&sim_tool, VTOOL,       0, x_("SIM_spice_parts"), 0, 0, 0, 0, N_("SPICE primitive set")},
2206 	{0, 0, (INTBIG*)&sim_tool, VTOOL,       0, x_("SIM_spice_runarguments"), 0, 0, 0, 0, N_("SPICE execution arguments")},
2207 	{0, 0, 0,                  VTECHNOLOGY, 0, x_("SIM_spice_model_file"), 0, 0, 0, 0, N_("Use header cards from file")},
2208 	{0, 0, 0,                  VTECHNOLOGY, 0, x_("SIM_spice_trailer_file"), 0, 0, 0, 0, N_("Use trailer cards from file")},
2209 	{0, 0, 0,                  VTECHNOLOGY, 0, x_("SIM_spice_header_level1"), 0, 0, 0, 0, N_("Level 1 built-in header cards")},
2210 	{0, 0, 0,                  VTECHNOLOGY, 0, x_("SIM_spice_header_level2"), 0, 0, 0, 0, N_("Level 2 built-in header cards")},
2211 	{0, 0, 0,                  VTECHNOLOGY, 0, x_("SIM_spice_header_level3"), 0, 0, 0, 0, N_("Level 3 built-in header cards")},
2212 	{0, 0, 0,                  VTECHNOLOGY, 0, x_("SIM_spice_resistance"), 0, 0, 0, 0, N_("Resistance")},
2213 	{0, 0, 0,                  VTECHNOLOGY, 0, x_("SIM_spice_capacitance"), 0, 0, 0, 0, N_("Capacitance")},
2214 	{0, 0, 0,                  VTECHNOLOGY, 0, x_("SIM_spice_edge_capacitance"), 0, 0, 0, 0, N_("Edge capacitance")},
2215 	{0, 0, 0,                  VTECHNOLOGY, 0, x_("SIM_spice_min_resistance"), 0, 0, 0, 0, N_("Min. resistance")},
2216 	{0, 0, 0,                  VTECHNOLOGY, 0, x_("SIM_spice_min_capacitance"), 0, 0, 0, 0, N_("Min. capacitance")},
2217 	{0, 0, 0,                  0,           0, 0, 0, 0, 0, 0, x_("")}
2218 };
2219 static OPTIONVARPROTO db_ovpsimverilog[] =			/* TOOLS: Simulation Interface: Verilog Options */
2220 {
2221 /*	{0, 0, 0,                  VNODEPROTO,  0, "SIM_verilog_behave_file", 0, 0, 0, 0, N_("")},  *** cell specific ***/
2222 	{0, 0, (INTBIG*)&sim_tool, VTOOL,       0, x_("SIM_verilog_state"), 0, 0, VERILOGUSEASSIGN, 0, N_("Use assign construct")},
2223 	{0, 0, (INTBIG*)&sim_tool, VTOOL,       0, x_("SIM_verilog_state"), 0, 0, VERILOGUSETRIREG, 0, N_("Default wire is trireg")},
2224 	{0, 0, 0,                  0,           0, 0, 0, 0, 0, 0, x_("")}
2225 };
2226 static OPTIONVARPROTO db_ovpsimfasthenry[] =		/* TOOLS: Simulation Interface: FastHenry Options */
2227 {
2228 	{0, 0, (INTBIG*)&sim_tool, VTOOL,       0, x_("SIM_fasthenry_state"), 0, 0, FHUSESINGLEFREQ, 0, N_("Use single frequency")},
2229 	{0, 0, (INTBIG*)&sim_tool, VTOOL,       0, x_("SIM_fasthenry_state"), 0, 0, FHMAKEMULTIPOLECKT, 0, N_("Make multipole subcircuit")},
2230 	{0, 0, (INTBIG*)&sim_tool, VTOOL,       0, x_("SIM_fasthenry_state"), 0, 0, FHMAKEPOSTSCRIPTVIEW, 0, N_("Make PostScript view")},
2231 	{0, 0, (INTBIG*)&sim_tool, VTOOL,       0, x_("SIM_fasthenry_state"), 0, 0, FHMAKESPICESUBCKT, 0, N_("Make SPICE subcircuit")},
2232 	{0, 0, (INTBIG*)&sim_tool, VTOOL,       0, x_("SIM_fasthenry_state"), 0, 0, FHEXECUTETYPE, 0, N_("Action after writing deck")},
2233 	{0, 0, (INTBIG*)&sim_tool, VTOOL,       0, x_("SIM_fasthenry_freqstart"), 0, 0, 0, 0, N_("FastHenry start frequency")},
2234 	{0, 0, (INTBIG*)&sim_tool, VTOOL,       0, x_("SIM_fasthenry_freqend"), 0, 0, 0, 0, N_("FastHenry end frequency")},
2235 	{0, 0, (INTBIG*)&sim_tool, VTOOL,       0, x_("SIM_fasthenry_runsperdecade"), 0, 0, 0, 0, N_("FastHenry runs per decade")},
2236 	{0, 0, (INTBIG*)&sim_tool, VTOOL,       0, x_("SIM_fasthenry_numpoles"), 0, 0, 0, 0, N_("FastHenry number of poles")},
2237 	{0, 0, (INTBIG*)&sim_tool, VTOOL,       0, x_("SIM_fasthenry_seglimit"), 0, 0, 0, 0, N_("FastHenry segment limit")},
2238 	{0, 0, (INTBIG*)&sim_tool, VTOOL,       0, x_("SIM_fasthenry_thickness"), 0, 0, 0, 0, N_("FastHenry thickness")},
2239 	{0, 0, (INTBIG*)&sim_tool, VTOOL,       0, x_("SIM_fasthenry_width_subdivs"), 0, 0, 0, 0, N_("FastHenry width subdivisions")},
2240 	{0, 0, (INTBIG*)&sim_tool, VTOOL,       0, x_("SIM_fasthenry_height_subdivs"), 0, 0, 0, 0, N_("FastHenry height subdivisions")},
2241 	{0, 0, 0,                  0,           0, 0, 0, 0, 0, 0, x_("")}
2242 };
2243 #endif
2244 #if ERCTOOL
2245 static OPTIONVARPROTO db_ovpercwell[] =					/* TOOLS: ERC: Well Check Options */
2246 {
2247 	{0, 0, (INTBIG*)&erc_tool, VTOOL,       0, x_("ERC_options"), 0, 0, PWELLCONOPTIONS, 0, N_("PWell contact checks")},
2248 	{0, 0, (INTBIG*)&erc_tool, VTOOL,       0, x_("ERC_options"), 0, 0, NWELLCONOPTIONS, 0, N_("NWell contact checks")},
2249 	{0, 0, (INTBIG*)&erc_tool, VTOOL,       0, x_("ERC_options"), 0, 0, PWELLONGROUND, 0, N_("Check PWell to ground")},
2250 	{0, 0, (INTBIG*)&erc_tool, VTOOL,       0, x_("ERC_options"), 0, 0, NWELLONPOWER, 0, N_("Check NWell to power")},
2251 	{0, 0, (INTBIG*)&erc_tool, VTOOL,       0, x_("ERC_options"), 0, 0, FINDEDGEDIST, 0, N_("Find farthest distance from contact to edge")},
2252 	{0, 0, 0,                  0,           0, 0, 0, 0, 0, 0, x_("")}
2253 };
2254 static OPTIONVARPROTO db_ovpercant[] =					/* TOOLS: ERC: Antenna Rules Options */
2255 {
2256 	{0, 0, 0,                  VTECHNOLOGY, 0, x_("ERC_antenna_arc_ratio"), 0, 0, 0, 0, N_("Maximum antenna ratio")},
2257 	{0, 0, 0,                  0,           0, 0, 0, 0, 0, 0, x_("")}
2258 };
2259 #endif
2260 static OPTIONVARPROTO db_ovpncc[] =					/* TOOLS: Network: NCC Options */
2261 {
2262 	{0, 0, (INTBIG*)&net_tool, VTOOL,       0, x_("NET_ncc_options"), 0, 0, NCCRECURSE, 0, N_("Recurse through hierarchy")},
2263 	{0, 0, (INTBIG*)&net_tool, VTOOL,       0, x_("NET_ncc_options"), 0, 0, NCCHIERARCHICAL, 0, N_("Expand hierarchy")},
2264 	{0, 0, (INTBIG*)&net_tool, VTOOL,       0, x_("NET_ncc_options"), 0, 0, NCCNOMERGEPARALLEL, 0, N_("Merge parallel components")},
2265 	{0, 0, (INTBIG*)&net_tool, VTOOL,       0, x_("NET_ncc_options"), 0, 0, NCCMERGESERIES, 0, N_("Merge series transistors")},
2266 	{0, 0, (INTBIG*)&net_tool, VTOOL,       0, x_("NET_ncc_options"), 0, 0, NCCIGNOREPWRGND, 0, N_("Ignore power and ground")},
2267 	{0, 0, (INTBIG*)&net_tool, VTOOL,       0, x_("NET_ncc_options"), 0, 0, NCCCHECKEXPORTNAMES, 0, N_("Check export names")},
2268 	{0, 0, (INTBIG*)&net_tool, VTOOL,       0, x_("NET_ncc_options"), 0, 0, NCCCHECKSIZE, 0, N_("Check component sizes")},
2269 	{0, 0, (INTBIG*)&net_tool, VTOOL,       0, x_("NET_ncc_options"), 0, 0, NCCINCLUDENOCOMPNETS, 0, N_("Allow no-component nets")},
2270 	{0, 0, (INTBIG*)&net_tool, VTOOL,       0, x_("NET_ncc_options"), 0, 0, NCCRESISTINCLUSION, 0, N_("NCC automatic resistor adjustment")},
2271 	{0, 0, (INTBIG*)&net_tool, VTOOL,       0, x_("NET_ncc_options"), 0, 0, NCCDISLOCAFTERMATCH|NCCENAFOCSYMGRPFRE|NCCENAFOCSYMGRPPRO|NCCSUPALLAMBREP|NCCVERBOSETEXT|NCCVERBOSEGRAPHICS|NCCGRAPHICPROGRESS|NCCENASTATISTICS, 0, N_("NCC Debugging settings")},
2272 	{0, 0, (INTBIG*)&net_tool, VTOOL,       0, x_("NET_ncc_component_tolerance"), 0, 0, 0, 0, N_("Size tolerance (%)")},
2273 	{0, 0, (INTBIG*)&net_tool, VTOOL,       0, x_("NET_ncc_component_tolerance_amt"), 0, 0, 0, 0, N_("Size tolerance (amt)")},
2274 	{0, 0, 0,                  0,           0, 0, 0, 0, 0, 0, x_("")}
2275 };
2276 static OPTIONVARPROTO db_ovpnetwork[] =				/* TOOLS: Network: Network Options */
2277 {
2278 	{0, 0, (INTBIG*)&net_tool, VTOOL,       0, x_("NET_options"), 0, 0, NETCONPWRGND, 0, N_("Unify Power and Ground")},
2279 	{0, 0, (INTBIG*)&net_tool, VTOOL,       0, x_("NET_options"), 0, 0, NETCONCOMMONNAME, 0, N_("Unify all like-named nets")},
2280 	{0, 0, (INTBIG*)&net_tool, VTOOL,       0, x_("NET_options"), 0, 0, NETIGNORERESISTORS, 0, N_("Ignore Resistors")},
2281 	{0, 0, (INTBIG*)&net_tool, VTOOL,       0, x_("NET_options"), 0, 0, NETDEFBUSBASE1, 0, N_("Bus starting index")},
2282 	{0, 0, (INTBIG*)&net_tool, VTOOL,       0, x_("NET_options"), 0, 0, NETDEFBUSBASEDESC, 0, N_("Bus ascending/descending")},
2283 	{0, 0, (INTBIG*)&net_tool, VTOOL,       0, x_("NET_unify_strings"), 0, 0, 0, 0, N_("Network unification prefix")},
2284 	{0, 0, 0,                  0,           0, 0, 0, 0, 0, 0, x_("")}
2285 };
2286 #if LOGEFFTOOL
2287 static OPTIONVARPROTO db_ovplogeffort[] =			/* TOOLS: Logical Effort: Logical Effort Options */
2288 {
2289 	{0, 0, (INTBIG*)&le_tool,  VTOOL,       0, x_("LE_state"), 0, 0, DISPLAYCAPACITANCE, 0, N_("Display capacitance")},
2290 	{0, 0, (INTBIG*)&le_tool,  VTOOL,       0, x_("LE_state"), 0, 0, HIGHLIGHTCOMPONENTS, 0, N_("Highlight components")},
2291 	{0, 0, (INTBIG*)&le_tool,  VTOOL,       0, x_("LE_state"), 0, 0, LEUSELESETTINGS, 0, N_("Use Local LE Settings")},
2292 	{0, 0, (INTBIG*)&le_tool,  VTOOL,       0, x_("LE_maximum_stage_effort"), 0, 0, 0, 0, N_("Maximum stage gain")},
2293 	{0, 0, (INTBIG*)&le_tool,  VTOOL,       0, x_("LE_global_fanout_effort"), 0, 0, 0, 0, N_("Global fanout")},
2294 	{0, 0, (INTBIG*)&le_tool,  VTOOL,       0, x_("LE_convergence_epsilon"), 0, 0, 0, 0, N_("Convergence Epsilon")},
2295 	{0, 0, (INTBIG*)&le_tool,  VTOOL,       0, x_("LE_diff_ratio_nmos"), 0, 0, 0, 0, N_("NMOS Diffusion ratio")},
2296 	{0, 0, (INTBIG*)&le_tool,  VTOOL,       0, x_("LE_diff_ratio_pmos"), 0, 0, 0, 0, N_("PMOS Diffusion ratio")},
2297 	{0, 0, (INTBIG*)&le_tool,  VTOOL,       0, x_("LE_gate_cap"), 0, 0, 0, 0, N_("Gate capacitance ratio")},
2298 	{0, 0, (INTBIG*)&le_tool,  VTOOL,       0, x_("LE_def_wire_ratio"), 0, 0, 0, 0, N_("Default wire ratio")},
2299 	{0, 0, (INTBIG*)&le_tool,  VTOOL,       0, x_("LE_max_iterations"), 0, 0, 0, 0, N_("Maximum iterations")},
2300 	{0, 0, (INTBIG*)&le_tool,  VTOOL,       0, x_("LE_keeper_size_adj"), 0, 0, 0, 0, N_("Keeper size ratio")},
2301 	{0, 0, 0,                  0,           0, 0, 0, 0, 0, 0, x_("")}
2302 };
2303 #endif
2304 #if ROUTTOOL
2305 static OPTIONVARPROTO db_ovprouting[] =				/* TOOLS: Routing: Routing Options */
2306 {
2307 	{0, 0, (INTBIG*)&ro_tool,  VTOOL,       0, x_("ROUT_prefered_arc"), 0, 0, 0, 0, N_("Prefered arc")},
2308 	{0, 0, (INTBIG*)&ro_tool,  VTOOL,       0, x_("ROUT_options"), 0, 0, MIMICUNROUTES, 0, N_("Mimic stitching can unstitch")},
2309 	{0, 0, (INTBIG*)&ro_tool,  VTOOL,       0, x_("ROUT_options"), 0, 0, MIMICIGNOREPORTS, 0, N_("Ports must match")},
2310 	{0, 0, (INTBIG*)&ro_tool,  VTOOL,       0, x_("ROUT_options"), 0, 0, MIMICONSIDERARCCOUNT, 0, N_("Number of existing arcs must match")},
2311 	{0, 0, (INTBIG*)&ro_tool,  VTOOL,       0, x_("ROUT_options"), 0, 0, MIMICIGNORENODETYPE, 0, N_("Node types must match")},
2312 	{0, 0, (INTBIG*)&ro_tool,  VTOOL,       0, x_("ROUT_options"), 0, 0, MIMICIGNORENODESIZE, 0, N_("Nodes sizes must match")},
2313 	{0, 0, (INTBIG*)&ro_tool,  VTOOL,       0, x_("ROUT_options"), 0, 0, MIMICINTERACTIVE, 0, N_("Mimic stitching runs interactively")},
2314 	{0, 0, 0,                  0,           0, 0, 0, 0, 0, 0, x_("")}
2315 };
2316 #endif
2317 #if VHDLTOOL
2318 static OPTIONVARPROTO db_ovpvhdl[] =				/* TOOLS: VHDL: VHDL Options */
2319 {
2320 	{0, 0, (INTBIG*)&vhdl_tool,VTOOL,       0, x_("VHDL_vhdl_on_disk"), 0, 0, 0, 0, N_("VHDL stored in cell")},
2321 	{0, 0, (INTBIG*)&vhdl_tool,VTOOL,       0, x_("VHDL_netlist_on_disk"), 0, 0, 0, 0, N_("Netlist stored in cell")},
2322 	{0, 0, 0,                  VTECHNOLOGY, 0, x_("TECH_vhdl_names"), 0, 0, 0, 0, N_("VHDL primitive names")},
2323 	{0, 0, 0,                  0,           0, 0, 0, 0, 0, 0, x_("")}
2324 };
2325 #endif
2326 #if SCTOOL
2327 static OPTIONVARPROTO db_ovpsilcomp[] =				/* TOOLS: Silicon Compiler: Silicon Compiler Options */
2328 {
2329 	{0, 0, (INTBIG*)&sc_tool,  VTOOL,       0, x_("SC_horiz_arc"), 0, 0, 0, 0, N_("Horizontal routing arc")},
2330 	{0, 0, (INTBIG*)&sc_tool,  VTOOL,       0, x_("SC_vert_arc"), 0, 0, 0, 0, N_("Vertical routing arc")},
2331 	{0, 0, (INTBIG*)&sc_tool,  VTOOL,       0, x_("SC_l1_width"), 0, 0, 0, 0, N_("Horizontal wire width")},
2332 	{0, 0, (INTBIG*)&sc_tool,  VTOOL,       0, x_("SC_l2_width"), 0, 0, 0, 0, N_("Vertical wire width")},
2333 	{0, 0, (INTBIG*)&sc_tool,  VTOOL,       0, x_("SC_pwr_width"), 0, 0, 0, 0, N_("Power wire width")},
2334 	{0, 0, (INTBIG*)&sc_tool,  VTOOL,       0, x_("SC_main_pwr_width"), 0, 0, 0, 0, N_("Main power wire width")},
2335 	{0, 0, (INTBIG*)&sc_tool,  VTOOL,       0, x_("SC_main_pwr_rail"), 0, 0, 0, 0, N_("Main power arc")},
2336 	{0, 0, (INTBIG*)&sc_tool,  VTOOL,       0, x_("SC_pwell_size"), 0, 0, 0, 0, N_("P-Well height")},
2337 	{0, 0, (INTBIG*)&sc_tool,  VTOOL,       0, x_("SC_pwell_offset"), 0, 0, 0, 0, N_("P-Well offset from bottom")},
2338 	{0, 0, (INTBIG*)&sc_tool,  VTOOL,       0, x_("SC_nwell_size"), 0, 0, 0, 0, N_("N-Well height")},
2339 	{0, 0, (INTBIG*)&sc_tool,  VTOOL,       0, x_("SC_nwell_offset"), 0, 0, 0, 0, N_("N-Well offset from top")},
2340 	{0, 0, (INTBIG*)&sc_tool,  VTOOL,       0, x_("SC_via_size"), 0, 0, 0, 0, N_("Via size")},
2341 	{0, 0, (INTBIG*)&sc_tool,  VTOOL,       0, x_("SC_min_spacing"), 0, 0, 0, 0, N_("Minimum metal spacing")},
2342 	{0, 0, (INTBIG*)&sc_tool,  VTOOL,       0, x_("SC_feedthru_size"), 0, 0, 0, 0, N_("Feedthrough size")},
2343 	{0, 0, (INTBIG*)&sc_tool,  VTOOL,       0, x_("SC_port_x_min_dist"), 0, 0, 0, 0, N_("Minimum port distance")},
2344 	{0, 0, (INTBIG*)&sc_tool,  VTOOL,       0, x_("SC_active_dist"), 0, 0, 0, 0, N_("Minimum active distance")},
2345 	{0, 0, (INTBIG*)&sc_tool,  VTOOL,       0, x_("SC_num_rows"), 0, 0, 0, 0, N_("Number of rows of cells")},
2346 	{0, 0, 0,                  0,           0, 0, 0, 0, 0, 0, x_("")}
2347 };
2348 #endif
2349 #if COMTOOL
2350 static OPTIONVARPROTO db_ovpcompaction[] =			/* TOOLS: Compaction: Compaction Options */
2351 {
2352 	{0, 0, (INTBIG*)&com_tool, VTOOL,       0, x_("COM_spread"), 0, 0, 0, 0, N_("Spreads")},
2353 	{0, 0, 0,                  0,           0, 0, 0, 0, 0, 0, x_("")}
2354 };
2355 #endif
2356 #if	LANGJAVA
2357 static OPTIONVARPROTO db_ovpjava[] =				/* WINDOWS: Java Options */
2358 {
2359 	{0, 0, (INTBIG*)&us_tool,  VTOOL,       0, x_("JAVA_flags"), 0, 0, JAVANOCOMPILER, 0, N_("Disable compiler")},
2360 	{0, 0, (INTBIG*)&us_tool,  VTOOL,       0, x_("JAVA_flags"), 0, 0, JAVANOEVALUATE, 0, N_("Disable evaluation")},
2361 	{0, 0, (INTBIG*)&us_tool,  VTOOL,       0, x_("JAVA_flags"), 0, 0, JAVAUSEJOSE, 0, N_("Enable Jose")},
2362 	{0, 0, 0,                  0,           0, 0, 0, 0, 0, 0, x_("")}
2363 };
2364 #endif
2365 
2366 #define OPTIONCIF                 01		/* CIF Options */
2367 #define OPTIONGDS                 02		/* GDS Options */
2368 #define OPTIONDXF                 04		/* DXF Options */
2369 #define OPTIONEDIF               010		/* EDIF Options */
2370 #define OPTIONPRINT              020		/* Print Options */
2371 #define OPTIONFRAME              040		/* Frame Options */
2372 #define OPTIONALIGNMENT         0100		/* Alignment Options */
2373 #define OPTIONTEXT              0200		/* Text Options */
2374 #define OPTIONNEWNODE           0400		/* New Node Options */
2375 #define OPTIONNEWARC           01000		/* New Arc Options */
2376 #define OPTIONDRC              02000		/* DRC Options */
2377 #define OPTIONSIMULATION       04000		/* Simulation Options */
2378 #define OPTIONSPICE           010000		/* Spice Options */
2379 #define OPTIONVERILOG         020000		/* Verilog Options */
2380 #define OPTIONVHDL            040000		/* VHDL Options */
2381 #define OPTIONSILCOMP        0100000		/* Silicon Compiler Options */
2382 #define OPTIONNETWORK        0200000		/* Network Options */
2383 #define OPTIONROUTING        0400000		/* Routing Options */
2384 #define OPTIONCOMPACTION    01000000		/* Compaction Options */
2385 #define OPTIONGRID          02000000		/* Grid Options */
2386 #define OPTIONLOGEFFORT     04000000		/* Logical Effort Options */
2387 #define OPTIONPORT         010000000		/* Port Display Options */
2388 #define OPTIONCOLOR        020000000		/* Color Options */
2389 #define OPTIONQUICKKEY     040000000		/* Quick Key Options */
2390 #define OPTIONSKILL       0100000000		/* SKILL Options */
2391 #define OPTIONCELL        0200000000		/* Cell Options */
2392 #define OPTIONSELECT      0400000000		/* Selection Options */
2393 #define OPTION3D         01000000000		/* 3D Options */
2394 #define OPTIONTECH       02000000000		/* Technology Options */
2395 #define OPTIONERCWELL    04000000000		/* ERC Well Check Options */
2396 #define OPTIONLAYPAT    010000000000		/* Layer Display Options */
2397 #define OPTIONFASTHENRY 020000000000		/* FastHenry Options */
2398 #define OPTIONDEF                 01		/* DEF Options */
2399 #define OPTIONUNITS               02		/* Technology Units */
2400 #define OPTIONICON                04		/* Icon Options */
2401 #define OPTIONLIBRARY            010		/* Library Options */
2402 #define OPTIONDRCR              0200		/* DRC Rules */
2403 #define OPTIONJAVA              0400		/* Java Options */
2404 #define OPTIONMSGLOC           01000		/* Save Messages Location */
2405 #define OPTIONGENERAL          02000		/* General Options */
2406 #define OPTIONLAYVIS           04000		/* Layer Visibility Options */
2407 #define OPTIONNCC             010000		/* NCC Options */
2408 #define OPTIONCDL             020000		/* CDL Options */
2409 #define OPTIONATTRIBUTES      040000		/* Attribute Options */
2410 #define OPTIONSUE            0100000		/* Sue Options */
2411 #define OPTIONCOPYRIGHT      0200000		/* Copyright Options */
2412 #define OPTIONERCANT        02000000		/* ERC Antenna Rules Options */
2413 
2414 static OPTIONVARCOMS db_optionvarcoms[] =
2415 {
2416 	{{0,OPTIONLIBRARY},    N_("File / IO Options / Library Options"), db_ovpforeignfilelibrary},
2417 	{{0,OPTIONCOPYRIGHT},  N_("File / IO Options / Copyright Options"), db_ovpcopyright},
2418 	{{OPTIONCIF,0},        N_("File / IO Options / CIF Options"), db_ovpforeignfilecif},
2419 	{{OPTIONGDS,0},        N_("File / IO Options / GDS II Options"), db_ovpforeignfilegds},
2420 	{{OPTIONEDIF,0},       N_("File / IO Options / EDIF Options"), db_ovpforeignfileedif},
2421 	{{0,OPTIONDEF},        N_("File / IO Options / DEF Options"), db_ovpforeignfiledef},
2422 	{{0,OPTIONCDL},        N_("File / IO Options / CDL Options"), db_ovpforeignfilecdl},
2423 	{{OPTIONDXF,0},        N_("File / IO Options / DXF Options"), db_ovpforeignfiledxf},
2424 	{{0,OPTIONSUE},        N_("File / IO Options / Sue Options"), db_ovpforeignfilesue},
2425 #ifdef FORCECADENCE
2426 	{{OPTIONSKILL,0},      N_("File / IO Options / SKILL Options"), db_ovpforeignfileskill},
2427 #endif
2428 	{{OPTIONPRINT,0},      N_("File / Print Options"), db_ovpprint},
2429 	{{OPTIONNEWNODE,0},    N_("Edit / New Node Options"), db_ovpnewnode},
2430 	{{OPTIONSELECT,0},     N_("Edit / Selection / Selection Options"), db_ovpselect},
2431 	{{OPTIONCELL,0},       N_("Cell / Cell Options"), db_ovpcell},
2432 	{{OPTIONNEWARC,0},     N_("Arc / New Arc Options"), db_ovpnewarc},
2433 	{{OPTIONPORT,0},       N_("Export / Port and Export Options"), db_ovpport},
2434 	{{OPTIONFRAME,0},      N_("View / Frame Options"), db_ovpframe},
2435 	{{0,OPTIONICON},       N_("View / Icon Options"), db_ovpicon},
2436 	{{OPTIONGRID,0},       N_("Windows / Grid Options"), db_ovpgrid},
2437 	{{OPTIONALIGNMENT,0},  N_("Windows / Alignment Options"), db_ovpalign},
2438 	{{0,OPTIONLAYVIS},     N_("Windows / Layer Visibility"), db_ovplayvis},
2439 	{{OPTIONCOLOR,0},      N_("Windows / Color Options"), db_ovpcolor},
2440 	{{OPTIONLAYPAT,0},     N_("Windows / Layer Display Options"), db_ovplaypat},
2441 	{{OPTIONTEXT,0},       N_("Windows / Text Options"), db_ovptext},
2442 	{{OPTION3D,0},         N_("Windows / 3D Display / 3D Options"), db_ovp3d},
2443 	{{0,OPTIONMSGLOC},     N_("Windows / Messages Window / Save Window Location"), db_ovpmsgloc},
2444 	{{0,OPTIONGENERAL},    N_("Info / User Interface / General Options"), db_ovpgeneral},
2445 	{{OPTIONQUICKKEY,0},   N_("Info / User Interface / Quick Key Options"), db_ovpquickkey},
2446 	{{OPTIONTECH,0},       N_("Technology / Technology Options"), db_ovptechopt},
2447 	{{0,OPTIONUNITS},      N_("Technology / Change Units"), db_ovptechunits},
2448 #if DRCTOOL
2449 	{{OPTIONDRC,0},        N_("Tools / DRC / DRC Options"), db_ovpdrc},
2450 	{{OPTIONDRCR,1},       N_("Tools / DRC / DRC Rules"), db_ovpdrcr},
2451 #endif
2452 #if SIMTOOL
2453 	{{OPTIONSIMULATION,0}, N_("Tools / Simulation (Built-in) / Simulation Options"), db_ovpsimulation},
2454 	{{OPTIONSPICE,0},      N_("Tools / Simulation (SPICE)  / Spice Options"), db_ovpsimspice},
2455 	{{OPTIONVERILOG,0},    N_("Tools / Simulation (Verilog)  / Verilog Options"), db_ovpsimverilog},
2456 	{{OPTIONFASTHENRY,0},  N_("Tools / Simulation (Others)  / FastHenry Options"), db_ovpsimfasthenry},
2457 #endif
2458 #if ERCTOOL
2459 	{{OPTIONERCWELL,0},    N_("Tools / Electrical Rules / Well Check Options"), db_ovpercwell},
2460 	{{0,OPTIONERCANT},     N_("Tools / Electrical Rules / Antenna Rules Options"), db_ovpercant},
2461 #endif
2462 	{{0,OPTIONNCC},        N_("Tools / Network / NCC Control and Options"), db_ovpncc},
2463 	{{OPTIONNETWORK,0},    N_("Tools / Network / Network Options"), db_ovpnetwork},
2464 #if LOGEFFTOOL
2465 	{{OPTIONLOGEFFORT,0},  N_("Tools / Logical Effort / Logical Effort Options"), db_ovplogeffort},
2466 #endif
2467 #if ROUTTOOL
2468 	{{OPTIONROUTING,0},    N_("Tools / Routing / Routing Options"), db_ovprouting},
2469 #endif
2470 #if VHDLTOOL
2471 	{{OPTIONVHDL,0},       N_("Tools / VHDL Compiler / VHDL Options"), db_ovpvhdl},
2472 #endif
2473 #if SCTOOL
2474 	{{OPTIONSILCOMP,0},    N_("Tools / Silicon Compiler / Silicon Compiler Options"), db_ovpsilcomp},
2475 #endif
2476 #if COMTOOL
2477 	{{OPTIONCOMPACTION,0}, N_("Tools / Compaction / Compaction Options"), db_ovpcompaction},
2478 #endif
2479 #if	LANGJAVA
2480 	{{0,OPTIONJAVA},       N_("Tools / Language Interpreter / Java Options"), db_ovpjava}
2481 #endif
2482 };
2483 
2484 /*
2485  * Routine to return the "name" of option "aindex" and its "bits".
2486  * Returns true if the aindex is out of range.
2487  */
describeoptions(INTBIG aindex,CHAR ** name,INTBIG * bits)2488 BOOLEAN describeoptions(INTBIG aindex, CHAR **name, INTBIG *bits)
2489 {
2490 	REGISTER INTBIG optioncomcount, i;
2491 
2492 	optioncomcount = sizeof(db_optionvarcoms) / sizeof(OPTIONVARCOMS);
2493 	if (aindex < 0 || aindex >= optioncomcount) return(TRUE);
2494 	*name = TRANSLATE(db_optionvarcoms[aindex].command);
2495 	for(i=0; i<SAVEDBITWORDS; i++)
2496 		bits[i] = db_optionvarcoms[aindex].bits[i];
2497 	return(FALSE);
2498 }
2499 
2500 /*
2501  * Routine to cache the current value of all options so that it can be determined
2502  * later what has changed.
2503  */
cacheoptionbitvalues(void)2504 void cacheoptionbitvalues(void)
2505 {
2506 	REGISTER INTBIG i, j, optioncomcount;
2507 	REGISTER OPTIONVARPROTO *ovp;
2508 	REGISTER VARIABLE *var;
2509 
2510 	optioncomcount = sizeof(db_optionvarcoms) / sizeof(OPTIONVARCOMS);
2511 	for(i=0; i<optioncomcount; i++)
2512 	{
2513 		ovp = db_optionvarcoms[i].variables;
2514 		for(j=0; ovp[j].variablename != 0; j++)
2515 		{
2516 			if (ovp[j].partial != 0) continue;
2517 			if (ovp[j].addr == 0) continue;
2518 			var = getval(*ovp[j].addr, ovp[j].type, -1, ovp[j].variablename);
2519 			if (var == NOVARIABLE) continue;
2520 			if ((var->type&VTYPE) != VINTEGER) continue;
2521 			if ((var->type&VISARRAY) != 0)
2522 			{
2523 				ovp[j].initialbits1 = ((INTBIG *)var->addr)[0];
2524 				ovp[j].initialbits2 = ((INTBIG *)var->addr)[1];
2525 			} else
2526 			{
2527 				ovp[j].initialbits1 = var->addr;
2528 				ovp[j].initialbits2 = 0;
2529 			}
2530 		}
2531 	}
2532 }
2533 
2534 /*
2535  * Routine to return true if variable "name" on object "addr" (type "type")
2536  * is an option variable.
2537  */
isoptionvariable(INTBIG addr,INTBIG type,CHAR * name)2538 BOOLEAN isoptionvariable(INTBIG addr, INTBIG type, CHAR *name)
2539 {
2540 	REGISTER INTBIG i, j, len, optioncomcount;
2541 	REGISTER BOOLEAN retval;
2542 	REGISTER OPTIONVARPROTO *ovp;
2543 	REGISTER VARIABLE *var;
2544 	Q_UNUSED( addr );
2545 
2546 	retval = FALSE;
2547 	optioncomcount = sizeof(db_optionvarcoms) / sizeof(OPTIONVARCOMS);
2548 	for(i=0; i<optioncomcount; i++)
2549 	{
2550 		ovp = db_optionvarcoms[i].variables;
2551 		for(j=0; ovp[j].variablename != 0; j++)
2552 		{
2553 			if (ovp[j].type != type) continue;
2554 			if (ovp[j].partial != 0)
2555 			{
2556 				len = estrlen(ovp[j].variablename);
2557 				if (namesamen(ovp[j].variablename, name, len) != 0) continue;
2558 			} else
2559 			{
2560 				if (namesame(ovp[j].variablename, name) != 0) continue;
2561 			}
2562 
2563 			/* see if option tracking has been disabled */
2564 			var = getvalkey((INTBIG)us_tool, VTOOL, VINTEGER, us_ignoreoptionchangeskey);
2565 			if (var != NOVARIABLE) continue;
2566 			ovp[j].dirty = TRUE;
2567 			retval = TRUE;
2568 		}
2569 	}
2570 	return(retval);
2571 }
2572 
2573 /*
2574  * Routine to list all options into item "item" of dialog "dia".
2575  */
listalloptions(INTBIG item,void * dia)2576 void listalloptions(INTBIG item, void *dia)
2577 {
2578 	REGISTER INTBIG i, j, optioncomcount, namedoption;
2579 	REGISTER OPTIONVARPROTO *ovp;
2580 	REGISTER void *infstr;
2581 
2582 	optioncomcount = sizeof(db_optionvarcoms) / sizeof(OPTIONVARCOMS);
2583 	for(i=0; i<optioncomcount; i++)
2584 	{
2585 		namedoption = 0;
2586 		ovp = db_optionvarcoms[i].variables;
2587 		for(j=0; ovp[j].variablename != 0; j++)
2588 		{
2589 			if (namedoption == 0)
2590 			{
2591 				infstr = initinfstr();
2592 				formatinfstr(infstr, x_("%s:"), TRANSLATE(db_optionvarcoms[i].command));
2593 				DiaStuffLine(dia, item, returninfstr(infstr));
2594 				namedoption = 1;
2595 			}
2596 			infstr = initinfstr();
2597 			formatinfstr(infstr, x_("   %s"), TRANSLATE(ovp[j].meaning));
2598 			DiaStuffLine(dia, item, returninfstr(infstr));
2599 		}
2600 	}
2601 }
2602 
2603 /*
2604  * Routine to display which options have changed.
2605  */
explainoptionchanges(INTBIG item,void * dia)2606 void explainoptionchanges(INTBIG item, void *dia)
2607 {
2608 	REGISTER INTBIG i, j, k, optioncomcount, namedoption, val1, val2, len;
2609 	REGISTER CHAR *name;
2610 	REGISTER BOOLEAN same;
2611 	REGISTER TECHNOLOGY *tech;
2612 	REGISTER NODEPROTO *np;
2613 	REGISTER ARCPROTO *ap;
2614 	REGISTER OPTIONVARPROTO *ovp;
2615 	REGISTER VARIABLE *var;
2616 	REGISTER void *infstr;
2617 
2618 	optioncomcount = sizeof(db_optionvarcoms) / sizeof(OPTIONVARCOMS);
2619 	for(i=0; i<optioncomcount; i++)
2620 	{
2621 		namedoption = 0;
2622 		ovp = db_optionvarcoms[i].variables;
2623 		for(j=0; ovp[j].variablename != 0; j++)
2624 		{
2625 			if (!ovp[j].dirty) continue;
2626 			if (ovp[j].addr == 0)
2627 			{
2628 				same = TRUE;
2629 				switch (ovp[j].type)
2630 				{
2631 					case VTECHNOLOGY:
2632 						for(tech = el_technologies; tech != NOTECHNOLOGY; tech = tech->nexttechnology)
2633 						{
2634 							if (ovp[j].partial == 0)
2635 							{
2636 								var = getval((INTBIG)tech, ovp[j].type, -1, ovp[j].variablename);
2637 								if (var != NOVARIABLE && (var->type&VDONTSAVE) == 0) same = FALSE;
2638 							} else
2639 							{
2640 								len = estrlen(ovp[j].variablename);
2641 								for(k=0; k<tech->numvar; k++)
2642 								{
2643 									var = &tech->firstvar[k];
2644 									name = makename(var->key);
2645 									if (namesamen(ovp[j].variablename, name, len) == 0)
2646 									{
2647 										if ((var->type&VDONTSAVE) == 0) same = FALSE;
2648 									}
2649 								}
2650 							}
2651 						}
2652 						break;
2653 					case VNODEPROTO:
2654 						for(tech = el_technologies; tech != NOTECHNOLOGY; tech = tech->nexttechnology)
2655 						{
2656 							for(np = tech->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
2657 							{
2658 								var = getval((INTBIG)np, ovp[j].type, -1, ovp[j].variablename);
2659 								if (var != NOVARIABLE && (var->type&VDONTSAVE) == 0) same = FALSE;
2660 							}
2661 							if (!same) break;
2662 						}
2663 						break;
2664 					case VARCPROTO:
2665 						for(tech = el_technologies; tech != NOTECHNOLOGY; tech = tech->nexttechnology)
2666 						{
2667 							for(ap = tech->firstarcproto; ap != NOARCPROTO; ap = ap->nextarcproto)
2668 							{
2669 								var = getval((INTBIG)ap, ovp[j].type, -1, ovp[j].variablename);
2670 								if (var != NOVARIABLE && (var->type&VDONTSAVE) == 0) same = FALSE;
2671 							}
2672 							if (!same) break;
2673 						}
2674 						break;
2675 				}
2676 				if (same) continue;
2677 			} else
2678 			{
2679 				if (ovp[j].maskbits1 != 0 || ovp[j].maskbits2 != 0)
2680 				{
2681 					var = getval(*ovp[j].addr, ovp[j].type, -1, ovp[j].variablename);
2682 					if (var == NOVARIABLE) val1 = val2 = 0; else
2683 					{
2684 						if ((var->type&VTYPE) != VINTEGER) continue;
2685 						if ((var->type&VISARRAY) != 0)
2686 						{
2687 							val1 = ((INTBIG *)var->addr)[0];
2688 							val2 = ((INTBIG *)var->addr)[1];
2689 						} else
2690 						{
2691 							val1 = var->addr;
2692 							val2 = 0;
2693 						}
2694 					}
2695 					same = TRUE;
2696 					if (ovp[j].maskbits1 != 0)
2697 					{
2698 						if ((val1 & ovp[j].maskbits1) != (ovp[j].initialbits1&ovp[j].maskbits1)) same = FALSE;
2699 					}
2700 					if (ovp[j].maskbits2 != 0)
2701 					{
2702 						if ((val2 & ovp[j].maskbits2) != (ovp[j].initialbits2&ovp[j].maskbits2)) same = FALSE;
2703 					}
2704 					if (same) continue;
2705 				}
2706 			}
2707 			if (namedoption == 0)
2708 			{
2709 				infstr = initinfstr();
2710 				formatinfstr(infstr, x_("%s:"), TRANSLATE(db_optionvarcoms[i].command));
2711 				if (item < 0) ttyputmsg(x_("%s"), returninfstr(infstr)); else
2712 					DiaStuffLine(dia, item, returninfstr(infstr));
2713 				namedoption = 1;
2714 			}
2715 			infstr = initinfstr();
2716 			formatinfstr(infstr, x_("   %s"), TRANSLATE(ovp[j].meaning));
2717 			if (item < 0) ttyputmsg(x_("%s"), returninfstr(infstr)); else
2718 				DiaStuffLine(dia, item, returninfstr(infstr));
2719 		}
2720 	}
2721 }
2722 
explainsavedoptions(INTBIG item,BOOLEAN onlychanged,void * dia)2723 void explainsavedoptions(INTBIG item, BOOLEAN onlychanged, void *dia)
2724 {
2725 	REGISTER INTBIG i, j, k, optioncomcount, namedoption, val1, val2, len;
2726 	REGISTER CHAR *name;
2727 	REGISTER OPTIONVARPROTO *ovp;
2728 	REGISTER BOOLEAN dirty, found;
2729 	REGISTER VARIABLE *var;
2730 	REGISTER TECHNOLOGY *tech;
2731 	REGISTER NODEPROTO *np;
2732 	REGISTER ARCPROTO *ap;
2733 	REGISTER void *infstr;
2734 
2735 	optioncomcount = sizeof(db_optionvarcoms) / sizeof(OPTIONVARCOMS);
2736 	for(i=0; i<optioncomcount; i++)
2737 	{
2738 		namedoption = 0;
2739 		ovp = db_optionvarcoms[i].variables;
2740 		for(j=0; ovp[j].variablename != 0; j++)
2741 		{
2742 			if (ovp[j].addr == 0)
2743 			{
2744 				found = FALSE;
2745 				dirty = FALSE;		/* must figure it out for real */
2746 				switch (ovp[j].type)
2747 				{
2748 					case VTECHNOLOGY:
2749 						for(tech = el_technologies; tech != NOTECHNOLOGY; tech = tech->nexttechnology)
2750 						{
2751 							if (ovp[j].partial == 0)
2752 							{
2753 								var = getval((INTBIG)tech, ovp[j].type, -1, ovp[j].variablename);
2754 								if (var != NOVARIABLE && (var->type&VDONTSAVE) == 0) { found = TRUE;   break; }
2755 							} else
2756 							{
2757 								len = estrlen(ovp[j].variablename);
2758 								for(k=0; k<tech->numvar; k++)
2759 								{
2760 									var = &tech->firstvar[k];
2761 									name = makename(var->key);
2762 									if (namesamen(ovp[j].variablename, name, len) == 0)
2763 									{
2764 										if ((var->type&VDONTSAVE) == 0) { found = TRUE;   break; }
2765 									}
2766 								}
2767 								if (found) break;
2768 							}
2769 						}
2770 						break;
2771 					case VNODEPROTO:
2772 						for(tech = el_technologies; tech != NOTECHNOLOGY; tech = tech->nexttechnology)
2773 						{
2774 							for(np = tech->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
2775 							{
2776 								var = getval((INTBIG)np, ovp[j].type, -1, ovp[j].variablename);
2777 								if (var != NOVARIABLE && (var->type&VDONTSAVE) == 0) { found = TRUE;   break; }
2778 							}
2779 							if (found) break;
2780 						}
2781 						break;
2782 					case VARCPROTO:
2783 						for(tech = el_technologies; tech != NOTECHNOLOGY; tech = tech->nexttechnology)
2784 						{
2785 							for(ap = tech->firstarcproto; ap != NOARCPROTO; ap = ap->nextarcproto)
2786 							{
2787 								var = getval((INTBIG)ap, ovp[j].type, -1, ovp[j].variablename);
2788 								if (var != NOVARIABLE && (var->type&VDONTSAVE) == 0) { found = TRUE;   break; }
2789 							}
2790 							if (found) break;
2791 						}
2792 						break;
2793 				}
2794 				if (!found) continue;
2795 			} else
2796 			{
2797 				var = getval(*ovp[j].addr, ovp[j].type, -1, ovp[j].variablename);
2798 				if (var == NOVARIABLE || (var->type&VDONTSAVE) != 0) continue;
2799 				dirty = FALSE;
2800 				if ((ovp[j].maskbits1 != 0 || ovp[j].maskbits2 != 0) && (var->type&VTYPE) == VINTEGER)
2801 				{
2802 					if ((var->type&VISARRAY) != 0)
2803 					{
2804 						val1 = ((INTBIG *)var->addr)[0];
2805 						val2 = ((INTBIG *)var->addr)[1];
2806 					} else
2807 					{
2808 						val1 = var->addr;
2809 						val2 = 0;
2810 					}
2811 					if (ovp[j].maskbits1 != 0)
2812 					{
2813 						if ((val1 & ovp[j].maskbits1) != (ovp[j].initialbits1&ovp[j].maskbits1)) dirty = TRUE;
2814 					}
2815 					if (ovp[j].maskbits2 != 0)
2816 					{
2817 						if ((val2 & ovp[j].maskbits2) != (ovp[j].initialbits2&ovp[j].maskbits2)) dirty = TRUE;
2818 					}
2819 				} else
2820 				{
2821 					if (ovp[j].dirty) dirty = TRUE;
2822 				}
2823 			}
2824 			if (onlychanged && !dirty) continue;
2825 			if (namedoption == 0)
2826 			{
2827 				infstr = initinfstr();
2828 				formatinfstr(infstr, x_("%s:"), TRANSLATE(db_optionvarcoms[i].command));
2829 				DiaStuffLine(dia, item, returninfstr(infstr));
2830 				namedoption = 1;
2831 			}
2832 			infstr = initinfstr();
2833 			if (!onlychanged && dirty) addstringtoinfstr(infstr, x_("*"));
2834 			formatinfstr(infstr, x_("   %s"), TRANSLATE(ovp[j].meaning));
2835 			DiaStuffLine(dia, item, returninfstr(infstr));
2836 		}
2837 	}
2838 }
2839 
2840 /*
2841  * Routine to return true if options have really changed.
2842  */
optionshavechanged(void)2843 BOOLEAN optionshavechanged(void)
2844 {
2845 	REGISTER INTBIG i, j, k, optioncomcount, val1, val2, same, len;
2846 	REGISTER CHAR *name;
2847 	REGISTER OPTIONVARPROTO *ovp;
2848 	REGISTER TECHNOLOGY *tech;
2849 	REGISTER NODEPROTO *np;
2850 	REGISTER ARCPROTO *ap;
2851 	REGISTER VARIABLE *var;
2852 
2853 	optioncomcount = sizeof(db_optionvarcoms) / sizeof(OPTIONVARCOMS);
2854 	for(i=0; i<optioncomcount; i++)
2855 	{
2856 		ovp = db_optionvarcoms[i].variables;
2857 		for(j=0; ovp[j].variablename != 0; j++)
2858 		{
2859 			if (!ovp[j].dirty) continue;
2860 			if (ovp[j].addr == 0)
2861 			{
2862 				switch (ovp[j].type)
2863 				{
2864 					case VTECHNOLOGY:
2865 						for(tech = el_technologies; tech != NOTECHNOLOGY; tech = tech->nexttechnology)
2866 						{
2867 							if (ovp[j].partial == 0)
2868 							{
2869 								var = getval((INTBIG)tech, ovp[j].type, -1, ovp[j].variablename);
2870 								if (var != NOVARIABLE && (var->type&VDONTSAVE) == 0) return(TRUE);
2871 							} else
2872 							{
2873 								len = estrlen(ovp[j].variablename);
2874 								for(k=0; k<tech->numvar; k++)
2875 								{
2876 									var = &tech->firstvar[k];
2877 									name = makename(var->key);
2878 									if (namesamen(ovp[j].variablename, name, len) == 0)
2879 									{
2880 										if ((var->type&VDONTSAVE) == 0) return(TRUE);
2881 									}
2882 								}
2883 							}
2884 						}
2885 						break;
2886 					case VNODEPROTO:
2887 						for(tech = el_technologies; tech != NOTECHNOLOGY; tech = tech->nexttechnology)
2888 						{
2889 							for(np = tech->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
2890 							{
2891 								var = getval((INTBIG)np, ovp[j].type, -1, ovp[j].variablename);
2892 								if (var != NOVARIABLE && (var->type&VDONTSAVE) == 0) return(TRUE);
2893 							}
2894 						}
2895 						break;
2896 					case VARCPROTO:
2897 						for(tech = el_technologies; tech != NOTECHNOLOGY; tech = tech->nexttechnology)
2898 						{
2899 							for(ap = tech->firstarcproto; ap != NOARCPROTO; ap = ap->nextarcproto)
2900 							{
2901 								var = getval((INTBIG)ap, ovp[j].type, -1, ovp[j].variablename);
2902 								if (var != NOVARIABLE && (var->type&VDONTSAVE) == 0) return(TRUE);
2903 							}
2904 						}
2905 						break;
2906 				}
2907 				continue;
2908 			}
2909 			if (ovp[j].maskbits1 != 0 || ovp[j].maskbits2 != 0)
2910 			{
2911 				var = getval(*ovp[j].addr, ovp[j].type, -1, ovp[j].variablename);
2912 				if (var == NOVARIABLE) val1 = val2 = 0; else
2913 				{
2914 					if ((var->type&VTYPE) != VINTEGER) continue;
2915 					if ((var->type&VISARRAY) != 0)
2916 					{
2917 						val1 = ((INTBIG *)var->addr)[0];
2918 						val2 = ((INTBIG *)var->addr)[1];
2919 					} else
2920 					{
2921 						val1 = var->addr;
2922 						val2 = 0;
2923 					}
2924 				}
2925 				same = 1;
2926 				if (ovp[j].maskbits1 != 0)
2927 				{
2928 					if ((val1 & ovp[j].maskbits1) != (ovp[j].initialbits1&ovp[j].maskbits1)) same = 0;
2929 				}
2930 				if (ovp[j].maskbits2 != 0)
2931 				{
2932 					if ((val2 & ovp[j].maskbits2) != (ovp[j].initialbits2&ovp[j].maskbits2)) same = 0;
2933 				}
2934 				if (same != 0) continue;
2935 			}
2936 			return(TRUE);
2937 		}
2938 	}
2939 	return(FALSE);
2940 }
2941 
2942 /*
2943  * Routine to make all options "temporary" (set their "VDONTSAVE" bit so that they are
2944  * not saved to disk).  Any exceptions to this may be specified in the
2945  * "LIB_save_options" variable of "lib".  In addition, all such option variables are
2946  * remembered so that the "temporary" state can be restored later in
2947  * "us_restoreoptionstate()".  This is done before saving a library so that the
2948  * options are *NOT* saved with the data.  Only the "options" library has these
2949  * option variables saved with it.
2950  */
makeoptionstemporary(LIBRARY * lib)2951 void makeoptionstemporary(LIBRARY *lib)
2952 {
2953 	REGISTER INTBIG teccount, arccount, nodecount, i, j, k, l, ind, optioncomcount,
2954 		len;
2955 	INTBIG savebits[SAVEDBITWORDS];
2956 	REGISTER CHAR *name;
2957 	REGISTER VARIABLE *var;
2958 	REGISTER TECHNOLOGY *tech;
2959 	REGISTER NODEPROTO *np;
2960 	REGISTER ARCPROTO *ap;
2961 	REGISTER OPTIONVARPROTO *ovp, *ovp2;
2962 
2963 	/* deallocate any former options variable cache */
2964 	if (db_optionvarcachecount > 0) efree((CHAR *)db_optionvarcache);
2965 	db_optionvarcachecount = 0;
2966 
2967 	/* see which options *SHOULD* be saved */
2968 	for(i=0; i<SAVEDBITWORDS; i++) savebits[i] = 0;
2969 	var = getval((INTBIG)lib, VLIBRARY, -1, x_("LIB_save_options"));
2970 	if (var != NOVARIABLE)
2971 	{
2972 		if ((var->type&VISARRAY) == 0)
2973 		{
2974 			savebits[0] = var->addr;
2975 		} else
2976 		{
2977 			len = getlength(var);
2978 			for(i=0; i<len; i++) savebits[i] = ((INTBIG *)var->addr)[i];
2979 		}
2980 	}
2981 
2982 	/* clear flags of which options to save */
2983 	optioncomcount = sizeof(db_optionvarcoms) / sizeof(OPTIONVARCOMS);
2984 	for(i=0; i<optioncomcount; i++)
2985 	{
2986 		ovp = db_optionvarcoms[i].variables;
2987 		for(j=0; ovp[j].variablename != 0; j++) ovp[j].saveflag = 0;
2988 	}
2989 
2990 	/* set flags on options that should be saved */
2991 	for(i=0; i<optioncomcount; i++)
2992 	{
2993 		/* see if this option package should be saved */
2994 		for(j=0; j<SAVEDBITWORDS; j++)
2995 			if ((db_optionvarcoms[i].bits[j]&savebits[j]) != 0) break;
2996 		if (j >= SAVEDBITWORDS) continue;
2997 
2998 		ovp = db_optionvarcoms[i].variables;
2999 		for(j=0; ovp[j].variablename != 0; j++)
3000 		{
3001 			ovp[j].saveflag = 1;
3002 
3003 			/* also save same option in other commands */
3004 			for(k=0; k<optioncomcount; k++)
3005 			{
3006 				if (k == i) continue;
3007 				ovp2 = db_optionvarcoms[k].variables;
3008 				for(l=0; ovp2[l].variablename != 0; l++)
3009 				{
3010 					if (ovp[j].addr == ovp2[l].addr &&
3011 						ovp[j].type == ovp2[l].type &&
3012 						namesame(ovp[j].variablename, ovp2[l].variablename) == 0)
3013 							ovp2[l].saveflag = 1;
3014 				}
3015 			}
3016 		}
3017 	}
3018 
3019 	/* determine the number of option variables */
3020 	teccount = arccount = nodecount = 0;
3021 	for(tech = el_technologies; tech != NOTECHNOLOGY; tech = tech->nexttechnology)
3022 	{
3023 		teccount++;
3024 		for(np = tech->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto) nodecount++;
3025 		for(ap = tech->firstarcproto; ap != NOARCPROTO; ap = ap->nextarcproto) arccount++;
3026 	}
3027 
3028 	db_optionvarcachecount = 0;
3029 	for(i=0; i<optioncomcount; i++)
3030 	{
3031 		ovp = db_optionvarcoms[i].variables;
3032 		for(j=0; ovp[j].variablename != 0; j++)
3033 		{
3034 			if (ovp[j].saveflag != 0) continue;
3035 			switch (ovp[j].type)
3036 			{
3037 				case VTECHNOLOGY:
3038 					if (ovp[j].partial == 0) db_optionvarcachecount += teccount; else
3039 					{
3040 						len = estrlen(ovp[j].variablename);
3041 						for(tech = el_technologies; tech != NOTECHNOLOGY; tech = tech->nexttechnology)
3042 						{
3043 							for(k=0; k<tech->numvar; k++)
3044 							{
3045 								var = &tech->firstvar[k];
3046 								name = makename(var->key);
3047 								if (namesamen(ovp[j].variablename, name, len) == 0)
3048 									db_optionvarcachecount++;
3049 							}
3050 						}
3051 					}
3052 					break;
3053 				case VNODEPROTO:  db_optionvarcachecount += nodecount;  break;
3054 				case VARCPROTO:   db_optionvarcachecount += arccount;   break;
3055 				default:          db_optionvarcachecount++;             break;
3056 			}
3057 		}
3058 	}
3059 
3060 	/* allocate space for the option variable cache */
3061 	db_optionvarcache = (OPTIONVARCACHE *)emalloc(db_optionvarcachecount * (sizeof (OPTIONVARCACHE)),
3062 		us_tool->cluster);
3063 	if (db_optionvarcache == 0)
3064 	{
3065 		db_optionvarcachecount = 0;
3066 		return;
3067 	}
3068 
3069 	/* load the option variable cache */
3070 	ind = 0;
3071 	for(i=0; i<optioncomcount; i++)
3072 	{
3073 		ovp = db_optionvarcoms[i].variables;
3074 		for(j=0; ovp[j].variablename != 0; j++)
3075 		{
3076 			if (ovp[j].saveflag != 0) continue;
3077 			switch (ovp[j].type)
3078 			{
3079 				case VTECHNOLOGY:
3080 					if (ovp[j].partial == 0)
3081 					{
3082 						for(tech = el_technologies; tech != NOTECHNOLOGY; tech = tech->nexttechnology)
3083 						{
3084 							db_optionvarcache[ind].addr = (INTBIG)tech;
3085 							db_optionvarcache[ind].type = VTECHNOLOGY;
3086 							db_optionvarcache[ind].variablename = ovp[j].variablename;
3087 							ind++;
3088 						}
3089 					} else
3090 					{
3091 						len = estrlen(ovp[j].variablename);
3092 						for(tech = el_technologies; tech != NOTECHNOLOGY; tech = tech->nexttechnology)
3093 						{
3094 							for(k=0; k<tech->numvar; k++)
3095 							{
3096 								var = &tech->firstvar[k];
3097 								name = makename(var->key);
3098 								if (namesamen(ovp[j].variablename, name, len) != 0) continue;
3099 								db_optionvarcache[ind].addr = (INTBIG)tech;
3100 								db_optionvarcache[ind].type = VTECHNOLOGY;
3101 								db_optionvarcache[ind].variablename = name;
3102 								ind++;
3103 							}
3104 						}
3105 					}
3106 					break;
3107 				case VNODEPROTO:
3108 					for(tech = el_technologies; tech != NOTECHNOLOGY; tech = tech->nexttechnology)
3109 					{
3110 						for(np = tech->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
3111 						{
3112 							db_optionvarcache[ind].addr = (INTBIG)np;
3113 							db_optionvarcache[ind].type = VNODEPROTO;
3114 							db_optionvarcache[ind].variablename = ovp[j].variablename;
3115 							ind++;
3116 						}
3117 					}
3118 					break;
3119 				case VARCPROTO:
3120 					for(tech = el_technologies; tech != NOTECHNOLOGY; tech = tech->nexttechnology)
3121 					{
3122 						for(ap = tech->firstarcproto; ap != NOARCPROTO; ap = ap->nextarcproto)
3123 						{
3124 							db_optionvarcache[ind].addr = (INTBIG)ap;
3125 							db_optionvarcache[ind].type = VARCPROTO;
3126 							db_optionvarcache[ind].variablename = ovp[j].variablename;
3127 							ind++;
3128 						}
3129 					}
3130 					break;
3131 				default:
3132 					db_optionvarcache[ind].addr = *ovp[j].addr;
3133 					db_optionvarcache[ind].type = ovp[j].type;
3134 					db_optionvarcache[ind].variablename = ovp[j].variablename;
3135 					ind++;
3136 					break;
3137 			}
3138 		}
3139 	}
3140 
3141 	/* now cache the parameter state and make them non-savable */
3142 	for(i=0; i<db_optionvarcachecount; i++)
3143 	{
3144 		var = getval(db_optionvarcache[i].addr, db_optionvarcache[i].type, -1,
3145 			db_optionvarcache[i].variablename);
3146 		if (var == NOVARIABLE) continue;
3147 		db_optionvarcache[i].oldtype = var->type;
3148 	}
3149 	for(i=0; i<db_optionvarcachecount; i++)
3150 	{
3151 		var = getval(db_optionvarcache[i].addr, db_optionvarcache[i].type, -1,
3152 			db_optionvarcache[i].variablename);
3153 		if (var == NOVARIABLE) continue;
3154 		var->type |= VDONTSAVE;
3155 	}
3156 
3157 	/* finally, cache the font association information */
3158 	db_makefontassociations(lib);
3159 }
3160 
3161 /*
3162  * Routine to look for non-default font usage and write the font name table.
3163  */
db_makefontassociations(LIBRARY * lib)3164 void db_makefontassociations(LIBRARY *lib)
3165 {
3166 	REGISTER NODEPROTO *np;
3167 	REGISTER NODEINST *ni;
3168 	REGISTER ARCINST *ai;
3169 	REGISTER PORTARCINST *pi;
3170 	REGISTER PORTEXPINST *pe;
3171 	REGISTER PORTPROTO *pp;
3172 	REGISTER INTBIG *fontusage, numfonts, i, used;
3173 	CHAR **list, **fontassociations;
3174 	REGISTER void *infstr;
3175 
3176 	numfonts = screengetfacelist(&list, FALSE);
3177 	fontusage = (INTBIG *)emalloc(numfonts * SIZEOFINTBIG, db_cluster);
3178 	if (fontusage == 0) return;
3179 	for(i=0; i<numfonts; i++) fontusage[i] = 0;
3180 	for(np = lib->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
3181 	{
3182 		for(ni = np->firstnodeinst; ni != NONODEINST; ni = ni->nextnodeinst)
3183 		{
3184 			db_makefontassociationvar(ni->numvar, ni->firstvar, fontusage, numfonts);
3185 			for(pi = ni->firstportarcinst; pi != NOPORTARCINST; pi = pi->nextportarcinst)
3186 				db_makefontassociationvar(pi->numvar, pi->firstvar, fontusage, numfonts);
3187 			for(pe = ni->firstportexpinst; pe != NOPORTEXPINST; pe = pe->nextportexpinst)
3188 				db_makefontassociationvar(pe->numvar, pe->firstvar, fontusage, numfonts);
3189 			if (ni->proto->primindex == 0)
3190 				db_makefontassociationdescript(ni->textdescript, fontusage, numfonts);
3191 		}
3192 		for(ai = np->firstarcinst; ai != NOARCINST; ai = ai->nextarcinst)
3193 			db_makefontassociationvar(ai->numvar, ai->firstvar, fontusage, numfonts);
3194 		for(pp = np->firstportproto; pp != NOPORTPROTO; pp = pp->nextportproto)
3195 		{
3196 			db_makefontassociationvar(pp->numvar, pp->firstvar, fontusage, numfonts);
3197 			db_makefontassociationdescript(pp->textdescript, fontusage, numfonts);
3198 		}
3199 		db_makefontassociationvar(np->numvar, np->firstvar, fontusage, numfonts);
3200 	}
3201 	db_makefontassociationvar(lib->numvar, lib->firstvar, fontusage, numfonts);
3202 
3203 	/* now look for fonts that are in use */
3204 	used = 0;
3205 	for(i=1; i<numfonts; i++)
3206 	{
3207 		if (fontusage[i] != 0) used++;
3208 	}
3209 	if (used > 0)
3210 	{
3211 		fontassociations = (CHAR **)emalloc(used * (sizeof (CHAR *)), db_cluster);
3212 		if (fontassociations == 0) return;
3213 		used = 0;
3214 		for(i=1; i<numfonts; i++)
3215 		{
3216 			if (fontusage[i] == 0) continue;
3217 			infstr = initinfstr();
3218 			formatinfstr(infstr, x_("%ld/%s"), i, list[i]);
3219 			(void)allocstring(&fontassociations[used], returninfstr(infstr), db_cluster);
3220 			used++;
3221 		}
3222 		nextchangequiet();
3223 		(void)setval((INTBIG)lib, VLIBRARY, x_("LIB_font_associations"),
3224 			(INTBIG)fontassociations, VSTRING|VISARRAY|(used<<VLENGTHSH));
3225 		efree((CHAR *)fontassociations);
3226 	}
3227 	efree((CHAR *)fontusage);
3228 }
3229 
3230 /*
3231  * Helper routine for "db_makefontassociations"
3232  */
db_makefontassociationvar(INTSML numvar,VARIABLE * firstvar,INTBIG * fontusage,INTBIG numfonts)3233 void db_makefontassociationvar(INTSML numvar, VARIABLE *firstvar, INTBIG *fontusage, INTBIG numfonts)
3234 {
3235 	REGISTER INTBIG i;
3236 	REGISTER VARIABLE *var;
3237 
3238 	for(i=0; i<numvar; i++)
3239 	{
3240 		var = &firstvar[i];
3241 		if ((var->type&VDISPLAY) != 0)
3242 			db_makefontassociationdescript(var->textdescript, fontusage, numfonts);
3243 	}
3244 }
3245 
3246 /*
3247  * Helper routine for "db_makefontassociations"
3248  */
db_makefontassociationdescript(UINTBIG * descript,INTBIG * fontusage,INTBIG numfonts)3249 void db_makefontassociationdescript(UINTBIG *descript, INTBIG *fontusage, INTBIG numfonts)
3250 {
3251 	REGISTER INTBIG face;
3252 
3253 	face = TDGETFACE(descript);
3254 	if (face != 0)
3255 	{
3256 		if (face < numfonts)
3257 			fontusage[face]++;
3258 	}
3259 }
3260 
3261 /*
3262  * Routine to restore the "temporary" state of all option variables (used after
3263  * the library has been written.
3264  */
restoreoptionstate(LIBRARY * lib)3265 void restoreoptionstate(LIBRARY *lib)
3266 {
3267 	REGISTER INTBIG i;
3268 	REGISTER VARIABLE *var;
3269 
3270 	/* restore the parameter state */
3271 	for(i=0; i<db_optionvarcachecount; i++)
3272 	{
3273 		var = getval(db_optionvarcache[i].addr, db_optionvarcache[i].type, -1,
3274 			db_optionvarcache[i].variablename);
3275 		if (var == NOVARIABLE) continue;
3276 		var->type = db_optionvarcache[i].oldtype;
3277 	}
3278 	if (getval((INTBIG)lib, VLIBRARY, VSTRING|VISARRAY, x_("LIB_font_associations")) != NOVARIABLE)
3279 	{
3280 		nextchangequiet();
3281 		(void)delval((INTBIG)lib, VLIBRARY, x_("LIB_font_associations"));
3282 	}
3283 }
3284 
3285 /******************** PARAMETERIZED CELLS ********************/
3286 
3287 /*
3288  * Routine to initialize the current list of parameterized cells.
3289  */
initparameterizedcells(void)3290 void initparameterizedcells(void)
3291 {
3292 	REGISTER PARCELL *pc;
3293 
3294 	while (db_firstparcell != NOPARCELL)
3295 	{
3296 		pc = db_firstparcell;
3297 		db_firstparcell = pc->nextparcell;
3298 		efree((CHAR *)pc->parname);
3299 		efree((CHAR *)pc->shortname);
3300 		db_freeparcell(pc);
3301 	}
3302 }
3303 
3304 /*
3305  * Routine to check to see if parameterization "parname" of cell "np" is in the
3306  * list of parameterized cells.  If found, returns pointer to the name (or
3307  * the short name if there is one).  If not found, returns 0.
3308  */
inparameterizedcells(NODEPROTO * np,CHAR * parname)3309 CHAR *inparameterizedcells(NODEPROTO *np, CHAR *parname)
3310 {
3311 	REGISTER PARCELL *pc;
3312 	REGISTER NODEPROTO *onp;
3313 
3314 	for(pc = db_firstparcell; pc != NOPARCELL; pc = pc->nextparcell)
3315 	{
3316 		FOR_CELLGROUP(onp, np)
3317 			if (pc->cell == onp) break;
3318 		if (onp == NONODEPROTO) continue;
3319 		if (namesame(pc->parname, parname) == 0)
3320 		{
3321 			if (pc->shortname != 0) return(pc->shortname);
3322 			return(pc->parname);
3323 		}
3324 	}
3325 	return(0);
3326 }
3327 
3328 /*
3329  * Routine to add parameterization "parname" of cell "np" to the
3330  * list of parameterized cells.
3331  */
addtoparameterizedcells(NODEPROTO * np,CHAR * parname,CHAR * shortname)3332 void addtoparameterizedcells(NODEPROTO *np, CHAR *parname, CHAR *shortname)
3333 {
3334 	REGISTER PARCELL *pc;
3335 
3336 	pc = db_allocparcell();
3337 	if (pc == NOPARCELL) return;
3338 	pc->cell = np;
3339 	(void)allocstring(&pc->parname, parname, db_cluster);
3340 	if (shortname == 0) pc->shortname = 0; else
3341 		(void)allocstring(&pc->shortname, shortname, db_cluster);
3342 	pc->nextparcell = db_firstparcell;
3343 	db_firstparcell = pc;
3344 }
3345 
3346 /*
3347  * Routine to create a parameterized name for node instance "ni".
3348  * If the node is not parameterized, returns zero.
3349  * If it returns a name, that name must be deallocated when done.
3350  */
parameterizedname(NODEINST * ni,CHAR * cellname)3351 CHAR *parameterizedname(NODEINST *ni, CHAR *cellname)
3352 {
3353 	REGISTER INTBIG i;
3354 	REGISTER VARIABLE *var, *evar;
3355 	CHAR *name;
3356 	REGISTER void *infstr;
3357 	REGISTER BOOLEAN oldonobjectstate;
3358 
3359 	if (ni->proto->primindex != 0) return(0);
3360 	for(i=0; i<ni->numvar; i++)
3361 	{
3362 		var = &ni->firstvar[i];
3363 		if (TDGETISPARAM(var->textdescript) != 0) break;
3364 	}
3365 	if (i >= ni->numvar) return(0);
3366 	infstr = initinfstr();
3367 	addstringtoinfstr(infstr, cellname);
3368 	for(i=0; i<ni->numvar; i++)
3369 	{
3370 		var = &ni->firstvar[i];
3371 		if (TDGETISPARAM(var->textdescript) == 0) continue;
3372 
3373 		/* accumulate the object that we are on (should use mutex) */
3374 		oldonobjectstate = db_onanobject;
3375 		if (!db_onanobject)
3376 		{
3377 			db_onanobject = TRUE;
3378 			db_onobjectaddr = (INTBIG)ni;
3379 			db_onobjecttype = VNODEINST;
3380 		}
3381 		db_lastonobjectaddr = (INTBIG)ni;
3382 		db_lastonobjecttype = VNODEINST;
3383 		evar = evalvar(var, (INTBIG)ni, VNODEINST);
3384 
3385 		/* complete the accumulation of the "getval" object (should use mutex) */
3386 		db_onanobject = oldonobjectstate;
3387 		formatinfstr(infstr, x_("-%s-%s"), truevariablename(var),
3388 			describevariable(evar, -1, -1));
3389 	}
3390 	(void)allocstring(&name, returninfstr(infstr), el_tempcluster);
3391 	return(name);
3392 }
3393 
3394 /*
3395  * Routine to implement a parameterized cell object.  Returns
3396  * NOPARCELL on error.
3397  */
db_allocparcell(void)3398 PARCELL *db_allocparcell(void)
3399 {
3400 	REGISTER PARCELL *pc;
3401 
3402 	if (db_parcellfree != NOPARCELL)
3403 	{
3404 		pc = db_parcellfree;
3405 		db_parcellfree = pc->nextparcell;
3406 	} else
3407 	{
3408 		pc = (PARCELL *)emalloc(sizeof (PARCELL), db_cluster);
3409 		if (pc == 0) return(NOPARCELL);
3410 	}
3411 	return(pc);
3412 }
3413 
3414 /*
3415  * Routine to return parameterized cell object "pc" to the free list.
3416  */
db_freeparcell(PARCELL * pc)3417 void db_freeparcell(PARCELL *pc)
3418 {
3419 	pc->nextparcell = db_parcellfree;
3420 	db_parcellfree = pc;
3421 }
3422 
3423 /************************* DEPRECATED VARIABLES *************************/
3424 
3425 CHAR *el_deprecatednodeprotovariables[] =
3426 {
3427 	x_("NET_last_good_ncc"),
3428 	x_("NET_last_good_ncc_facet"),
3429 	x_("SIM_window_signal_order"),
3430 	0
3431 };
3432 
3433 struct
3434 {
3435 	TOOL **tooladdr;
3436 	CHAR *varname;
3437 } el_deprecatedtoolvariables[] =
3438 {
3439 	{&net_tool, x_("NET_auto_name")},
3440 	{&net_tool, x_("NET_use_port_names")},
3441 	{&net_tool, x_("NET_compare_hierarchy")},
3442 	{&net_tool, x_("D")},
3443 	{&net_tool, x_("<")},
3444 	{&net_tool, x_("\001")},
3445 	{&us_tool,  x_("USER_alignment_obj")},
3446 	{&us_tool,  x_("USER_alignment_edge")},
3447 	{&sim_tool, x_("SIM_fasthenry_defthickness")},
3448 	{&dr_tool,  x_("DRC_pointout")},
3449 	{0, 0}
3450 };
3451 
isdeprecatedvariable(INTBIG addr,INTBIG type,CHAR * name)3452 BOOLEAN isdeprecatedvariable(INTBIG addr, INTBIG type, CHAR *name)
3453 {
3454 	REGISTER INTBIG i;
3455 
3456 	if (type == VNODEPROTO)
3457 	{
3458 		for(i=0; el_deprecatednodeprotovariables[i] != 0; i++)
3459 			if (namesame(name, el_deprecatednodeprotovariables[i]) == 0) return(TRUE);
3460 		return(FALSE);
3461 	}
3462 	if (type == VTOOL)
3463 	{
3464 		for(i=0; el_deprecatedtoolvariables[i].tooladdr != 0; i++)
3465 		{
3466 			if (*el_deprecatedtoolvariables[i].tooladdr != (TOOL *)addr) continue;
3467 			if (namesame(name, el_deprecatedtoolvariables[i].varname) == 0) return(TRUE);
3468 		}
3469 		return(FALSE);
3470 	}
3471 	return(FALSE);
3472 }
3473 
3474 /************************* DATA FOR TYPES *************************/
3475 
3476 /*
3477  * In the "type" field of a variable, the VCREF bit is typically set
3478  * to indicate that the variable points into the fixed C structures, and
3479  * is not part of the extendable attributes in "firstvar/numvar".  However,
3480  * in the tables below, the VCREF bit is used to indicate dereferencing
3481  * in array attributes.  Those arrays that are fixed in size or otherwise
3482  * part of the C structure need no dereferencing, and have the VCREF bit set
3483  * (see RTNODE->pointers, GRAPHICS->raster, NODEINST->textdescript, PORTPROTO->textdescript,
3484  * and POLYGON->textdescript).  Those arrays that vary in length have only pointers in
3485  * their C structures, and need dereferencing (see PORTPROTO->connects, LIBRARY->lambda,
3486  * TECHNOLOGY->layers, NETWORK->arcaddr, and NETWORK->networklist).  These
3487  * do not have the VCREF bit set.
3488  */
3489 
3490 static NODEINST db_ptni;
3491 static NAMEVARS db_nodevars[] =
3492 {
3493 	{x_("arraysize"),         VINTEGER|VCANTSET,          (INTBIG*)&db_ptni.arraysize},
3494 	{x_("firstportarcinst"),  VPORTARCINST|VCANTSET,      (INTBIG*)&db_ptni.firstportarcinst},
3495 	{x_("firstportexpinst"),  VPORTEXPINST|VCANTSET,      (INTBIG*)&db_ptni.firstportexpinst},
3496 	{x_("geom"),              VGEOM|VCANTSET,             (INTBIG*)&db_ptni.geom},
3497 	{x_("highx"),             VINTEGER|VCANTSET,          (INTBIG*)&db_ptni.highx},
3498 	{x_("highy"),             VINTEGER|VCANTSET,          (INTBIG*)&db_ptni.highy},
3499 	{x_("lowx"),              VINTEGER|VCANTSET,          (INTBIG*)&db_ptni.lowx},
3500 	{x_("lowy"),              VINTEGER|VCANTSET,          (INTBIG*)&db_ptni.lowy},
3501 	{x_("nextinst"),          VNODEINST|VCANTSET,         (INTBIG*)&db_ptni.nextinst},
3502 	{x_("nextnodeinst"),      VNODEINST|VCANTSET,         (INTBIG*)&db_ptni.nextnodeinst},
3503 	{x_("parent"),            VNODEPROTO|VCANTSET,        (INTBIG*)&db_ptni.parent},
3504 	{x_("previnst"),          VNODEINST|VCANTSET,         (INTBIG*)&db_ptni.previnst},
3505 	{x_("prevnodeinst"),      VNODEINST|VCANTSET,         (INTBIG*)&db_ptni.prevnodeinst},
3506 	{x_("proto"),             VNODEPROTO|VCANTSET,        (INTBIG*)&db_ptni.proto},
3507 	{x_("rotation"),          VSHORT|VCANTSET,            (INTBIG*)&db_ptni.rotation},
3508 	{x_("temp1"),             VINTEGER,                   (INTBIG*)&db_ptni.temp1},
3509 	{x_("temp2"),             VINTEGER,                   (INTBIG*)&db_ptni.temp2},
3510 	{x_("textdescript"),      VINTEGER|VISARRAY|(TEXTDESCRIPTSIZE<<VLENGTHSH)|VCREF, (INTBIG*)db_ptni.textdescript},
3511 	{x_("transpose"),         VSHORT|VCANTSET,            (INTBIG*)&db_ptni.transpose},
3512 	{x_("userbits"),          VINTEGER,                   (INTBIG*)&db_ptni.userbits},
3513 	{NULL, 0, NULL}  /* 0 */
3514 };
3515 
3516 /*
3517  * entry 9 of the table below ("globalnetchar") gets changed by "db_initnodeprotolist"
3518  * entry 10 of the table below ("globalnetworks") gets changed by "db_initnodeprotolist"
3519  */
3520 static NODEPROTO db_ptnp;
3521 static NAMEVARS db_nodeprotovars[] =
3522 {
3523 	{x_("adirty"),            VINTEGER|VCANTSET,          (INTBIG*)&db_ptnp.adirty},
3524 	{x_("cellview"),          VVIEW,                      (INTBIG*)&db_ptnp.cellview},
3525 	{x_("creationdate"),      VINTEGER|VCANTSET,          (INTBIG*)&db_ptnp.creationdate},
3526 	{x_("firstarcinst"),      VARCINST|VCANTSET,          (INTBIG*)&db_ptnp.firstarcinst},
3527 	{x_("firstinst"),         VNODEINST|VCANTSET,         (INTBIG*)&db_ptnp.firstinst},
3528 	{x_("firstnetwork"),      VNETWORK|VCANTSET,          (INTBIG*)&db_ptnp.firstnetwork},
3529 	{x_("firstnodeinst"),     VNODEINST|VCANTSET,         (INTBIG*)&db_ptnp.firstnodeinst},
3530 	{x_("firstportproto"),    VPORTPROTO|VCANTSET,        (INTBIG*)&db_ptnp.firstportproto},
3531 	{x_("globalnetcount"),    VINTEGER|VCANTSET,          (INTBIG*)&db_ptnp.globalnetcount},
3532 	{x_("globalnetchar"),     VINTEGER|VISARRAY|VCANTSET, (INTBIG*)&db_ptnp.globalnetchar},
3533 	{x_("globalnetworks"),    VNETWORK|VISARRAY|VCANTSET, (INTBIG*)&db_ptnp.globalnetworks},
3534 	{x_("highx"),             VINTEGER,                   (INTBIG*)&db_ptnp.highx},
3535 	{x_("highy"),             VINTEGER,                   (INTBIG*)&db_ptnp.highy},
3536 	{x_("lib"),               VLIBRARY|VCANTSET,          (INTBIG*)&db_ptnp.lib},
3537 	{x_("lowx"),              VINTEGER,                   (INTBIG*)&db_ptnp.lowx},
3538 	{x_("lowy"),              VINTEGER,                   (INTBIG*)&db_ptnp.lowy},
3539 	{x_("netd"),              VUNKNOWN|VCANTSET,          (INTBIG*)&db_ptnp.netd},
3540 	{x_("newestversion"),     VNODEPROTO|VCANTSET,        (INTBIG*)&db_ptnp.newestversion},
3541 	{x_("nextcellgrp"),       VNODEPROTO|VCANTSET,        (INTBIG*)&db_ptnp.nextcellgrp},
3542 	{x_("nextcont"),          VNODEPROTO|VCANTSET,        (INTBIG*)&db_ptnp.nextcont},
3543 	{x_("nextnodeproto"),     VNODEPROTO|VCANTSET,        (INTBIG*)&db_ptnp.nextnodeproto},
3544 	{x_("numportprotos"),     VINTEGER|VCANTSET,          (INTBIG*)&db_ptnp.numportprotos},
3545 	{x_("portprotohashtablesize"),VINTEGER|VCANTSET,      (INTBIG*)&db_ptnp.portprotohashtablesize},
3546 	{x_("prevnodeproto"),     VNODEPROTO|VCANTSET,        (INTBIG*)&db_ptnp.prevnodeproto},
3547 	{x_("prevversion"),       VNODEPROTO|VCANTSET,        (INTBIG*)&db_ptnp.prevversion},
3548 	{x_("primindex"),         VINTEGER|VCANTSET,          (INTBIG*)&db_ptnp.primindex},
3549 	{x_("protoname"),         VSTRING,                    (INTBIG*)&db_ptnp.protoname},
3550 	{x_("revisiondate"),      VINTEGER|VCANTSET,          (INTBIG*)&db_ptnp.revisiondate},
3551 	{x_("rtree"),             VRTNODE|VCANTSET,           (INTBIG*)&db_ptnp.rtree},
3552 	{x_("tech"),              VTECHNOLOGY|VCANTSET,       (INTBIG*)&db_ptnp.tech},
3553 	{x_("temp1"),             VINTEGER,                   (INTBIG*)&db_ptnp.temp1},
3554 	{x_("temp2"),             VINTEGER,                   (INTBIG*)&db_ptnp.temp2},
3555 	{x_("userbits"),          VINTEGER,                   (INTBIG*)&db_ptnp.userbits},
3556 	{x_("version"),           VINTEGER|VCANTSET,          (INTBIG*)&db_ptnp.version},
3557 	{NULL, 0, NULL}  /* 0 */
3558 };
3559 
3560 static PORTARCINST db_ptpi;
3561 static NAMEVARS db_portavars[] =
3562 {
3563 	{x_("conarcinst"),        VARCINST|VCANTSET,          (INTBIG*)&db_ptpi.conarcinst},
3564 	{x_("nextportarcinst"),   VPORTARCINST|VCANTSET,      (INTBIG*)&db_ptpi.nextportarcinst},
3565 	{x_("proto"),             VPORTPROTO|VCANTSET,        (INTBIG*)&db_ptpi.proto},
3566 	{NULL, 0, NULL}  /* 0 */
3567 };
3568 
3569 static PORTEXPINST db_ptpe;
3570 static NAMEVARS db_portevars[] =
3571 {
3572 	{x_("exportproto"),       VPORTPROTO|VCANTSET,        (INTBIG*)&db_ptpe.exportproto},
3573 	{x_("nextportexpinst"),   VPORTEXPINST|VCANTSET,      (INTBIG*)&db_ptpe.nextportexpinst},
3574 	{x_("proto"),             VPORTPROTO|VCANTSET,        (INTBIG*)&db_ptpe.proto},
3575 	{NULL, 0, NULL}  /* 0 */
3576 };
3577 
3578 static PORTPROTO db_ptpp;
3579 static NAMEVARS db_portprotovars[] =
3580 {
3581 	{x_("connects"),          VARCPROTO|VISARRAY|VCANTSET,(INTBIG*)&db_ptpp.connects},
3582 	{x_("network"),           VNETWORK|VCANTSET,          (INTBIG*)&db_ptpp.network},
3583 	{x_("nextportproto"),     VPORTPROTO|VCANTSET,        (INTBIG*)&db_ptpp.nextportproto},
3584 	{x_("parent"),            VNODEPROTO|VCANTSET,        (INTBIG*)&db_ptpp.parent},
3585 	{x_("protoname"),         VSTRING,                    (INTBIG*)&db_ptpp.protoname},
3586 	{x_("subnodeinst"),       VNODEINST|VCANTSET,         (INTBIG*)&db_ptpp.subnodeinst},
3587 	{x_("subportexpinst"),    VPORTEXPINST|VCANTSET,      (INTBIG*)&db_ptpp.subportexpinst},
3588 	{x_("subportproto"),      VPORTPROTO|VCANTSET,        (INTBIG*)&db_ptpp.subportproto},
3589 	{x_("temp1"),             VINTEGER,                   (INTBIG*)&db_ptpp.temp1},
3590 	{x_("temp2"),             VINTEGER,                   (INTBIG*)&db_ptpp.temp2},
3591 	{x_("textdescript"),      VINTEGER|VISARRAY|(TEXTDESCRIPTSIZE<<VLENGTHSH)|VCREF,(INTBIG*)db_ptpp.textdescript},
3592 	{x_("userbits"),          VINTEGER,                   (INTBIG*)&db_ptpp.userbits},
3593 	{NULL, 0, NULL}  /* 0 */
3594 };
3595 
3596 static ARCINST db_ptai;
3597 static NAMEVARS db_arcvars[] =
3598 {
3599 	{x_("endshrink"),         VINTEGER|VCANTSET,          (INTBIG*)&db_ptai.endshrink},
3600 	{x_("geom"),              VGEOM|VCANTSET,             (INTBIG*)&db_ptai.geom},
3601 	{x_("length"),            VINTEGER|VCANTSET,          (INTBIG*)&db_ptai.length},
3602 	{x_("network"),           VNETWORK|VCANTSET,          (INTBIG*)&db_ptai.network},
3603 	{x_("nextarcinst"),       VARCINST|VCANTSET,          (INTBIG*)&db_ptai.nextarcinst},
3604 	{x_("nodeinst1"),         VNODEINST|VCANTSET,         (INTBIG*)&db_ptai.end[0].nodeinst},
3605 	{x_("nodeinst2"),         VNODEINST|VCANTSET,         (INTBIG*)&db_ptai.end[1].nodeinst},
3606 	{x_("parent"),            VNODEPROTO|VCANTSET,        (INTBIG*)&db_ptai.parent},
3607 	{x_("portarcinst1"),      VPORTARCINST|VCANTSET,      (INTBIG*)&db_ptai.end[0].portarcinst},
3608 	{x_("portarcinst2"),      VPORTARCINST|VCANTSET,      (INTBIG*)&db_ptai.end[1].portarcinst},
3609 	{x_("prevarcinst"),       VARCINST|VCANTSET,          (INTBIG*)&db_ptai.prevarcinst},
3610 	{x_("proto"),             VARCPROTO|VCANTSET,         (INTBIG*)&db_ptai.proto},
3611 	{x_("temp1"),             VINTEGER,                   (INTBIG*)&db_ptai.temp1},
3612 	{x_("temp2"),             VINTEGER,                   (INTBIG*)&db_ptai.temp2},
3613 	{x_("userbits"),          VINTEGER,                   (INTBIG*)&db_ptai.userbits},
3614 	{x_("width"),             VINTEGER|VCANTSET,          (INTBIG*)&db_ptai.width},
3615 	{x_("xpos1"),             VINTEGER|VCANTSET,          (INTBIG*)&db_ptai.end[0].xpos},
3616 	{x_("xpos2"),             VINTEGER|VCANTSET,          (INTBIG*)&db_ptai.end[1].xpos},
3617 	{x_("ypos1"),             VINTEGER|VCANTSET,          (INTBIG*)&db_ptai.end[0].ypos},
3618 	{x_("ypos2"),             VINTEGER|VCANTSET,          (INTBIG*)&db_ptai.end[1].ypos},
3619 	{NULL, 0, NULL}  /* 0 */
3620 };
3621 
3622 static ARCPROTO db_ptap;
3623 static NAMEVARS db_arcprotovars[] =
3624 {
3625 	{x_("arcindex"),          VINTEGER|VCANTSET,          (INTBIG*)&db_ptap.arcindex},
3626 	{x_("nextarcproto"),      VARCPROTO|VCANTSET,         (INTBIG*)&db_ptap.nextarcproto},
3627 	{x_("nominalwidth"),      VINTEGER,                   (INTBIG*)&db_ptap.nominalwidth},
3628 	{x_("protoname"),         VSTRING,                    (INTBIG*)&db_ptap.protoname},
3629 	{x_("tech"),              VTECHNOLOGY|VCANTSET,       (INTBIG*)&db_ptap.tech},
3630 	{x_("temp1"),             VINTEGER,                   (INTBIG*)&db_ptap.temp1},
3631 	{x_("temp2"),             VINTEGER,                   (INTBIG*)&db_ptap.temp2},
3632 	{x_("userbits"),          VINTEGER,                   (INTBIG*)&db_ptap.userbits},
3633 	{NULL, 0, NULL}  /* 0 */
3634 };
3635 
3636 static GEOM db_ptgeom;
3637 static NAMEVARS db_geomvars[] =
3638 {
3639 	{x_("entryisnode"),       VBOOLEAN|VCANTSET,          (INTBIG*)&db_ptgeom.entryisnode},
3640 	{x_("entryaddr"),         VINTEGER|VCANTSET,          (INTBIG*)&db_ptgeom.entryaddr},
3641 	{x_("highx"),             VINTEGER|VCANTSET,          (INTBIG*)&db_ptgeom.highx},
3642 	{x_("highy"),             VINTEGER|VCANTSET,          (INTBIG*)&db_ptgeom.highy},
3643 	{x_("lowx"),              VINTEGER|VCANTSET,          (INTBIG*)&db_ptgeom.lowx},
3644 	{x_("lowy"),              VINTEGER|VCANTSET,          (INTBIG*)&db_ptgeom.lowy},
3645 	{NULL, 0, NULL}  /* 0 */
3646 };
3647 
3648 static LIBRARY db_ptlib;
3649 static NAMEVARS db_libvars[] =
3650 {
3651 	{x_("curnodeproto"),      VNODEPROTO,                 (INTBIG*)&db_ptlib.curnodeproto},
3652 	{x_("firstnodeproto"),    VNODEPROTO|VCANTSET,        (INTBIG*)&db_ptlib.firstnodeproto},
3653 	{x_("lambda"),            VINTEGER|VISARRAY|VCANTSET, (INTBIG*)&db_ptlib.lambda},
3654 	{x_("libname"),           VSTRING,                    (INTBIG*)&db_ptlib.libname},
3655 	{x_("libfile"),           VSTRING,                    (INTBIG*)&db_ptlib.libfile},
3656 	{x_("nextlibrary"),       VLIBRARY|VCANTSET,          (INTBIG*)&db_ptlib.nextlibrary},
3657 	{x_("nodeprotohashtablesize"),VINTEGER|VCANTSET,      (INTBIG*)&db_ptlib.nodeprotohashtablesize},
3658 	{x_("numnodeprotos"),     VINTEGER|VCANTSET,          (INTBIG*)&db_ptlib.numnodeprotos},
3659 	{x_("tailnodeproto"),     VNODEPROTO|VCANTSET,        (INTBIG*)&db_ptlib.tailnodeproto},
3660 	{x_("temp1"),             VINTEGER,                   (INTBIG*)&db_ptlib.temp1},
3661 	{x_("temp2"),             VINTEGER,                   (INTBIG*)&db_ptlib.temp2},
3662 	{x_("userbits"),          VINTEGER,                   (INTBIG*)&db_ptlib.userbits},
3663 	{NULL, 0, NULL}  /* 0 */
3664 };
3665 
3666 /*
3667  * entry 5 of the table below ("layers") gets changed by "db_inittechlist"
3668  */
3669 static TECHNOLOGY db_pttech;
3670 static NAMEVARS db_techvars[] =
3671 {
3672 	{x_("arcprotocount"),     VINTEGER|VCANTSET,          (INTBIG*)&db_pttech.arcprotocount},
3673 	{x_("deflambda"),         VINTEGER|VCANTSET,          (INTBIG*)&db_pttech.deflambda},
3674 	{x_("firstarcproto"),     VARCPROTO|VCANTSET,         (INTBIG*)&db_pttech.firstarcproto},
3675 	{x_("firstnodeproto"),    VNODEPROTO|VCANTSET,        (INTBIG*)&db_pttech.firstnodeproto},
3676 	{x_("layercount"),        VINTEGER|VCANTSET,          (INTBIG*)&db_pttech.layercount},
3677 	{x_("layers"),            VGRAPHICS|VISARRAY|VCANTSET,(INTBIG*)&db_pttech.layers},
3678 	{x_("nexttechnology"),    VTECHNOLOGY|VCANTSET,       (INTBIG*)&db_pttech.nexttechnology},
3679 	{x_("nodeprotocount"),    VINTEGER|VCANTSET,          (INTBIG*)&db_pttech.nodeprotocount},
3680 	{x_("techdescript"),      VSTRING|VCANTSET,           (INTBIG*)&db_pttech.techdescript},
3681 	{x_("techindex"),         VINTEGER|VCANTSET,          (INTBIG*)&db_pttech.techindex},
3682 	{x_("techname"),          VSTRING,                    (INTBIG*)&db_pttech.techname},
3683 	{x_("temp1"),             VINTEGER,                   (INTBIG*)&db_pttech.temp1},
3684 	{x_("temp2"),             VINTEGER,                   (INTBIG*)&db_pttech.temp2},
3685 	{x_("userbits"),          VINTEGER,                   (INTBIG*)&db_pttech.userbits},
3686 	{NULL, 0, NULL}  /* 0 */
3687 };
3688 
3689 static TOOL db_pttool;
3690 static NAMEVARS db_toolvars[] =
3691 {
3692 	{x_("toolindex"),         VINTEGER|VCANTSET,          (INTBIG*)&db_pttool.toolindex},
3693 	{x_("toolname"),          VSTRING|VCANTSET,           (INTBIG*)&db_pttool.toolname},
3694 	{x_("toolstate"),         VINTEGER,                   (INTBIG*)&db_pttool.toolstate},
3695 	{NULL, 0, NULL}  /* 0 */
3696 };
3697 
3698 /*
3699  * entry 6 of the table below ("pointers") gets changed by "db_initrtnodelist"
3700  */
3701 static RTNODE db_ptrtn;
3702 static NAMEVARS db_rtnvars[] =
3703 {
3704 	{x_("flag"),              VSHORT|VCANTSET,            (INTBIG*)&db_ptrtn.flag},
3705 	{x_("highx"),             VINTEGER|VCANTSET,          (INTBIG*)&db_ptrtn.highx},
3706 	{x_("highy"),             VINTEGER|VCANTSET,          (INTBIG*)&db_ptrtn.highy},
3707 	{x_("lowx"),              VINTEGER|VCANTSET,          (INTBIG*)&db_ptrtn.lowx},
3708 	{x_("lowy"),              VINTEGER|VCANTSET,          (INTBIG*)&db_ptrtn.lowy},
3709 	{x_("parent"),            VRTNODE|VCANTSET,           (INTBIG*)&db_ptrtn.parent},
3710 	{x_("pointers"),          VRTNODE|VISARRAY|VCANTSET|VCREF, (INTBIG*)db_ptrtn.pointers},
3711 	{x_("total"),             VSHORT|VCANTSET,            (INTBIG*)&db_ptrtn.total},
3712 	{NULL, 0, NULL}  /* 0 */
3713 };
3714 
3715 /*
3716  * entry 0 of the table below ("arcaddr") gets changed by "db_initnetworklist"
3717  * entry 6 of the table below ("networklist") also gets changed
3718  */
3719 static NETWORK db_ptnet;
3720 static NAMEVARS db_netvars[] =
3721 {
3722 	{x_("arcaddr"),           VARCINST|VISARRAY|VCANTSET, (INTBIG*)&db_ptnet.arcaddr},
3723 	{x_("arccount"),          VSHORT|VCANTSET,            (INTBIG*)&db_ptnet.arccount},
3724 	{x_("arctotal"),          VSHORT|VCANTSET,            (INTBIG*)&db_ptnet.arctotal},
3725 	{x_("buslinkcount"),      VSHORT|VCANTSET,            (INTBIG*)&db_ptnet.buslinkcount},
3726 	{x_("globalnet"),         VSHORT|VCANTSET,            (INTBIG*)&db_ptnet.globalnet},
3727 	{x_("namecount"),         VSHORT|VCANTSET,            (INTBIG*)&db_ptnet.namecount},
3728 	{x_("netnameaddr"),       VINTEGER|VCANTSET,          (INTBIG*)&db_ptnet.netnameaddr},
3729 	{x_("networklist"),       VNETWORK|VISARRAY|VCANTSET, (INTBIG*)&db_ptnet.networklist},
3730 	{x_("nextnetwork"),       VNETWORK|VCANTSET,          (INTBIG*)&db_ptnet.nextnetwork},
3731 	{x_("parent"),            VNODEPROTO|VCANTSET,        (INTBIG*)&db_ptnet.parent},
3732 	{x_("portcount"),         VSHORT|VCANTSET,            (INTBIG*)&db_ptnet.portcount},
3733 	{x_("prevnetwork"),       VNETWORK|VCANTSET,          (INTBIG*)&db_ptnet.prevnetwork},
3734 	{x_("refcount") ,         VSHORT|VCANTSET,            (INTBIG*)&db_ptnet.refcount},
3735 	{x_("buswidth"),          VSHORT|VCANTSET,            (INTBIG*)&db_ptnet.buswidth},
3736 	{x_("temp1"),             VINTEGER,                   (INTBIG*)&db_ptnet.temp1},
3737 	{x_("temp2"),             VINTEGER,                   (INTBIG*)&db_ptnet.temp2},
3738 	{NULL, 0, NULL}  /* 0 */
3739 };
3740 
3741 static VIEW db_ptview;
3742 static NAMEVARS db_viewvars[] =
3743 {
3744 	{x_("nextview"),          VVIEW|VCANTSET,             (INTBIG*)&db_ptview.nextview},
3745 	{x_("sviewname"),         VSTRING|VCANTSET,           (INTBIG*)&db_ptview.sviewname},
3746 	{x_("temp1"),             VINTEGER,                   (INTBIG*)&db_ptview.temp1},
3747 	{x_("temp2"),             VINTEGER,                   (INTBIG*)&db_ptview.temp2},
3748 	{x_("viewname"),          VSTRING|VCANTSET,           (INTBIG*)&db_ptview.viewname},
3749 	{x_("viewstate"),         VINTEGER|VCANTSET,          (INTBIG*)&db_ptview.viewstate},
3750 	{NULL, 0, NULL}  /* 0 */
3751 };
3752 
3753 static WINDOWPART db_ptwin;
3754 static NAMEVARS db_winvars[] =
3755 {
3756 	{x_("buttonhandler"),     VADDRESS,                   (INTBIG*)&db_ptwin.buttonhandler},
3757 	{x_("changehandler"),     VADDRESS,                   (INTBIG*)&db_ptwin.changehandler},
3758 	{x_("charhandler"),       VADDRESS,                   (INTBIG*)&db_ptwin.charhandler},
3759 	{x_("curnodeproto"),      VNODEPROTO,                 (INTBIG*)&db_ptwin.curnodeproto},
3760 	{x_("editor"),            VADDRESS,                   (INTBIG*)&db_ptwin.editor},
3761 	{x_("expwindow"),         VADDRESS,                   (INTBIG*)&db_ptwin.expwindow},
3762 	{x_("frame"),             VWINDOWFRAME|VCANTSET,      (INTBIG*)&db_ptwin.frame},
3763 	{x_("framehx"),           VINTEGER,                   (INTBIG*)&db_ptwin.framehx},
3764 	{x_("framehy"),           VINTEGER,                   (INTBIG*)&db_ptwin.framehy},
3765 	{x_("framelx"),           VINTEGER,                   (INTBIG*)&db_ptwin.framelx},
3766 	{x_("framely"),           VINTEGER,                   (INTBIG*)&db_ptwin.framely},
3767 	{x_("gridx"),             VINTEGER,                   (INTBIG*)&db_ptwin.gridx},
3768 	{x_("gridy"),             VINTEGER,                   (INTBIG*)&db_ptwin.gridy},
3769 	{x_("hratio"),            VINTEGER,                   (INTBIG*)&db_ptwin.hratio},
3770 	{x_("inplacedepth"),      VINTEGER,                   (INTBIG*)&db_ptwin.inplacedepth},
3771 	{x_("inplacestack"),      VNODEINST|VISARRAY|(MAXINPLACEDEPTH<<VLENGTHSH)|VCREF,(INTBIG*)db_ptwin.inplacestack},
3772 	{x_("intocell"),          VINTEGER|VISARRAY|(9<<VLENGTHSH)|VCREF,(INTBIG*)db_ptwin.intocell},
3773 	{x_("linkedwindowpart"),  VWINDOWPART|VCANTSET,       (INTBIG*)&db_ptwin.linkedwindowpart},
3774 	{x_("location"),          VSTRING|VCANTSET,           (INTBIG*)&db_ptwin.location},
3775 	{x_("nextwindowpart"),    VWINDOWPART|VCANTSET,       (INTBIG*)&db_ptwin.nextwindowpart},
3776 	{x_("outofcell"),         VINTEGER|VISARRAY|(9<<VLENGTHSH)|VCREF,(INTBIG*)db_ptwin.outofcell},
3777 	{x_("prevwindowpart"),    VWINDOWPART|VCANTSET,       (INTBIG*)&db_ptwin.prevwindowpart},
3778 	{x_("redisphandler"),     VADDRESS,                   (INTBIG*)&db_ptwin.redisphandler},
3779 	{x_("scalex"),            VFLOAT,                     (INTBIG*)&db_ptwin.scalex},
3780 	{x_("scaley"),            VFLOAT,                     (INTBIG*)&db_ptwin.scaley},
3781 	{x_("screenhx"),          VINTEGER,                   (INTBIG*)&db_ptwin.screenhx},
3782 	{x_("screenhy"),          VINTEGER,                   (INTBIG*)&db_ptwin.screenhy},
3783 	{x_("screenlx"),          VINTEGER,                   (INTBIG*)&db_ptwin.screenlx},
3784 	{x_("screenly"),          VINTEGER,                   (INTBIG*)&db_ptwin.screenly},
3785 	{x_("state"),             VINTEGER,                   (INTBIG*)&db_ptwin.state},
3786 	{x_("termhandler"),       VADDRESS,                   (INTBIG*)&db_ptwin.termhandler},
3787 	{x_("thumbhx"),           VINTEGER,                   (INTBIG*)&db_ptwin.thumbhx},
3788 	{x_("thumbhy"),           VINTEGER,                   (INTBIG*)&db_ptwin.thumbhy},
3789 	{x_("thumblx"),           VINTEGER,                   (INTBIG*)&db_ptwin.thumblx},
3790 	{x_("thumbly"),           VINTEGER,                   (INTBIG*)&db_ptwin.thumbly},
3791 	{x_("topnodeproto"),      VNODEPROTO,                 (INTBIG*)&db_ptwin.topnodeproto},
3792 	{x_("usehx"),             VINTEGER,                   (INTBIG*)&db_ptwin.usehx},
3793 	{x_("usehy"),             VINTEGER,                   (INTBIG*)&db_ptwin.usehy},
3794 	{x_("uselx"),             VINTEGER,                   (INTBIG*)&db_ptwin.uselx},
3795 	{x_("usely"),             VINTEGER,                   (INTBIG*)&db_ptwin.usely},
3796 	{x_("vratio"),            VINTEGER,                   (INTBIG*)&db_ptwin.vratio},
3797 	{NULL, 0, NULL}  /* 0 */
3798 };
3799 
3800 static GRAPHICS db_ptgra;
3801 static NAMEVARS db_gravars[] =
3802 {
3803 	{x_("bits"),              VINTEGER,                   (INTBIG*)&db_ptgra.bits},
3804 	{x_("bwstyle"),           VSHORT,                     (INTBIG*)&db_ptgra.bwstyle},
3805 	{x_("col"),               VINTEGER,                   (INTBIG*)&db_ptgra.col},
3806 	{x_("colstyle"),          VSHORT,                     (INTBIG*)&db_ptgra.colstyle},
3807 	{x_("raster"),            VSHORT|VISARRAY|(16<<VLENGTHSH)|VCREF, (INTBIG*)db_ptgra.raster},
3808 	{NULL, 0, NULL}  /* 0 */
3809 };
3810 
3811 static CONSTRAINT db_ptcon;
3812 static NAMEVARS db_convars[] =
3813 {
3814 	{x_("conname"),           VSTRING|VCANTSET,           (INTBIG*)&db_ptcon.conname},
3815 	{NULL, 0, NULL}  /* 0 */
3816 };
3817 
3818 static WINDOWFRAME db_ptwf;
3819 static NAMEVARS db_wfvars[] =
3820 {
3821 	{x_("floating"),          VBOOLEAN,                   (INTBIG*)&db_ptwf.floating},
3822 	{x_("width"),             VINTEGER,                   (INTBIG*)&db_ptwf.swid},
3823 	{x_("height"),            VINTEGER,                   (INTBIG*)&db_ptwf.shei},
3824 	{x_("yreverse"),          VINTEGER,                   (INTBIG*)&db_ptwf.revy},
3825 	{NULL, 0, NULL}  /* 0 */
3826 };
3827 
3828 /*
3829  * entry 0 of the table below ("xv") gets changed by "db_initpolygonlist"
3830  * entry 1 of the table below ("yv") also gets changed
3831  */
3832 static POLYGON db_ptpoly;
3833 static NAMEVARS db_polyvars[] =
3834 {
3835 	/* the first two entries here cannot be moved (see "db_initpolygonlist()") */
3836 	{x_("xv"),                VINTEGER|VISARRAY|VCANTSET, (INTBIG*)&db_ptpoly.xv},
3837 	{x_("yv"),                VINTEGER|VISARRAY|VCANTSET, (INTBIG*)&db_ptpoly.yv},
3838 	{x_("limit"),             VINTEGER|VCANTSET,          (INTBIG*)&db_ptpoly.limit},
3839 	{x_("count"),             VINTEGER|VCANTSET,          (INTBIG*)&db_ptpoly.count},
3840 	{x_("style"),             VINTEGER,                   (INTBIG*)&db_ptpoly.style},
3841 	{x_("string"),            VSTRING|VCANTSET,           (INTBIG*)&db_ptpoly.string},
3842 	{x_("textdescript"),      VINTEGER|VISARRAY|(TEXTDESCRIPTSIZE<<VLENGTHSH)|VCREF,(INTBIG*)db_ptpoly.textdescript},
3843 	{x_("tech"),              VTECHNOLOGY,                (INTBIG*)&db_ptpoly.tech},
3844 	{x_("desc"),              VGRAPHICS|VCANTSET,         (INTBIG*)&db_ptpoly.desc},
3845 	{x_("layer"),             VINTEGER,                   (INTBIG*)&db_ptpoly.layer},
3846 	{x_("portproto"),         VPORTPROTO,                 (INTBIG*)&db_ptpoly.portproto},
3847 	{x_("nextpolygon"),       VPOLYGON|VCANTSET,          (INTBIG*)&db_ptpoly.nextpolygon},
3848 	{NULL, 0, NULL}  /* 0 */
3849 };
3850 
3851 /************************* CODE FOR TYPES *************************/
3852 
db_initnodeinstlist(NODEINST * ni)3853 void db_initnodeinstlist(NODEINST *ni)
3854 {
3855 	if (ni == NONODEINST)
3856 	{
3857 		db_thisapack->state = NULLNAME;
3858 		return;
3859 	}
3860 	db_thisapack->state = PORTANAME;		/* then PORTENAME, SPECNAME, VARNAME */
3861 	db_thisapack->portarcinstname = ni->firstportarcinst;	/* PORTANAME */
3862 	db_thisapack->portexpinstname = ni->firstportexpinst;	/* PORTENAME */
3863 	db_thisapack->vars = db_nodevars;						/* SPECNAME */
3864 	db_thisapack->proto = (INTBIG)&db_ptni;					/* SPECNAME */
3865 	db_thisapack->object = (INTBIG)ni;						/* SPECNAME */
3866 	db_thisapack->specindex = 0;							/* SPECNAME */
3867 	db_thisapack->numvar = &ni->numvar;						/* VARNAME */
3868 	db_thisapack->firstvar = &ni->firstvar;					/* VARNAME */
3869 	db_thisapack->varindex = 0;								/* VARNAME */
3870 }
3871 
db_initnodeprotolist(NODEPROTO * np)3872 void db_initnodeprotolist(NODEPROTO *np)
3873 {
3874 	if (np == NONODEPROTO)
3875 	{
3876 		db_thisapack->state = NULLNAME;
3877 		return;
3878 	}
3879 	if (np->primindex == 0)
3880 	{
3881 		db_thisapack->state = ARCINAME;		/* then NODEINAME, PORTCNAME, SPECNAME, VARNAME */
3882 		db_thisapack->arciname  = np->firstarcinst;			/* ARCINAME */
3883 		db_thisapack->nodeiname = np->firstnodeinst;		/* NODEINAME */
3884 	} else db_thisapack->state = PORTCNAME;	/* then SPECNAME, VARNAME */
3885 	if (np->globalnetcount > 0)
3886 	{
3887 		db_nodeprotovars[9].type = VINTEGER|VISARRAY|(np->globalnetcount<<VLENGTHSH)|VCANTSET;
3888 		db_nodeprotovars[10].type = VNETWORK|VISARRAY|(np->globalnetcount<<VLENGTHSH)|VCANTSET;
3889 	} else
3890 	{
3891 		db_nodeprotovars[9].type = VINTEGER|VCANTSET;
3892 		db_nodeprotovars[10].type = VINTEGER|VCANTSET;
3893 	}
3894 	db_thisapack->portprotoname = np->firstportproto;		/* PORTCNAME */
3895 	db_thisapack->vars = db_nodeprotovars;					/* SPECNAME */
3896 	db_thisapack->proto = (INTBIG)&db_ptnp;					/* SPECNAME */
3897 	db_thisapack->object = (INTBIG)np;						/* SPECNAME */
3898 	db_thisapack->specindex = 0;							/* SPECNAME */
3899 	db_thisapack->numvar = &np->numvar;						/* VARNAME */
3900 	db_thisapack->firstvar = &np->firstvar;					/* VARNAME */
3901 	db_thisapack->varindex = 0;								/* VARNAME */
3902 }
3903 
db_initportarcinstlist(PORTARCINST * pi)3904 void db_initportarcinstlist(PORTARCINST *pi)
3905 {
3906 	if (pi == NOPORTARCINST)
3907 	{
3908 		db_thisapack->state = NULLNAME;
3909 		return;
3910 	}
3911 	db_thisapack->state = SPECNAME;			/* then VARNAME */
3912 	db_thisapack->vars = db_portavars;					/* SPECNAME */
3913 	db_thisapack->proto = (INTBIG)&db_ptpi;				/* SPECNAME */
3914 	db_thisapack->object = (INTBIG)pi;					/* SPECNAME */
3915 	db_thisapack->specindex = 0;						/* SPECNAME */
3916 	db_thisapack->numvar = &pi->numvar;					/* VARNAME */
3917 	db_thisapack->firstvar = &pi->firstvar;				/* VARNAME */
3918 	db_thisapack->varindex = 0;							/* VARNAME */
3919 }
3920 
db_initportexpinstlist(PORTEXPINST * pe)3921 void db_initportexpinstlist(PORTEXPINST *pe)
3922 {
3923 	if (pe == NOPORTEXPINST)
3924 	{
3925 		db_thisapack->state = NULLNAME;
3926 		return;
3927 	}
3928 	db_thisapack->state = SPECNAME;			/* then VARNAME */
3929 	db_thisapack->vars = db_portevars;					/* SPECNAME */
3930 	db_thisapack->proto = (INTBIG)&db_ptpe;				/* SPECNAME */
3931 	db_thisapack->object = (INTBIG)pe;					/* SPECNAME */
3932 	db_thisapack->specindex = 0;						/* SPECNAME */
3933 	db_thisapack->numvar = &pe->numvar;					/* VARNAME */
3934 	db_thisapack->firstvar = &pe->firstvar;				/* VARNAME */
3935 	db_thisapack->varindex = 0;							/* VARNAME */
3936 }
3937 
db_initportprotolist(PORTPROTO * pp)3938 void db_initportprotolist(PORTPROTO *pp)
3939 {
3940 	if (pp == NOPORTPROTO)
3941 	{
3942 		db_thisapack->state = NULLNAME;
3943 		return;
3944 	}
3945 	db_thisapack->state = SPECNAME;			/* then VARNAME */
3946 	db_thisapack->vars = db_portprotovars;				/* SPECNAME */
3947 	db_thisapack->proto = (INTBIG)&db_ptpp;				/* SPECNAME */
3948 	db_thisapack->object = (INTBIG)pp;					/* SPECNAME */
3949 	db_thisapack->specindex = 0;						/* SPECNAME */
3950 	db_thisapack->numvar = &pp->numvar;					/* VARNAME */
3951 	db_thisapack->firstvar = &pp->firstvar;				/* VARNAME */
3952 	db_thisapack->varindex = 0;							/* VARNAME */
3953 }
3954 
db_initarcinstlist(ARCINST * ai)3955 void db_initarcinstlist(ARCINST *ai)
3956 {
3957 	if (ai == NOARCINST)
3958 	{
3959 		db_thisapack->state = NULLNAME;
3960 		return;
3961 	}
3962 	db_thisapack->state = SPECNAME;			/* then VARNAME */
3963 	db_thisapack->vars = db_arcvars;					/* SPECNAME */
3964 	db_thisapack->proto = (INTBIG)&db_ptai;				/* SPECNAME */
3965 	db_thisapack->object = (INTBIG)ai;					/* SPECNAME */
3966 	db_thisapack->specindex = 0;						/* SPECNAME */
3967 	db_thisapack->numvar = &ai->numvar;					/* VARNAME */
3968 	db_thisapack->firstvar = &ai->firstvar;				/* VARNAME */
3969 	db_thisapack->varindex = 0;							/* VARNAME */
3970 }
3971 
db_initarcprotolist(ARCPROTO * ap)3972 void db_initarcprotolist(ARCPROTO *ap)
3973 {
3974 	if (ap == NOARCPROTO)
3975 	{
3976 		db_thisapack->state = NULLNAME;
3977 		return;
3978 	}
3979 	db_thisapack->state = SPECNAME;			/* then VARNAME */
3980 	db_thisapack->vars = db_arcprotovars;				/* SPECNAME */
3981 	db_thisapack->proto = (INTBIG)&db_ptap;				/* SPECNAME */
3982 	db_thisapack->object = (INTBIG)ap;					/* SPECNAME */
3983 	db_thisapack->specindex = 0;						/* SPECNAME */
3984 	db_thisapack->numvar = &ap->numvar;					/* VARNAME */
3985 	db_thisapack->firstvar = &ap->firstvar;				/* VARNAME */
3986 	db_thisapack->varindex = 0;							/* VARNAME */
3987 }
3988 
db_initgeomlist(GEOM * geom)3989 void db_initgeomlist(GEOM *geom)
3990 {
3991 	if (geom == NOGEOM)
3992 	{
3993 		db_thisapack->state = NULLNAME;
3994 		return;
3995 	}
3996 	switch(geom->entryisnode)
3997 	{
3998 		case TRUE:  db_geomvars[1].type = VNODEINST|VCANTSET;   break;
3999 		case FALSE: db_geomvars[1].type = VARCINST|VCANTSET;    break;
4000 	}
4001 	db_thisapack->state = SPECNAME;			/* then VARNAME */
4002 	db_thisapack->vars = db_geomvars;					/* SPECNAME */
4003 	db_thisapack->proto = (INTBIG)&db_ptgeom;			/* SPECNAME */
4004 	db_thisapack->object = (INTBIG)geom;				/* SPECNAME */
4005 	db_thisapack->specindex = 0;						/* SPECNAME */
4006 	db_thisapack->numvar = &geom->numvar;				/* VARNAME */
4007 	db_thisapack->firstvar = &geom->firstvar;			/* VARNAME */
4008 	db_thisapack->varindex = 0;							/* VARNAME */
4009 }
4010 
db_initliblist(LIBRARY * lib)4011 void db_initliblist(LIBRARY *lib)
4012 {
4013 	if (lib == NOLIBRARY)
4014 	{
4015 		db_thisapack->state = NULLNAME;
4016 		return;
4017 	}
4018 	db_thisapack->state = NODENAME;			/* then SPECNAME, VARNAME */
4019 	db_thisapack->nodeprotoname = lib->firstnodeproto;	/* NODENAME */
4020 	db_thisapack->vars = db_libvars;					/* SPECNAME */
4021 	db_thisapack->proto = (INTBIG)&db_ptlib;			/* SPECNAME */
4022 	db_thisapack->object = (INTBIG)lib;					/* SPECNAME */
4023 	db_thisapack->specindex = 0;						/* SPECNAME */
4024 	db_thisapack->numvar = &lib->numvar;				/* VARNAME */
4025 	db_thisapack->firstvar = &lib->firstvar;			/* VARNAME */
4026 	db_thisapack->varindex = 0;							/* VARNAME */
4027 }
4028 
db_inittechlist(TECHNOLOGY * tech)4029 void db_inittechlist(TECHNOLOGY *tech)
4030 {
4031 	if (tech == NOTECHNOLOGY)
4032 	{
4033 		db_thisapack->state = NULLNAME;
4034 		return;
4035 	}
4036 	db_techvars[5].type = VGRAPHICS|VISARRAY|(tech->layercount<<VLENGTHSH)|VCANTSET;
4037 	db_thisapack->state = ARCNAME;		/* then NODENAME, SPECNAME, VARNAME */
4038 	db_thisapack->arcprotoname = tech->firstarcproto;	/* ARCNAME */
4039 	db_thisapack->nodeprotoname = tech->firstnodeproto;	/* NODENAME */
4040 	db_thisapack->vars = db_techvars;					/* SPECNAME */
4041 	db_thisapack->proto = (INTBIG)&db_pttech;			/* SPECNAME */
4042 	db_thisapack->object = (INTBIG)tech;				/* SPECNAME */
4043 	db_thisapack->specindex = 0;						/* SPECNAME */
4044 	db_thisapack->numvar = &tech->numvar;				/* VARNAME */
4045 	db_thisapack->firstvar = &tech->firstvar;			/* VARNAME */
4046 	db_thisapack->varindex = 0;							/* VARNAME */
4047 }
4048 
db_inittoollist(TOOL * tool)4049 void db_inittoollist(TOOL *tool)
4050 {
4051 	if (tool == NOTOOL)
4052 	{
4053 		db_thisapack->state = NULLNAME;
4054 		return;
4055 	}
4056 	db_thisapack->state = SPECNAME;			/* then VARNAME */
4057 	db_thisapack->vars = db_toolvars;					/* SPECNAME */
4058 	db_thisapack->proto = (INTBIG)&db_pttool;			/* SPECNAME */
4059 	db_thisapack->object = (INTBIG)tool;				/* SPECNAME */
4060 	db_thisapack->specindex = 0;						/* SPECNAME */
4061 	db_thisapack->numvar = &tool->numvar;				/* VARNAME */
4062 	db_thisapack->firstvar = &tool->firstvar;			/* VARNAME */
4063 	db_thisapack->varindex = 0;							/* VARNAME */
4064 }
4065 
db_initrtnodelist(RTNODE * rtn)4066 void db_initrtnodelist(RTNODE *rtn)
4067 {
4068 	if (rtn == NORTNODE)
4069 	{
4070 		db_thisapack->state = NULLNAME;
4071 		return;
4072 	}
4073 	db_rtnvars[6].type = VISARRAY | (rtn->total<<VLENGTHSH) | VCANTSET | VCREF;
4074 	if (rtn->flag == 0) db_rtnvars[6].type |= VRTNODE; else
4075 		db_rtnvars[6].type |= VGEOM;
4076 	db_thisapack->state = SPECNAME;			/* then VARNAME */
4077 	db_thisapack->vars = db_rtnvars;					/* SPECNAME */
4078 	db_thisapack->proto = (INTBIG)&db_ptrtn;			/* SPECNAME */
4079 	db_thisapack->object = (INTBIG)rtn;					/* SPECNAME */
4080 	db_thisapack->specindex = 0;						/* SPECNAME */
4081 	db_thisapack->numvar = &rtn->numvar;				/* VARNAME */
4082 	db_thisapack->firstvar = &rtn->firstvar;			/* VARNAME */
4083 	db_thisapack->varindex = 0;							/* VARNAME */
4084 }
4085 /*
4086  * entry 6 of the table below ("layers") gets changed by "db_inittechlist"
4087  */
4088 
db_initnetworklist(NETWORK * net)4089 void db_initnetworklist(NETWORK *net)
4090 {
4091 	if (net == NONETWORK)
4092 	{
4093 		db_thisapack->state = NULLNAME;
4094 		return;
4095 	}
4096 	if (net->arccount <= 0) db_netvars[0].type = VADDRESS|VCANTSET; else
4097 		if (net->arctotal == 0) db_netvars[0].type = VARCINST|VCANTSET; else
4098 			db_netvars[0].type = VARCINST|VISARRAY|(net->arccount<<VLENGTHSH)|VCANTSET;
4099 	if (net->buswidth <= 1) db_netvars[6].type = VADDRESS|VCANTSET; else
4100 		db_netvars[6].type = VNETWORK|VISARRAY|(net->buswidth<<VLENGTHSH)|VCANTSET;
4101 	db_thisapack->state = SPECNAME;			/* then VARNAME */
4102 	db_thisapack->vars = db_netvars;					/* SPECNAME */
4103 	db_thisapack->proto = (INTBIG)&db_ptnet;			/* SPECNAME */
4104 	db_thisapack->object = (INTBIG)net;					/* SPECNAME */
4105 	db_thisapack->specindex = 0;						/* SPECNAME */
4106 	db_thisapack->numvar = &net->numvar;				/* VARNAME */
4107 	db_thisapack->firstvar = &net->firstvar;			/* VARNAME */
4108 	db_thisapack->varindex = 0;							/* VARNAME */
4109 }
4110 
db_initviewlist(VIEW * view)4111 void db_initviewlist(VIEW *view)
4112 {
4113 	if (view == NOVIEW)
4114 	{
4115 		db_thisapack->state = NULLNAME;
4116 		return;
4117 	}
4118 	db_thisapack->state = SPECNAME;			/* then VARNAME */
4119 	db_thisapack->vars = db_viewvars;					/* SPECNAME */
4120 	db_thisapack->proto = (INTBIG)&db_ptview;			/* SPECNAME */
4121 	db_thisapack->object = (INTBIG)view;				/* SPECNAME */
4122 	db_thisapack->specindex = 0;						/* SPECNAME */
4123 	db_thisapack->numvar = &view->numvar;				/* VARNAME */
4124 	db_thisapack->firstvar = &view->firstvar;			/* VARNAME */
4125 	db_thisapack->varindex = 0;							/* VARNAME */
4126 }
4127 
db_initwindowlist(WINDOWPART * win)4128 void db_initwindowlist(WINDOWPART *win)
4129 {
4130 	if (win == NOWINDOWPART)
4131 	{
4132 		db_thisapack->state = NULLNAME;
4133 		return;
4134 	}
4135 	db_thisapack->state = SPECNAME;			/* then VARNAME */
4136 	db_thisapack->vars = db_winvars;					/* SPECNAME */
4137 	db_thisapack->proto = (INTBIG)&db_ptwin;			/* SPECNAME */
4138 	db_thisapack->object = (INTBIG)win;					/* SPECNAME */
4139 	db_thisapack->specindex = 0;						/* SPECNAME */
4140 	db_thisapack->numvar = &win->numvar;				/* VARNAME */
4141 	db_thisapack->firstvar = &win->firstvar;			/* VARNAME */
4142 	db_thisapack->varindex = 0;							/* VARNAME */
4143 }
4144 
db_initgraphicslist(GRAPHICS * gra)4145 void db_initgraphicslist(GRAPHICS *gra)
4146 {
4147 	if (gra == NOGRAPHICS)
4148 	{
4149 		db_thisapack->state = NULLNAME;
4150 		return;
4151 	}
4152 	db_thisapack->state = SPECNAME;			/* then VARNAME */
4153 	db_thisapack->vars = db_gravars;					/* SPECNAME */
4154 	db_thisapack->proto = (INTBIG)&db_ptgra;			/* SPECNAME */
4155 	db_thisapack->object = (INTBIG)gra;					/* SPECNAME */
4156 	db_thisapack->specindex = 0;						/* SPECNAME */
4157 	db_thisapack->numvar = &gra->numvar;				/* VARNAME */
4158 	db_thisapack->firstvar = &gra->firstvar;			/* VARNAME */
4159 	db_thisapack->varindex = 0;							/* VARNAME */
4160 }
4161 
db_initconstraintlist(CONSTRAINT * con)4162 void db_initconstraintlist(CONSTRAINT *con)
4163 {
4164 	if (con == NOCONSTRAINT)
4165 	{
4166 		db_thisapack->state = NULLNAME;
4167 		return;
4168 	}
4169 	db_thisapack->state = SPECNAME;			/* then VARNAME */
4170 	db_thisapack->vars = db_convars;					/* SPECNAME */
4171 	db_thisapack->proto = (INTBIG)&db_ptcon;			/* SPECNAME */
4172 	db_thisapack->object = (INTBIG)con;					/* SPECNAME */
4173 	db_thisapack->specindex = 0;						/* SPECNAME */
4174 	db_thisapack->numvar = &con->numvar;				/* VARNAME */
4175 	db_thisapack->firstvar = &con->firstvar;			/* VARNAME */
4176 	db_thisapack->varindex = 0;							/* VARNAME */
4177 }
4178 
db_initwindowframelist(WINDOWFRAME * wf)4179 void db_initwindowframelist(WINDOWFRAME *wf)
4180 {
4181 	if (wf == NOWINDOWFRAME)
4182 	{
4183 		db_thisapack->state = NULLNAME;
4184 		return;
4185 	}
4186 	db_thisapack->state = SPECNAME;			/* then VARNAME */
4187 	db_thisapack->vars = db_wfvars;						/* SPECNAME */
4188 	db_thisapack->proto = (INTBIG)&db_ptwf;				/* SPECNAME */
4189 	db_thisapack->object = (INTBIG)wf;					/* SPECNAME */
4190 	db_thisapack->specindex = 0;						/* SPECNAME */
4191 	db_thisapack->numvar = &wf->numvar;					/* VARNAME */
4192 	db_thisapack->firstvar = &wf->firstvar;				/* VARNAME */
4193 	db_thisapack->varindex = 0;							/* VARNAME */
4194 }
4195 
db_initpolygonlist(POLYGON * poly)4196 void db_initpolygonlist(POLYGON *poly)
4197 {
4198 	if (poly == NOPOLYGON)
4199 	{
4200 		db_thisapack->state = NULLNAME;
4201 		return;
4202 	}
4203 	db_thisapack->state = SPECNAME;			/* then VARNAME */
4204 	db_thisapack->vars = db_polyvars;					/* SPECNAME */
4205 	db_thisapack->proto = (INTBIG)&db_ptpoly;			/* SPECNAME */
4206 	db_thisapack->object = (INTBIG)poly;				/* SPECNAME */
4207 	db_thisapack->specindex = 0;						/* SPECNAME */
4208 	db_thisapack->numvar = &poly->numvar;				/* VARNAME */
4209 	db_thisapack->firstvar = &poly->firstvar;			/* VARNAME */
4210 	db_thisapack->varindex = 0;							/* VARNAME */
4211 	db_polyvars[0].type = VINTEGER|VCANTSET|VISARRAY|(poly->count << VLENGTHSH);
4212 	db_polyvars[1].type = VINTEGER|VCANTSET|VISARRAY|(poly->count << VLENGTHSH);
4213 }
4214 
4215 /************************* DISPLAYABLE VARIABLE ROUTINES *************************/
4216 
4217 /*
4218  * this routine is used to determine the screen location of
4219  * letters in displayable text.  The displayable variable is
4220  * "var"; it resides on object "addr" of type "type"; uses technology
4221  * "tech"; and is being displayed in window "win".  The routine
4222  * calculates the position of line "line" and returns it in (x, y).
4223  * If "lowleft" is true, the returned position is the lower-left
4224  * corner of the text, otherwise it is the position of the center of the text.
4225  */
getdisparrayvarlinepos(INTBIG addr,INTBIG type,TECHNOLOGY * tech,WINDOWPART * win,VARIABLE * var,INTBIG line,INTBIG * x,INTBIG * y,BOOLEAN lowleft)4226 void getdisparrayvarlinepos(INTBIG addr, INTBIG type, TECHNOLOGY *tech, WINDOWPART *win, VARIABLE *var,
4227 	INTBIG line, INTBIG *x, INTBIG *y, BOOLEAN lowleft)
4228 {
4229 	CHAR *string;
4230 	INTBIG cx, cy, distx, disty;
4231 	INTBIG tsx, tsy, style;
4232 	REGISTER INTSML saverot, savetrn;
4233 	REGISTER GEOM *geom;
4234 	REGISTER NODEPROTO *np;
4235 	REGISTER PORTPROTO *pp;
4236 	REGISTER INTBIG screen, realscreen, len, lambda;
4237 	REGISTER NODEINST *ni;
4238 	REGISTER ARCINST *ai;
4239 	REGISTER LIBRARY *lib;
4240 	REGISTER TECHNOLOGY *lambdatech;
4241 	XARRAY trans;
4242 
4243 	switch (type)
4244 	{
4245 		case VNODEINST:
4246 			ni = (NODEINST *)addr;
4247 			makerot(ni, trans);
4248 			geom = ni->geom;
4249 			lambdatech = ni->proto->tech;
4250 			lib = ni->parent->lib;
4251 			cx = (geom->lowx + geom->highx) / 2;
4252 			cy = (geom->lowy + geom->highy) / 2;
4253 			break;
4254 		case VARCINST:
4255 			ai = (ARCINST *)addr;
4256 			geom = ai->geom;
4257 			lambdatech = ai->proto->tech;
4258 			lib = ai->parent->lib;
4259 			cx = (geom->lowx + geom->highx) / 2;
4260 			cy = (geom->lowy + geom->highy) / 2;
4261 			break;
4262 		case VPORTPROTO:
4263 			pp = (PORTPROTO *)addr;
4264 			ni = pp->subnodeinst;
4265 			lambdatech = ni->proto->tech;
4266 			lib = pp->parent->lib;
4267 			saverot = ni->rotation;   savetrn = ni->transpose;
4268 			ni->rotation = ni->transpose = 0;
4269 			portposition(pp->subnodeinst, pp->subportproto, &cx, &cy);
4270 			ni->rotation = saverot;   ni->transpose = savetrn;
4271 			ni = pp->subnodeinst;
4272 			makerot(ni, trans);
4273 			break;
4274 		case VNODEPROTO:
4275 			np = (NODEPROTO *)addr;
4276 			lambdatech = np->tech;
4277 			lib = np->lib;
4278 			cx = cy = 0;		/* cell variables are offset from (0,0) */
4279 			break;
4280 		default:
4281 			lambdatech = NOTECHNOLOGY;
4282 			lib = NOLIBRARY;
4283 	}
4284 	lambdatech = tech;
4285 	if (lowleft)
4286 	{
4287 		distx = TDGETXOFF(var->textdescript);
4288 		lambda = lib->lambda[lambdatech->techindex];
4289 		distx = distx * lambda / 4;
4290 		disty = TDGETYOFF(var->textdescript);
4291 		disty = disty * lambda / 4;
4292 		cx += distx;   cy += disty;
4293 		if (type == VNODEINST || type == VPORTPROTO)
4294 			xform(cx, cy, &cx, &cy, trans);
4295 	}
4296 
4297 	/* add variable name if requested */
4298 	string = describedisplayedvariable(var, line, -1);
4299 	screensettextinfo(win, tech, var->textdescript);
4300 	if (*string != 0) screengettextsize(win, string, &tsx, &tsy); else
4301 	{
4302 		screengettextsize(win, x_("Xy"), &tsx, &tsy);
4303 		tsx = 0;
4304 	}
4305 
4306 	switch (TDGETPOS(var->textdescript))
4307 	{
4308 		case VTPOSCENT:      style = TEXTCENT;      break;
4309 		case VTPOSBOXED:     style = TEXTBOX;       break;
4310 		case VTPOSUP:        style = TEXTBOT;       break;
4311 		case VTPOSDOWN:      style = TEXTTOP;       break;
4312 		case VTPOSLEFT:      style = TEXTRIGHT;     break;
4313 		case VTPOSRIGHT:     style = TEXTLEFT;      break;
4314 		case VTPOSUPLEFT:    style = TEXTBOTRIGHT;  break;
4315 		case VTPOSUPRIGHT:   style = TEXTBOTLEFT;   break;
4316 		case VTPOSDOWNLEFT:  style = TEXTTOPRIGHT;  break;
4317 		case VTPOSDOWNRIGHT: style = TEXTTOPLEFT;   break;
4318 	}
4319 	if (type == VNODEINST || type == VPORTPROTO)
4320 		style = rotatelabel(style, TDGETROTATION(var->textdescript), trans);
4321 
4322 	realscreen = screen = applyyscale(win, cy - win->screenly) + win->usely;
4323 	if ((var->type&VISARRAY) == 0) len = 1; else
4324 		len = getlength(var);
4325 	switch (style)
4326 	{
4327 		case TEXTBOX:
4328 		case TEXTCENT:				/* text is centered about grab point */
4329 		case TEXTLEFT:				/* text is to right of grab point */
4330 		case TEXTRIGHT:				/* text is to left of grab point */
4331 			if (lowleft) realscreen = screen - ((line+1)*tsy - len*tsy/2); else
4332 				realscreen = screen - (line*tsy - len*tsy/2) - tsy/2;
4333 			break;
4334 		case TEXTBOT:				/* text is above grab point */
4335 		case TEXTBOTRIGHT:			/* text is to upper-left of grab point */
4336 		case TEXTBOTLEFT:			/* text is to upper-right of grab point */
4337 			realscreen = screen + (len-line-1) * tsy;
4338 			break;
4339 		case TEXTTOP:				/* text is below grab point */
4340 		case TEXTTOPRIGHT:			/* text is to lower-left of grab point */
4341 		case TEXTTOPLEFT:		/* text is to lower-right of grab point */
4342 			if (lowleft) realscreen = screen - (line+1) * tsy; else
4343 				realscreen = screen - line * tsy;
4344 			break;
4345 	}
4346 	*y = (INTBIG)((realscreen - win->usely) / win->scaley) + win->screenly;
4347 
4348 	realscreen = screen = applyxscale(win, cx - win->screenlx) + win->uselx;
4349 	switch (style)
4350 	{
4351 		case TEXTBOX:
4352 		case TEXTCENT:				/* text is centered about grab point */
4353 		case TEXTBOT:				/* text is above grab point */
4354 		case TEXTTOP:				/* text is below grab point */
4355 			if (lowleft) realscreen = screen - tsx/2;
4356 			break;
4357 		case TEXTRIGHT:				/* text is to left of grab point */
4358 		case TEXTBOTRIGHT:			/* text is to upper-left of grab point */
4359 		case TEXTTOPRIGHT:			/* text is to lower-left of grab point */
4360 			if (lowleft) realscreen = screen - tsx;
4361 			break;
4362 	}
4363 	*x = (INTBIG)((realscreen - win->uselx) / win->scalex) + win->screenlx;
4364 }
4365 
4366 /*
4367  * this routine fills polygon poly with an outline of a displayable
4368  * variable's text.  The displayable variable is "var", it resides
4369  * on object "geom", and is being displayed in window "win".
4370  * It is used to draw variable highlighting.
4371  */
makedisparrayvarpoly(GEOM * geom,WINDOWPART * win,VARIABLE * var,POLYGON * poly)4372 void makedisparrayvarpoly(GEOM *geom, WINDOWPART *win, VARIABLE *var, POLYGON *poly)
4373 {
4374 	INTBIG centerobjx, centerobjy, realobjwidth, realobjheight, len, j,
4375 		screenwidth, screenheight, lx, hx, ly, hy, sslx, sshx, ssly, sshy;
4376 	float sscalex, sscaley;
4377 	static BOOLEAN canscalefonts, fontscalingunknown = TRUE;
4378 	REGISTER BOOLEAN reltext;
4379 	REGISTER NODEINST *ni;
4380 	REGISTER INTBIG distx, disty, lambda;
4381 	REGISTER TECHNOLOGY *tech;
4382 	REGISTER NODEPROTO *np;
4383 	XARRAY trans;
4384 	INTBIG tsx, tsy, lineheight, style;
4385 	CHAR *string;
4386 
4387 	if (poly->limit < 4) (void)extendpolygon(poly, 4);
4388 	if (geom == NOGEOM)
4389 	{
4390 		/* cell variables are offset from (0,0) */
4391 		lx = hx = ly = hy = 0;
4392 		tech = el_curtech;
4393 		lambda = el_curlib->lambda[tech->techindex];
4394 	} else
4395 	{
4396 		boundobj(geom, &lx, &hx, &ly, &hy);
4397 		lambda = figurelambda(geom);
4398 		np = geomparent(geom);
4399 		if (np->tech == NOTECHNOLOGY)
4400 			np->tech = whattech(np);
4401 		tech = np->tech;
4402 	}
4403 	distx = TDGETXOFF(var->textdescript);
4404 	distx = distx * lambda / 4;
4405 	disty = TDGETYOFF(var->textdescript);
4406 	disty = disty * lambda / 4;
4407 	centerobjx = (lx + hx) / 2 + distx;
4408 	centerobjy = (ly + hy) / 2 + disty;
4409 
4410 	/* rotate grab point if on a node */
4411 	if (geom != NOGEOM && geom->entryisnode)
4412 	{
4413 		ni = geom->entryaddr.ni;
4414 		centerobjx = (ni->lowx + ni->highx) / 2 + distx;
4415 		centerobjy = (ni->lowy + ni->highy) / 2 + disty;
4416 		makerot(ni, trans);
4417 		xform(centerobjx, centerobjy, &centerobjx, &centerobjy, trans);
4418 	}
4419 
4420 	if (fontscalingunknown)
4421 	{
4422 		fontscalingunknown = FALSE;
4423 		canscalefonts = graphicshas(CANSCALEFONTS);
4424 	}
4425 	reltext = FALSE;
4426 	if (canscalefonts)
4427 	{
4428 		if ((TDGETSIZE(var->textdescript)&TXTQLAMBDA) != 0) reltext = TRUE;
4429 	}
4430 	if (reltext)
4431 	{
4432 		/* set window to a sensible range */
4433 		sslx = win->screenlx;   win->screenlx = win->uselx * lambda / 12;
4434 		sshx = win->screenhx;   win->screenhx = win->usehx * lambda / 12;
4435 		ssly = win->screenly;   win->screenly = win->usely * lambda / 12;
4436 		sshy = win->screenhy;   win->screenhy = win->usehy * lambda / 12;
4437 		sscalex = win->scalex;   sscaley = win->scaley;
4438 		computewindowscale(win);
4439 	}
4440 
4441 	screensettextinfo(win, tech, var->textdescript);
4442 	screengettextsize(win, x_("Xy"), &tsx, &lineheight);
4443 	if ((var->type&VISARRAY) == 0) len = 1; else
4444 		len = getlength(var);
4445 	screenwidth = 0;
4446 	for(j=0; j<len; j++)
4447 	{
4448 		string = describedisplayedvariable(var, j, -1);
4449 		screengettextsize(win, string, &tsx, &tsy);
4450 		if (tsx > screenwidth) screenwidth = tsx;
4451 	}
4452 
4453 	screenheight = lineheight * len;
4454 	realobjwidth = (INTBIG)(screenwidth / win->scalex);
4455 	realobjheight = (INTBIG)(screenheight / win->scaley);
4456 
4457 	if (reltext)
4458 	{
4459 		/* restore window */
4460 		win->screenlx = sslx;   win->screenhx = sshx;
4461 		win->screenly = ssly;   win->screenhy = sshy;
4462 		win->scalex = sscalex;  win->scaley = sscaley;
4463 	}
4464 
4465 	switch (TDGETPOS(var->textdescript))
4466 	{
4467 		case VTPOSCENT:
4468 		case VTPOSBOXED:     style = TEXTCENT;      break;
4469 		case VTPOSUP:        style = TEXTBOT;       break;
4470 		case VTPOSDOWN:      style = TEXTTOP;       break;
4471 		case VTPOSLEFT:      style = TEXTRIGHT;     break;
4472 		case VTPOSRIGHT:     style = TEXTLEFT;      break;
4473 		case VTPOSUPLEFT:    style = TEXTBOTRIGHT;  break;
4474 		case VTPOSUPRIGHT:   style = TEXTBOTLEFT;   break;
4475 		case VTPOSDOWNLEFT:  style = TEXTTOPRIGHT;  break;
4476 		case VTPOSDOWNRIGHT: style = TEXTTOPLEFT;   break;
4477 	}
4478 	if (geom != NOGEOM && geom->entryisnode)
4479 	{
4480 		makerot(geom->entryaddr.ni, trans);
4481 		style = rotatelabel(style, TDGETROTATION(var->textdescript), trans);
4482 	}
4483 
4484 	/* set X position */
4485 	switch (style)
4486 	{
4487 		case TEXTCENT:				/* text is centered about grab point */
4488 		case TEXTBOT:				/* text is above grab point */
4489 		case TEXTTOP:				/* text is below grab point */
4490 			poly->xv[0] = poly->xv[1] = centerobjx - realobjwidth/2;
4491 			poly->xv[2] = poly->xv[3] = centerobjx + realobjwidth/2;
4492 			break;
4493 		case TEXTLEFT:				/* text is to right of grab point */
4494 		case TEXTBOTLEFT:			/* text is to upper-right of grab point */
4495 		case TEXTTOPLEFT:			/* text is to lower-right of grab point */
4496 			poly->xv[0] = poly->xv[1] = centerobjx;
4497 			poly->xv[2] = poly->xv[3] = centerobjx + realobjwidth;
4498 			break;
4499 		case TEXTRIGHT:				/* text is to left of grab point */
4500 		case TEXTBOTRIGHT:			/* text is to upper-left of grab point */
4501 		case TEXTTOPRIGHT:			/* text is to lower-left of grab point */
4502 			poly->xv[0] = poly->xv[1] = centerobjx - realobjwidth;
4503 			poly->xv[2] = poly->xv[3] = centerobjx;
4504 			break;
4505 	}
4506 
4507 	/* set Y position */
4508 	switch (style)
4509 	{
4510 		case TEXTCENT:				/* text is centered about grab point */
4511 		case TEXTLEFT:				/* text is to right of grab point */
4512 		case TEXTRIGHT:				/* text is to left of grab point */
4513 			poly->yv[0] = poly->yv[3] = centerobjy - realobjheight/2;
4514 			poly->yv[1] = poly->yv[2] = centerobjy + realobjheight/2;
4515 			break;
4516 		case TEXTBOT:				/* text is above grab point */
4517 		case TEXTBOTRIGHT:			/* text is to upper-left of grab point */
4518 		case TEXTBOTLEFT:			/* text is to upper-right of grab point */
4519 			poly->yv[0] = poly->yv[3] = centerobjy;
4520 			poly->yv[1] = poly->yv[2] = centerobjy + realobjheight;
4521 			break;
4522 		case TEXTTOP:				/* text is below grab point */
4523 		case TEXTTOPRIGHT:			/* text is to lower-left of grab point */
4524 		case TEXTTOPLEFT:			/* text is to lower-right of grab point */
4525 			poly->yv[0] = poly->yv[3] = centerobjy - realobjheight;
4526 			poly->yv[1] = poly->yv[2] = centerobjy;
4527 			break;
4528 	}
4529 	poly->count = 4;
4530 }
4531 
4532 /*
4533  * routine to return the name of the variable whose key is "key" and whose
4534  * type is "type"
4535  */
changedvariablename(INTBIG type,INTBIG key,INTBIG subtype)4536 CHAR *changedvariablename(INTBIG type, INTBIG key, INTBIG subtype)
4537 {
4538 	if ((subtype&VCREF) == 0)
4539 	{
4540 		if (key == -1) return(_("NULL"));
4541 		return(makename(key));
4542 	}
4543 
4544 	switch (type&VTYPE)
4545 	{
4546 		case VNODEINST:    return(db_nodevars[key].name);
4547 		case VNODEPROTO:   return(db_nodeprotovars[key].name);
4548 		case VPORTARCINST: return(db_portavars[key].name);
4549 		case VPORTEXPINST: return(db_portevars[key].name);
4550 		case VPORTPROTO:   return(db_portprotovars[key].name);
4551 		case VARCINST:     return(db_arcvars[key].name);
4552 		case VARCPROTO:    return(db_arcprotovars[key].name);
4553 		case VGEOM:        return(db_geomvars[key].name);
4554 		case VRTNODE:      return(db_rtnvars[key].name);
4555 		case VLIBRARY:     return(db_libvars[key].name);
4556 		case VTECHNOLOGY:  return(db_techvars[key].name);
4557 		case VTOOL:        return(db_toolvars[key].name);
4558 		case VVIEW:        return(db_viewvars[key].name);
4559 		case VNETWORK:     return(db_netvars[key].name);
4560 		case VWINDOWPART:  return(db_winvars[key].name);
4561 		case VGRAPHICS:    return(db_gravars[key].name);
4562 		case VCONSTRAINT:  return(db_convars[key].name);
4563 		case VWINDOWFRAME: return(db_wfvars[key].name);
4564 	}
4565 	return(_("NULL"));
4566 }
4567 
4568 /*
4569  * routine to adjust the coordinate values in "poly" to account for the
4570  * display offset in the type field "textdescription".  Assumes that the
4571  * initial values are the center of the object.  The object on which this
4572  * text resides is in "geom".  Routine also sets the style and the font of
4573  * text message to use with this coordinate.
4574  */
adjustdisoffset(INTBIG addr,INTBIG type,TECHNOLOGY * tech,POLYGON * poly,UINTBIG * textdescription)4575 void adjustdisoffset(INTBIG addr, INTBIG type, TECHNOLOGY *tech,
4576 	POLYGON *poly, UINTBIG *textdescription)
4577 {
4578 	REGISTER INTBIG lambda;
4579 	INTBIG distx, disty, plx, phx, ply, phy;
4580 	REGISTER INTBIG i;
4581 	REGISTER NODEINST *ni;
4582 	XARRAY trans;
4583 
4584 	lambda = el_curlib->lambda[tech->techindex];
4585 	switch (type&VTYPE)
4586 	{
4587 		case VNODEINST: lambda = lambdaofnode((NODEINST *)addr);   break;
4588 		case VARCINST:  lambda = lambdaofarc((ARCINST *)addr);     break;
4589 	}
4590 	distx = TDGETXOFF(textdescription);
4591 	distx = distx * lambda / 4;
4592 	disty = TDGETYOFF(textdescription);
4593 	disty = disty * lambda / 4;
4594 	if (TDGETPOS(textdescription) == VTPOSBOXED)
4595 	{
4596 		getbbox(poly, &plx, &phx, &ply, &phy);
4597 		if (distx > 0) plx += distx*2; else
4598 			if (distx < 0) phx += distx*2;
4599 		if (disty > 0) ply += disty*2; else
4600 			if (disty < 0) phy += disty*2;
4601 		makerectpoly(plx, phx, ply, phy, poly);
4602 	} else
4603 	{
4604 		/* just shift the polygon */
4605 		for(i=0; i<poly->count; i++)
4606 		{
4607 			poly->xv[i] += distx;
4608 			poly->yv[i] += disty;
4609 		}
4610 	}
4611 
4612 	/* determine the text message style */
4613 	switch (TDGETPOS(textdescription))
4614 	{
4615 		case VTPOSCENT:      poly->style = TEXTCENT;      break;
4616 		case VTPOSBOXED:     poly->style = TEXTBOX;       break;
4617 		case VTPOSUP:        poly->style = TEXTBOT;       break;
4618 		case VTPOSDOWN:      poly->style = TEXTTOP;       break;
4619 		case VTPOSLEFT:      poly->style = TEXTRIGHT;     break;
4620 		case VTPOSRIGHT:     poly->style = TEXTLEFT;      break;
4621 		case VTPOSUPLEFT:    poly->style = TEXTBOTRIGHT;  break;
4622 		case VTPOSUPRIGHT:   poly->style = TEXTBOTLEFT;   break;
4623 		case VTPOSDOWNLEFT:  poly->style = TEXTTOPRIGHT;  break;
4624 		case VTPOSDOWNRIGHT: poly->style = TEXTTOPLEFT;   break;
4625 	}
4626 	if (type == VNODEINST)
4627 	{
4628 		ni = (NODEINST *)addr;
4629 		makeangle(ni->rotation, ni->transpose, trans);
4630 		poly->style = rotatelabel(poly->style, TDGETROTATION(textdescription), trans);
4631 	}
4632 	if (type == VPORTPROTO)
4633 	{
4634 		ni = ((PORTPROTO *)addr)->subnodeinst;
4635 		makeangle(ni->rotation, ni->transpose, trans);
4636 		poly->style = rotatelabel(poly->style, TDGETROTATION(textdescription), trans);
4637 	}
4638 	TDCOPY(poly->textdescript, textdescription);
4639 	poly->tech = tech;
4640 }
4641 
4642 /************************* HELPER ROUTINES *************************/
4643 
4644 /*
4645  * routine to convert a variable name in "name" to a key and return it.
4646  * If the name is not in the database, the routine returns a negative value
4647  * that is one less than the negative table index entry.
4648  */
db_getkey(CHAR * name)4649 INTBIG db_getkey(CHAR *name)
4650 {
4651 	REGISTER INTBIG hi, lo, med, lastmed, i;
4652 
4653 	/* binary search name space for the variable name */
4654 	i = lo = 0;   hi = lastmed = el_numnames;
4655 	for(;;)
4656 	{
4657 		/* find mid-point: quit if done */
4658 		med = (hi + lo) / 2;
4659 		if (med == lastmed) break;
4660 		lastmed = med;
4661 
4662 		/* test the entry: return the key if a match */
4663 		i = namesame(name, el_namespace[med]);
4664 		if (i == 0) return(med);
4665 
4666 		/* decide which way to search in list */
4667 		if (i < 0) hi = med; else lo = med;
4668 	}
4669 
4670 	/* create a new position: adjust for position location */
4671 	if (i > 0) med++;
4672 	return(-med-1);
4673 }
4674 
4675 /*
4676  * routine to determine the appropriate memory cluster to use for the
4677  * variable whose address is "addr" and type is "type".
4678  */
db_whichcluster(INTBIG addr,INTBIG type)4679 CLUSTER *db_whichcluster(INTBIG addr, INTBIG type)
4680 {
4681 	REGISTER GEOM *geom;
4682 	REGISTER NODEPROTO *np;
4683 	REGISTER NODEINST *ni;
4684 
4685 	switch (type&VTYPE)
4686 	{
4687 		case VNODEINST:
4688 			ni = (NODEINST *)addr;
4689 			if (ni->parent == NONODEPROTO) return(db_cluster);
4690 			return(ni->parent->lib->cluster);
4691 		case VNODEPROTO:
4692 			np = (NODEPROTO *)addr;
4693 			if (np->primindex == 0) return(np->lib->cluster);
4694 			return(np->tech->cluster);
4695 		case VPORTARCINST:
4696 			return(((PORTARCINST *)addr)->conarcinst->parent->lib->cluster);
4697 		case VPORTEXPINST:
4698 			return(((PORTEXPINST *)addr)->exportproto->parent->lib->cluster);
4699 		case VPORTPROTO:
4700 			np = ((PORTPROTO *)addr)->parent;
4701 			if (np->primindex == 0) return(np->lib->cluster);
4702 			return(np->tech->cluster);
4703 		case VARCINST: return(((ARCINST *)addr)->parent->lib->cluster);
4704 		case VARCPROTO: return(((ARCPROTO *)addr)->tech->cluster);
4705 		case VGEOM: geom = (GEOM *)addr;
4706 			if (geom->entryisnode)
4707 				return(geom->entryaddr.ni->parent->lib->cluster);
4708 			return(geom->entryaddr.ai->parent->lib->cluster);
4709 		case VTECHNOLOGY: return(((TECHNOLOGY *)addr)->cluster);
4710 		case VTOOL: return(((TOOL *)addr)->cluster);
4711 		case VNETWORK: return(((NETWORK *)addr)->parent->lib->cluster);
4712 		case VWINDOWPART: return(us_tool->cluster);
4713 		case VWINDOWFRAME: return(us_tool->cluster);
4714 	}
4715 	return(db_cluster);
4716 }
4717 
4718 /*
4719  * routine to determine the appropriate cell associated with the
4720  * variable whose address is "addr" and type is "type".
4721  */
db_whichnodeproto(INTBIG addr,INTBIG type)4722 NODEPROTO *db_whichnodeproto(INTBIG addr, INTBIG type)
4723 {
4724 	REGISTER GEOM *geom;
4725 	REGISTER NODEPROTO *np;
4726 
4727 	switch (type&VTYPE)
4728 	{
4729 		case VNODEINST: return(((NODEINST *)addr)->parent);
4730 		case VNODEPROTO:
4731 			np = (NODEPROTO *)addr;
4732 			if (np->primindex == 0) return(np); else return(NONODEPROTO);
4733 		case VPORTARCINST: return(((PORTARCINST *)addr)->conarcinst->parent);
4734 		case VPORTEXPINST: return(((PORTEXPINST *)addr)->exportproto->parent);
4735 		case VPORTPROTO: return(((PORTPROTO *)addr)->parent);
4736 		case VARCINST: return(((ARCINST *)addr)->parent);
4737 		case VGEOM: geom = (GEOM *)addr;
4738 			if (geom->entryisnode) return(geom->entryaddr.ni->parent);
4739 			return(geom->entryaddr.ai->parent);
4740 		case VNETWORK: return(((NETWORK *)addr)->parent);
4741 	}
4742 	return(NONODEPROTO);
4743 }
4744 
4745 /*
4746  * internal routine to set entry "med" in the list of variables at "*firstvar"
4747  * with "*numvar" entries (this entry has the key "key").  If "med" is negative
4748  * then the entry does not exist in the list and must be created.  The entry is
4749  * set to the address "newaddr" and type "newtype".  Memory is allocated from
4750  * cluster "cluster".  Returns true if there is an error.
4751  */
4752 #ifdef DEBUGMEMORY
db_setvalkey(INTSML * numvar,VARIABLE ** firstvar,INTBIG med,INTBIG key,INTBIG newaddr,INTBIG newtype,CLUSTER * cluster,CHAR * module,INTBIG line)4753 BOOLEAN db_setvalkey(INTSML *numvar, VARIABLE **firstvar, INTBIG med, INTBIG key,
4754 	INTBIG newaddr, INTBIG newtype, CLUSTER *cluster, CHAR *module, INTBIG line)
4755 #else
4756 BOOLEAN db_setvalkey(INTSML *numvar, VARIABLE **firstvar, INTBIG med, INTBIG key,
4757 	INTBIG newaddr, INTBIG newtype, CLUSTER *cluster)
4758 #endif
4759 {
4760 	REGISTER VARIABLE *newv, *var;
4761 	REGISTER INTBIG i;
4762 
4763 	/* if there is no existing variable, create it */
4764 	if (med < 0)
4765 	{
4766 		/* get the entry position in the list */
4767 		med = -med - 1;
4768 
4769 		/* allocate space for new list */
4770 		newv = (VARIABLE *)emalloc(((*numvar+1)*(sizeof (VARIABLE))), cluster);
4771 		if (newv == 0) return(TRUE);
4772 
4773 		/* copy old list up to the new entry */
4774 		for(i=0; i<med; i++)
4775 		{
4776 			newv[i].key  = (*firstvar)[i].key;
4777 			newv[i].type = (*firstvar)[i].type;
4778 			TDCOPY(newv[i].textdescript, (*firstvar)[i].textdescript);
4779 			newv[i].addr = (*firstvar)[i].addr;
4780 		}
4781 
4782 		/* add the new entry */
4783 		newv[med].key = key;
4784 		newv[med].type = VUNKNOWN|VDONTSAVE;
4785 		TDCLEAR(newv[med].textdescript);
4786 		TDSETSIZE(newv[med].textdescript, TXTSETQLAMBDA(4));
4787 		newv[med].addr = 0;
4788 		var = &newv[med];
4789 
4790 		/* copy old list after the new entry */
4791 		for(i = med; i < *numvar; i++)
4792 		{
4793 			newv[i+1].key  = (*firstvar)[i].key;
4794 			newv[i+1].type = (*firstvar)[i].type;
4795 			TDCOPY(newv[i+1].textdescript, (*firstvar)[i].textdescript);
4796 			newv[i+1].addr = (*firstvar)[i].addr;
4797 		}
4798 
4799 		/* clean-up */
4800 		if (*numvar != 0) efree((CHAR *)*firstvar);
4801 		*firstvar = newv;
4802 		(*numvar)++;
4803 	} else var = &(*firstvar)[med];
4804 
4805 	/* set the variable */
4806 #ifdef DEBUGMEMORY
4807 	if (db_setvalvar(var, newaddr, newtype, cluster, module, line) != 0) return(TRUE);
4808 #else
4809 	if (db_setvalvar(var, newaddr, newtype, cluster) != 0) return(TRUE);
4810 #endif
4811 
4812 	return(FALSE);
4813 }
4814 
4815 /*
4816  * routine to set the value of the variable "var" to the value "newaddr" and
4817  * type "newtype".  Memory is allocated from cluster "cluster".  Returns
4818  * true upon error.
4819  */
4820 #ifdef DEBUGMEMORY
db_setvalvar(VARIABLE * var,INTBIG newaddr,INTBIG newtype,CLUSTER * cluster,CHAR * module,INTBIG line)4821 BOOLEAN db_setvalvar(VARIABLE *var, INTBIG newaddr, INTBIG newtype,
4822 	CLUSTER *cluster, CHAR *module, INTBIG line)
4823 #else
4824 BOOLEAN db_setvalvar(VARIABLE *var, INTBIG newaddr, INTBIG newtype,
4825 	CLUSTER *cluster)
4826 #endif
4827 {
4828 	REGISTER INTBIG i, len, datasize;
4829 	INTBIG longval;
4830 	REGISTER UCHAR1 *inaddr;
4831 
4832 	/* if the variable or key is not valid then ignore this */
4833 	if (var == NOVARIABLE)
4834 	{
4835 		ttyputerr(_("No valid variable"));
4836 		return(TRUE);
4837 	}
4838 	if ((var->type&VCREF) != 0)
4839 	{
4840 		/* setting a fixed attribute on an object */
4841 		if ((newtype&VISARRAY) != 0)
4842 		{
4843 			ttyputmsg(_("Cannot set array in C structure"));
4844 			return(FALSE);
4845 		}
4846 		if (((INTBIG)(var->type&(VTYPE|VISARRAY))) != (newtype&(VTYPE|VISARRAY)))
4847 		{
4848 			ttyputerr(_("Type mismatch"));
4849 			return(TRUE);
4850 		}
4851 #ifdef DEBUGMEMORY
4852 		if (db_setval((UCHAR1 *)&newaddr, (UCHAR1 *)db_realaddress, newtype, cluster,
4853 			module, line)) return(TRUE);
4854 #else
4855 		if (db_setval((UCHAR1 *)&newaddr, (UCHAR1 *)db_realaddress, newtype, cluster))
4856 			return(TRUE);
4857 #endif
4858 		return(FALSE);
4859 	}
4860 
4861 	/* if this change isn't subject to undo, free previous memory now */
4862 	if (db_donextchangequietly || db_dochangesquietly)
4863 	{
4864 		db_freevar(var->addr, var->type);
4865 	}
4866 
4867 	/* change the variable type */
4868 	var->type = newtype;
4869 
4870 	/* allocate and fill space on the new variables */
4871 	if ((newtype&(VCODE1|VCODE2)) != 0)
4872 	{
4873 		if (var->key == sch_globalnamekey || var->key == el_node_name_key || var->key == el_arc_name_key)
4874 		{
4875 			ttyputmsg(_("Language code forbidden for variable %s"), makename(var->key));
4876 			var->type = VSTRING|newtype&(VDISPLAY|VDONTSAVE|VCANTSET);
4877 		}
4878 #ifdef DEBUGMEMORY
4879 		if (db_setval((UCHAR1 *)&newaddr, (UCHAR1 *)&var->addr, VSTRING, cluster,
4880 			module, line)) return(TRUE);
4881 #else
4882 		if (db_setval((UCHAR1 *)&newaddr, (UCHAR1 *)&var->addr, VSTRING, cluster))
4883 			return(TRUE);
4884 #endif
4885 	} else if ((newtype&VISARRAY) != 0)
4886 	{
4887 		var->addr = newaddr;
4888 		len = getlength(var);
4889 		datasize = db_getdatasize(newtype);
4890 		if ((newtype&VLENGTH) == 0)
4891 		{
4892 #ifdef DEBUGMEMORY
4893 			var->addr = (INTBIG)_emalloc((len+1)*datasize, cluster, module, line);
4894 #else
4895 			var->addr = (INTBIG)emalloc((len+1)*datasize, cluster);
4896 #endif
4897 			if (var->addr == 0) return(TRUE);
4898 			for(i=0; i<datasize; i++)
4899 				((UCHAR1 *)var->addr)[len*datasize+i] = 0xff;
4900 		} else
4901 		{
4902 #ifdef DEBUGMEMORY
4903 			var->addr = (INTBIG)_emalloc(len*datasize, cluster, module, line);
4904 #else
4905 			var->addr = (INTBIG)emalloc(len*datasize, cluster);
4906 #endif
4907 			if (var->addr == 0) return(TRUE);
4908 		}
4909 		for(i=0; i<len; i++)
4910 		{
4911 			if ((newtype&VTYPE) == VSHORT)
4912 			{
4913 				longval = ((INTSML *)newaddr)[i];
4914 #ifdef DEBUGMEMORY
4915 				if (db_setval((UCHAR1 *)&longval, &((UCHAR1 *)var->addr)[i*datasize], newtype,
4916 					cluster, module, line)) return(TRUE);
4917 #else
4918 				if (db_setval((UCHAR1 *)&longval, &((UCHAR1 *)var->addr)[i*datasize], newtype,
4919 					cluster)) return(TRUE);
4920 #endif
4921 			} else
4922 			{
4923 				inaddr = (UCHAR1 *)(newaddr + i*datasize);
4924 #ifdef DEBUGMEMORY
4925 				if (db_setval(inaddr, &((UCHAR1 *)var->addr)[i*datasize], newtype,
4926 					cluster, module, line)) return(TRUE);
4927 #else
4928 				if (db_setval(inaddr, &((UCHAR1 *)var->addr)[i*datasize], newtype,
4929 					cluster)) return(TRUE);
4930 #endif
4931 			}
4932 		}
4933 	} else
4934 	{
4935 #ifdef DEBUGMEMORY
4936 		if (db_setval((UCHAR1 *)&newaddr, (UCHAR1 *)&var->addr, newtype, cluster,
4937 			module, line)) return(TRUE);
4938 #else
4939 		if (db_setval((UCHAR1 *)&newaddr, (UCHAR1 *)&var->addr, newtype, cluster))
4940 			return(TRUE);
4941 #endif
4942 	}
4943 
4944 	return(FALSE);
4945 }
4946 
4947 /*
4948  * routine to get entry "aindex" of array variable "var" and place it in "value".
4949  * Returns true upon error.
4950  */
db_getindvar(VARIABLE * var,INTBIG aindex,INTBIG * value)4951 BOOLEAN db_getindvar(VARIABLE *var, INTBIG aindex, INTBIG *value)
4952 {
4953 	INTBIG type, len;
4954 	REGISTER INTBIG datasize;
4955 	REGISTER void *loc;
4956 
4957 	/* if the variable or key is not valid then ignore this */
4958 	if (var == NOVARIABLE) return(TRUE);
4959 
4960 	/* if the variable is not an array, quit now */
4961 	type = var->type;
4962 	if ((type&VISARRAY) == 0) return(TRUE);
4963 
4964 	/* ensure that the index is within the range of the array */
4965 	len = getlength(var);
4966 	if (aindex < 0) aindex = 0;
4967 	if (aindex >= len) aindex = len - 1;
4968 
4969 	/* determine the size of the array entries */
4970 	datasize = db_getdatasize(type);
4971 
4972 	/* set the entry */
4973 	if ((type&VCREF) != 0)
4974 	{
4975 		/* get the address of the old array entry (fixed attributes) */
4976 		loc = (void *)(db_realaddress + aindex*datasize);
4977 	} else
4978 	{
4979 		/* get the address of the old array entry (variable attributes) */
4980 		loc = &((CHAR *)var->addr)[aindex*datasize];
4981 	}
4982 
4983 	/* set an arbitrary attribute on an object */
4984 	*value = db_assignvalue(loc, datasize);
4985 	return(FALSE);
4986 }
4987 
4988 /*
4989  * routine to set entry "aindex" of array variable "var" (which is on object
4990  * "objaddr" of type "objtype") to the value "newaddr".  Returns nonzero
4991  * upon error.
4992  */
4993 #ifdef DEBUGMEMORY
db_setindvar(INTBIG objaddr,INTBIG objtype,VARIABLE * var,INTBIG aindex,INTBIG newaddr,CHAR * module,INTBIG line)4994 BOOLEAN db_setindvar(INTBIG objaddr, INTBIG objtype, VARIABLE *var, INTBIG aindex,
4995 	INTBIG newaddr, CHAR *module, INTBIG line)
4996 #else
4997 BOOLEAN db_setindvar(INTBIG objaddr, INTBIG objtype, VARIABLE *var, INTBIG aindex,
4998 	INTBIG newaddr)
4999 #endif
5000 {
5001 	REGISTER INTBIG datasize;
5002 	REGISTER INTBIG len, oldvalue, type;
5003 	REGISTER void *loc;
5004 
5005 	/* if the variable or key is not valid then ignore this */
5006 	if (var == NOVARIABLE) return(TRUE);
5007 
5008 	/* if the variable is not an array, quit now */
5009 	type = var->type;
5010 	if ((type&VISARRAY) == 0) return(TRUE);
5011 
5012 	/* ensure that the index is within the range of the array */
5013 	len = getlength(var);
5014 	if (aindex < 0) aindex = 0;
5015 	if (aindex >= len) aindex = len - 1;
5016 
5017 	/* determine the size of the array entries */
5018 	datasize = db_getdatasize(type);
5019 
5020 	/* set the entry */
5021 	if ((type&VCREF) != 0)
5022 	{
5023 		/* get the address of the old array entry (fixed attributes) */
5024 		loc = (void *)(db_realaddress + aindex*datasize);
5025 	} else
5026 	{
5027 		/* get the address of the old array entry (variable attributes) */
5028 		loc = &((UCHAR1 *)var->addr)[aindex*datasize];
5029 	}
5030 
5031 	/* set an arbitrary attribute on an object */
5032 	oldvalue = db_assignvalue(loc, datasize);
5033 #ifdef DEBUGMEMORY
5034 	if (db_setval((UCHAR1 *)&newaddr, (UCHAR1 *)loc, type,
5035 		db_whichcluster(objaddr, objtype), module, line)) return(TRUE);
5036 #else
5037 	if (db_setval((UCHAR1 *)&newaddr, (UCHAR1 *)loc, type,
5038 		db_whichcluster(objaddr, objtype))) return(TRUE);
5039 #endif
5040 
5041 	/* handle change control, constraint, and broadcast */
5042 	if (!db_donextchangequietly && !db_dochangesquietly)
5043 	{
5044 		/* tell constraint system about modified variable */
5045 		(*el_curconstraint->modifyvariable)(objaddr, objtype, var->key, type,
5046 			aindex, oldvalue);
5047 
5048 		/* mark a change */
5049 		(void)db_change((INTBIG)objaddr, VARIABLEMOD, objtype, var->key, type,
5050 			aindex, oldvalue, 0);
5051 	} else
5052 	{
5053 		if ((type&(VCODE1|VCODE2)) != 0 || (type&VTYPE) == VSTRING)
5054 			efree((CHAR *)oldvalue);
5055 	}
5056 
5057 	return(FALSE);
5058 }
5059 
5060 /*
5061  * routine to insert the value "newaddr" before entry "aindex" of array
5062  * variable "var" (which is on object "objaddr" of type "objtype").
5063  * Returns true upon error.
5064  */
db_insindvar(INTBIG objaddr,INTBIG objtype,VARIABLE * var,INTBIG aindex,INTBIG newaddr)5065 BOOLEAN db_insindvar(INTBIG objaddr, INTBIG objtype, VARIABLE *var, INTBIG aindex,
5066 	INTBIG newaddr)
5067 {
5068 	REGISTER INTBIG i, j, len, origlen, newsize, truelen, type, *newdata;
5069 	REGISTER INTBIG datasize;
5070 	CLUSTER *cluster;
5071 
5072 	/* if the variable or key is not valid then ignore this */
5073 	if (var == NOVARIABLE) return(TRUE);
5074 
5075 	/* if the variable is not an array, quit now */
5076 	type = var->type;
5077 	if ((type&VISARRAY) == 0) return(TRUE);
5078 	origlen = len = getlength(var);
5079 
5080 	/* ensure that the index is valid */
5081 	if (aindex < 0) aindex = 0;
5082 
5083 	/* determine the size of the new array */
5084 	newsize = len;
5085 	if (aindex > newsize) newsize = aindex;
5086 	newsize++;
5087 	truelen = newsize;
5088 
5089 	/* if this is a variable-length array, include the terminator */
5090 	if ((var->type&VLENGTH) == 0) { origlen++;   newsize++; }
5091 
5092 	/* determine the size of the array entries */
5093 	datasize = db_getdatasize(type);
5094 
5095 	/* allocate a new array */
5096 	cluster = db_whichcluster(objaddr, objtype);
5097 	newdata = (INTBIG *)emalloc(datasize * newsize, cluster);
5098 	if (newdata == 0) return(TRUE);
5099 
5100 	/* copy and insert */
5101 	j = 0;
5102 	for(i=0; i<newsize; i++)
5103 	{
5104 		if (i == aindex)
5105 		{
5106 #ifdef DEBUGMEMORY
5107 			if (db_setval((UCHAR1 *)&newaddr, &((UCHAR1 *)newdata)[aindex*datasize], type,
5108 				cluster, (CHAR *)__FILE__, (INTBIG)__LINE__)) return(TRUE);
5109 #else
5110 			if (db_setval((UCHAR1 *)&newaddr, &((UCHAR1 *)newdata)[aindex*datasize], type,
5111 				cluster)) return(TRUE);
5112 #endif
5113 			continue;
5114 		}
5115 		if (j < origlen)
5116 		{
5117 			switch (type&VTYPE)
5118 			{
5119 				case VCHAR:   ((CHAR   *)newdata)[i] = ((CHAR   *)var->addr)[j];   break;
5120 				case VFLOAT:  ((float  *)newdata)[i] = ((float  *)var->addr)[j];   break;
5121 				case VDOUBLE: ((double *)newdata)[i] = ((double *)var->addr)[j];   break;
5122 				case VSHORT:  ((INTSML *)newdata)[i] = ((INTSML *)var->addr)[j];   break;
5123 				default:      ((INTBIG *)newdata)[i] = ((INTBIG *)var->addr)[j];   break;
5124 			}
5125 			j++;
5126 		} else
5127 		{
5128 			if ((type&(VCODE1|VCODE2)) != 0 || (type&VTYPE) == VSTRING)
5129 			{
5130 				(void)allocstring(&((CHAR **)newdata)[i], x_(""), cluster);
5131 			} else
5132 			{
5133 				switch (type&VTYPE)
5134 				{
5135 					case VCHAR:   ((CHAR   *)newdata)[i] = 0;     break;
5136 					case VFLOAT:  ((float  *)newdata)[i] = 0.0;   break;
5137 					case VDOUBLE: ((double *)newdata)[i] = 0.0;   break;
5138 					case VSHORT:  ((INTSML *)newdata)[i] = 0;     break;
5139 					default:      ((INTBIG *)newdata)[i] = 0;     break;
5140 				}
5141 			}
5142 		}
5143 	}
5144 	efree((CHAR *)var->addr);
5145 	var->addr = (INTBIG)newdata;
5146 
5147 	/* bump the array size */
5148 	if ((var->type&VLENGTH) != 0)
5149 		var->type = (var->type & ~VLENGTH) | (truelen << VLENGTHSH);
5150 
5151 	/* handle change control, constraint, and broadcast */
5152 	if (!db_donextchangequietly && !db_dochangesquietly)
5153 	{
5154 		/* tell constraint system about inserted variable */
5155 		(*el_curconstraint->insertvariable)(objaddr, objtype, var->key, aindex);
5156 
5157 		/* mark a change */
5158 		(void)db_change((INTBIG)objaddr, VARIABLEINS, objtype, var->key, type,
5159 			aindex, 0, 0);
5160 	}
5161 
5162 	return(FALSE);
5163 }
5164 
5165 /*
5166  * routine to delete entry "aindex" of array variable "var" (which is on object
5167  * "objaddr" of type "objtype").  Returns true upon error.
5168  */
db_delindvar(INTBIG objaddr,INTBIG objtype,VARIABLE * var,INTBIG aindex)5169 BOOLEAN db_delindvar(INTBIG objaddr, INTBIG objtype, VARIABLE *var, INTBIG aindex)
5170 {
5171 	REGISTER INTBIG i, len, truelen, oldvalue, type;
5172 	REGISTER INTBIG datasize;
5173 	REGISTER void *loc;
5174 
5175 	/* if the variable or key is not valid then ignore this */
5176 	if (var == NOVARIABLE) return(TRUE);
5177 
5178 	/* if the variable is not an array, quit now */
5179 	type = var->type;
5180 	if ((type&VISARRAY) == 0) return(TRUE);
5181 
5182 	/* ensure that the index is within the range of the array */
5183 	truelen = len = getlength(var);
5184 
5185 	/* can only delete valid line number */
5186 	if (aindex < 0 || aindex >= len) return(TRUE);
5187 
5188 	/* cannot delete last entry */
5189 	if (truelen == 1) return(TRUE);
5190 
5191 	/* if this is a variable-length array, include the terminator */
5192 	if ((var->type&VLENGTH) == 0) len++;
5193 
5194 	/* determine the size of the array entries */
5195 	datasize = db_getdatasize(type);
5196 
5197 	/* get the address of the old array entry */
5198 	loc = &((CHAR *)var->addr)[aindex*datasize];
5199 	oldvalue = db_assignvalue(loc, datasize);
5200 
5201 	/* shift the data */
5202 	for(i=aindex; i<len-1; i++)
5203 	{
5204 		switch (type&VTYPE)
5205 		{
5206 			case VCHAR:
5207 				((CHAR *)var->addr)[i] = ((CHAR *)var->addr)[i+1];
5208 				break;
5209 			case VFLOAT:
5210 				((float *)var->addr)[i] = ((float *)var->addr)[i+1];
5211 				break;
5212 			case VDOUBLE:
5213 				((double *)var->addr)[i] = ((double *)var->addr)[i+1];
5214 				break;
5215 			case VSHORT:
5216 				((INTSML *)var->addr)[i] = ((INTSML *)var->addr)[i+1];
5217 				break;
5218 			default:
5219 				((INTBIG *)var->addr)[i] = ((INTBIG *)var->addr)[i+1];
5220 				break;
5221 		}
5222 	}
5223 
5224 	/* decrement the array size */
5225 	if ((var->type&VLENGTH) != 0)
5226 		var->type = (var->type & ~VLENGTH) | ((truelen-1) << VLENGTHSH);
5227 
5228 	/* handle change control, constraint, and broadcast */
5229 	if (!db_donextchangequietly && !db_dochangesquietly)
5230 	{
5231 		/* tell constraint system about deleted variable */
5232 		(*el_curconstraint->deletevariable)(objaddr, objtype, var->key, aindex, oldvalue);
5233 
5234 		/* mark a change */
5235 		(void)db_change((INTBIG)objaddr, VARIABLEDEL, objtype, var->key, type,
5236 			aindex, oldvalue, 0);
5237 	}
5238 
5239 	return(FALSE);
5240 }
5241 
5242 /*
5243  * routine to set an individual variable entry at address "to" to the value
5244  * at address "from".  This type is of type "type" and if allocatable, is
5245  * filled from cluster "cluster".
5246  */
5247 #ifdef DEBUGMEMORY
db_setval(UCHAR1 * from,UCHAR1 * to,INTBIG type,CLUSTER * cluster,CHAR * module,INTBIG line)5248 BOOLEAN db_setval(UCHAR1 *from, UCHAR1 *to, INTBIG type, CLUSTER *cluster,
5249 	CHAR *module, INTBIG line)
5250 #else
5251 BOOLEAN db_setval(UCHAR1 *from, UCHAR1 *to, INTBIG type, CLUSTER *cluster)
5252 #endif
5253 {
5254 	/* character sized variable */
5255 	if ((type&VTYPE) == VCHAR || (type&VTYPE) == VBOOLEAN)
5256 	{
5257 		*to = *from;
5258 		return(FALSE);
5259 	}
5260 
5261 	/* double sized variable */
5262 	if ((type&VTYPE) == VDOUBLE)
5263 	{
5264 		((double *)to)[0] = ((double *)from)[0];
5265 		return(FALSE);
5266 	}
5267 
5268 	/* float sized variable */
5269 	if ((type&VTYPE) == VFLOAT)
5270 	{
5271 		((float *)to)[0] = ((float *)from)[0];
5272 		return(FALSE);
5273 	}
5274 
5275 	/* short sized variable */
5276 	if ((type&VTYPE) == VSHORT)
5277 	{
5278 		((INTSML *)to)[0] = (INTSML)(((INTBIG *)from)[0]);
5279 		return(FALSE);
5280 	}
5281 
5282 	/* integer sized variable */
5283 	if ((type&(VCODE1|VCODE2)) == 0 && (type&VTYPE) != VSTRING)
5284 	{
5285 		((INTBIG *)to)[0] = ((INTBIG *)from)[0];
5286 		return(FALSE);
5287 	}
5288 
5289 	/* string or code variable */
5290 #ifdef DEBUGMEMORY
5291 	return(_allocstring((CHAR **)to, ((CHAR **)from)[0], cluster, module, line));
5292 #else
5293 	return(allocstring((CHAR **)to, ((CHAR **)from)[0], cluster));
5294 #endif
5295 }
5296 
5297 /*
5298  * routine to erase a list of variables when the object is deleted
5299  */
db_freevars(VARIABLE ** firstvar,INTSML * numvar)5300 void db_freevars(VARIABLE **firstvar, INTSML *numvar)
5301 {
5302 	REGISTER INTBIG i;
5303 	REGISTER VARIABLE *var;
5304 	if (*numvar == 0) return;
5305 	for(i = 0; i < *numvar; i++)
5306 	{
5307 		var = &(*firstvar)[i];
5308 		db_freevar(var->addr, var->type);
5309 	}
5310 	efree((CHAR *)*firstvar);
5311 	*numvar = 0;
5312 }
5313 
5314 /*
5315  * routine to free any memory allocated to the variable whose address is "addr"
5316  * and whose type is "type"
5317  */
db_freevar(INTBIG addr,INTBIG type)5318 void db_freevar(INTBIG addr, INTBIG type)
5319 {
5320 	REGISTER INTBIG i, len;
5321 
5322 	/* determine whether individual elements are allocated */
5323 	if ((type&(VCODE1|VCODE2)) != 0 || (type&VTYPE) == VSTRING)
5324 	{
5325 		/* the old variable was allocated */
5326 		if ((type&VISARRAY) != 0)
5327 		{
5328 			len = (type&VLENGTH) >> VLENGTHSH;
5329 			if (len == 0)
5330 			{
5331 				for(i=0; ((INTBIG *)addr)[i] != -1; i++)
5332 					efree((CHAR *)((INTBIG *)addr)[i]);
5333 			} else for(i=0; i<len; i++) efree((CHAR *)((INTBIG *)addr)[i]);
5334 		} else efree((CHAR *)addr);
5335 	}
5336 	if ((type&VISARRAY) != 0) efree((CHAR *)addr);
5337 }
5338 
5339 /*
5340  * routine to do a binary search on the variables in "numvar" and "firstvar"
5341  * for an entry with the key "key".  If found, its index is returned,
5342  * otherwise a negative value is returned that, when negated, is the position
5343  * in the list BEFORE which the key should be inserted (i.e. the value -1
5344  * means that the key belongs in the first entry and the value -3 means that
5345  * the key belongs after the second entry).
5346  */
db_binarysearch(INTSML numvar,VARIABLE * firstvar,INTBIG key)5347 INTBIG db_binarysearch(INTSML numvar, VARIABLE *firstvar, INTBIG key)
5348 {
5349 	REGISTER INTBIG hi, lo, med, lastmed;
5350 	REGISTER INTBIG i=key;
5351 
5352 	if (numvar == 0) return(-1);
5353 	lo = 0;   hi = lastmed = numvar;
5354 	for(;;)
5355 	{
5356 		/* find mid-point: quit if done */
5357 		med = (hi + lo) / 2;
5358 		if (med == lastmed) break;
5359 		lastmed = med;
5360 
5361 		/* test the entry: return the value if a match */
5362 		i = firstvar[med].key;
5363 		if (i == key) return(med);
5364 
5365 		/* decide which way to search in list */
5366 		if (i > key) hi = med; else lo = med;
5367 	}
5368 	if (i < key) med++;
5369 	return(-med-1);
5370 }
5371 
db_renamevar(INTSML numvar,VARIABLE * firstvar,INTBIG oldkey,INTBIG newkey)5372 void db_renamevar(INTSML numvar, VARIABLE *firstvar, INTBIG oldkey,
5373 	INTBIG newkey)
5374 {
5375 	REGISTER INTBIG i, j, k;
5376 	REGISTER INTBIG oldaddr, oldtype;
5377 	UINTBIG olddescript[TEXTDESCRIPTSIZE];
5378 	REGISTER VARIABLE *var;
5379 
5380 	if (numvar == 0) return;
5381 
5382 	for(i=0; i<numvar; i++)
5383 	{
5384 		var = &firstvar[i];
5385 		if (var->key != oldkey) continue;
5386 
5387 		/* save the old information about this variable */
5388 		oldtype = var->type;
5389 		TDCOPY(olddescript, var->textdescript);
5390 		oldaddr = var->addr;
5391 
5392 		/* compact out the old key */
5393 		for(j=i+1; j<numvar; j++)
5394 		{
5395 			firstvar[j-1].key  = firstvar[j].key;
5396 			firstvar[j-1].type = firstvar[j].type;
5397 			TDCOPY(firstvar[j-1].textdescript, firstvar[j].textdescript);
5398 			firstvar[j-1].addr = firstvar[j].addr;
5399 		}
5400 
5401 		/* now insert the new key */
5402 		for(j=0; j<numvar-1; j++) if (newkey < firstvar[j].key) break;
5403 		for(k=numvar-1; k>j; k--)
5404 		{
5405 			firstvar[k].key  = firstvar[k-1].key;
5406 			firstvar[k].type = firstvar[k-1].type;
5407 			TDCOPY(firstvar[k].textdescript, firstvar[k-1].textdescript);
5408 			firstvar[k].addr = firstvar[k-1].addr;
5409 		}
5410 
5411 		/* insert the renamed variable in the right place */
5412 		firstvar[j].key = newkey;
5413 		firstvar[j].type = oldtype;
5414 		TDCOPY(firstvar[j].textdescript, olddescript);
5415 		firstvar[j].addr = oldaddr;
5416 	}
5417 }
5418 
5419 /*
5420  * routine to fill the parameters "fir" and "num" with the "firstvar" and
5421  * "numvar" attributes on object "addr", type "type".  Returns false if
5422  * successful, true if the object has no "firstvar/numvar".
5423  */
db_getvarptr(INTBIG addr,INTBIG type,VARIABLE *** fir,INTSML ** num)5424 BOOLEAN db_getvarptr(INTBIG addr, INTBIG type, VARIABLE ***fir, INTSML **num)
5425 {
5426 	REGISTER NODEINST *ni;
5427 	REGISTER NODEPROTO *np;
5428 	REGISTER PORTARCINST *pi;
5429 	REGISTER PORTEXPINST *pe;
5430 	REGISTER PORTPROTO *pp;
5431 	REGISTER ARCINST *ai;
5432 	REGISTER ARCPROTO *ap;
5433 	REGISTER GEOM *g;
5434 	REGISTER LIBRARY *lib;
5435 	REGISTER TECHNOLOGY *tech;
5436 	REGISTER TOOL *tool;
5437 	REGISTER RTNODE *rtn;
5438 	REGISTER NETWORK *net;
5439 	REGISTER VIEW *v;
5440 
5441 	switch (type&VTYPE)
5442 	{
5443 		case VNODEINST:
5444 			ni = (NODEINST *)addr;
5445 			*fir = &ni->firstvar;    *num = &ni->numvar;    break;
5446 		case VNODEPROTO:
5447 			np = (NODEPROTO *)addr;
5448 			*fir = &np->firstvar;    *num = &np->numvar;    break;
5449 		case VPORTARCINST:
5450 			pi = (PORTARCINST *)addr;
5451 			*fir = &pi->firstvar;    *num = &pi->numvar;    break;
5452 		case VPORTEXPINST:
5453 			pe = (PORTEXPINST *)addr;
5454 			*fir = &pe->firstvar;    *num = &pe->numvar;    break;
5455 		case VPORTPROTO:
5456 			pp = (PORTPROTO *)addr;
5457 			*fir = &pp->firstvar;    *num = &pp->numvar;    break;
5458 		case VARCINST:
5459 			ai = (ARCINST *)addr;
5460 			*fir = &ai->firstvar;    *num = &ai->numvar;    break;
5461 		case VARCPROTO:
5462 			ap = (ARCPROTO *)addr;
5463 			*fir = &ap->firstvar;    *num = &ap->numvar;    break;
5464 		case VGEOM:
5465 			g = (GEOM *)addr;
5466 			*fir = &g->firstvar;     *num = &g->numvar;     break;
5467 		case VLIBRARY:
5468 			lib = (LIBRARY *)addr;
5469 			*fir = &lib->firstvar;   *num = &lib->numvar;   break;
5470 		case VTECHNOLOGY:
5471 			tech = (TECHNOLOGY *)addr;
5472 			*fir = &tech->firstvar;  *num = &tech->numvar;  break;
5473 		case VTOOL:
5474 			tool = (TOOL *)addr;
5475 			*fir = &tool->firstvar;  *num = &tool->numvar;  break;
5476 		case VRTNODE:
5477 			rtn = (RTNODE *)addr;
5478 			*fir = &rtn->firstvar;   *num = &rtn->numvar;   break;
5479 		case VNETWORK:
5480 			net = (NETWORK *)addr;
5481 			*fir = &net->firstvar;   *num = &net->numvar;   break;
5482 		case VVIEW:
5483 			v = (VIEW *)addr;
5484 			*fir = &v->firstvar;     *num = &v->numvar;     break;
5485 		default: return(TRUE);
5486 	}
5487 	return(FALSE);
5488 }
5489 
db_getdatasize(INTBIG type)5490 INTBIG db_getdatasize(INTBIG type)
5491 {
5492 	if ((type&VTYPE) == VCHAR || (type&VTYPE) == VBOOLEAN) return(SIZEOFCHAR);
5493 	if ((type&VTYPE) == VSHORT) return(SIZEOFINTSML);
5494 	if ((type&VTYPE) == VFLOAT) return(sizeof(float));
5495 	if ((type&VTYPE) == VDOUBLE) return(sizeof(double));
5496 	return(SIZEOFINTBIG);
5497 }
5498 
db_assignvalue(void * loc,INTBIG datasize)5499 INTBIG db_assignvalue(void *loc, INTBIG datasize)
5500 {
5501 	if (datasize == SIZEOFINTBIG)   return(*((INTBIG *)loc));
5502 	if (datasize == SIZEOFINTSML)   return(*((INTSML *)loc));
5503 	if (datasize == SIZEOFCHAR)     return(*((CHAR *)loc));
5504 	if (datasize == sizeof(float))  return(castint(*((float *)loc)));
5505 	if (datasize == sizeof(double)) return(castint((float)(*((double *)loc))));
5506 	return(*((INTBIG *)loc));
5507 }
5508 
db_describetype(INTBIG type)5509 CHAR *db_describetype(INTBIG type)
5510 {
5511 	REGISTER void *infstr;
5512 
5513 	infstr = initinfstr();
5514 	switch (type&VTYPE)
5515 	{
5516 		case VINTEGER:     addstringtoinfstr(infstr, _("Integer"));       break;
5517 		case VADDRESS:     addstringtoinfstr(infstr, _("Address"));       break;
5518 		case VCHAR:        addstringtoinfstr(infstr, _("Character"));     break;
5519 		case VSTRING:      addstringtoinfstr(infstr, _("String"));        break;
5520 		case VFLOAT:       addstringtoinfstr(infstr, _("Float"));         break;
5521 		case VDOUBLE:      addstringtoinfstr(infstr, _("Double"));        break;
5522 		case VNODEINST:    addstringtoinfstr(infstr, _("NodeInst"));      break;
5523 		case VNODEPROTO:   addstringtoinfstr(infstr, _("NodeProto"));     break;
5524 		case VPORTARCINST: addstringtoinfstr(infstr, _("PortArcInst"));   break;
5525 		case VPORTEXPINST: addstringtoinfstr(infstr, _("PortExpInst"));   break;
5526 		case VPORTPROTO:   addstringtoinfstr(infstr, _("PortProto"));     break;
5527 		case VARCINST:     addstringtoinfstr(infstr, _("ArcInst"));       break;
5528 		case VARCPROTO:    addstringtoinfstr(infstr, _("ArcProto"));      break;
5529 		case VGEOM:        addstringtoinfstr(infstr, _("Geom"));          break;
5530 		case VLIBRARY:     addstringtoinfstr(infstr, _("Library"));       break;
5531 		case VTECHNOLOGY:  addstringtoinfstr(infstr, _("Technology"));    break;
5532 		case VTOOL:        addstringtoinfstr(infstr, _("Tool"));          break;
5533 		case VRTNODE:      addstringtoinfstr(infstr, _("RTNode"));        break;
5534 		case VFRACT:       addstringtoinfstr(infstr, _("Fixed-Point"));   break;
5535 		case VNETWORK:     addstringtoinfstr(infstr, _("Network"));       break;
5536 		case VVIEW:        addstringtoinfstr(infstr, _("View"));          break;
5537 		case VWINDOWPART:  addstringtoinfstr(infstr, _("Window"));        break;
5538 		case VGRAPHICS:    addstringtoinfstr(infstr, _("Graphics"));      break;
5539 		case VSHORT:       addstringtoinfstr(infstr, _("Short"));         break;
5540 		case VBOOLEAN:     addstringtoinfstr(infstr, _("Boolean"));       break;
5541 		case VCONSTRAINT:  addstringtoinfstr(infstr, _("Constraint"));    break;
5542 		case VWINDOWFRAME: addstringtoinfstr(infstr, _("WindowFrame"));   break;
5543 		case VGENERAL:     addstringtoinfstr(infstr, _("General"));       break;
5544 		default:           addstringtoinfstr(infstr, _("Unknown"));       break;
5545 	}
5546 	if ((type&VISARRAY) != 0) addstringtoinfstr(infstr, _(" array"));
5547 	return(returninfstr(infstr));
5548 }
5549