1 /* -*- tab-width: 4 -*-
2  *
3  * Electric(tm) VLSI Design System
4  *
5  * File: iotexto.c
6  * Input/output tool: textual format output
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 "eio.h"
34 
35 static INTBIG io_cellnumber, io_nodeinsterror, io_portarcinsterror, io_portexpinsterror,
36 	  io_portprotoerror, io_arcinsterror, io_geomerror, io_rtnodeerror, io_libraryerror;
37 
38 /* prototypes for local routines */
39 static void    io_textrecurse(NODEPROTO*);
40 static INTBIG  io_countvars(INTBIG, VARIABLE*);
41 static void    io_writevars(INTBIG, VARIABLE*, NODEPROTO*);
42 static CHAR   *io_makestring(VARIABLE*, NODEPROTO*);
43 static void    io_makestringvar(void*, INTBIG, INTBIG, NODEPROTO*);
44 static void    io_addstring(void*, CHAR*);
45 static void    io_printname(CHAR*, FILE*);
46 
io_writetextlibrary(LIBRARY * lib)47 BOOLEAN io_writetextlibrary(LIBRARY *lib)
48 {
49 	REGISTER CHAR *name;
50 	CHAR file[256], *truename;
51 	REGISTER INTBIG i, j, t, noc, arcinst, poc, cell, cellgroup;
52 	REGISTER NODEPROTO *np, *onp;
53 	REGISTER PORTPROTO *pp;
54 	REGISTER LIBRARY *olib;
55 	REGISTER NODEINST *ni;
56 	REGISTER PORTARCINST *pi;
57 	REGISTER PORTEXPINST *pe;
58 	REGISTER ARCINST *ai;
59 	REGISTER TECHNOLOGY *tech;
60 	REGISTER VIEW *v;
61 	REGISTER NODEPROTO **cells;
62 
63 	(void)estrcpy(file, lib->libfile);
64 	name = &file[estrlen(file)-5];
65 	if (estrcmp(name, x_(".elib")) == 0) *name = 0;
66 	name = &file[estrlen(file)-4];
67 	if (estrcmp(name, x_(".txt")) != 0) (void)estrcat(file, x_(".txt"));
68 	name = truepath(file);
69 	io_fileout = xcreate(name, io_filetypetlib, _("Readable Dump File"), &truename);
70 	if (io_fileout == NULL)
71 	{
72 		if (truename != 0) ttyputerr(_("Cannot write %s"), truename);
73 		return(TRUE);
74 	}
75 
76 	/* clear error counters */
77 	io_nodeinsterror = io_portarcinsterror = io_portexpinsterror = 0;
78 	io_portprotoerror = io_arcinsterror = io_geomerror = io_libraryerror = 0;
79 	io_rtnodeerror = 0;
80 
81 	/* determine proper library order */
82 	for(olib = el_curlib; olib != NOLIBRARY; olib = olib->nextlibrary)
83 		for(np = olib->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
84 			np->temp1 = -1;
85 	io_cellnumber = 0;
86 	for(np = lib->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
87 		if (np->firstinst == NONODEINST) io_textrecurse(np);
88 	for(np = lib->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
89 		if (np->temp1 < 0) io_textrecurse(np);
90 	if (io_cellnumber > 0)
91 	{
92 		cells = (NODEPROTO **)emalloc((io_cellnumber * sizeof(NODEPROTO *)),
93 			io_tool->cluster);
94 		if (cells == 0)
95 		{
96 			ttyputnomemory();
97 			return(TRUE);
98 		}
99 		for(olib = el_curlib; olib != NOLIBRARY; olib = olib->nextlibrary)
100 		{
101 			for(np = olib->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
102 			{
103 				if (np->temp1 >= 0 && np->temp1 < io_cellnumber)
104 					cells[np->temp1] = np;
105 			}
106 		}
107 	}
108 
109 	/* determine cell groupings */
110 	for(np = lib->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
111 		np->temp2 = 0;
112 	cellgroup = 0;
113 	for(np = lib->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
114 	{
115 		if (np->temp2 != 0) continue;
116 		cellgroup++;
117 		FOR_CELLGROUP(onp, np)
118 			onp->temp2 = cellgroup;
119 	}
120 
121 	/* write header information */
122 	xprintf(io_fileout, x_("****library: \"%s\"\n"), lib->libname);
123 	xprintf(io_fileout, x_("version: %s\n"), el_version);
124 	xprintf(io_fileout, x_("aids: %ld\n"), el_maxtools);
125 	for(i=0; i<el_maxtools; i++)
126 	{
127 		xprintf(io_fileout, x_("aidname: %s\n"), el_tools[i].toolname);
128 		if (io_countvars(el_tools[i].numvar, el_tools[i].firstvar) != 0)
129 			io_writevars(el_tools[i].numvar, el_tools[i].firstvar, NONODEPROTO);
130 	}
131 	xprintf(io_fileout, x_("userbits: %ld\n"), lib->userbits);
132 	xprintf(io_fileout, x_("techcount: %ld\n"), el_maxtech);
133 	for(tech = el_technologies; tech != NOTECHNOLOGY; tech = tech->nexttechnology)
134 	{
135 		xprintf(io_fileout, x_("techname: %s lambda: %ld\n"), tech->techname, lib->lambda[tech->techindex]);
136 		io_writevars(tech->numvar, tech->firstvar, NONODEPROTO);
137 	}
138 	for(v = el_views; v != NOVIEW; v = v->nextview)
139 		xprintf(io_fileout, x_("view: %s{%s}\n"), v->viewname, v->sviewname);
140 	xprintf(io_fileout, x_("cellcount: %ld\n"), io_cellnumber);
141 	if (lib->curnodeproto != NONODEPROTO)
142 		xprintf(io_fileout, x_("maincell: %ld\n"), lib->curnodeproto->temp1);
143 
144 	/* write variables on the library */
145 	io_writevars(lib->numvar, lib->firstvar, NONODEPROTO);
146 
147 	/* write the rest of the database */
148 	for(cell = 0; cell < io_cellnumber; cell++)
149 	{
150 		/* write the nodeproto name */
151 		np = cells[cell];
152 		xprintf(io_fileout, x_("***cell: %ld/%ld\n"), np->temp1, np->temp2);
153 		xprintf(io_fileout, x_("name: %s"), np->protoname);
154 		if (*np->cellview->sviewname != 0)
155 			xprintf(io_fileout, x_("{%s}"), np->cellview->sviewname);
156 		xprintf(io_fileout, x_("\n"));
157 		xprintf(io_fileout, x_("version: %ld\n"), np->version);
158 		xprintf(io_fileout, x_("creationdate: %ld\n"), np->creationdate);
159 		xprintf(io_fileout, x_("revisiondate: %ld\n"), np->revisiondate);
160 
161 		/* write the nodeproto bounding box */
162 		xprintf(io_fileout, x_("lowx: %ld highx: %ld lowy: %ld highy: %ld\n"),
163 			np->lowx, np->highx, np->lowy, np->highy);
164 
165 		/* cells in external libraries mention the library and stop */
166 		if (np->lib != lib)
167 		{
168 			xprintf(io_fileout, x_("externallibrary: \"%s\"\n"),
169 				np->lib->libfile);
170 			continue;
171 		}
172 
173 		/* write tool information */
174 		xprintf(io_fileout, x_("aadirty: %ld\n"), np->adirty);
175 		xprintf(io_fileout, x_("userbits: %ld\n"), np->userbits);
176 
177 		/* count and number the nodes, arcs, and ports */
178 		noc = arcinst = poc = 0;
179 		for(ni = np->firstnodeinst; ni != NONODEINST; ni = ni->nextnodeinst)
180 			ni->temp1 = noc++;
181 		for(ai = np->firstarcinst; ai != NOARCINST; ai = ai->nextarcinst)
182 			ai->temp1 = arcinst++;
183 		for(pp = np->firstportproto; pp != NOPORTPROTO; pp = pp->nextportproto)
184 			pp->temp1 = poc++;
185 		xprintf(io_fileout, x_("nodes: %ld arcs: %ld porttypes: %ld\n"), noc, arcinst, poc);
186 
187 		/* write variables on the cell */
188 		io_writevars(np->numvar, np->firstvar, np);
189 
190 		/* write the nodes in this cell */
191 		for(ni = np->firstnodeinst; ni != NONODEINST; ni = ni->nextnodeinst)
192 		{
193 			xprintf(io_fileout, x_("**node: %ld\n"), ni->temp1);
194 			if (ni->proto->primindex == 0)
195 				xprintf(io_fileout, x_("type: [%ld]\n"), ni->proto->temp1); else
196 					xprintf(io_fileout, x_("type: %s:%s\n"),
197 						ni->proto->tech->techname, ni->proto->protoname);
198 			xprintf(io_fileout, x_("lowx: %ld highx: %ld lowy: %ld highy: %ld\n"), ni->lowx,
199 				ni->highx, ni->lowy, ni->highy);
200 			if (ni->transpose != 0) t = 1; else t = 0;
201 			xprintf(io_fileout, x_("rotation: %d transpose: %d\n"), ni->rotation, t);
202 			if (ni->proto->primindex == 0)
203 			{
204 				xprintf(io_fileout, x_("descript: %ld/%ld\n"), ni->textdescript[0],
205 					ni->textdescript[1]);
206 			}
207 			xprintf(io_fileout, x_("userbits: %ld\n"), ni->userbits);
208 			io_writevars(ni->numvar, ni->firstvar, np);
209 
210 			pi = ni->firstportarcinst;   pe = ni->firstportexpinst;
211 			for(pp = ni->proto->firstportproto, i=0; pp != NOPORTPROTO; pp = pp->nextportproto, i++)
212 			{
213 				j = 0;
214 				while (pi != NOPORTARCINST && pi->proto == pp)
215 				{
216 					if (j == 0) xprintf(io_fileout, x_("*port: %s\n"), pp->protoname);
217 					j++;
218 					xprintf(io_fileout, x_("arc: %ld\n"), pi->conarcinst->temp1);
219 					io_writevars(pi->numvar, pi->firstvar, np);
220 					pi = pi->nextportarcinst;
221 				}
222 				while (pe != NOPORTEXPINST && pe->proto == pp)
223 				{
224 					if (j == 0) xprintf(io_fileout, x_("*port: %s\n"), pp->protoname);
225 					j++;
226 					xprintf(io_fileout, x_("exported: %ld\n"), pe->exportproto->temp1);
227 					io_writevars(pe->numvar, pe->firstvar, np);
228 					pe = pe->nextportexpinst;
229 				}
230 			}
231 		}
232 
233 		/* write the portprotos in this cell */
234 		poc = 0;
235 		for(pp = np->firstportproto; pp != NOPORTPROTO; pp = pp->nextportproto)
236 		{
237 			xprintf(io_fileout, x_("**porttype: %ld\n"), poc++);
238 			xprintf(io_fileout, x_("subnode: %ld\n"), pp->subnodeinst->temp1);
239 			xprintf(io_fileout, x_("subport: %s\n"), pp->subportproto->protoname);
240 			xprintf(io_fileout, x_("name: %s\n"), pp->protoname);
241 
242 			/* need to write both words */
243 			xprintf(io_fileout, x_("descript: %ld/%ld\n"), pp->textdescript[0],
244 				pp->textdescript[1]);
245 			xprintf(io_fileout, x_("userbits: %ld\n"), pp->userbits);
246 			io_writevars(pp->numvar, pp->firstvar, np);
247 		}
248 
249 		/* write the arcs in this cell */
250 		for(ai = np->firstarcinst; ai != NOARCINST; ai = ai->nextarcinst)
251 		{
252 			xprintf(io_fileout, x_("**arc: %ld\n"), ai->temp1);
253 			xprintf(io_fileout, x_("type: %s:%s\n"), ai->proto->tech->techname, ai->proto->protoname);
254 			xprintf(io_fileout, x_("width: %ld length: %ld\n"), ai->width, ai->length);
255 			xprintf(io_fileout, x_("userbits: %ld\n"), ai->userbits);
256 			for(i=0; i<2; i++)
257 			{
258 				xprintf(io_fileout, x_("*end: %ld\n"), i);
259 				xprintf(io_fileout, x_("node: %ld\n"), ai->end[i].nodeinst->temp1);
260 				xprintf(io_fileout, x_("nodeport: %s\n"), ai->end[i].portarcinst->proto->protoname);
261 				xprintf(io_fileout, x_("xpos: %ld ypos: %ld\n"), ai->end[i].xpos, ai->end[i].ypos);
262 			}
263 			io_writevars(ai->numvar, ai->firstvar, np);
264 		}
265 		xprintf(io_fileout, x_("celldone: %s\n"), np->protoname);
266 	}
267 
268 	/* print any variable-related error messages */
269 	if (io_nodeinsterror != 0)
270 		ttyputmsg(x_("Warning: %ld NODEINST pointers point outside cell: not saved"), io_nodeinsterror);
271 	if (io_arcinsterror != 0)
272 		ttyputmsg(x_("Warning: %ld ARCINST pointers point outside cell: not saved"), io_arcinsterror);
273 	if (io_portprotoerror != 0)
274 		ttyputmsg(x_("Warning: %ld PORTPROTO pointers point outside cell: not saved"), io_portprotoerror);
275 	if (io_portarcinsterror != 0)
276 		ttyputmsg(x_("Warning: %ld PORTARCINST pointers could not be saved"), io_portarcinsterror);
277 	if (io_portexpinsterror != 0)
278 		ttyputmsg(x_("Warning: %ld PORTEXPINST pointers could not be saved"), io_portexpinsterror);
279 	if (io_geomerror != 0)
280 		ttyputmsg(x_("Warning: %ld GEOM pointers could not be saved"), io_geomerror);
281 	if (io_rtnodeerror != 0)
282 		ttyputmsg(x_("Warning: %ld RTNODE pointers could not be saved"), io_rtnodeerror);
283 	if (io_libraryerror != 0)
284 		ttyputmsg(x_("Warning: LIBRARY pointers could not be saved"), io_libraryerror);
285 
286 	/* clean up and return */
287 	xclose(io_fileout);
288 	ttyputmsg(_("%s written"), truename);
289 	lib->userbits &= ~(LIBCHANGEDMAJOR | LIBCHANGEDMINOR);
290 	if (io_cellnumber > 0) efree((CHAR *)cells);
291 	return(FALSE);
292 }
293 
294 /*
295  * routine to help order the library for proper nonforward references
296  * in the outout
297  */
io_textrecurse(NODEPROTO * np)298 void io_textrecurse(NODEPROTO *np)
299 {
300 	REGISTER NODEINST *ni;
301 
302 	for(ni = np->firstnodeinst; ni != NONODEINST; ni = ni->nextnodeinst)
303 	{
304 		if (ni->proto->primindex != 0) continue;
305 		if (ni->proto->temp1 == -1) io_textrecurse(ni->proto);
306 	}
307 
308 	/* add this cell to the list */
309 	np->temp1 = io_cellnumber++;
310 }
311 
312 /*
313  * routine to return the number of permanent variables on an object
314  */
io_countvars(INTBIG numvar,VARIABLE * firstvar)315 INTBIG io_countvars(INTBIG numvar, VARIABLE *firstvar)
316 {
317 	REGISTER INTBIG i, j;
318 
319 	i = 0;
320 	for(j=0; j<numvar; j++)
321 		if ((firstvar[j].type & VDONTSAVE) == 0) i++;
322 	return(i);
323 }
324 
325 /*
326  * routine to write the variables on an object.  The current cell is
327  * "curnodeproto" such that any references to objects in a cell must be in
328  * this cell.
329  */
io_writevars(INTBIG numvar,VARIABLE * firstvar,NODEPROTO * curnodeproto)330 void io_writevars(INTBIG numvar, VARIABLE *firstvar, NODEPROTO *curnodeproto)
331 {
332 	REGISTER CHAR *pt;
333 	REGISTER INTBIG i;
334 	REGISTER VARIABLE *var;
335 
336 	i = io_countvars(numvar, firstvar);
337 	if (i == 0) return;
338 
339 	xprintf(io_fileout, x_("variables: %ld\n"), i);
340 	for(i=0; i<numvar; i++)
341 	{
342 		var = &firstvar[i];
343 		if ((var->type & VDONTSAVE) != 0) continue;
344 		pt = io_makestring(var, curnodeproto);
345 		if (pt == 0) pt = x_("");
346 		io_printname((CHAR *)var->key, io_fileout);
347 		if ((var->type&(VLENGTH|VISARRAY)) != VISARRAY)
348 		{
349 			xprintf(io_fileout, x_("[0%o,0%o/0%o]: "), var->type, var->textdescript[0],
350 				var->textdescript[1]);
351 		} else
352 		{
353 			xprintf(io_fileout, x_("(%ld)[0%o,0%o/0%o]: "), getlength(var), var->type,
354 				var->textdescript[0], var->textdescript[1]);
355 		}
356 		xprintf(io_fileout, x_("%s\n"), pt);
357 	}
358 }
359 
360 /*
361  * routine to convert variable "var" to a string for printing in the text file.
362  * returns zero on error
363  */
io_makestring(VARIABLE * var,NODEPROTO * curnodeproto)364 CHAR *io_makestring(VARIABLE *var, NODEPROTO *curnodeproto)
365 {
366 	REGISTER INTBIG i, len;
367 	CHAR line[50];
368 	REGISTER CHAR *pt;
369 	REGISTER void *infstr;
370 
371 	if (var == NOVARIABLE) return(0);
372 
373 	infstr = initinfstr();
374 	if ((var->type&VISARRAY) != 0)
375 	{
376 		len = getlength(var);
377 		for(i=0; i<len; i++)
378 		{
379 			if (i == 0) addtoinfstr(infstr, '['); else
380 				addtoinfstr(infstr, ',');
381 
382 			if ((var->type&VTYPE) == VGENERAL)
383 			{
384 				if ((i&1) == 0)
385 				{
386 					(void)esnprintf(line, 50, x_("0%lo"), ((INTBIG *)var->addr)[i+1]);
387 					addstringtoinfstr(infstr, line);
388 				} else
389 				{
390 					io_makestringvar(infstr, ((INTBIG *)var->addr)[i], ((INTBIG *)var->addr)[i-1],
391 						curnodeproto);
392 				}
393 			} else
394 			{
395 				switch ((var->type&VTYPE))
396 				{
397 					case VCHAR:
398 						io_makestringvar(infstr, var->type, ((INTBIG)((CHAR *)var->addr)[i]),
399 							curnodeproto);
400 						break;
401 
402 					case VSHORT:
403 						io_makestringvar(infstr, var->type, ((INTBIG)((INTSML *)var->addr)[i]),
404 							curnodeproto);
405 						break;
406 
407 					case VDOUBLE:
408 						io_makestringvar(infstr, var->type, ((INTBIG)((double *)var->addr)[i]),
409 							curnodeproto);
410 						break;
411 
412 					default:
413 						io_makestringvar(infstr, var->type, ((INTBIG *)var->addr)[i], curnodeproto);
414 						break;
415 				}
416 			}
417 		}
418 		addtoinfstr(infstr, ']');
419 	} else io_makestringvar(infstr, var->type, var->addr, curnodeproto);
420 	pt = returninfstr(infstr);
421 	return(pt);
422 }
423 
424 /*
425  * routine to make a string from the value in "addr" which has a type in
426  * "type".
427  */
io_makestringvar(void * infstr,INTBIG type,INTBIG addr,NODEPROTO * curnodeproto)428 void io_makestringvar(void *infstr, INTBIG type, INTBIG addr, NODEPROTO *curnodeproto)
429 {
430 	CHAR line[100];
431 	REGISTER INTBIG cindex;
432 	REGISTER NODEINST *ni;
433 	REGISTER NODEPROTO *np;
434 	REGISTER PORTARCINST *pi;
435 	REGISTER PORTEXPINST *pe;
436 	REGISTER PORTPROTO *pp;
437 	REGISTER ARCINST *ai;
438 	REGISTER ARCPROTO *ap;
439 	REGISTER GEOM *geom;
440 	REGISTER RTNODE *rtn;
441 	REGISTER LIBRARY *lib;
442 	REGISTER TECHNOLOGY *tech;
443 	REGISTER TOOL *tool;
444 
445 	if ((type&(VCODE1|VCODE2)) != 0) type = VSTRING;
446 	switch (type&VTYPE)
447 	{
448 		case VINTEGER:
449 		case VSHORT:
450 		case VBOOLEAN:
451 		case VFRACT:
452 			(void)esnprintf(line, 100, x_("%ld"), addr);
453 			addstringtoinfstr(infstr, line);
454 			break;
455 		case VADDRESS:
456 			(void)esnprintf(line, 100, x_("0%lo"), addr);
457 			addstringtoinfstr(infstr, line);
458 			break;
459 		case VCHAR:
460 			addtoinfstr(infstr, (CHAR)addr);
461 			break;
462 		case VSTRING:
463 			addtoinfstr(infstr, '"');
464 			io_addstring(infstr, (CHAR *)addr);
465 			addtoinfstr(infstr, '"');
466 			break;
467 		case VFLOAT:
468 			(void)esnprintf(line, 100, x_("%f"), castfloat(addr));
469 			addstringtoinfstr(infstr, line);
470 			break;
471 		case VDOUBLE:
472 			(void)esnprintf(line, 100, x_("%f"), castfloat(addr));
473 			addstringtoinfstr(infstr, line);
474 			break;
475 		case VNODEINST:
476 			ni = (NODEINST *)addr;
477 			cindex = -1;
478 			if (ni != NONODEINST)
479 			{
480 				if (ni->parent == curnodeproto) cindex = ni->temp1; else
481 					io_nodeinsterror++;
482 			}
483 			(void)esnprintf(line, 100, x_("%ld"), cindex);
484 			addstringtoinfstr(infstr, line);
485 			break;
486 		case VNODEPROTO:
487 			np = (NODEPROTO *)addr;
488 			if (np == NONODEPROTO)
489 			{
490 				addstringtoinfstr(infstr, x_("-1"));
491 				break;
492 			}
493 			if (np->primindex == 0)
494 			{
495 				(void)esnprintf(line, 100, x_("%ld"), np->temp1);
496 				addstringtoinfstr(infstr, line);
497 			} else
498 			{
499 				io_addstring(infstr, np->tech->techname);
500 				addtoinfstr(infstr, ':');
501 				io_addstring(infstr, np->protoname);
502 			}
503 			break;
504 		case VPORTARCINST:
505 			io_portarcinsterror++;
506 			pi = (PORTARCINST *)addr;
507 			if (pi == NOPORTARCINST)
508 			{
509 				addstringtoinfstr(infstr, x_("NOPORTARCINST"));
510 				break;
511 			}
512 			(void)esnprintf(line, 100, x_("portarc%ld"), (INTBIG)pi);
513 			addstringtoinfstr(infstr, line);
514 			break;
515 		case VPORTEXPINST:
516 			io_portexpinsterror++;
517 			pe = (PORTEXPINST *)addr;
518 			if (pe == NOPORTEXPINST)
519 			{
520 				addstringtoinfstr(infstr, x_("NOPORTEXPINST"));
521 				break;
522 			}
523 			(void)esnprintf(line, 100, x_("portexp%ld"), (INTBIG)pe);
524 			addstringtoinfstr(infstr, line);
525 			break;
526 		case VPORTPROTO:
527 			pp = (PORTPROTO *)addr;
528 			cindex = -1;
529 			if (pp != NOPORTPROTO)
530 			{
531 				if (pp->parent == curnodeproto) cindex = pp->temp1; else
532 					io_portprotoerror++;
533 			}
534 			(void)esnprintf(line, 100, x_("%ld"), cindex);
535 			addstringtoinfstr(infstr, line);
536 			break;
537 		case VARCINST:
538 			ai = (ARCINST *)addr;
539 			cindex = -1;
540 			if (ai != NOARCINST)
541 			{
542 				if (ai->parent == curnodeproto) cindex = ai->temp1; else
543 					io_arcinsterror++;
544 			}
545 			(void)esnprintf(line, 100, x_("%ld"), cindex);
546 			addstringtoinfstr(infstr, line);
547 			break;
548 		case VARCPROTO:
549 			ap = (ARCPROTO *)addr;
550 			if (ap == NOARCPROTO)
551 			{
552 				addstringtoinfstr(infstr, x_("NOARCPROTO"));
553 				break;
554 			}
555 			io_addstring(infstr, ap->tech->techname);
556 			addtoinfstr(infstr, ':');
557 			io_addstring(infstr, ap->protoname);
558 			break;
559 		case VGEOM:
560 			io_geomerror++;
561 			geom = (GEOM *)addr;
562 			if (geom == NOGEOM)
563 			{
564 				addstringtoinfstr(infstr, x_("NOGEOM"));
565 				break;
566 			}
567 			(void)esnprintf(line, 100, x_("geom%ld"), (INTBIG)geom);
568 			addstringtoinfstr(infstr, line);
569 			break;
570 		case VLIBRARY:
571 			io_libraryerror++;
572 			lib = (LIBRARY *)addr;
573 			if (lib == NOLIBRARY)
574 			{
575 				addstringtoinfstr(infstr, x_("NOLIBRARY"));
576 				break;
577 			}
578 			addtoinfstr(infstr, '"');
579 			io_addstring(infstr, lib->libname);
580 			addtoinfstr(infstr, '"');
581 			break;
582 		case VTECHNOLOGY:
583 			tech = (TECHNOLOGY *)addr;
584 			if (tech == NOTECHNOLOGY)
585 			{
586 				addstringtoinfstr(infstr, x_("NOTECHNOLOGY"));
587 				break;
588 			}
589 			io_addstring(infstr, tech->techname);
590 			break;
591 		case VTOOL:
592 			tool = (TOOL *)addr;
593 			if (tool == NOTOOL)
594 			{
595 				addstringtoinfstr(infstr, x_("NOTOOL"));
596 				break;
597 			}
598 			io_addstring(infstr, tool->toolname);
599 			break;
600 		case VRTNODE:
601 			io_rtnodeerror++;
602 			rtn = (RTNODE *)addr;
603 			if (rtn == NORTNODE)
604 			{
605 				addstringtoinfstr(infstr, x_("NORTNODE"));
606 				break;
607 			}
608 			(void)esnprintf(line, 100, x_("rtn%ld"), (INTBIG)rtn);
609 			addstringtoinfstr(infstr, line);
610 			break;
611 		case VNETWORK:
612 		case VVIEW:
613 		case VWINDOWPART:
614 		case VGRAPHICS:
615 		case VCONSTRAINT:
616 		case VGENERAL:
617 		case VWINDOWFRAME:
618 		case VPOLYGON:
619 			break;
620 	}
621 }
622 
623 /*
624  * routine to add the string "str" to the infinite string and to quote the
625  * special characters '[', ']', '"', and '^'.
626  */
io_addstring(void * infstr,CHAR * str)627 void io_addstring(void *infstr, CHAR *str)
628 {
629 
630 	while (*str != 0)
631 	{
632 		if (*str == '[' || *str == ']' || *str == '"' || *str == '^')
633 			addtoinfstr(infstr, '^');
634 		addtoinfstr(infstr, *str++);
635 	}
636 }
637 
638 /*
639  * routine to print the variable name in "name" on file "file".  The
640  * conversion performed is to quote with a backslash any of the characters
641  * '(', '[', or '^'.
642  */
io_printname(CHAR * name,FILE * file)643 void io_printname(CHAR *name, FILE *file)
644 {
645 	REGISTER CHAR *pt;
646 
647 	for(pt = name; *pt != 0; pt++)
648 	{
649 		if (*pt == '^' || *pt == '[' || *pt == '(') xputc('^', file);
650 		xputc(*pt, file);
651 	}
652 }
653