1 /* -*- tab-width: 4 -*-
2 *
3 * Electric(tm) VLSI Design System
4 *
5 * File: iobinaryi.c
6 * Input/output tool: binary format input
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 #include "global.h"
32 #include "database.h"
33 #include "eio.h"
34 #include "tech.h"
35 #include "tecgen.h"
36 #include "tecart.h"
37 #include "tecschem.h"
38 #include "tecmocmos.h"
39 #include "tecmocmossub.h"
40 #include "edialogs.h"
41 #include "usr.h"
42
43 #define REPORTINC 2000 /* bytes between graphical updates */
44
45 #define LONGJMPABORTED 1 /* for "Aborted" */
46 #define LONGJMPEOF 2 /* for "Premature end of file" */
47
48 typedef struct
49 {
50 BOOLEAN toolbitsmessed; /* 0: tool order is correct */
51 INTBIG aabcount; /* number of toolbits for old files */
52 INTBIG bytecount; /* position within input file */
53 CHAR **realname; /* variable names */
54 INTBIG namecount; /* number of variable names */
55 INTBIG filelength; /* length of the file */
56 INTBIG reported; /* reported progress in file */
57 UCHAR1 sizeofsmall; /* number of bytes in file for an INTSML */
58 UCHAR1 sizeofbig; /* number of bytes in file for an INTBIG */
59 UCHAR1 sizeofchar; /* number of bytes in file for a CHAR */
60
61 /* totals of objects in the file */
62 INTBIG magic; /* file's magic number */
63 INTBIG emajor, eminor, edetail; /* library's version information */
64 INTBIG aacount; /* number of tools */
65 INTBIG techcount; /* number of technologies */
66 INTBIG nodepprotoindex; /* number of primitive node prototypes */
67 INTBIG portpprotoindex; /* number of primitive port prototypes */
68 INTBIG arcprotoindex; /* number of arc prototypes */
69 INTBIG nodeprotoindex; /* number of cells */
70 INTBIG nodeindex; /* number of node instances */
71 INTBIG portprotoindex; /* index of port prototypes */
72 INTBIG portprotolimit; /* total number of port prototypes */
73 INTBIG arcindex; /* number of arc instances */
74 INTBIG geomindex; /* number of geometry modules */
75 INTBIG cellindex; /* number of cells */
76 INTBIG curnodeproto; /* current cell */
77
78 /* input error message arrays */
79 CHAR **techerror; /* name of unknown technologies */
80 CHAR **toolerror; /* name of unknown tools */
81 BOOLEAN *nodepprotoerror; /* flag for unknown prim. NODEPROTOs */
82 CHAR **nodepprotoorig; /* name of unknown prim. NODEPROTOs */
83 INTBIG *nodepprototech; /* tech. assoc. with prim. NODEPROTOs */
84 CHAR **portpprotoerror; /* name of unknown PORTPROTOs */
85 CHAR **arcprotoerror; /* name of unknown ARCPROTOs */
86 INTBIG swap_bytes; /* are the bytes swapped? 1 if so */
87 BOOLEAN converttextdescriptors; /* convert textdescript fields */
88 BOOLEAN alwaystextdescriptors; /* always have textdescript fields */
89 INTBIG swapped_floats; /* number of swappped floating-point variables */
90 INTBIG swapped_doubles; /* number of swappped double-precision variables */
91 INTBIG clipped_integers; /* number of clipped integers */
92 FILE *filein; /* channel for input */
93 INTBIG *newnames; /* for adding new names to global namespace */
94 jmp_buf filerror; /* nonlocal jump when I/O fails */
95 NODEINST **nodelist; /* list of nodes for readin */
96 INTBIG *nodecount; /* number of nodeinsts in each cell */
97 ARCINST **arclist; /* list of arcs for readin */
98 INTBIG *arccount; /* number of arcinsts in each cell */
99 NODEPROTO **nodeprotolist; /* list of cells for readin */
100 FAKECELL **fakecelllist; /* list of fakecells for readin */
101 TECHNOLOGY **techlist; /* list of technologies for readin */
102 INTBIG *toollist; /* list of tools for readin */
103 PORTPROTO **portprotolist; /* list of portprotos for readin */
104 INTBIG *portcount; /* number of portprotos in each cell */
105 PORTPROTO **portpprotolist; /* list of primitive portprotos for readin */
106 NODEPROTO **nodepprotolist; /* list of primitive nodeprotos for readin */
107 ARCPROTO **arcprotolist; /* list of arcprotos for readin */
108 } BININPUTDATA;
109
110 static BININPUTDATA io_binindata; /* all data pertaining to reading a file */
111 static CHAR1 *io_tempstring; /* for reading temporary strings */
112 static INTBIG io_tempstringlength = 0; /* length of temporary string */
113 static CHAR io_mainlibdirectory[500]; /* root directory where binary file lives */
114 void *io_inputprogressdialog; /* for showing input progress */
115
116 /* prototypes for local routines */
117 static CHAR *io_doreadlibrary(LIBRARY*);
118 static BOOLEAN io_readnodeproto(NODEPROTO*, LIBRARY*);
119 static BOOLEAN io_readnodeinst(NODEINST*);
120 static void io_readgeom(BOOLEAN*, INTBIG*);
121 static BOOLEAN io_readarcinst(ARCINST*);
122 static BOOLEAN io_readnamespace(void);
123 static void io_ignorevariables(void);
124 static INTBIG io_readvariables(INTBIG, INTBIG);
125 static INTBIG io_getinvar(INTBIG*, INTBIG);
126 static INTBIG io_arrangetoolbits(INTBIG);
127 static INTBIG io_convertnodeproto(NODEPROTO**, CHAR**);
128 static BOOLEAN io_convertportproto(PORTPROTO**, BOOLEAN);
129 static void io_convertarcproto(ARCPROTO**);
130 static ARCPROTO *io_getarcprotolist(INTBIG);
131 static PORTPROTO *io_getportpprotolist(INTBIG);
132 static NODEPROTO *io_getnodepprotolist(INTBIG);
133 static TECHNOLOGY *io_gettechlist(INTBIG);
134 static void io_getin(void *, INTBIG, INTBIG, BOOLEAN);
135 static CHAR *io_getstring(CLUSTER*);
136 static CHAR *io_gettempstring(void);
137 static void io_getinbig(void *data);
138 static void io_getinubig(void *data);
139 static void io_readexternalnodeproto(LIBRARY *lib, INTBIG i);
140 static void io_ensureallports(LIBRARY *lib);
141 static void io_binfindallports(LIBRARY *lib, PORTPROTO *pp, INTBIG *lx, INTBIG *hx,
142 INTBIG *ly, INTBIG *hy, BOOLEAN *first, ARCPROTO **onlyarc, XARRAY trans);
143 static void io_fixexternalvariables(VARIABLE *firstvar, INTSML numvar);
144
145 /*
146 * Routine to free all memory associated with this module.
147 */
io_freebininmemory(void)148 void io_freebininmemory(void)
149 {
150 if (io_tempstringlength != 0) efree((CHAR *)io_tempstring);
151 }
152
io_readbinlibrary(LIBRARY * lib)153 BOOLEAN io_readbinlibrary(LIBRARY *lib)
154 {
155 REGISTER BOOLEAN ret;
156 REGISTER INTBIG len, filelen;
157 REGISTER LIBRARY *olib, *nextlib;
158
159 /* mark all libraries as "not being read", but "wanted" */
160 for(olib = el_curlib; olib != NOLIBRARY; olib = olib->nextlibrary)
161 {
162 olib->temp1 = 0;
163 olib->userbits &= ~UNWANTEDLIB;
164 }
165
166 /* remember the path to this first library */
167 estrcpy(io_mainlibdirectory, truepath(lib->libfile));
168 filelen = estrlen(io_mainlibdirectory);
169 len = estrlen(skippath(io_mainlibdirectory));
170 if (len < filelen)
171 {
172 io_mainlibdirectory[filelen-len-1] = 0;
173 } else
174 {
175 io_mainlibdirectory[0] = 0;
176 }
177
178
179 ret = io_doreadbinlibrary(lib, TRUE);
180 if (ret == 0 && (lib->userbits&HIDDENLIBRARY) == 0)
181 {
182 ttyputmsg(_("Read library %s on %s"), lib->libname,
183 timetostring(getcurrenttime()));
184 #ifdef ONUNIX
185 efprintf(stdout, _("Read library %s on %s\n"), lib->libname,
186 timetostring(getcurrenttime()));
187 #endif
188 }
189
190 /* delete unwanted libraries */
191 for(olib = el_curlib; olib != NOLIBRARY; olib = nextlib)
192 {
193 nextlib = olib->nextlibrary;
194 if ((olib->userbits&UNWANTEDLIB) == 0) continue;
195 killlibrary(olib);
196 }
197 return(ret);
198 }
199
io_doreadbinlibrary(LIBRARY * lib,BOOLEAN newprogress)200 BOOLEAN io_doreadbinlibrary(LIBRARY *lib, BOOLEAN newprogress)
201 {
202 REGISTER CHAR *result;
203 CHAR *filename;
204 REGISTER void *infstr;
205
206 /* find the library file */
207 result = truepath(lib->libfile);
208
209 io_binindata.filein = xopen(result, io_filetypeblib, el_libdir, &filename);
210 if (io_binindata.filein == NULL)
211 {
212 ttyputerr(_("File '%s' not found"), result);
213 return(TRUE);
214 }
215
216 /* update the library file name if the true location is different */
217 if (estrcmp(filename, lib->libfile) != 0)
218 (void)reallocstring(&lib->libfile, filename, lib->cluster);
219
220 /* prepare status dialog */
221 if (io_verbose < 0)
222 {
223 io_binindata.filelength = filesize(io_binindata.filein);
224 if (io_binindata.filelength > 0)
225 {
226 if (newprogress)
227 {
228 io_inputprogressdialog = DiaInitProgress(x_(""), _("Reading library"));
229 if (io_inputprogressdialog == 0)
230 {
231 xclose(io_binindata.filein);
232 return(TRUE);
233 }
234 }
235 DiaSetProgress(io_inputprogressdialog, 0, io_binindata.filelength);
236 infstr = initinfstr();
237 formatinfstr(infstr, _("Reading library %s"), lib->libname);
238 DiaSetCaptionProgress(io_inputprogressdialog, returninfstr(infstr));
239 DiaSetTextProgress(io_inputprogressdialog, _("Initializing..."));
240 }
241 } else io_binindata.filelength = 0;
242 io_binindata.reported = 0;
243 io_binindata.bytecount = 0;
244
245 /* assume regular format */
246 io_binindata.swap_bytes = 0;
247 io_binindata.swapped_floats = 0;
248 io_binindata.swapped_doubles = 0;
249 io_binindata.clipped_integers = 0;
250
251 /* mark that the library is being read */
252 lib->temp1 = 1;
253
254 /* now read the file */
255 result = io_doreadlibrary(lib);
256
257 /* mark that the library is not being read */
258 lib->temp1 = 0;
259
260 /* clean up */
261 xclose(io_binindata.filein);
262 if (io_verbose < 0 && io_binindata.filelength > 0 && newprogress && io_inputprogressdialog != 0)
263 {
264 DiaDoneProgress(io_inputprogressdialog);
265 io_inputprogressdialog = 0;
266 io_binindata.filelength = 0;
267 }
268 if (io_binindata.swapped_floats != 0)
269 ttyputverbose(M_("Read %ld swapped float variables; may be incorrect"),
270 io_binindata.swapped_floats);
271 if (io_binindata.swapped_doubles != 0)
272 ttyputverbose(M_("Read %ld swapped double variables; may be incorrect"),
273 io_binindata.swapped_doubles);
274 if (io_binindata.clipped_integers != 0)
275 ttyputverbose(M_("Read %ld clipped integers; may be incorrect"),
276 io_binindata.clipped_integers);
277 if (*result == 0) return(FALSE);
278 ttyputerr(_("Error reading library %s: %s"), lib->libname, result);
279 return(TRUE);
280 }
281
io_doreadlibrary(LIBRARY * lib)282 CHAR *io_doreadlibrary(LIBRARY *lib)
283 {
284 REGISTER INTBIG te;
285 REGISTER BOOLEAN imosconv, showerror;
286 REGISTER BOOLEAN *geomtype;
287 REGISTER INTBIG i, thisone, *geommoreup, top, advise, errorcode,
288 bot, look, nodeindex, arcindex, geomindex, oldunit, convertmosiscmostechnologies;
289 INTBIG num, den, j, count, cou, arcinstpos, nodeinstpos, portprotopos;
290 REGISTER CHAR *name, *sname, *thecellname;
291 REGISTER NODEPROTO *np, *onp, *lastnp, *newestversion;
292 REGISTER NODEINST *ni;
293 GEOM *geom;
294 REGISTER ARCPROTO *ap;
295 REGISTER ARCINST *ai;
296 REGISTER PORTPROTO *pp;
297 REGISTER TECHNOLOGY *tech;
298 REGISTER PORTEXPINST **portexpinstlist;
299 REGISTER PORTARCINST **portarcinstlist;
300 REGISTER TOOL *tool;
301 CHAR *version;
302 UCHAR1 chmagic[4];
303 REGISTER VIEW *v;
304 REGISTER LIBRARY *savelib, *olib;
305 REGISTER void *infstr;
306
307 errorcode = setjmp(io_binindata.filerror);
308 if (errorcode != 0)
309 {
310 if (errorcode == LONGJMPABORTED) return(_("Aborted"));
311 if (errorcode == LONGJMPEOF) return(_("Premature end of file"));
312 return(_("Unknown error"));
313 }
314
315 /* read magic number */
316 io_getin(&io_binindata.magic, 4, SIZEOFINTBIG, TRUE);
317 if (io_binindata.magic != MAGIC1 && io_binindata.magic != MAGIC2 &&
318 io_binindata.magic != MAGIC3 && io_binindata.magic != MAGIC4 &&
319 io_binindata.magic != MAGIC5 && io_binindata.magic != MAGIC6 &&
320 io_binindata.magic != MAGIC7 && io_binindata.magic != MAGIC8 &&
321 io_binindata.magic != MAGIC9 && io_binindata.magic != MAGIC10 &&
322 io_binindata.magic != MAGIC11 && io_binindata.magic != MAGIC12 &&
323 io_binindata.magic != MAGIC13)
324 {
325 /* try swapping the bytes */
326 chmagic[0] = (UCHAR1)(io_binindata.magic & 0xFF);
327 chmagic[1] = (UCHAR1)((io_binindata.magic >> 8) & 0xFF);
328 chmagic[2] = (UCHAR1)((io_binindata.magic >> 16) & 0xFF);
329 chmagic[3] = (UCHAR1)((io_binindata.magic >> 24) & 0xFF);
330 io_binindata.magic = (chmagic[0] << 24) | (chmagic[1] << 16) |
331 (chmagic[2] << 8) | chmagic[3];
332 if (io_binindata.magic != MAGIC1 && io_binindata.magic != MAGIC2 &&
333 io_binindata.magic != MAGIC3 && io_binindata.magic != MAGIC4 &&
334 io_binindata.magic != MAGIC5 && io_binindata.magic != MAGIC6 &&
335 io_binindata.magic != MAGIC7 && io_binindata.magic != MAGIC8 &&
336 io_binindata.magic != MAGIC9 && io_binindata.magic != MAGIC10 &&
337 io_binindata.magic != MAGIC11 && io_binindata.magic != MAGIC12 &&
338 io_binindata.magic != MAGIC13)
339 return(_("Bad file format")); else
340 {
341 io_binindata.swap_bytes = 1;
342 ttyputverbose(M_("File has swapped bytes in the header. Will attempt to read it."));
343 }
344 }
345 if (io_verbose > 0) switch (io_binindata.magic)
346 {
347 case MAGIC1: ttyputmsg(M_("This library is 12 versions old")); break;
348 case MAGIC2: ttyputmsg(M_("This library is 11 versions old")); break;
349 case MAGIC3: ttyputmsg(M_("This library is 10 versions old")); break;
350 case MAGIC4: ttyputmsg(M_("This library is 9 versions old")); break;
351 case MAGIC5: ttyputmsg(M_("This library is 8 versions old")); break;
352 case MAGIC6: ttyputmsg(M_("This library is 7 versions old")); break;
353 case MAGIC7: ttyputmsg(M_("This library is 6 versions old")); break;
354 case MAGIC8: ttyputmsg(M_("This library is 5 versions old")); break;
355 case MAGIC9: ttyputmsg(M_("This library is 4 versions old")); break;
356 case MAGIC10: ttyputmsg(M_("This library is 3 version old")); break;
357 case MAGIC11: ttyputmsg(M_("This library is 2 version old")); break;
358 case MAGIC12: ttyputmsg(M_("This library is 1 version old")); break;
359 }
360
361 /* determine size of "big" and "small" integers on disk */
362 if (io_binindata.magic <= MAGIC10)
363 {
364 io_getin(&io_binindata.sizeofsmall, 1, 1, FALSE);
365 io_getin(&io_binindata.sizeofbig, 1, 1, FALSE);
366 } else
367 {
368 io_binindata.sizeofsmall = 2;
369 io_binindata.sizeofbig = 4;
370 }
371 if (io_binindata.magic <= MAGIC11)
372 {
373 io_getin(&io_binindata.sizeofchar, 1, 1, FALSE);
374 } else
375 {
376 io_binindata.sizeofchar = 1;
377 }
378 if (io_binindata.sizeofsmall > SIZEOFINTSML || io_binindata.sizeofbig > SIZEOFINTBIG)
379 ttyputmsg(_("Warning: file has larger integers than memory: clipping may occur."));
380 if (io_binindata.sizeofchar > SIZEOFCHAR)
381 ttyputmsg(_("Warning: file has unicode text: not all characters are preserved."));
382
383 /* get count of objects in the file */
384 io_getinbig(&io_binindata.aacount);
385 io_getinbig(&io_binindata.techcount);
386 io_getinbig(&io_binindata.nodepprotoindex);
387 io_getinbig(&io_binindata.portpprotoindex);
388 io_getinbig(&io_binindata.arcprotoindex);
389 io_getinbig(&io_binindata.nodeprotoindex);
390 io_getinbig(&io_binindata.nodeindex);
391 io_getinbig(&io_binindata.portprotoindex);
392 io_binindata.portprotolimit = io_binindata.portprotoindex;
393 io_getinbig(&io_binindata.arcindex);
394 io_getinbig(&io_binindata.geomindex);
395 if (io_binindata.magic <= MAGIC9 && io_binindata.magic >= MAGIC11)
396 {
397 /* versions 9 through 11 stored a "cell count" */
398 io_getinbig(&io_binindata.cellindex);
399 } else
400 {
401 io_binindata.cellindex = io_binindata.nodeprotoindex;
402 }
403 io_getinbig(&io_binindata.curnodeproto);
404 if (io_verbose > 0)
405 {
406 ttyputmsg(M_("Reading %ld tools, %ld technologies"), io_binindata.aacount,
407 io_binindata.techcount);
408 ttyputmsg(M_(" %ld prim nodes, %ld prim ports, %ld arc protos"),
409 io_binindata.nodepprotoindex, io_binindata.portpprotoindex,
410 io_binindata.arcprotoindex);
411 ttyputmsg(M_(" %ld cells, %ld cells, %ld ports, %ld nodes, %ld arcs"),
412 io_binindata.cellindex, io_binindata.nodeprotoindex,
413 io_binindata.portprotoindex, io_binindata.nodeindex,
414 io_binindata.arcindex);
415 }
416
417 /* get the Electric version (version 8 and later) */
418 if (io_binindata.magic <= MAGIC8) version = io_getstring(el_tempcluster); else
419 (void)allocstring(&version, x_("3.35"), el_tempcluster);
420 parseelectricversion(version, &io_binindata.emajor, &io_binindata.eminor, &io_binindata.edetail);
421
422 /* for versions before 6.03q, convert MOSIS CMOS technology names */
423 convertmosiscmostechnologies = 0;
424 if (io_binindata.emajor < 6 ||
425 (io_binindata.emajor == 6 && io_binindata.eminor < 3) ||
426 (io_binindata.emajor == 6 && io_binindata.eminor == 3 && io_binindata.edetail < 17))
427 {
428 if ((asktech(mocmossub_tech, x_("get-state"))&MOCMOSSUBNOCONV) == 0)
429 convertmosiscmostechnologies = 1;
430 }
431
432 /* for versions before 6.04c, convert text descriptor values */
433 io_binindata.converttextdescriptors = FALSE;
434 if (io_binindata.emajor < 6 ||
435 (io_binindata.emajor == 6 && io_binindata.eminor < 4) ||
436 (io_binindata.emajor == 6 && io_binindata.eminor == 4 && io_binindata.edetail < 3))
437 {
438 io_binindata.converttextdescriptors = TRUE;
439 }
440
441 /* for versions 6.05x and later, always have text descriptor values */
442 io_binindata.alwaystextdescriptors = TRUE;
443 if (io_binindata.emajor < 6 ||
444 (io_binindata.emajor == 6 && io_binindata.eminor < 5) ||
445 (io_binindata.emajor == 6 && io_binindata.eminor == 5 && io_binindata.edetail < 24))
446 {
447 io_binindata.alwaystextdescriptors = FALSE;
448 }
449
450
451 #ifdef REPORTCONVERSION
452 ttyputmsg(x_("Library is version %s (%ld.%ld.%ld)"), version, io_binindata.emajor,
453 io_binindata.eminor, io_binindata.edetail);
454 if (convertmosiscmostechnologies != 0)
455 ttyputmsg(x_(" Converting MOSIS CMOS technologies (mocmossub => mocmos)"));
456 #endif
457
458 /* get the newly created views (version 9 and later) */
459 for(v = el_views; v != NOVIEW; v = v->nextview) v->temp1 = 0;
460 el_unknownview->temp1 = -1;
461 el_layoutview->temp1 = -2;
462 el_schematicview->temp1 = -3;
463 el_iconview->temp1 = -4;
464 el_simsnapview->temp1 = -5;
465 el_skeletonview->temp1 = -6;
466 el_vhdlview->temp1 = -7;
467 el_netlistview->temp1 = -8;
468 el_docview->temp1 = -9;
469 el_netlistnetlispview->temp1 = -10;
470 el_netlistalsview->temp1 = -11;
471 el_netlistquiscview->temp1 = -12;
472 el_netlistrsimview->temp1 = -13;
473 el_netlistsilosview->temp1 = -14;
474 el_verilogview->temp1 = -15;
475 if (io_binindata.magic <= MAGIC9)
476 {
477 io_getinbig(&j);
478 for(i=0; i<j; i++)
479 {
480 name = io_getstring(db_cluster);
481 sname = io_getstring(db_cluster);
482 v = getview(name);
483 if (v == NOVIEW)
484 {
485 v = allocview();
486 if (v == NOVIEW) return(_("No memory"));
487 v->viewname = name;
488 v->sviewname = sname;
489 if (namesamen(name, x_("Schematic-Page-"), 15) == 0)
490 v->viewstate |= MULTIPAGEVIEW;
491 v->nextview = el_views;
492 el_views = v;
493 } else
494 {
495 efree(name);
496 efree(sname);
497 }
498 v->temp1 = i + 1;
499 }
500 }
501
502 /* get the number of toolbits to ignore */
503 if (io_binindata.magic <= MAGIC3 && io_binindata.magic >= MAGIC6)
504 {
505 /* versions 3, 4, 5, and 6 find this in the file */
506 io_getinbig(&io_binindata.aabcount);
507 } else
508 {
509 /* versions 1 and 2 compute this (versions 7 and later ignore it) */
510 io_binindata.aabcount = io_binindata.aacount;
511 }
512
513 /* erase the current database */
514 if (io_verbose > 0) ttyputmsg(M_("Erasing old library"));
515 eraselibrary(lib);
516
517 /* allocate pointers */
518 io_binindata.nodelist = (NODEINST **)emalloc(((sizeof (NODEINST *)) * io_binindata.nodeindex), el_tempcluster);
519 if (io_binindata.nodelist == 0) return(_("No memory"));
520 io_binindata.nodecount = emalloc((SIZEOFINTBIG * io_binindata.nodeprotoindex), el_tempcluster);
521 if (io_binindata.nodecount == 0) return(_("No memory"));
522 io_binindata.nodeprotolist = (NODEPROTO **)emalloc(((sizeof (NODEPROTO *)) * io_binindata.nodeprotoindex), el_tempcluster);
523 if (io_binindata.nodeprotolist == 0) return(_("No memory"));
524 io_binindata.portprotolist = (PORTPROTO **)emalloc(((sizeof (PORTPROTO *)) * io_binindata.portprotoindex), el_tempcluster);
525 if (io_binindata.portprotolist == 0) return(_("No memory"));
526 io_binindata.portcount = emalloc((SIZEOFINTBIG * io_binindata.nodeprotoindex), el_tempcluster);
527 if (io_binindata.portcount == 0) return(_("No memory"));
528 io_binindata.portpprotolist = (PORTPROTO **)emalloc(((sizeof (PORTPROTO *)) * io_binindata.portpprotoindex), el_tempcluster);
529 if (io_binindata.portpprotolist == 0) return(_("No memory"));
530 io_binindata.portpprotoerror = (CHAR **)emalloc(((sizeof (CHAR *)) * io_binindata.portpprotoindex), el_tempcluster);
531 if (io_binindata.portpprotoerror == 0) return(_("No memory"));
532 portexpinstlist = (PORTEXPINST **)emalloc(((sizeof (PORTEXPINST *)) * io_binindata.portprotoindex), el_tempcluster);
533 if (portexpinstlist == 0) return(_("No memory"));
534 portarcinstlist = (PORTARCINST **)emalloc(((sizeof (PORTARCINST *)) * io_binindata.arcindex * 2), el_tempcluster);
535 if (portarcinstlist == 0) return(_("No memory"));
536 io_binindata.arclist = (ARCINST **)emalloc(((sizeof (ARCINST *)) * io_binindata.arcindex), el_tempcluster);
537 if (io_binindata.arclist == 0) return(_("No memory"));
538 io_binindata.arccount = emalloc((SIZEOFINTBIG * io_binindata.nodeprotoindex), el_tempcluster);
539 if (io_binindata.arccount == 0) return(_("No memory"));
540 io_binindata.nodepprotolist = (NODEPROTO **)emalloc(((sizeof (NODEPROTO *)) * io_binindata.nodepprotoindex), el_tempcluster);
541 if (io_binindata.nodepprotolist == 0) return(_("No memory"));
542 io_binindata.nodepprototech = emalloc((SIZEOFINTBIG * io_binindata.nodepprotoindex), el_tempcluster);
543 if (io_binindata.nodepprototech == 0) return(_("No memory"));
544 io_binindata.nodepprotoerror = (BOOLEAN *)emalloc(((sizeof (BOOLEAN)) * io_binindata.nodepprotoindex), el_tempcluster);
545 if (io_binindata.nodepprotoerror == 0) return(_("No memory"));
546 io_binindata.nodepprotoorig = (CHAR **)emalloc(((sizeof (CHAR *)) * io_binindata.nodepprotoindex), el_tempcluster);
547 if (io_binindata.nodepprotoorig == 0) return(_("No memory"));
548 io_binindata.arcprotolist = (ARCPROTO **)emalloc(((sizeof (ARCPROTO *)) * io_binindata.arcprotoindex), el_tempcluster);
549 if (io_binindata.arcprotolist == 0) return(_("No memory"));
550 io_binindata.arcprotoerror = (CHAR **)emalloc(((sizeof (CHAR *)) * io_binindata.arcprotoindex), el_tempcluster);
551 if (io_binindata.arcprotoerror == 0) return(_("No memory"));
552 io_binindata.techlist = (TECHNOLOGY **)emalloc(((sizeof (TECHNOLOGY *)) * io_binindata.techcount), el_tempcluster);
553 if (io_binindata.techlist == 0) return(_("No memory"));
554 io_binindata.techerror = (CHAR **)emalloc(((sizeof (CHAR *)) * io_binindata.techcount), el_tempcluster);
555 if (io_binindata.techerror == 0) return(_("No memory"));
556 io_binindata.toollist = emalloc((SIZEOFINTBIG * io_binindata.aacount), el_tempcluster);
557 if (io_binindata.toollist == 0) return(_("No memory"));
558 io_binindata.toolerror = (CHAR **)emalloc(((sizeof (CHAR *)) * io_binindata.aacount), el_tempcluster);
559 if (io_binindata.toolerror == 0) return(_("No memory"));
560
561 /* versions 9 to 11 allocate cell pointers */
562 if (io_binindata.magic <= MAGIC9 && io_binindata.magic >= MAGIC11)
563 {
564 io_binindata.fakecelllist = (FAKECELL **)emalloc(((sizeof (FAKECELL *)) * io_binindata.cellindex), el_tempcluster);
565 if (io_binindata.fakecelllist == 0) return(_("No memory"));
566 }
567
568 /* versions 4 and earlier allocate geometric pointers */
569 if (io_binindata.magic > MAGIC5)
570 {
571 geomtype = (BOOLEAN *)emalloc(((sizeof (BOOLEAN)) * io_binindata.geomindex), el_tempcluster);
572 if (geomtype == 0) return(_("No memory"));
573 geommoreup = emalloc((SIZEOFINTBIG * io_binindata.geomindex), el_tempcluster);
574 if (geommoreup == 0) return(_("No memory"));
575 if (geomtype == 0 || geommoreup == 0) return(_("No memory"));
576 }
577
578 /* get number of arcinsts and nodeinsts in each cell */
579 if (io_binindata.magic != MAGIC1)
580 {
581 /* versions 2 and later find this in the file */
582 nodeinstpos = arcinstpos = portprotopos = 0;
583 for(i=0; i<io_binindata.nodeprotoindex; i++)
584 {
585 io_getinbig(&io_binindata.arccount[i]);
586 io_getinbig(&io_binindata.nodecount[i]);
587 io_getinbig(&io_binindata.portcount[i]);
588 if (io_binindata.arccount[i] >= 0 || io_binindata.nodecount[i] >= 0)
589 {
590 arcinstpos += io_binindata.arccount[i];
591 nodeinstpos += io_binindata.nodecount[i];
592 }
593 portprotopos += io_binindata.portcount[i];
594 }
595
596 /* verify that the number of node instances is equal to the total in the file */
597 if (nodeinstpos != io_binindata.nodeindex)
598 {
599 ttyputerr(_("Error: cells have %ld nodes but library has %ld"),
600 nodeinstpos, io_binindata.nodeindex);
601 return(_("Bad file"));
602 }
603 if (arcinstpos != io_binindata.arcindex)
604 {
605 ttyputerr(_("Error: cells have %ld arcs but library has %ld"),
606 arcinstpos, io_binindata.arcindex);
607 return(_("Bad file"));
608 }
609 if (portprotopos != io_binindata.portprotoindex)
610 {
611 ttyputerr(_("Error: cells have %ld ports but library has %ld"),
612 portprotopos, io_binindata.portprotoindex);
613 return(_("Bad file"));
614 }
615 } else
616 {
617 /* version 1 computes this information */
618 io_binindata.arccount[0] = io_binindata.arcindex;
619 io_binindata.nodecount[0] = io_binindata.nodeindex;
620 io_binindata.portcount[0] = io_binindata.portprotoindex;
621 for(i=1; i<io_binindata.nodeprotoindex; i++)
622 io_binindata.arccount[i] = io_binindata.nodecount[i] = io_binindata.portcount[i] = 0;
623 }
624
625 /* allocate all cells in the library */
626 /* versions 9 to 11 allocate fakecells now */
627 if (io_binindata.magic <= MAGIC9 && io_binindata.magic >= MAGIC11)
628 {
629 for(i=0; i<io_binindata.cellindex; i++)
630 {
631 io_binindata.fakecelllist[i] = (FAKECELL *)emalloc(sizeof (FAKECELL), io_tool->cluster);
632 if (io_binindata.fakecelllist[i] == NOFAKECELL) return(_("No memory"));
633 }
634 }
635
636 /* allocate all cells in the library */
637 lib->numnodeprotos = 0;
638 for(i=0; i<io_binindata.nodeprotoindex; i++)
639 {
640 if (io_binindata.arccount[i] < 0 && io_binindata.nodecount[i] < 0)
641 {
642 /* this cell is from an external library */
643 io_binindata.nodeprotolist[i] = 0;
644 } else
645 {
646 io_binindata.nodeprotolist[i] = allocnodeproto(lib->cluster);
647 if (io_binindata.nodeprotolist[i] == NONODEPROTO) return(_("No memory"));
648 io_binindata.nodeprotolist[i]->cellview = el_unknownview;
649 io_binindata.nodeprotolist[i]->newestversion = io_binindata.nodeprotolist[i];
650 lib->numnodeprotos++;
651 }
652 }
653
654 /* allocate the nodes, arcs, and ports in each cell */
655 nodeinstpos = arcinstpos = portprotopos = 0;
656 for(i=0; i<io_binindata.nodeprotoindex; i++)
657 {
658 np = io_binindata.nodeprotolist[i];
659 if (np == 0)
660 {
661 /* for external references, clear the port proto list */
662 for(j=0; j<io_binindata.portcount[i]; j++)
663 io_binindata.portprotolist[portprotopos+j] = NOPORTPROTO;
664 portprotopos += io_binindata.portcount[i];
665 continue;
666 }
667
668 /* allocate node instances in this cell */
669 for(j=0; j<io_binindata.nodecount[i]; j++)
670 {
671 io_binindata.nodelist[nodeinstpos+j] = allocnodeinst(lib->cluster);
672 if (io_binindata.nodelist[nodeinstpos+j] == NONODEINST) return(_("No memory"));
673 }
674 if (io_binindata.nodecount[i] == 0) np->firstnodeinst = NONODEINST; else
675 np->firstnodeinst = io_binindata.nodelist[nodeinstpos];
676 for(j=0; j<io_binindata.nodecount[i]; j++)
677 {
678 ni = io_binindata.nodelist[j+nodeinstpos];
679 geom = allocgeom(lib->cluster);
680 if (geom == NOGEOM) return(_("No memory"));
681 ni->geom = geom;
682
683 /* compute linked list of nodes in this cell */
684 if (j == 0) ni->prevnodeinst = NONODEINST; else
685 ni->prevnodeinst = io_binindata.nodelist[j+nodeinstpos-1];
686 if (j+1 == io_binindata.nodecount[i]) ni->nextnodeinst = NONODEINST; else
687 ni->nextnodeinst = io_binindata.nodelist[j+nodeinstpos+1];
688 }
689 nodeinstpos += io_binindata.nodecount[i];
690
691 /* allocate port prototypes in this cell */
692 for(j=0; j<io_binindata.portcount[i]; j++)
693 {
694 thisone = j + portprotopos;
695 io_binindata.portprotolist[thisone] = allocportproto(lib->cluster);
696 if (io_binindata.portprotolist[thisone] == NOPORTPROTO) return(_("No memory"));
697 portexpinstlist[thisone] = allocportexpinst(lib->cluster);
698 if (portexpinstlist[thisone] == NOPORTEXPINST) return(_("No memory"));
699 io_binindata.portprotolist[thisone]->subportexpinst = portexpinstlist[thisone];
700 }
701 portprotopos += io_binindata.portcount[i];
702
703 /* allocate arc instances and port arc instances in this cell */
704 for(j=0; j<io_binindata.arccount[i]; j++)
705 {
706 io_binindata.arclist[arcinstpos+j] = allocarcinst(lib->cluster);
707 if (io_binindata.arclist[arcinstpos+j] == NOARCINST) return(_("No memory"));
708 }
709 for(j=0; j<io_binindata.arccount[i]*2; j++)
710 {
711 portarcinstlist[arcinstpos*2+j] = allocportarcinst(lib->cluster);
712 if (portarcinstlist[arcinstpos*2+j] == NOPORTARCINST) return(_("No memory"));
713 }
714 if (io_binindata.arccount[i] == 0) np->firstarcinst = NOARCINST; else
715 np->firstarcinst = io_binindata.arclist[arcinstpos];
716 for(j=0; j<io_binindata.arccount[i]; j++)
717 {
718 thisone = j + arcinstpos;
719 ai = io_binindata.arclist[thisone];
720 geom = allocgeom(lib->cluster);
721 if (geom == NOGEOM) return(_("No memory"));
722 ai->geom = geom;
723 ai->end[0].portarcinst = portarcinstlist[thisone*2];
724 ai->end[1].portarcinst = portarcinstlist[thisone*2+1];
725
726 /* compute linked list of arcs in this cell */
727 if (j == 0) ai->prevarcinst = NOARCINST; else
728 ai->prevarcinst = io_binindata.arclist[j+arcinstpos-1];
729 if (j+1 == io_binindata.arccount[i]) ai->nextarcinst = NOARCINST; else
730 ai->nextarcinst = io_binindata.arclist[j+arcinstpos+1];
731 }
732 arcinstpos += io_binindata.arccount[i];
733
734 if (io_verbose > 0)
735 ttyputmsg(M_("Allocated %ld arcs, %ld nodes, %ld ports for cell %ld"),
736 io_binindata.arccount[i], io_binindata.nodecount[i], io_binindata.portcount[i], i);
737 }
738
739 efree((CHAR *)portarcinstlist);
740 efree((CHAR *)portexpinstlist);
741
742 /* setup pointers for technologies and primitives */
743 io_binindata.nodepprotoindex = 0;
744 io_binindata.portpprotoindex = 0;
745 io_binindata.arcprotoindex = 0;
746 for(te=0; te<io_binindata.techcount; te++)
747 {
748 /* associate the technology name with the true technology */
749 name = io_gettempstring();
750 if (name == 0) return(_("No memory"));
751 tech = NOTECHNOLOGY;
752 if (convertmosiscmostechnologies != 0)
753 {
754 if (namesame(name, x_("mocmossub")) == 0) tech = gettechnology(x_("mocmos")); else
755 if (namesame(name, x_("mocmos")) == 0) tech = gettechnology(x_("mocmosold"));
756 }
757 if (tech == NOTECHNOLOGY) tech = gettechnology(name);
758
759 /* conversion code for old technologies */
760 imosconv = FALSE;
761 if (tech == NOTECHNOLOGY)
762 {
763 if (namesame(name, x_("imos")) == 0)
764 {
765 tech = gettechnology(x_("mocmos"));
766 if (tech != NOTECHNOLOGY) imosconv = TRUE;
767 } else if (namesame(name, x_("logic")) == 0) tech = sch_tech;
768 }
769
770 if (tech == NOTECHNOLOGY)
771 {
772 if (namesame(name, x_("epic8c")) == 0 || namesame(name, x_("epic7c")) == 0)
773 tech = gettechnology(x_("epic7s"));
774 }
775
776 if (tech == NOTECHNOLOGY)
777 {
778 tech = el_technologies;
779 (void)allocstring(&io_binindata.techerror[te], name, el_tempcluster);
780 } else io_binindata.techerror[te] = 0;
781 io_binindata.techlist[te] = tech;
782
783 /* get the number of primitive node prototypes */
784 io_getinbig(&count);
785 for(j=0; j<count; j++)
786 {
787 io_binindata.nodepprotoorig[io_binindata.nodepprotoindex] = 0;
788 io_binindata.nodepprotoerror[io_binindata.nodepprotoindex] = FALSE;
789 name = io_gettempstring();
790 if (name == 0) return(_("No memory"));
791 if (imosconv) name += 6;
792 for(np = tech->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
793 if (estrcmp(np->protoname, name) == 0) break;
794 if (np == NONODEPROTO)
795 {
796 /* automatic conversion of "Active-Node" in to "P-Active-Node" (MOSIS CMOS) */
797 if (estrcmp(name, x_("Active-Node")) == 0)
798 {
799 for(np = tech->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
800 if (estrcmp(np->protoname, x_("P-Active-Node")) == 0) break;
801 }
802 }
803 if (np == NONODEPROTO)
804 {
805 if (io_verbose > 0)
806 ttyputmsg(M_("No node exactly named %s in technology %s"), name, tech->techname);
807 advise = 1;
808
809 /* look for substring name match at start of name */
810 i = estrlen(name);
811 for(np = tech->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
812 if (namesamen(np->protoname, name, mini(estrlen(np->protoname), i)) == 0)
813 break;
814
815 /* look for substring match at end of name */
816 if (np == NONODEPROTO)
817 {
818 for(np = tech->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
819 {
820 thisone = estrlen(np->protoname);
821 if (i >= thisone) continue;
822 if (namesame(&np->protoname[thisone-i], name) == 0) break;
823 }
824 }
825
826 /* special cases: convert "message" and "cell-center" nodes */
827 if (np == NONODEPROTO)
828 {
829 np = io_convertoldprimitives(tech, name);
830 if (np != NONODEPROTO) advise = 0;
831 }
832
833 /* give up and use first primitive in this technology */
834 if (np == NONODEPROTO) np = tech->firstnodeproto;
835
836 /* construct the error message */
837 if (advise != 0)
838 {
839 infstr = initinfstr();
840 if (io_binindata.techerror[te] != 0) addstringtoinfstr(infstr, io_binindata.techerror[te]); else
841 addstringtoinfstr(infstr, tech->techname);
842 addtoinfstr(infstr, ':');
843 addstringtoinfstr(infstr, name);
844 (void)allocstring(&io_binindata.nodepprotoorig[io_binindata.nodepprotoindex], returninfstr(infstr), el_tempcluster);
845 io_binindata.nodepprotoerror[io_binindata.nodepprotoindex] = TRUE;
846 }
847 }
848 io_binindata.nodepprototech[io_binindata.nodepprotoindex] = te;
849 io_binindata.nodepprotolist[io_binindata.nodepprotoindex] = np;
850
851 /* get the number of primitive port prototypes */
852 io_getinbig(&cou);
853 for(i=0; i<cou; i++)
854 {
855 io_binindata.portpprotoerror[io_binindata.portpprotoindex] = 0;
856 name = io_gettempstring();
857 if (name == 0) return(_("No memory"));
858 pp = getportproto(np, name);
859
860 /* convert special port names */
861 if (pp == NOPORTPROTO)
862 pp = io_convertoldportname(name, np);
863
864 if (pp == NOPORTPROTO)
865 {
866 pp = np->firstportproto;
867 if (!io_binindata.nodepprotoerror[io_binindata.nodepprotoindex])
868 {
869 infstr = initinfstr();
870 addstringtoinfstr(infstr, name);
871 addstringtoinfstr(infstr, _(" on "));
872 if (io_binindata.nodepprotoorig[io_binindata.nodepprotoindex] != 0)
873 addstringtoinfstr(infstr, io_binindata.nodepprotoorig[io_binindata.nodepprotoindex]); else
874 {
875 if (io_binindata.techerror[te] != 0)
876 addstringtoinfstr(infstr, io_binindata.techerror[te]); else
877 addstringtoinfstr(infstr, tech->techname);
878 addtoinfstr(infstr, ':');
879 addstringtoinfstr(infstr, np->protoname);
880 }
881 (void)allocstring(&io_binindata.portpprotoerror[io_binindata.portpprotoindex],
882 returninfstr(infstr), el_tempcluster);
883 }
884 }
885 io_binindata.portpprotolist[io_binindata.portpprotoindex++] = pp;
886 }
887 io_binindata.nodepprotoindex++;
888 }
889
890 /* get the number of arc prototypes */
891 io_getinbig(&count);
892 for(j=0; j<count; j++)
893 {
894 io_binindata.arcprotoerror[io_binindata.arcprotoindex] = 0;
895 name = io_gettempstring();
896 if (name == 0) return(_("No memory"));
897 if (imosconv) name += 6;
898 for(ap = tech->firstarcproto; ap != NOARCPROTO; ap = ap->nextarcproto)
899 if (estrcmp(ap->protoname, name) == 0) break;
900 if (ap == NOARCPROTO)
901 {
902 if (tech == art_tech)
903 {
904 if (estrcmp(name, x_("Dash-1")) == 0) ap = art_dottedarc; else
905 if (estrcmp(name, x_("Dash-2")) == 0) ap = art_dashedarc; else
906 if (estrcmp(name, x_("Dash-3")) == 0) ap = art_thickerarc;
907 }
908 }
909 if (ap == NOARCPROTO)
910 {
911 ap = tech->firstarcproto;
912 infstr = initinfstr();
913 if (io_binindata.techerror[te] != 0)
914 addstringtoinfstr(infstr, io_binindata.techerror[te]); else
915 addstringtoinfstr(infstr, tech->techname);
916 addtoinfstr(infstr, ':');
917 addstringtoinfstr(infstr, name);
918 (void)allocstring(&io_binindata.arcprotoerror[io_binindata.arcprotoindex], returninfstr(infstr), el_tempcluster);
919 }
920 io_binindata.arcprotolist[io_binindata.arcprotoindex++] = ap;
921 }
922 }
923
924 /* setup pointers for tools */
925 io_binindata.toolbitsmessed = FALSE;
926 for(i=0; i<io_binindata.aacount; i++)
927 {
928 name = io_gettempstring();
929 if (name == 0) return(_("No memory"));
930 io_binindata.toolerror[i] = 0;
931 for(j=0; j<el_maxtools; j++)
932 if (estrcmp(name, el_tools[j].toolname) == 0) break;
933 if (j >= el_maxtools)
934 {
935 (void)allocstring(&io_binindata.toolerror[i], name, el_tempcluster);
936 j = -1;
937 }
938 if (i != j) io_binindata.toolbitsmessed = TRUE;
939 io_binindata.toollist[i] = j;
940 }
941 if (io_binindata.magic <= MAGIC3 && io_binindata.magic >= MAGIC6)
942 {
943 /* versions 3, 4, 5, and 6 must ignore toolbits associations */
944 for(i=0; i<io_binindata.aabcount; i++) (void)io_gettempstring();
945 }
946
947 /* get the library userbits */
948 if (io_binindata.magic <= MAGIC7)
949 {
950 /* version 7 and later simply read the relevant data */
951 io_getinubig(&lib->userbits);
952 } else
953 {
954 /* version 6 and earlier must sift through the information */
955 if (io_binindata.aabcount >= 1) io_getinubig(&lib->userbits);
956 for(i=1; i<io_binindata.aabcount; i++) io_getinubig(&j);
957 }
958 lib->userbits &= ~(LIBCHANGEDMAJOR | LIBCHANGEDMINOR);
959 lib->userbits |= READFROMDISK;
960
961 /* set the lambda values in the library */
962 for(tech = el_technologies; tech != NOTECHNOLOGY; tech = tech->nexttechnology)
963 lib->lambda[tech->techindex] = el_curlib->lambda[tech->techindex];
964 for(i=0; i<io_binindata.techcount; i++)
965 {
966 io_getinbig(&j);
967 if (io_binindata.techerror[i] != 0) continue;
968 tech = io_binindata.techlist[i];
969
970 /* for version 4 or earlier, scale lambda by 20 */
971 if (eatoi(version) <= 4) j *= 20;
972
973 /* account for any differences of internal unit in this library */
974 oldunit = ((lib->userbits & LIBUNITS) >> LIBUNITSSH) << INTERNALUNITSSH;
975 if (oldunit != (el_units&INTERNALUNITS))
976 {
977 db_getinternalunitscale(&num, &den, el_units, oldunit);
978 j = muldiv(j, den, num);
979 }
980
981 /* if this is to be the current library, adjust technologies */
982 if (lib == el_curlib)
983 changetechnologylambda(tech, j);
984 lib->lambda[tech->techindex] = j;
985 }
986
987 /* read the global namespace */
988 io_binindata.realname = 0;
989 io_binindata.newnames = 0;
990 if (io_readnamespace()) return(_("No memory"));
991
992 /* read the library variables */
993 if (io_verbose > 0) ttyputmsg(M_("Reading library variables"));
994 if (io_readvariables((INTBIG)lib, VLIBRARY) < 0) return(_("Reading library variables"));
995
996 /* read the tool variables */
997 if (io_verbose > 0) ttyputmsg(M_("Reading tool variables"));
998 for(i=0; i<io_binindata.aacount; i++)
999 {
1000 j = io_binindata.toollist[i];
1001 if (j < 0) io_ignorevariables(); else
1002 if (io_readvariables((INTBIG)&el_tools[j], VTOOL) < 0)
1003 return(_("Reading tool variables"));
1004 }
1005
1006 /* read the technology variables */
1007 if (io_verbose > 0) ttyputmsg(M_("Reading technology/primitive variables"));
1008 for(te=0; te<io_binindata.techcount; te++)
1009 {
1010 tech = io_binindata.techlist[te];
1011 j = io_readvariables((INTBIG)tech, VTECHNOLOGY);
1012 if (j < 0) return(_("Reading technology/primitive variables"));
1013 if (j > 0) (void)io_gettechlist(te);
1014 }
1015
1016 /* read the arcproto variables */
1017 for(i=0; i<io_binindata.arcprotoindex; i++)
1018 {
1019 ap = io_binindata.arcprotolist[i];
1020 j = io_readvariables((INTBIG)ap, VARCPROTO);
1021 if (j < 0) return(_("Reading arcproto variables"));
1022 if (j > 0) (void)io_getarcprotolist(i);
1023 }
1024
1025 /* read the primitive nodeproto variables */
1026 for(i=0; i<io_binindata.nodepprotoindex; i++)
1027 {
1028 np = io_binindata.nodepprotolist[i];
1029 j = io_readvariables((INTBIG)np, VNODEPROTO);
1030 if (j < 0) return(_("Reading primitive variables"));
1031 if (j > 0) (void)io_getnodepprotolist(i);
1032 }
1033
1034 /* read the primitive portproto variables */
1035 for(i=0; i<io_binindata.portpprotoindex; i++)
1036 {
1037 pp = io_binindata.portpprotolist[i];
1038 j = io_readvariables((INTBIG)pp, VPORTPROTO);
1039 if (j < 0) return(_("Reading export variables"));
1040 if (j > 0) (void)io_getportpprotolist(i);
1041 }
1042
1043 /* read the view variables (version 9 and later) */
1044 if (io_binindata.magic <= MAGIC9)
1045 {
1046 io_getinbig(&count);
1047 for(i=0; i<count; i++)
1048 {
1049 io_getinbig(&j);
1050 for(v = el_views; v != NOVIEW; v = v->nextview)
1051 if (v->temp1 == j) break;
1052 if (v == NOVIEW)
1053 {
1054 ttyputmsg(_("View index %ld not found"), j);
1055 io_ignorevariables();
1056 continue;
1057 }
1058 if (io_readvariables((INTBIG)v, VVIEW) < 0)
1059 return(_("Reading view variables"));
1060 }
1061 }
1062
1063 /* read the cells (version 9 to 11) */
1064 if (io_binindata.magic <= MAGIC9 && io_binindata.magic >= MAGIC11)
1065 {
1066 for(i=0; i<io_binindata.cellindex; i++)
1067 {
1068 thecellname = io_getstring(lib->cluster);
1069 io_ignorevariables();
1070
1071 allocstring(&io_binindata.fakecelllist[i]->cellname, thecellname, io_tool->cluster);
1072 }
1073 }
1074
1075 /* read the cells */
1076 io_binindata.portprotoindex = 0;
1077 lastnp = NONODEPROTO;
1078 lib->firstnodeproto = NONODEPROTO;
1079 for(i=0; i<io_binindata.nodeprotoindex; i++)
1080 {
1081 np = io_binindata.nodeprotolist[i];
1082 if (np == 0) continue;
1083 if (io_readnodeproto(np, lib)) return(_("Reading nodeproto"));
1084 if (lastnp == NONODEPROTO)
1085 {
1086 lib->firstnodeproto = np;
1087 np->prevnodeproto = NONODEPROTO;
1088 } else
1089 {
1090 np->prevnodeproto = lastnp;
1091 lastnp->nextnodeproto = np;
1092 }
1093 lastnp = np;
1094 np->nextnodeproto = NONODEPROTO;
1095 }
1096 lib->tailnodeproto = lastnp;
1097
1098 /* add in external cells */
1099 for(i=0; i<io_binindata.nodeprotoindex; i++)
1100 {
1101 np = io_binindata.nodeprotolist[i];
1102 if (np != 0) continue;
1103 io_readexternalnodeproto(lib, i);
1104 }
1105
1106 /* now that external cells are resolved, fix all variables that may have used them */
1107 io_fixexternalvariables(lib->firstvar, lib->numvar);
1108 for(i=0; i<io_binindata.aacount; i++)
1109 {
1110 j = io_binindata.toollist[i];
1111 if (j < 0) continue;
1112 tool = &el_tools[j];
1113 io_fixexternalvariables(tool->firstvar, tool->numvar);
1114 }
1115 for(te=0; te<io_binindata.techcount; te++)
1116 {
1117 tech = io_binindata.techlist[te];
1118 io_fixexternalvariables(tech->firstvar, tech->numvar);
1119 }
1120 for(i=0; i<io_binindata.arcprotoindex; i++)
1121 {
1122 ap = io_binindata.arcprotolist[i];
1123 io_fixexternalvariables(ap->firstvar, ap->numvar);
1124 }
1125 for(i=0; i<io_binindata.nodepprotoindex; i++)
1126 {
1127 np = io_binindata.nodepprotolist[i];
1128 io_fixexternalvariables(np->firstvar, np->numvar);
1129 }
1130 for(i=0; i<io_binindata.portpprotoindex; i++)
1131 {
1132 pp = io_binindata.portpprotolist[i];
1133 io_fixexternalvariables(pp->firstvar, pp->numvar);
1134 }
1135 for(v = el_views; v != NOVIEW; v = v->nextview)
1136 io_fixexternalvariables(v->firstvar, v->numvar);
1137 for(i=0; i<io_binindata.nodeprotoindex; i++)
1138 {
1139 np = io_binindata.nodeprotolist[i];
1140 io_fixexternalvariables(np->firstvar, np->numvar);
1141 }
1142
1143 /* convert port references in external cells */
1144 for(i=0; i<io_binindata.nodeprotoindex; i++)
1145 {
1146 np = io_binindata.nodeprotolist[i];
1147
1148 /* ignore this cell if it is in a library being read */
1149 olib = np->lib;
1150 showerror = TRUE;
1151 if (olib != lib && olib->temp1 != 0) showerror = FALSE;
1152
1153 /* convert its ports */
1154 for(pp = np->firstportproto; pp != NOPORTPROTO; pp = pp->nextportproto)
1155 {
1156 if (pp->temp2 == 0) continue;
1157 if (io_convertportproto(&pp->subportproto, showerror))
1158 {
1159 if (showerror)
1160 ttyputmsg(_(" While reading library %s, on cell %s, port %s (lib %s temp1 is %ld)"),
1161 lib->libname, describenodeproto(np), pp->protoname, np->lib->libname,
1162 np->lib->temp1);
1163 }
1164 pp->temp2 = 0;
1165 }
1166 }
1167 if (io_verbose > 0) ttyputmsg(M_("Done reading cells"));
1168
1169 /* read the cell contents: arcs and nodes */
1170 nodeindex = arcindex = geomindex = 0;
1171 for(i=0; i<io_binindata.nodeprotoindex; i++)
1172 {
1173 if (stopping(STOPREASONBINARY)) return(_("Library incomplete"));
1174 np = io_binindata.nodeprotolist[i];
1175 if (io_verbose != 0)
1176 {
1177 savelib = el_curlib; el_curlib = lib;
1178 if (io_verbose < 0 && io_binindata.filelength > 0 && io_inputprogressdialog != 0)
1179 {
1180 infstr = initinfstr();
1181 formatinfstr(infstr, _("Reading %s"), describenodeproto(np));
1182 DiaSetTextProgress(io_inputprogressdialog, returninfstr(infstr));
1183 } else ttyputmsg(_("Reading %s"), describenodeproto(np));
1184 el_curlib = savelib;
1185 }
1186 if (io_binindata.magic > MAGIC5)
1187 {
1188 /* versions 4 and earlier must read some geometric information */
1189 j = geomindex;
1190 io_readgeom(&geomtype[j], &geommoreup[j]); j++;
1191 io_readgeom(&geomtype[j], &geommoreup[j]); j++;
1192 top = j; io_readgeom(&geomtype[j], &geommoreup[j]); j++;
1193 bot = j; io_readgeom(&geomtype[j], &geommoreup[j]); j++;
1194 for(;;)
1195 {
1196 io_readgeom(&geomtype[j], &geommoreup[j]); j++;
1197 if (geommoreup[j-1] == top) break;
1198 }
1199 geomindex = j;
1200 for(look = bot; look != top; look = geommoreup[look])
1201 if (!geomtype[look])
1202 {
1203 io_binindata.arclist[arcindex]->parent = np;
1204 if (io_readarcinst(io_binindata.arclist[arcindex]))
1205 return(_("Reading arc"));
1206 arcindex++;
1207 } else
1208 {
1209 io_binindata.nodelist[nodeindex]->parent = np;
1210 if (io_readnodeinst(io_binindata.nodelist[nodeindex]))
1211 return(_("Reading node"));
1212 nodeindex++;
1213 }
1214 } else
1215 {
1216 /* version 5 and later find the arcs and nodes in linear order */
1217 for(j=0; j<io_binindata.arccount[i]; j++)
1218 {
1219 io_binindata.arclist[arcindex]->parent = np;
1220 if (io_readarcinst(io_binindata.arclist[arcindex]))
1221 return(_("Reading arc"));
1222 arcindex++;
1223 }
1224 for(j=0; j<io_binindata.nodecount[i]; j++)
1225 {
1226 io_binindata.nodelist[nodeindex]->parent = np;
1227 if (io_readnodeinst(io_binindata.nodelist[nodeindex]))
1228 return(_("Reading node"));
1229 nodeindex++;
1230 }
1231 }
1232 }
1233
1234 if (io_verbose < 0 && io_binindata.filelength > 0 && io_inputprogressdialog != 0)
1235 {
1236 DiaSetProgress(io_inputprogressdialog, 999, 1000);
1237 DiaSetTextProgress(io_inputprogressdialog, _("Cleaning up..."));
1238 }
1239
1240 /* transform indices to pointers */
1241 if (io_binindata.curnodeproto >= 0 && io_binindata.curnodeproto < io_binindata.nodeprotoindex)
1242 lib->curnodeproto = io_binindata.nodeprotolist[io_binindata.curnodeproto]; else
1243 lib->curnodeproto = NONODEPROTO;
1244
1245 /* set version pointers (this may be slow for libraries with many cells) */
1246 for(np = lib->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
1247 {
1248 newestversion = NONODEPROTO;
1249 for(onp = lib->firstnodeproto; onp != NONODEPROTO; onp = onp->nextnodeproto)
1250 {
1251 if (onp == np) continue;
1252 if (onp->cellview != np->cellview) continue;
1253 if (namesame(onp->protoname, np->protoname) != 0) continue;
1254 if (onp->version <= np->version) continue;
1255 if (newestversion != NONODEPROTO && newestversion->version >= onp->version)
1256 continue;
1257 newestversion = onp;
1258 }
1259 if (newestversion != NONODEPROTO)
1260 {
1261 /* cell "np" is an old one */
1262 np->prevversion = newestversion->prevversion;
1263 newestversion->prevversion = np;
1264 np->newestversion = newestversion;
1265 }
1266 }
1267
1268 /* create proper cell lists (version 9 to 11) */
1269 if (io_binindata.magic <= MAGIC9 && io_binindata.magic >= MAGIC11)
1270 io_buildcellgrouppointersfromnames(lib);
1271
1272 /* link up the nodes and arcs to their geometry modules */
1273 for(i=0; i<io_binindata.nodeindex; i++)
1274 {
1275 ni = io_binindata.nodelist[i];
1276 geom = ni->geom;
1277 geom->entryisnode = TRUE; geom->entryaddr.ni = ni;
1278 linkgeom(geom, ni->parent);
1279 }
1280 for(i=0; i<io_binindata.arcindex; i++)
1281 {
1282 ai = io_binindata.arclist[i];
1283 (void)setshrinkvalue(ai, FALSE);
1284 geom = ai->geom;
1285 geom->entryisnode = FALSE; geom->entryaddr.ai = ai;
1286 linkgeom(geom, ai->parent);
1287 }
1288
1289 /* create ports on cells that were not found in other libraries */
1290 io_ensureallports(lib);
1291
1292 /* store the version number in the library */
1293 nextchangequiet();
1294 (void)setval((INTBIG)lib, VLIBRARY, x_("LIB_former_version"),
1295 (INTBIG)version, VSTRING|VDONTSAVE);
1296 efree(version);
1297
1298 /* create those pointers not on the disk file */
1299 if (io_verbose < 0 && io_binindata.filelength > 0)
1300 io_fixnewlib(lib, io_inputprogressdialog); else
1301 io_fixnewlib(lib, 0);
1302
1303 /* look for any database changes that did not matter */
1304 for(te=0; te<io_binindata.techcount; te++)
1305 if (io_binindata.techerror[te] != 0)
1306 {
1307 if (io_verbose > 0)
1308 ttyputmsg(M_("Unknown technology %s not used so all is well"),
1309 io_binindata.techerror[te]);
1310 efree(io_binindata.techerror[te]);
1311 }
1312 for(i=0; i<io_binindata.aacount; i++)
1313 if (io_binindata.toolerror[i] != 0)
1314 {
1315 if (io_verbose > 0)
1316 ttyputmsg(M_("Unknown tool %s not used so all is well"),
1317 io_binindata.toolerror[i]);
1318 efree(io_binindata.toolerror[i]);
1319 }
1320 for(i=0; i<io_binindata.nodepprotoindex; i++)
1321 if (io_binindata.nodepprotoorig[i] != 0)
1322 {
1323 if (io_verbose > 0 && io_binindata.nodepprotoerror[i])
1324 ttyputmsg(M_("Unknown node %s not used so all is well"),
1325 io_binindata.nodepprotoorig[i]);
1326 efree(io_binindata.nodepprotoorig[i]);
1327 }
1328 for(i=0; i<io_binindata.portpprotoindex; i++)
1329 if (io_binindata.portpprotoerror[i] != 0)
1330 {
1331 if (io_verbose > 0) ttyputmsg(M_("Unknown port %s not used so all is well"),
1332 io_binindata.portpprotoerror[i]);
1333 efree(io_binindata.portpprotoerror[i]);
1334 }
1335 for(i=0; i<io_binindata.arcprotoindex; i++)
1336 if (io_binindata.arcprotoerror[i] != 0)
1337 {
1338 if (io_verbose > 0) ttyputmsg(M_("Unknown arc %s not used so all is well"),
1339 io_binindata.arcprotoerror[i]);
1340 efree(io_binindata.arcprotoerror[i]);
1341 }
1342
1343 /* warn if the MOSIS CMOS technologies were converted */
1344 if (convertmosiscmostechnologies != 0)
1345 {
1346 for(np = lib->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
1347 {
1348 for(ni = np->firstnodeinst; ni != NONODEINST; ni = ni->nextnodeinst)
1349 if (ni->proto->primindex != 0 && ni->proto->tech == mocmos_tech) break;
1350 if (ni != NONODEINST) break;
1351 for(ai = np->firstarcinst; ai != NOARCINST; ai = ai->nextarcinst)
1352 if (ai->proto->tech == mocmos_tech) break;
1353 if (ai != NOARCINST) break;
1354 }
1355 if (np != NONODEPROTO)
1356 DiaMessageInDialog(
1357 _("Warning: library %s has older 'mocmossub' technology, converted to new 'mocmos'"),
1358 lib->libname);
1359 }
1360
1361 /* free the memory used here */
1362 if (io_binindata.realname != 0)
1363 {
1364 for(i=0; i<io_binindata.namecount; i++) efree(io_binindata.realname[i]);
1365 efree((CHAR *)io_binindata.realname);
1366 }
1367 if (io_binindata.newnames != 0) efree((CHAR *)io_binindata.newnames);
1368 if (io_binindata.magic > MAGIC5)
1369 {
1370 /* versions 4 and earlier used geometric data */
1371 efree((CHAR *)geomtype);
1372 efree((CHAR *)geommoreup);
1373 }
1374 efree((CHAR *)io_binindata.nodelist);
1375 efree((CHAR *)io_binindata.nodecount);
1376 efree((CHAR *)io_binindata.nodeprotolist);
1377 efree((CHAR *)io_binindata.arclist);
1378 efree((CHAR *)io_binindata.arccount);
1379 efree((CHAR *)io_binindata.nodepprotolist);
1380 efree((CHAR *)io_binindata.nodepprototech);
1381 efree((CHAR *)io_binindata.portprotolist);
1382 efree((CHAR *)io_binindata.portcount);
1383 efree((CHAR *)io_binindata.portpprotolist);
1384 efree((CHAR *)io_binindata.arcprotolist);
1385 efree((CHAR *)io_binindata.techlist);
1386 efree((CHAR *)io_binindata.toollist);
1387 efree((CHAR *)io_binindata.techerror);
1388 efree((CHAR *)io_binindata.toolerror);
1389 efree((CHAR *)io_binindata.nodepprotoerror);
1390 efree((CHAR *)io_binindata.nodepprotoorig);
1391 efree((CHAR *)io_binindata.portpprotoerror);
1392 efree((CHAR *)io_binindata.arcprotoerror);
1393 if (io_binindata.magic <= MAGIC9 && io_binindata.magic >= MAGIC11)
1394 efree((CHAR *)io_binindata.fakecelllist);
1395
1396 return(x_(""));
1397 }
1398
1399 /******************** COMPONENT INPUT ********************/
1400
1401 /* routine to read node prototype. returns true upon error */
io_readnodeproto(NODEPROTO * np,LIBRARY * lib)1402 BOOLEAN io_readnodeproto(NODEPROTO *np, LIBRARY *lib)
1403 {
1404 INTBIG i, portcount, k;
1405 REGISTER INTBIG j;
1406 REGISTER CHAR *cellname;
1407 REGISTER PORTPROTO *pp, *lpt;
1408 REGISTER VIEW *v;
1409
1410 /* read the cell information (version 9 and later) */
1411 if (io_binindata.magic <= MAGIC9)
1412 {
1413 if (io_binindata.magic >= MAGIC11)
1414 {
1415 /* only versions 9 to 11 */
1416 io_getinbig(&k);
1417 allocstring(&np->protoname, io_binindata.fakecelllist[k]->cellname, lib->cluster);
1418 } else
1419 {
1420 /* version 12 or later */
1421 np->protoname = io_getstring(db_cluster);
1422 io_getinbig(&k);
1423 np->nextcellgrp = io_binindata.nodeprotolist[k];
1424 io_getinbig(&k);
1425 // np->nextcont = io_binindata.nodeprotolist[k];
1426 }
1427 io_getinbig(&np->cellview);
1428 for(v = el_views; v != NOVIEW; v = v->nextview)
1429 if (v->temp1 == (INTBIG)np->cellview) break;
1430 if (v == NOVIEW) v = el_unknownview;
1431 np->cellview = v;
1432 io_getinbig(&i);
1433 np->version = i;
1434 io_getinubig(&np->creationdate);
1435 io_getinubig(&np->revisiondate);
1436
1437 /* copy cell information to the nodeproto */
1438 np->lib = lib;
1439 }
1440
1441 /* versions 8 and earlier read a cell name */
1442 if (io_binindata.magic >= MAGIC8)
1443 {
1444 cellname = io_getstring(lib->cluster);
1445 if (cellname == 0) return(TRUE);
1446 if (io_verbose > 0) ttyputmsg(_("Reading cell %s"), cellname);
1447
1448 /* copy cell information to the nodeproto */
1449 np->lib = lib;
1450 np->protoname = cellname;
1451 }
1452
1453 /* set the nodeproto primitive index */
1454 np->primindex = 0;
1455
1456 /* read the nodeproto bounding box */
1457 io_getinbig(&np->lowx);
1458 io_getinbig(&np->highx);
1459 io_getinbig(&np->lowy);
1460 io_getinbig(&np->highy);
1461
1462 /* reset the first nodeinst index */
1463 np->firstinst = NONODEINST;
1464
1465 /* zap the technology field */
1466 np->tech = NOTECHNOLOGY;
1467
1468 /* read the library list of nodeproto indices (versions 5 or older) */
1469 if (io_binindata.magic >= MAGIC5)
1470 {
1471 io_getinbig(&np->prevnodeproto);
1472 if (io_convertnodeproto(&np->prevnodeproto, 0) != 0)
1473 ttyputmsg(_("...while reading cell %s"), np->protoname);
1474 io_getinbig(&np->nextnodeproto);
1475 if (io_convertnodeproto(&np->nextnodeproto, 0) != 0)
1476 ttyputmsg(_("...while reading cell %s"), np->protoname);
1477 }
1478
1479 /* read the number of portprotos on this nodeproto */
1480 io_getinbig(&portcount);
1481 np->numportprotos = portcount;
1482
1483 /* read the portprotos on this nodeproto */
1484 lpt = NOPORTPROTO;
1485 for(j=0; j<portcount; j++)
1486 {
1487 /* set pointers to portproto */
1488 pp = io_binindata.portprotolist[io_binindata.portprotoindex++];
1489 if (lpt == NOPORTPROTO) np->firstportproto = pp; else
1490 lpt->nextportproto = pp;
1491 lpt = pp;
1492
1493 /* set the parent pointer */
1494 pp->parent = np;
1495
1496 /* read the connecting subnodeinst for this portproto */
1497 io_getinbig(&i);
1498 if (i >= 0 && i < io_binindata.nodeindex)
1499 pp->subnodeinst = io_binindata.nodelist[i]; else
1500 {
1501 ttyputerr(_("Warning: corrupt data on port. Do a 'Check and Repair Library'"));
1502 pp->subnodeinst = NONODEINST;
1503 }
1504
1505 /* read the sub-port prototype of the subnodeinst */
1506 io_getinbig(&i);
1507 pp->subportproto = (PORTPROTO *)i;
1508 if (i >= 0 && io_binindata.portprotolist[i] == NOPORTPROTO)
1509 {
1510 pp->temp2 = 1;
1511 } else
1512 {
1513 (void)io_convertportproto(&pp->subportproto, TRUE);
1514 pp->temp2 = 0;
1515 }
1516
1517 /* read the portproto name and text descriptor */
1518 pp->protoname = io_getstring(lib->cluster);
1519 if (pp->protoname == 0) return(TRUE);
1520 if (io_binindata.magic <= MAGIC9)
1521 {
1522 if (io_binindata.converttextdescriptors)
1523 {
1524 /* conversion is done later */
1525 io_getinubig(&pp->textdescript[0]);
1526 pp->textdescript[1] = 0;
1527 } else
1528 {
1529 io_getinubig(&pp->textdescript[0]);
1530 io_getinubig(&pp->textdescript[1]);
1531 }
1532 }
1533
1534 /* ignore the "seen" bits (versions 8 and older) */
1535 if (io_binindata.magic > MAGIC9) io_getinubig(&k);
1536
1537 /* read the portproto tool information */
1538 if (io_binindata.magic <= MAGIC7)
1539 {
1540 /* version 7 and later simply read the relevant data */
1541 io_getinubig(&pp->userbits);
1542
1543 /* versions 7 and 8 ignore net number */
1544 if (io_binindata.magic >= MAGIC8) io_getinbig(&k);
1545 } else
1546 {
1547 /* version 6 and earlier must sift through the information */
1548 if (io_binindata.aabcount >= 1) io_getinubig(&pp->userbits);
1549 for(i=1; i<io_binindata.aabcount; i++) io_getinubig(&k);
1550 }
1551
1552 /* read variable information */
1553 if (io_readvariables((INTBIG)pp, VPORTPROTO) < 0) return(TRUE);
1554 }
1555
1556 /* set final pointer in portproto list */
1557 if (lpt == NOPORTPROTO) np->firstportproto = NOPORTPROTO; else
1558 lpt->nextportproto = NOPORTPROTO;
1559
1560 /* read the cell's geometry modules */
1561 if (io_binindata.magic > MAGIC5)
1562 {
1563 /* versions 4 and older have geometry module pointers (ignore it) */
1564 io_getinbig(&i);
1565 io_getinbig(&i);
1566 io_getinbig(&i);
1567 io_getinbig(&i);
1568 io_getinbig(&i);
1569 }
1570
1571 /* read tool information */
1572 io_getinubig(&np->adirty);
1573 np->adirty = io_arrangetoolbits((INTBIG)np->adirty);
1574 if (io_binindata.magic <= MAGIC7)
1575 {
1576 /* version 7 and later simply read the relevant data */
1577 io_getinubig(&np->userbits);
1578
1579 /* versions 7 and 8 ignore net number */
1580 if (io_binindata.magic >= MAGIC8) io_getinbig(&k);
1581 } else
1582 {
1583 /* version 6 and earlier must sift through the information */
1584 if (io_binindata.aabcount >= 1) io_getinubig(&np->userbits);
1585 for(i=1; i<io_binindata.aabcount; i++) io_getinubig(&k);
1586 }
1587 /* build the dummy geometric structure for this cell */
1588 if (geomstructure(np)) return(TRUE);
1589
1590 /* read variable information */
1591 if (io_readvariables((INTBIG)np, VNODEPROTO) < 0) return(TRUE);
1592 return(FALSE);
1593 }
1594
1595 /* routine to read node prototype for external references */
io_readexternalnodeproto(LIBRARY * lib,INTBIG i)1596 void io_readexternalnodeproto(LIBRARY *lib, INTBIG i)
1597 {
1598 INTBIG portcount, k, vers, lowx, highx, lowy, highy, len, filelen, filetype;
1599 UINTBIG creation, revision;
1600 REGISTER INTBIG j, newcell, index;
1601 REGISTER LIBRARY *elib;
1602 REGISTER BOOLEAN failed;
1603 REGISTER CHAR *protoname, *libname, *pt;
1604 CHAR *filename, *libfile, *oldline2, *libfilepath, *libfilename,
1605 *dummycellname, **localportnames, *cellname;
1606 FILE *io;
1607 REGISTER PORTPROTO *pp, *lpt;
1608 REGISTER NODEPROTO *np, *onp, *npdummy;
1609 REGISTER NODEINST *ni;
1610 REGISTER VIEW *v;
1611 REGISTER FAKECELL *fc;
1612 BININPUTDATA savebinindata;
1613 REGISTER void *infstr;
1614
1615 /* read the cell information */
1616 if (io_binindata.magic >= MAGIC11)
1617 {
1618 /* version 11 and earlier */
1619 io_getinbig(&k);
1620 fc = io_binindata.fakecelllist[k];
1621 cellname = fc->cellname;
1622 } else
1623 {
1624 cellname = io_getstring(db_cluster);
1625 io_getinbig(&k);
1626 io_getinbig(&k);
1627 }
1628 io_getinbig(&k);
1629 for(v = el_views; v != NOVIEW; v = v->nextview)
1630 if (v->temp1 == k) break;
1631 if (v == NOVIEW) v = el_unknownview;
1632 io_getinbig(&vers);
1633 io_getinubig(&creation);
1634 io_getinubig(&revision);
1635
1636 /* read the nodeproto bounding box */
1637 io_getinbig(&lowx);
1638 io_getinbig(&highx);
1639 io_getinbig(&lowy);
1640 io_getinbig(&highy);
1641
1642 /* get the path to the library file */
1643 libfile = io_getstring(el_tempcluster);
1644 filelen = estrlen(libfile);
1645
1646 /* see if this library is already read in */
1647 infstr = initinfstr();
1648 addstringtoinfstr(infstr, skippath(libfile));
1649 libname = returninfstr(infstr);
1650 len = estrlen(libname);
1651 if (len < filelen)
1652 {
1653 libfilename = &libfile[filelen-len-1];
1654 *libfilename++ = 0;
1655 libfilepath = libfile;
1656 } else
1657 {
1658 libfilename = libfile;
1659 libfilepath = x_("");
1660 }
1661
1662 filetype = io_filetypeblib;
1663 if (len > 5 && namesame(&libname[len-5], x_(".elib")) == 0)
1664 {
1665 libname[len-5] = 0;
1666 } else if (len > 4 && namesame(&libname[len-4], x_(".txt")) == 0)
1667 {
1668 libname[len-4] = 0;
1669 filetype = io_filetypetlib;
1670 }
1671 elib = getlibrary(libname);
1672 if (elib == NOLIBRARY)
1673 {
1674 /* library does not exist: see if file is there */
1675 io = xopen(libfilename, filetype, io_mainlibdirectory, &filename);
1676 if (io == 0)
1677 {
1678 /* try the path specified in the reference */
1679 io = xopen(libfilename, filetype, truepath(libfilepath), &filename);
1680 if (io == 0)
1681 {
1682 /* try the library area */
1683 io = xopen(libfilename, filetype, el_libdir, &filename);
1684 }
1685 }
1686 if (io != 0)
1687 {
1688 xclose(io);
1689 ttyputmsg(_("Reading referenced library %s on %s"), filename,
1690 timetostring(getcurrenttime()));
1691 #ifdef ONUNIX
1692 efprintf(stdout, _("Reading referenced library %s on %s\n"), filename,
1693 timetostring(getcurrenttime()));
1694 #endif
1695 } else
1696 {
1697 infstr = initinfstr();
1698 formatinfstr(infstr, _("Reference library '%s'"), libname);
1699 pt = fileselect(returninfstr(infstr), filetype, x_(""));
1700 if (pt != 0) filename = pt;
1701 }
1702 elib = newlibrary(libname, filename);
1703 if (elib == NOLIBRARY) { efree(libfile); return; }
1704
1705 /* read the external library */
1706 savebinindata = io_binindata;
1707 if (io_verbose < 0 && io_binindata.filelength > 0 && io_inputprogressdialog != 0)
1708 {
1709 (void)allocstring(&oldline2, DiaGetTextProgress(io_inputprogressdialog), el_tempcluster);
1710 }
1711
1712 len = estrlen(elib->libfile);
1713 io_libinputrecursivedepth++;
1714 io_libinputreadmany++;
1715 if (len > 4 && namesame(&elib->libfile[len-4], x_(".txt")) == 0)
1716 {
1717 /* ends in ".txt", presume text file */
1718 failed = io_doreadtextlibrary(elib, FALSE);
1719 } else
1720 {
1721 /* all other endings: presume binary file */
1722 failed = io_doreadbinlibrary(elib, FALSE);
1723 }
1724 io_libinputrecursivedepth--;
1725 if (failed) elib->userbits |= UNWANTEDLIB; else
1726 {
1727 /* queue this library for announcement through change control */
1728 io_queuereadlibraryannouncement(elib);
1729 }
1730 io_binindata = savebinindata;
1731 if (io_verbose < 0 && io_binindata.filelength > 0 && io_inputprogressdialog != 0)
1732 {
1733 DiaSetProgress(io_inputprogressdialog, io_binindata.bytecount, io_binindata.filelength);
1734 infstr = initinfstr();
1735 formatinfstr(infstr, _("Reading library %s"), lib->libname);
1736 DiaSetCaptionProgress(io_inputprogressdialog, returninfstr(infstr));
1737 DiaSetTextProgress(io_inputprogressdialog, oldline2);
1738 efree(oldline2);
1739 }
1740 }
1741
1742 /* read the portproto names on this nodeproto */
1743 io_getinbig(&portcount);
1744 if (portcount > 0)
1745 localportnames = (CHAR **)emalloc(portcount * (sizeof (CHAR *)), el_tempcluster);
1746 for(j=0; j<portcount; j++)
1747 {
1748 /* read the portproto name */
1749 protoname = io_gettempstring();
1750 if (protoname == 0) break;
1751 (void)allocstring(&localportnames[j], protoname, el_tempcluster);
1752 }
1753
1754 /* find this cell in the external library */
1755 npdummy = NONODEPROTO;
1756 for(index=0; ; index++)
1757 {
1758 infstr = initinfstr();
1759 formatinfstr(infstr, _("%sFROM%s"), cellname, elib->libname);
1760 if (index > 0) formatinfstr(infstr, x_(".%ld"), index);
1761 (void)allocstring(&dummycellname, returninfstr(infstr), el_tempcluster);
1762 for(np = lib->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
1763 if (namesame(np->protoname, dummycellname) == 0) break;
1764 if (np == NONODEPROTO) break;
1765 efree((CHAR *)dummycellname);
1766 }
1767 for(np = elib->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
1768 {
1769 if (np->lib != elib)
1770 {
1771 ttyputerr(_("ERROR: Bad cell in library %s"), elib->libname);
1772 continue;
1773 }
1774 if (np->cellview != v) continue;
1775 if (namesame(np->protoname, dummycellname) == 0) npdummy = np;
1776 if (np->version != vers) continue;
1777 if (namesame(np->protoname, cellname) != 0) continue;
1778 break;
1779 }
1780 if (np == NONODEPROTO) np = npdummy;
1781 if (np == NONODEPROTO)
1782 {
1783 /* cell not found in library: issue warning */
1784 infstr = initinfstr();
1785 addstringtoinfstr(infstr, cellname);
1786 if (v != el_unknownview)
1787 formatinfstr(infstr, x_("{%s}"), v->sviewname);
1788 ttyputerr(_("Cannot find cell %s in library %s"),
1789 returninfstr(infstr), elib->libname);
1790 }
1791
1792 /* if cell found, check that size is unchanged */
1793 if (np != NONODEPROTO)
1794 {
1795 #if 0
1796 if (np->lowx != lowx || np->highx != highx ||
1797 np->lowy != lowy || np->highy != highy)
1798 #else
1799 if (np->highx-np->lowx != highx-lowx ||
1800 np->highy-np->lowy != highy-lowy)
1801 #endif
1802 {
1803 ttyputerr(_("Error: cell %s in library %s has changed size since its use in library %s"),
1804 nldescribenodeproto(np), elib->libname, lib->libname);
1805 ttyputerr(_(" Cell %s in library %s is now %sx%s but the instance in library %s is %sx%s"),
1806 nldescribenodeproto(np), elib->libname, latoa(np->highx-np->lowx,0),
1807 latoa(np->highy-np->lowy,0), lib->libname, latoa(highx-lowx,0), latoa(highy-lowy,0));
1808 np = NONODEPROTO;
1809 }
1810 }
1811
1812 /* if cell found, check that ports match */
1813 if (np != NONODEPROTO)
1814 {
1815 for(pp = np->firstportproto; pp != NOPORTPROTO; pp = pp->nextportproto)
1816 pp->temp1 = 0;
1817 for(j=0; j<portcount; j++)
1818 {
1819 protoname = localportnames[j];
1820 for(pp = np->firstportproto; pp != NOPORTPROTO; pp = pp->nextportproto)
1821 if (namesame(protoname, pp->protoname) == 0) break;
1822 if (pp == NOPORTPROTO)
1823 {
1824 ttyputerr(_("Error: cell %s in library %s must have port %s"),
1825 describenodeproto(np), elib->libname, protoname);
1826 np = NONODEPROTO;
1827 break;
1828 }
1829 pp->temp1 = 1;
1830 }
1831 }
1832 #if 0
1833 if (np != NONODEPROTO)
1834 {
1835 for(pp = np->firstportproto; pp != NOPORTPROTO; pp = pp->nextportproto)
1836 {
1837 if (pp->temp1 != 0) continue;
1838 ttyputerr(_("Error: cell %s in library %s, should not have port %s"),
1839 describenodeproto(np), elib->libname, pp->protoname);
1840 np = NONODEPROTO;
1841 break;
1842 }
1843 }
1844 #endif
1845
1846 /* if cell found, warn if minor modification was made */
1847 if (np != NONODEPROTO)
1848 {
1849 if (np->revisiondate != revision)
1850 {
1851 ttyputerr(_("Warning: cell %s in library %s has changed since its use in library %s"),
1852 describenodeproto(np), elib->libname, lib->libname);
1853 }
1854 }
1855
1856 /* make new cell if needed */
1857 if (np != NONODEPROTO) newcell = 0; else
1858 {
1859 /* create a cell that meets these specs */
1860 newcell = 1;
1861 ttyputerr(_("...Creating dummy version of cell in library %s"), lib->libname);
1862 np = allocnodeproto(lib->cluster);
1863 if (np == NONODEPROTO) return;
1864 np->primindex = 0;
1865 np->lowx = lowx;
1866 np->highx = highx;
1867 np->lowy = lowy;
1868 np->highy = highy;
1869 np->firstinst = NONODEINST;
1870 np->firstnodeinst = NONODEINST;
1871 np->firstarcinst = NOARCINST;
1872 np->tech = NOTECHNOLOGY;
1873 np->lib = lib;
1874 np->firstportproto = NOPORTPROTO;
1875 np->adirty = 0;
1876 np->cellview = v;
1877 np->creationdate = creation;
1878 np->revisiondate = revision;
1879 setval((INTBIG)np, VNODEPROTO, x_("IO_true_library"), (INTBIG)elib->libname, VSTRING);
1880
1881 /* rename cell */
1882 (void)allocstring(&np->protoname, dummycellname, lib->cluster);
1883
1884 /* determine version number of this cell */
1885 np->version = 1;
1886 FOR_CELLGROUP(onp, np)
1887 {
1888 if (onp->cellview == v && namesame(onp->protoname, np->protoname) == 0 &&
1889 onp->version >= np->version)
1890 np->version = onp->version + 1;
1891 }
1892
1893 /* insert in the library and cell structures */
1894 if (i != 0) /* why not always? */
1895 {
1896 /* NEW CELL-based CODE */
1897 db_insertnodeproto(np);
1898 }
1899
1900 /* create initial R-tree data */
1901 if (geomstructure(np)) return;
1902
1903 /* create an artwork "Crossed box" to define the cell size */
1904 ni = allocnodeinst(lib->cluster);
1905 ni->proto = art_crossedboxprim;
1906 ni->parent = np;
1907 ni->nextnodeinst = np->firstnodeinst;
1908 np->firstnodeinst = ni;
1909 ni->lowx = lowx; ni->highx = highx;
1910 ni->lowy = lowy; ni->highy = highy;
1911 ni->geom = allocgeom(lib->cluster);
1912 ni->geom->entryisnode = TRUE; ni->geom->entryaddr.ni = ni;
1913 linkgeom(ni->geom, np);
1914 }
1915 io_binindata.nodeprotolist[i] = np;
1916 efree(dummycellname);
1917
1918 /* read the portprotos on this nodeproto */
1919 lpt = NOPORTPROTO;
1920 for(j=0; j<portcount; j++)
1921 {
1922 /* read the portproto name */
1923 protoname = localportnames[j];
1924 pp = getportproto(np, protoname);
1925 if (pp == NOPORTPROTO)
1926 {
1927 if (newcell == 0)
1928 ttyputerr(_("Cannot find port %s on cell %s in library %s"),
1929 protoname, describenodeproto(np), elib->libname);
1930 pp = allocportproto(lib->cluster);
1931 (void)allocstring(&pp->protoname, protoname, lib->cluster);
1932 pp->parent = np;
1933 if (lpt == NOPORTPROTO) np->firstportproto = pp; else
1934 lpt->nextportproto = pp;
1935 lpt = pp;
1936 pp->temp2 = 0;
1937 }
1938 io_binindata.portprotolist[io_binindata.portprotoindex] = pp;
1939 io_binindata.portprotoindex++;
1940 }
1941
1942 /* free memory */
1943 for(j=0; j<portcount; j++)
1944 efree(localportnames[j]);
1945 if (portcount > 0) efree((CHAR *)localportnames);
1946 efree(libfile);
1947 }
1948
1949 /* routine to read a node instance. returns true upon error */
io_readnodeinst(NODEINST * ni)1950 BOOLEAN io_readnodeinst(NODEINST *ni)
1951 {
1952 INTBIG i, k;
1953 REGISTER INTBIG j, arcindex;
1954 CHAR *inst;
1955 REGISTER PORTARCINST *pi, *lpo;
1956 REGISTER PORTEXPINST *pe, *lpe;
1957 PORTPROTO *pp;
1958 REGISTER ARCINST *ai;
1959 static INTBIG orignodenamekey = 0;
1960
1961 /* read the nodeproto index */
1962 io_getinbig(&ni->proto);
1963 if (io_convertnodeproto(&ni->proto, &inst) != 0)
1964 ttyputmsg(_("...while reading node instance"));
1965 if (inst != 0)
1966 {
1967 if (orignodenamekey == 0) orignodenamekey = makekey(x_("NODE_original_name"));
1968 nextchangequiet();
1969 (void)setvalkey((INTBIG)ni, VNODEINST, orignodenamekey, (INTBIG)inst, VSTRING|VDONTSAVE);
1970 }
1971
1972 /* read the descriptive information */
1973 io_getinbig(&ni->lowx);
1974 io_getinbig(&ni->lowy);
1975 io_getinbig(&ni->highx);
1976 io_getinbig(&ni->highy);
1977
1978 /* ignore anchor point for cell references (version 13 and later) */
1979 if (io_binindata.magic <= MAGIC13)
1980 {
1981 if (ni->proto->primindex == 0)
1982 {
1983 io_getinbig(&i);
1984 io_getinbig(&i);
1985 }
1986 }
1987
1988 /* read rotation and transposition */
1989 io_getinbig(&i);
1990 io_getinbig(&k);
1991 ni->rotation = (INTSML)k;
1992
1993 /* in 7.01 and higher, allow mirror bits */
1994 if (io_binindata.emajor > 7 || (io_binindata.emajor == 7 && io_binindata.eminor >= 1))
1995 {
1996 /* new version: allow mirror bits */
1997 ni->transpose = 0;
1998 if ((i&1) != 0)
1999 {
2000 /* the old-style transpose bit */
2001 ni->transpose = 1;
2002 } else
2003 {
2004 /* check for new style mirror bits */
2005 if ((i&2) != 0)
2006 {
2007 if ((i&4) != 0)
2008 {
2009 /* mirror in X and Y */
2010 ni->rotation = (ni->rotation + 1800) % 3600;
2011 } else
2012 {
2013 /* mirror in X */
2014 ni->rotation = (ni->rotation + 900) % 3600;
2015 ni->transpose = 1;
2016 }
2017 } else if ((i&4) != 0)
2018 {
2019 /* mirror in Y */
2020 ni->rotation = (ni->rotation + 2700) % 3600;
2021 ni->transpose = 1;
2022 }
2023 }
2024 } else
2025 {
2026 /* old version: just treat it as a transpose */
2027 if (i != 0) ni->transpose = 1; else
2028 ni->transpose = 0;
2029 }
2030
2031 /* versions 9 and later get text descriptor for cell name */
2032 if (io_binindata.magic <= MAGIC9)
2033 {
2034 if (io_binindata.converttextdescriptors)
2035 {
2036 /* conversion is done later */
2037 io_getinubig(&ni->textdescript[0]);
2038 ni->textdescript[1] = 0;
2039 } else
2040 {
2041 io_getinubig(&ni->textdescript[0]);
2042 io_getinubig(&ni->textdescript[1]);
2043 }
2044 }
2045
2046 /* read the nodeinst name (versions 1, 2, or 3 only) */
2047 if (io_binindata.magic >= MAGIC3)
2048 {
2049 inst = io_getstring(el_tempcluster);
2050 if (inst == 0) return(TRUE);
2051 if (*inst != 0)
2052 {
2053 nextchangequiet();
2054 if (setvalkey((INTBIG)ni, VNODEINST, el_node_name_key,
2055 (INTBIG)inst, VSTRING|VDISPLAY) == NOVARIABLE) return(TRUE);
2056 }
2057 efree(inst);
2058 }
2059
2060 /* ignore the geometry index (versions 4 or older) */
2061 if (io_binindata.magic > MAGIC5) io_getinbig(&i);
2062
2063 /* read the arc ports */
2064 io_getinbig(&i);
2065 lpo = NOPORTARCINST;
2066 for(j=0; j<i; j++)
2067 {
2068 /* read the arcinst information (and the particular end on the arc) */
2069 io_getinbig(&k);
2070 arcindex = k >> 1;
2071 if (k < 0 || arcindex >= io_binindata.arcindex) return(TRUE);
2072 ai = io_binindata.arclist[arcindex];
2073 pi = ai->end[k&1].portarcinst;
2074 pi->conarcinst = ai;
2075
2076 /* link in the portarcinst */
2077 if (j == 0) ni->firstportarcinst = pi; else lpo->nextportarcinst = pi;
2078 lpo = pi;
2079
2080 /* read the arcinst index */
2081 io_getinbig(&pi->proto);
2082 (void)io_convertportproto(&pi->proto, TRUE);
2083
2084 /* read variable information */
2085 if (io_readvariables((INTBIG)pi, VPORTARCINST) < 0) return(TRUE);
2086 }
2087
2088 /* setup the last portinst pointer */
2089 if (i == 0) ni->firstportarcinst = NOPORTARCINST; else
2090 lpo->nextportarcinst = NOPORTARCINST;
2091
2092 /* read the exports */
2093 io_getinbig(&i);
2094 lpe = NOPORTEXPINST;
2095 for(j=0; j<i; j++)
2096 {
2097 /* read the export index */
2098 io_getinbig(&pp);
2099 (void)io_convertportproto(&pp, TRUE);
2100 pe = pp->subportexpinst;
2101 pe->exportproto = pp;
2102
2103 if (j == 0) ni->firstportexpinst = pe; else lpe->nextportexpinst = pe;
2104 lpe = pe;
2105
2106 /* read the export prototype */
2107 io_getinbig(&pe->proto);
2108 (void)io_convertportproto(&pe->proto, TRUE);
2109 pp->subportproto = pe->proto;
2110
2111 /* read variable information */
2112 if (io_readvariables((INTBIG)pe, VPORTEXPINST) < 0) return(TRUE);
2113 }
2114
2115 /* setup the last portinst pointer */
2116 if (i == 0) ni->firstportexpinst = NOPORTEXPINST; else
2117 lpe->nextportexpinst = NOPORTEXPINST;
2118
2119 /* ignore the "seen" bits (versions 8 and older) */
2120 if (io_binindata.magic > MAGIC9) io_getinubig(&k);
2121
2122 /* read the tool information */
2123 if (io_binindata.magic <= MAGIC7)
2124 {
2125 /* version 7 and later simply read the relevant data */
2126 io_getinubig(&ni->userbits);
2127 } else
2128 {
2129 /* version 6 and earlier must sift through the information */
2130 if (io_binindata.aabcount >= 1) io_getinubig(&ni->userbits);
2131 for(i=1; i<io_binindata.aabcount; i++) io_getinubig(&k);
2132 }
2133
2134 /* read variable information */
2135 if (io_readvariables((INTBIG)ni, VNODEINST) < 0) return(TRUE);
2136
2137 return(FALSE);
2138 }
2139
2140 /* routine to read (and mostly ignore) a geometry module */
io_readgeom(BOOLEAN * isnode,INTBIG * moreup)2141 void io_readgeom(BOOLEAN *isnode, INTBIG *moreup)
2142 {
2143 INTBIG i, type;
2144
2145 io_getinbig(&type); /* read entrytype */
2146 if (type != 0) *isnode = TRUE; else
2147 *isnode = FALSE;
2148 if (*isnode) io_getinbig(&i);/* skip entryaddr */
2149 io_getinbig(&i); /* skip lowx */
2150 io_getinbig(&i); /* skip highx */
2151 io_getinbig(&i); /* skip lowy */
2152 io_getinbig(&i); /* skip highy */
2153 io_getinbig(&i); /* skip moreleft */
2154 io_getinbig(&i); /* skip ll */
2155 io_getinbig(&i); /* skip moreright */
2156 io_getinbig(&i); /* skip lr */
2157 io_getinbig(moreup); /* read moreup */
2158 io_getinbig(&i); /* skip lu */
2159 io_getinbig(&i); /* skip moredown */
2160 io_getinbig(&i); /* skip ld */
2161 io_ignorevariables(); /* skip variables */
2162 }
2163
io_readarcinst(ARCINST * ai)2164 BOOLEAN io_readarcinst(ARCINST *ai)
2165 {
2166 INTBIG i, j, index;
2167 REGISTER CHAR *inst;
2168
2169 /* read the arcproto pointer */
2170 io_getinbig(&ai->proto);
2171 io_convertarcproto(&ai->proto);
2172
2173 /* read the arc length (versions 5 or older) */
2174 if (io_binindata.magic >= MAGIC5) io_getinbig(&ai->length);
2175
2176 /* read the arc width */
2177 io_getinbig(&ai->width);
2178
2179 /* ignore the signals value (versions 6, 7, or 8) */
2180 if (io_binindata.magic <= MAGIC6 && io_binindata.magic >= MAGIC8)
2181 io_getinbig(&i);
2182
2183 /* read the arcinst name (versions 3 or older) */
2184 if (io_binindata.magic >= MAGIC3)
2185 {
2186 inst = io_getstring(el_tempcluster);
2187 if (inst == 0) return(TRUE);
2188 if (*inst != 0)
2189 {
2190 nextchangequiet();
2191 if (setvalkey((INTBIG)ai, VARCINST, el_arc_name_key,
2192 (INTBIG)inst, VSTRING|VDISPLAY) == NOVARIABLE) return(TRUE);
2193 }
2194 efree(inst);
2195 }
2196
2197 /* read the arcinst end information */
2198 for(i=0; i<2; i++)
2199 {
2200 io_getinbig(&ai->end[i].xpos);
2201 io_getinbig(&ai->end[i].ypos);
2202
2203 /* read the arcinst's connecting nodeinst index */
2204 io_getinbig(&ai->end[i].nodeinst);
2205 index = (INTBIG)ai->end[i].nodeinst;
2206 if (index >= 0 && index < io_binindata.nodeindex)
2207 ai->end[i].nodeinst = io_binindata.nodelist[index]; else
2208 {
2209 ttyputerr(_("Warning: corrupt data on arc. Do a 'Check and Repair Library'"));
2210 ai->end[i].nodeinst = NONODEINST;
2211 }
2212 }
2213
2214 /* compute the arc length (versions 6 or newer) */
2215 if (io_binindata.magic <= MAGIC6) ai->length = computedistance(ai->end[0].xpos,
2216 ai->end[0].ypos, ai->end[1].xpos, ai->end[1].ypos);
2217
2218 /* ignore the geometry index (versions 4 or older) */
2219 if (io_binindata.magic > MAGIC5) io_getinbig(&i);
2220
2221 /* ignore the "seen" bits (versions 8 and older) */
2222 if (io_binindata.magic > MAGIC9) io_getinubig(&i);
2223
2224 /* read the arcinst's tool information */
2225 if (io_binindata.magic <= MAGIC7)
2226 {
2227 /* version 7 and later simply read the relevant data */
2228 io_getinubig(&ai->userbits);
2229
2230 /* versions 7 and 8 ignore net number */
2231 if (io_binindata.magic >= MAGIC8) io_getinbig(&j);
2232 } else
2233 {
2234 /* version 6 and earlier must sift through the information */
2235 if (io_binindata.aabcount >= 1) io_getinubig(&ai->userbits);
2236 for(i=1; i<io_binindata.aabcount; i++) io_getinubig(&j);
2237 }
2238
2239 /* read variable information */
2240 if (io_readvariables((INTBIG)ai, VARCINST) < 0) return(TRUE);
2241 return(FALSE);
2242 }
2243
2244 /******************** VARIABLE ROUTINES ********************/
2245
2246 /* routine to read the global namespace. returns true upon error */
io_readnamespace(void)2247 BOOLEAN io_readnamespace(void)
2248 {
2249 REGISTER INTBIG i;
2250
2251 io_getinbig(&io_binindata.namecount);
2252 if (io_verbose > 0) ttyputmsg(M_("Reading %ld variable names"), io_binindata.namecount);
2253 if (io_binindata.namecount == 0) return(FALSE);
2254
2255 /* read in the namespace */
2256 io_binindata.newnames = (INTBIG *)emalloc((SIZEOFINTBIG * io_binindata.namecount), el_tempcluster);
2257 if (io_binindata.newnames == 0) return(TRUE);
2258 io_binindata.realname = (CHAR **)emalloc(((sizeof (CHAR *)) * io_binindata.namecount), el_tempcluster);
2259 if (io_binindata.realname == 0) return(TRUE);
2260 for(i=0; i<io_binindata.namecount; i++)
2261 {
2262 io_binindata.realname[i] = io_getstring(el_tempcluster);
2263 if (io_binindata.realname[i] == 0) return(TRUE);
2264 io_binindata.newnames[i] = 0;
2265 }
2266 return(FALSE);
2267 }
2268
2269 /*
2270 * routine to ignore one set of object variables on readin
2271 */
io_ignorevariables(void)2272 void io_ignorevariables(void)
2273 {
2274 NODEINST node;
2275
2276 initdummynode(&node);
2277 (void)io_readvariables((INTBIG)&node, VNODEINST);
2278
2279 /* this next line is not strictly legal!!! */
2280 if (node.numvar != 0) db_freevars(&node.firstvar, &node.numvar);
2281 }
2282
2283 /*
2284 * routine to read a set of object variables. returns negative upon error and
2285 * otherwise returns the number of variables read
2286 */
io_readvariables(INTBIG addr,INTBIG type)2287 INTBIG io_readvariables(INTBIG addr, INTBIG type)
2288 {
2289 REGISTER INTBIG i, j, datasize, ty, keyval;
2290 REGISTER INTBIG ret;
2291 REGISTER VARIABLE *var;
2292 REGISTER BOOLEAN invalid;
2293 INTBIG count, newtype, len, newaddr, cou, defineddescript;
2294 UINTBIG newdescript[TEXTDESCRIPTSIZE];
2295 INTSML key;
2296
2297 io_getinbig(&count);
2298 if (io_verbose > 0 && count > 0)
2299 ttyputmsg(M_("Reading %ld variables on %s object"),
2300 count, describeobject(addr, type));
2301 for(i=0; i<count; i++)
2302 {
2303 io_getin(&key, io_binindata.sizeofsmall, SIZEOFINTSML, FALSE);
2304 io_getinbig(&newtype);
2305 ty = newtype;
2306 if (io_verbose > 0 && (type == VTOOL || type == VTECHNOLOGY))
2307 ttyputmsg(M_(" Reading variable %ld: %s (type=0%o)"), i, io_binindata.realname[key], ty);
2308
2309 /* version 9 and later reads text description on displayable variables */
2310 defineddescript = 0;
2311 if (io_binindata.magic <= MAGIC9)
2312 {
2313 if (io_binindata.alwaystextdescriptors)
2314 {
2315 io_getinubig(&newdescript[0]);
2316 io_getinubig(&newdescript[1]);
2317 defineddescript = 1;
2318 } else
2319 {
2320 if ((ty&VDISPLAY) != 0)
2321 {
2322 if (io_binindata.converttextdescriptors)
2323 {
2324 /* conversion is done later */
2325 io_getinubig(&newdescript[0]);
2326 newdescript[1] = 0;
2327 } else
2328 {
2329 io_getinubig(&newdescript[0]);
2330 io_getinubig(&newdescript[1]);
2331 }
2332 defineddescript = 1;
2333 }
2334 }
2335 }
2336 if (defineddescript == 0)
2337 {
2338 TDCLEAR(newdescript);
2339 defaulttextdescript(newdescript, NOGEOM);
2340 }
2341 if ((ty&VISARRAY) != 0)
2342 {
2343 io_getinbig(&len);
2344 cou = len;
2345 if ((ty&VLENGTH) == 0) cou++;
2346 if ((ty&VTYPE) == VCHAR) datasize = SIZEOFCHAR; else
2347 if ((ty&VTYPE) == VDOUBLE) datasize = SIZEOFINTBIG*2; else
2348 if ((ty&VTYPE) == VSHORT) datasize = 2; else
2349 datasize = SIZEOFINTBIG;
2350 newaddr = (INTBIG)emalloc((cou*datasize), el_tempcluster);
2351 if (newaddr == 0) return(-1);
2352 if ((ty&VTYPE) == VGENERAL)
2353 {
2354 for(j=0; j<len; j += 2)
2355 {
2356 io_getinbig((INTBIG *)(newaddr + (j+1)*datasize));
2357 ret = io_getinvar((INTBIG *)(newaddr + j*datasize),
2358 *(INTBIG *)(newaddr + (j+1)*datasize));
2359 if (ret < 0) return(-1);
2360 if (ret > 0)
2361 {
2362 ttyputmsg(_("...while reading variable '%s' on %s object"),
2363 io_binindata.realname[key], us_variabletypename(type));
2364 }
2365 }
2366 } else
2367 {
2368 for(j=0; j<len; j++)
2369 {
2370 ret = io_getinvar((INTBIG *)(newaddr + j*datasize), ty);
2371 if (ret < 0) return(-1);
2372 if (ret > 0)
2373 {
2374 ttyputmsg(_("...while reading variable '%s' on %s object"),
2375 io_binindata.realname[key], us_variabletypename(type));
2376 }
2377 }
2378 }
2379 if ((ty&VLENGTH) == 0)
2380 for(j=0; j<datasize; j++)
2381 ((CHAR *)newaddr)[len*datasize+j] = -1;
2382 } else
2383 {
2384 if ((newtype&VTYPE) == VDOUBLE) newtype = (newtype & ~VTYPE) | VFLOAT;
2385 ret = io_getinvar(&newaddr, ty);
2386 if (ret < 0) return(-1);
2387 if (ret > 0)
2388 {
2389 ttyputmsg(_("...while reading variable '%s' on %s object"),
2390 io_binindata.realname[key], us_variabletypename(type));
2391 }
2392 }
2393
2394 /* copy this variable into database */
2395 if (key < 0 || key >= io_binindata.namecount)
2396 {
2397 ttyputmsg(_("Bad variable index (%ld, limit is %ld) on %s object"),
2398 key, io_binindata.namecount, describeobject(addr, type));
2399 return(-1);
2400 }
2401
2402 /* see if the variable is deprecated */
2403 invalid = isdeprecatedvariable(addr, type, io_binindata.realname[key]);
2404 if (!invalid)
2405 {
2406 if (io_binindata.newnames[key] == 0)
2407 io_binindata.newnames[key] = makekey(io_binindata.realname[key]);
2408 keyval = io_binindata.newnames[key];
2409 nextchangequiet();
2410
2411 var = setvalkey(addr, type, keyval, newaddr, newtype);
2412 if (var == NOVARIABLE) return(-1);
2413 TDCOPY(var->textdescript, newdescript);
2414
2415 /* handle updating of technology caches */
2416 if (type == VTECHNOLOGY)
2417 changedtechnologyvariable(keyval);
2418 }
2419
2420 /* free the memory allocated for the creation of this variable */
2421 if ((ty&VTYPE) == VSTRING || (ty&(VCODE1|VCODE2)) != 0)
2422 {
2423 if ((ty&VISARRAY) == 0) efree((CHAR *)newaddr); else
2424 for(j=0; j<len; j++) efree((CHAR *)((INTBIG *)newaddr)[j]);
2425 }
2426 if ((ty&VISARRAY) != 0) efree((CHAR *)newaddr);
2427 }
2428 return(count);
2429 }
2430
2431 /*
2432 * Helper routine to read a variable at address "addr" of type "ty".
2433 * Returns zero if OK, negative on memory error, positive if there were
2434 * correctable problems in the read.
2435 */
io_getinvar(INTBIG * addr,INTBIG ty)2436 INTBIG io_getinvar(INTBIG *addr, INTBIG ty)
2437 {
2438 INTBIG i;
2439 REGISTER CHAR *pp;
2440 REGISTER ARCINST *ai;
2441 PORTPROTO *ppr;
2442 double doub;
2443
2444 if ((ty&(VCODE1|VCODE2)) != 0) ty = VSTRING;
2445 switch (ty&VTYPE)
2446 {
2447 case VADDRESS:
2448 case VINTEGER:
2449 case VFRACT:
2450 io_getinbig(addr);
2451 if ((ty&VTYPE) == VFLOAT)
2452 {
2453 if (io_binindata.swap_bytes != 0) io_binindata.swapped_floats++;
2454 }
2455 break;
2456 case VFLOAT:
2457 io_getin(addr, sizeof(float), sizeof(float), FALSE);
2458 if (io_binindata.swap_bytes != 0) io_binindata.swapped_doubles++;
2459 break;
2460 case VDOUBLE:
2461 io_getin(&doub, sizeof(double), sizeof(double), FALSE);
2462 *addr = castint((float)doub);
2463 if (io_binindata.swap_bytes != 0) io_binindata.swapped_doubles++;
2464 break;
2465 case VSHORT:
2466 io_getin(addr, io_binindata.sizeofsmall, SIZEOFINTSML, TRUE);
2467 break;
2468 case VBOOLEAN:
2469 case VCHAR:
2470 io_getin(addr, 1, 1, FALSE);
2471 break;
2472 case VSTRING:
2473 pp = io_getstring(el_tempcluster);
2474 if (pp == 0) return(-1);
2475 *addr = (INTBIG)pp;
2476 break;
2477 case VNODEINST:
2478 io_getinbig(addr);
2479 if (*addr < 0 || *addr >= io_binindata.nodeindex) *addr = -1; else
2480 *addr = (INTBIG)io_binindata.nodelist[*addr];
2481 break;
2482 case VNODEPROTO:
2483 io_getinbig(addr);
2484 if (io_convertnodeproto((NODEPROTO **)addr, 0) != 0) return(1);
2485 break;
2486 case VARCPROTO:
2487 io_getinbig(addr);
2488 io_convertarcproto((ARCPROTO **)addr);
2489 break;
2490 case VPORTPROTO:
2491 io_getinbig(addr);
2492 (void)io_convertportproto((PORTPROTO **)addr, TRUE);
2493 break;
2494 case VARCINST:
2495 io_getinbig(addr);
2496 if (*addr < 0 || *addr >= io_binindata.arcindex) *addr = -1; else
2497 *addr = (INTBIG)io_binindata.arclist[*addr];
2498 break;
2499 case VGEOM:
2500 *addr = -1;
2501 io_getinbig(&i);
2502 if (io_binindata.magic <= MAGIC5)
2503 {
2504 /* versions 5 and later store extra information */
2505 if (i != 0)
2506 {
2507 io_getinbig(addr);
2508 if (*addr < 0 || *addr >= io_binindata.nodeindex) *addr = -1;
2509 else *addr = (INTBIG)io_binindata.nodelist[*addr]->geom;
2510 } else
2511 {
2512 io_getinbig(addr);
2513 if (*addr < 0 || *addr >= io_binindata.arcindex) *addr = -1;
2514 else *addr = (INTBIG)io_binindata.arclist[*addr]->geom;
2515 }
2516 }
2517 break;
2518 case VTECHNOLOGY:
2519 io_getinbig(addr);
2520 if (*addr != -1) *addr = (INTBIG)io_gettechlist(*addr);
2521 break;
2522 case VPORTARCINST:
2523 io_getinbig(addr);
2524 if (*addr != -1)
2525 {
2526 ai = io_binindata.arclist[(*addr) >> 1];
2527 i = (*addr) & 1;
2528 *addr = (INTBIG)ai->end[i].portarcinst;
2529 }
2530 break;
2531 case VPORTEXPINST:
2532 io_getinbig(addr);
2533 if (*addr != -1)
2534 {
2535 ppr = (PORTPROTO *)*addr;
2536 (void)io_convertportproto(&ppr, TRUE);
2537 *addr = (INTBIG)ppr->subportexpinst;
2538 }
2539 break;
2540 case VLIBRARY:
2541 pp = io_getstring(el_tempcluster);
2542 if (pp == 0) return(-1);
2543 *addr = (INTBIG)getlibrary(pp);
2544 break;
2545 case VTOOL:
2546 io_getinbig(addr);
2547 if (*addr < 0 || *addr >= io_binindata.aacount) *addr = -1; else
2548 {
2549 i = io_binindata.toollist[*addr];
2550 if (i < 0 || i >= el_maxtools)
2551 {
2552 i = 0;
2553 if (io_binindata.toolerror[*addr] != 0)
2554 {
2555 ttyputerr(_("WARNING: no tool called '%s', using 'user'"),
2556 io_binindata.toolerror[*addr]);
2557 efree(io_binindata.toolerror[*addr]);
2558 io_binindata.toolerror[*addr] = 0;
2559 }
2560 }
2561 *addr = (INTBIG)&el_tools[i];
2562 }
2563 break;
2564 case VRTNODE:
2565 *addr = -1;
2566 break;
2567 }
2568 return(0);
2569 }
2570
2571 /*
2572 * routine to fix variables that make reference to external cells.
2573 */
io_fixexternalvariables(VARIABLE * firstvar,INTSML numvar)2574 void io_fixexternalvariables(VARIABLE *firstvar, INTSML numvar)
2575 {
2576 REGISTER INTBIG i;
2577 REGISTER INTBIG j, k, type, len;
2578 REGISTER VARIABLE *var;
2579 REGISTER NODEPROTO *np, **nparray;
2580
2581 for(i=0; i<numvar; i++)
2582 {
2583 var = &firstvar[i];
2584 type = var->type;
2585 if ((type&VDONTSAVE) != 0) continue;
2586 if ((type&VTYPE) != VNODEPROTO) continue;
2587 if ((type&VISARRAY) != 0)
2588 {
2589 len = (type&VLENGTH) >> VLENGTHSH;
2590 nparray = (NODEPROTO **)var->addr;
2591 if (len == 0) for(len=0; nparray[len] != NONODEPROTO; len++) ;
2592 for(j=0; j<len; j++)
2593 {
2594 np = nparray[j];
2595 if ((INTBIG)np >= 0 && (INTBIG)np < io_binindata.nodeprotoindex)
2596 {
2597 k = (INTBIG)np;
2598 nparray[j] = io_binindata.nodeprotolist[k];
2599 }
2600 }
2601 } else
2602 {
2603 np = (NODEPROTO *)var->addr;
2604 if ((INTBIG)np >= 0 && (INTBIG)np < io_binindata.nodeprotoindex)
2605 {
2606 k = (INTBIG)np;
2607 var->addr = (INTBIG)io_binindata.nodeprotolist[k];
2608 }
2609 }
2610 }
2611 }
2612
2613 /******************** INPUT HELPER ROUTINES ********************/
2614
2615 /*
2616 * routine to return the proper tool bits word given the arrangement
2617 * of tools. These words have one bit per tool according to
2618 * the tool's position which may get re-arranged.
2619 */
io_arrangetoolbits(INTBIG val)2620 INTBIG io_arrangetoolbits(INTBIG val)
2621 {
2622 REGISTER INTBIG out, i, j;
2623
2624 /* if the bits are not re-arranged, result is simple */
2625 if (!io_binindata.toolbitsmessed) return(val);
2626
2627 /* re-arrange the bits in the word */
2628 out = 0;
2629 for(i=0; i<io_binindata.aacount; i++)
2630 {
2631 j = io_binindata.toollist[i];
2632 if (j < 0) continue;
2633 if ((val & (1 << i)) != 0) out |= 1 << j;
2634 }
2635 return(out);
2636 }
2637
2638 /*
2639 * routine to convert the nodeproto index at "np" to a true nodeproto pointer.
2640 * Sets "origname" to a string with the original name of this prototype (if there were
2641 * conversion problems in the file). Sets "origname" to zero if the pointer is fine.
2642 */
io_convertnodeproto(NODEPROTO ** np,CHAR ** origname)2643 INTBIG io_convertnodeproto(NODEPROTO **np, CHAR **origname)
2644 {
2645 REGISTER INTBIG i, nindex, error;
2646
2647 if (*np == NONODEPROTO) return(0);
2648 i = (INTBIG)*np;
2649 if (origname != 0) *origname = 0;
2650 error = 0;
2651 if (i < 0)
2652 {
2653 nindex = -i - 2;
2654 if (nindex >= io_binindata.nodepprotoindex)
2655 {
2656 ttyputerr(_("Error: want primitive node index %ld when limit is %ld"),
2657 nindex, io_binindata.nodepprotoindex);
2658 nindex = 0;
2659 error = 1;
2660 }
2661 *np = io_getnodepprotolist(nindex);
2662 if (origname != 0) *origname = io_binindata.nodepprotoorig[nindex];
2663 } else
2664 {
2665 if (i >= io_binindata.nodeprotoindex)
2666 {
2667 ttyputerr(_("Error: want cell index %ld when limit is %ld"),
2668 i, io_binindata.nodeprotoindex);
2669 *np = io_getnodepprotolist(0);
2670 error = 1;
2671 } else
2672 {
2673 *np = io_binindata.nodeprotolist[i];
2674 if (*np == 0)
2675 {
2676 /* reference to cell in another library: unresolved now */
2677 *np = (NODEPROTO *)i;
2678 }
2679 }
2680 }
2681 return(error);
2682 }
2683
io_convertportproto(PORTPROTO ** pp,BOOLEAN showerror)2684 BOOLEAN io_convertportproto(PORTPROTO **pp, BOOLEAN showerror)
2685 {
2686 REGISTER INTBIG i, pindex;
2687 REGISTER BOOLEAN err;
2688
2689 if (*pp == NOPORTPROTO) return(FALSE);
2690 i = (INTBIG)*pp;
2691 err = FALSE;
2692 if (i < 0)
2693 {
2694 pindex = -i - 2;
2695 if (pindex >= io_binindata.portpprotoindex)
2696 {
2697 if (showerror)
2698 ttyputerr(_("Error: want primitive port index %ld when limit is %ld"),
2699 pindex, io_binindata.portpprotoindex);
2700 pindex = 0;
2701 err = TRUE;
2702 }
2703 *pp = io_getportpprotolist(pindex);
2704 } else
2705 {
2706 if (i >= io_binindata.portprotolimit)
2707 {
2708 if (showerror)
2709 ttyputerr(_("Error: want port index %ld when limit is %ld"),
2710 i, io_binindata.portprotolimit);
2711 i = 0;
2712 err = TRUE;
2713 }
2714 *pp = io_binindata.portprotolist[i];
2715 }
2716 return(err);
2717 }
2718
io_convertarcproto(ARCPROTO ** ap)2719 void io_convertarcproto(ARCPROTO **ap)
2720 {
2721 REGISTER INTBIG i, aindex;
2722
2723 if (*ap == NOARCPROTO) return;
2724 i = (INTBIG)*ap;
2725 aindex = -i - 2;
2726 if (aindex >= io_binindata.arcprotoindex || aindex < 0)
2727 {
2728 ttyputerr(_("Want primitive arc index %ld when range is 0 to %ld"),
2729 aindex, io_binindata.arcprotoindex);
2730 aindex = 0;
2731 }
2732 *ap = io_getarcprotolist(aindex);
2733 }
2734
2735 /*
2736 * Routine to ensure that all ports in library "lib" are valid. Invalid ports are
2737 * caused when references to cells outside of this library cannot be found. When
2738 * that happens, dummy cells are generated with invalid ports. At this point, the
2739 * ports can be defined by examining their usage.
2740 */
io_ensureallports(LIBRARY * lib)2741 void io_ensureallports(LIBRARY *lib)
2742 {
2743 REGISTER NODEPROTO *np, *onp, *pin;
2744 REGISTER PORTPROTO *pp;
2745 REGISTER NODEINST *ni;
2746 REGISTER ARCINST *ai;
2747 REGISTER ARCPROTO *ap;
2748 ARCPROTO *onlyarc;
2749 REGISTER TECHNOLOGY *tech;
2750 REGISTER PORTARCINST *pi;
2751 REGISTER PORTEXPINST *pe;
2752 REGISTER INTBIG thisend;
2753 INTBIG lx, hx, ly, hy, x, y;
2754 BOOLEAN first;
2755 XARRAY rot, trn, trans;
2756
2757 /* look at every port in the library */
2758 for(np = lib->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
2759 {
2760 for(pp = np->firstportproto; pp != NOPORTPROTO; pp = pp->nextportproto)
2761 {
2762 if (pp->subnodeinst != NONODEINST) continue;
2763
2764 /* undefined port: figure out what connects to it */
2765 for(tech = el_technologies; tech != NOTECHNOLOGY; tech = tech->nexttechnology)
2766 for(ap = tech->firstarcproto; ap != NOARCPROTO; ap = ap->nextarcproto)
2767 ap->temp1 = 0;
2768 first = TRUE;
2769 onlyarc = NOARCPROTO;
2770 for(onp = lib->firstnodeproto; onp != NONODEPROTO; onp = onp->nextnodeproto)
2771 {
2772 for(ni = onp->firstnodeinst; ni != NONODEINST; ni = ni->nextnodeinst)
2773 {
2774 if (ni->proto != np) continue;
2775 makerotI(ni, rot);
2776 maketransI(ni, trn);
2777 transmult(rot, trn, trans);
2778
2779 /* found an instance of the external cell */
2780 for(pi = ni->firstportarcinst; pi != NOPORTARCINST; pi = pi->nextportarcinst)
2781 {
2782 if (pi->proto != pp) continue;
2783 ai = pi->conarcinst;
2784 if (!first && ai->proto != onlyarc) onlyarc = NOARCPROTO;
2785 if (first) onlyarc = ai->proto;
2786 ai->proto->temp1 = 1;
2787 if (ai->end[0].portarcinst == pi) thisend = 0; else thisend = 1;
2788 x = ai->end[thisend].xpos;
2789 y = ai->end[thisend].ypos;
2790 xform(x, y, &x, &y, trans);
2791 if (first)
2792 {
2793 lx = hx = x;
2794 ly = hy = y;
2795 first = FALSE;
2796 } else
2797 {
2798 if (x < lx) lx = x;
2799 if (x > hx) hx = x;
2800 if (y < ly) ly = y;
2801 if (y > hy) hy = y;
2802 }
2803 }
2804 for(pe = ni->firstportexpinst; pe != NOPORTEXPINST; pe = pe->nextportexpinst)
2805 {
2806 if (pe->proto != pp) continue;
2807 io_binfindallports(lib, pe->exportproto, &lx, &hx, &ly, &hy, &first,
2808 &onlyarc, trans);
2809 }
2810 }
2811 }
2812
2813 if (first)
2814 {
2815 /* nothing found to tell where the port should go: put it in the middle */
2816 lx = hx = (np->lowx + np->highx) / 2;
2817 ly = hy = (np->lowy + np->highy) / 2;
2818 }
2819
2820 /* found where the port should go: create it */
2821 if (onlyarc == NOARCPROTO) pin = gen_univpinprim; else
2822 pin = getpinproto(onlyarc);
2823 lx = hx = (lx + hx) / 2;
2824 ly = hy = (ly + hy) / 2;
2825
2826 ni = allocnodeinst(lib->cluster);
2827 ni->proto = pin;
2828 ni->parent = np;
2829 ni->nextnodeinst = np->firstnodeinst;
2830 np->firstnodeinst = ni;
2831 ni->lowx = lx; ni->highx = hx;
2832 ni->lowy = ly; ni->highy = hy;
2833 ni->geom = allocgeom(lib->cluster);
2834 ni->geom->entryisnode = TRUE; ni->geom->entryaddr.ni = ni;
2835 linkgeom(ni->geom, np);
2836
2837 pe = allocportexpinst(lib->cluster);
2838 pe->exportproto = pp;
2839 pe->proto = ni->proto->firstportproto;
2840 ni->firstportexpinst = pe;
2841 pp->subnodeinst = ni;
2842 pp->subportexpinst = pe;
2843 pp->connects = pe->proto->connects;
2844 pp->subportproto = pe->proto;
2845 pp->userbits = pe->proto->userbits;
2846 TDCLEAR(pp->textdescript);
2847 defaulttextsize(1, pp->textdescript);
2848 defaulttextdescript(pp->textdescript, NOGEOM);
2849 }
2850 }
2851 }
2852
2853 /*
2854 * Helper routine for "io_ensureallports" to find all exports in library "lib" attached
2855 * to port "pp" and gather the bounding box of all arc connections in "lx", "hx", "ly", and
2856 * "hy". Sets "first" to false once a wire is found, and sets "onlyarc" to the type of arc
2857 * found. Uses "prevtrans" as the transformation matrix to this point.
2858 */
io_binfindallports(LIBRARY * lib,PORTPROTO * pp,INTBIG * lx,INTBIG * hx,INTBIG * ly,INTBIG * hy,BOOLEAN * first,ARCPROTO ** onlyarc,XARRAY prevtrans)2859 void io_binfindallports(LIBRARY *lib, PORTPROTO *pp, INTBIG *lx, INTBIG *hx, INTBIG *ly, INTBIG *hy,
2860 BOOLEAN *first, ARCPROTO **onlyarc, XARRAY prevtrans)
2861 {
2862 REGISTER NODEINST *ni;
2863 REGISTER NODEPROTO *np;
2864 REGISTER PORTARCINST *pi;
2865 REGISTER PORTEXPINST *pe;
2866 REGISTER ARCINST *ai;
2867 REGISTER INTBIG thisend;
2868 INTBIG x, y;
2869 XARRAY rot, trn, thistran, trans;
2870
2871 /* look at all nodes that use the instance with this port */
2872 for(np = lib->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
2873 {
2874 for(ni = np->firstnodeinst; ni != NONODEINST; ni = ni->nextnodeinst)
2875 {
2876 if (ni->proto != pp->parent) continue;
2877
2878 /* find an arc at this port */
2879 makerotI(ni, rot);
2880 maketransI(ni, trn);
2881 transmult(rot, trn, thistran);
2882 transmult(thistran, prevtrans, trans);
2883 for(pi = ni->firstportarcinst; pi != NOPORTARCINST; pi = pi->nextportarcinst)
2884 {
2885 if (pi->proto != pp) continue;
2886 ai = pi->conarcinst;
2887 if (!(*first) && ai->proto != *onlyarc) *onlyarc = NOARCPROTO;
2888 if (*first) *onlyarc = ai->proto;
2889 ai->proto->temp1 = 1;
2890 if (ai->end[0].portarcinst == pi) thisend = 0; else thisend = 1;
2891 x = ai->end[thisend].xpos;
2892 y = ai->end[thisend].ypos;
2893 xform(x, y, &x, &y, trans);
2894 if (*first)
2895 {
2896 *lx = *hx = x;
2897 *ly = *hy = y;
2898 *first = FALSE;
2899 } else
2900 {
2901 if (x < *lx) *lx = x;
2902 if (x > *hx) *hx = x;
2903 if (y < *ly) *ly = y;
2904 if (y > *hy) *hy = y;
2905 }
2906 }
2907 for(pe = ni->firstportexpinst; pe != NOPORTEXPINST; pe = pe->nextportexpinst)
2908 {
2909 if (pe->proto != pp) continue;
2910 io_binfindallports(lib, pe->exportproto, lx, hx, ly, hy, first,
2911 onlyarc, trans);
2912 }
2913 }
2914 }
2915 }
2916
2917 /******************** DATA ACCESS ROUTINES ********************/
2918
io_getarcprotolist(INTBIG i)2919 ARCPROTO *io_getarcprotolist(INTBIG i)
2920 {
2921 REGISTER ARCPROTO *ap;
2922 REGISTER CHAR *name;
2923 REGISTER void *infstr;
2924
2925 if (io_binindata.arcprotoerror[i] != 0)
2926 {
2927 ap = NOARCPROTO;
2928 while (ap == NOARCPROTO)
2929 {
2930 infstr = initinfstr();
2931 formatinfstr(infstr, _("Cannot find arc %s', use which instead [%s] "),
2932 io_binindata.arcprotoerror[i], io_binindata.arcprotolist[i]->protoname);
2933 name = ttygetline(returninfstr(infstr));
2934 if (name == 0 || *name == 0) break;
2935 for(ap = io_binindata.arcprotolist[i]->tech->firstarcproto; ap != NOARCPROTO; ap = ap->nextarcproto)
2936 if (namesame(ap->protoname, name) == 0) break;
2937 }
2938 if (ap != NOARCPROTO) io_binindata.arcprotolist[i] = ap;
2939 efree(io_binindata.arcprotoerror[i]);
2940 io_binindata.arcprotoerror[i] = 0;
2941 }
2942 return(io_binindata.arcprotolist[i]);
2943 }
2944
io_getportpprotolist(INTBIG i)2945 PORTPROTO *io_getportpprotolist(INTBIG i)
2946 {
2947 if (io_binindata.portpprotoerror[i] != 0)
2948 {
2949 ttyputerr(_("WARNING: port %s not found, using %s"), io_binindata.portpprotoerror[i],
2950 io_binindata.portpprotolist[i]->protoname);
2951 efree(io_binindata.portpprotoerror[i]);
2952 io_binindata.portpprotoerror[i] = 0;
2953 }
2954 return(io_binindata.portpprotolist[i]);
2955 }
2956
io_getnodepprotolist(INTBIG i)2957 NODEPROTO *io_getnodepprotolist(INTBIG i)
2958 {
2959 REGISTER NODEPROTO *np;
2960 REGISTER CHAR *name;
2961 REGISTER void *infstr;
2962
2963 (void)io_gettechlist(io_binindata.nodepprototech[i]);
2964 if (io_binindata.nodepprotoerror[i])
2965 {
2966 np = NONODEPROTO;
2967 while (np == NONODEPROTO)
2968 {
2969 infstr = initinfstr();
2970 formatinfstr(infstr, _("Cannot find primitive '%s', use which instead [%s] "),
2971 io_binindata.nodepprotoorig[i], io_binindata.nodepprotolist[i]->protoname);
2972 name = ttygetline(returninfstr(infstr));
2973 if (name == 0 || *name == 0) break;
2974 for(np = io_binindata.nodepprotolist[i]->tech->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
2975 if (namesame(np->protoname, name) == 0) break;
2976 }
2977 if (np != NONODEPROTO) io_binindata.nodepprotolist[i] = np;
2978 io_binindata.nodepprotoerror[i] = FALSE;
2979 }
2980 return(io_binindata.nodepprotolist[i]);
2981 }
2982
io_gettechlist(INTBIG i)2983 TECHNOLOGY *io_gettechlist(INTBIG i)
2984 {
2985 extern COMCOMP us_noyesp;
2986 REGISTER INTBIG count;
2987 CHAR *pars[10];
2988
2989 if (io_binindata.techerror[i] != 0)
2990 {
2991 ttyputerr(_("WARNING: technology '%s' does not exist, using '%s'"),
2992 io_binindata.techerror[i], io_binindata.techlist[i]->techname);
2993 efree(io_binindata.techerror[i]);
2994 io_binindata.techerror[i] = 0;
2995 count = ttygetparam(_("Is this OK? [n] "), &us_noyesp, 2, pars);
2996 if (count <= 0 || namesamen(pars[0], x_("yes"), estrlen(pars[0])) != 0)
2997 longjmp(io_binindata.filerror, LONGJMPABORTED);
2998 ttyputerr(_("WARNING: saving this library with a substitute technology may corrupt it!"));
2999 }
3000 return(io_binindata.techlist[i]);
3001 }
3002
3003 /******************** I/O ROUTINES ********************/
3004
io_getinbig(void * data)3005 void io_getinbig(void *data)
3006 {
3007 io_getin(data, io_binindata.sizeofbig, SIZEOFINTBIG, TRUE);
3008 }
3009
io_getinubig(void * data)3010 void io_getinubig(void *data)
3011 {
3012 io_getin(data, io_binindata.sizeofbig, SIZEOFINTBIG, FALSE);
3013 }
3014
3015 /*
3016 * routine to read "disksize" bytes of data from disk and store them in the "memorysize"-
3017 * long object at "data". If "signextend" is nonzero, do sign-extension if the
3018 * memory object is larger.
3019 */
io_getin(void * data,INTBIG disksize,INTBIG memorysize,BOOLEAN signextend)3020 void io_getin(void *data, INTBIG disksize, INTBIG memorysize, BOOLEAN signextend)
3021 {
3022 REGISTER INTBIG ret;
3023 UCHAR1 swapbyte;
3024 UCHAR1 buf[128];
3025 INTBIG i;
3026
3027 /* sanity check */
3028 if (disksize == 0)
3029 {
3030 ttyputmsg(_("Warning: null length data; database may be bad (byte %ld)"),
3031 io_binindata.bytecount);
3032 return;
3033 }
3034
3035 /* check for direct transfer */
3036 if (disksize == memorysize && io_binindata.swap_bytes == 0)
3037 {
3038 /* just peel it off the disk */
3039 ret = xfread((UCHAR1*)data, 1, disksize, io_binindata.filein);
3040 if (ret == 0) longjmp(io_binindata.filerror, LONGJMPEOF);
3041 } else
3042 {
3043 /* not a simple read, use a buffer */
3044 ret = xfread(buf, 1, disksize, io_binindata.filein);
3045 if (ret == 0) longjmp(io_binindata.filerror, LONGJMPEOF);
3046 if (io_binindata.swap_bytes > 0)
3047 {
3048 switch (disksize)
3049 {
3050 case 2:
3051 swapbyte = buf[0]; buf[0] = buf[1]; buf[1] = swapbyte;
3052 break;
3053 case 4:
3054 swapbyte = buf[3]; buf[3] = buf[0]; buf[0] = swapbyte;
3055 swapbyte = buf[2]; buf[2] = buf[1]; buf[1] = swapbyte;
3056 break;
3057 case 8:
3058 swapbyte = buf[7]; buf[7] = buf[0]; buf[0] = swapbyte;
3059 swapbyte = buf[6]; buf[6] = buf[1]; buf[1] = swapbyte;
3060 swapbyte = buf[5]; buf[5] = buf[2]; buf[2] = swapbyte;
3061 swapbyte = buf[4]; buf[4] = buf[3]; buf[3] = swapbyte;
3062 break;
3063 }
3064 }
3065 if (disksize == memorysize)
3066 {
3067 for(i=0; i<memorysize; i++) ((UCHAR1 *)data)[i] = buf[i];
3068 } else
3069 {
3070 if (disksize > memorysize)
3071 {
3072 /* trouble! disk has more bits than memory. check for clipping */
3073 for(i=0; i<memorysize; i++) ((UCHAR1 *)data)[i] = buf[i];
3074 for(i=memorysize; i<disksize; i++)
3075 if (buf[i] != 0 && buf[i] != (UCHAR1)0xFF)
3076 io_binindata.clipped_integers++;
3077 } else
3078 {
3079 /* disk has smaller integer */
3080 if (!signextend || (buf[disksize-1] & 0x80) == 0)
3081 {
3082 for(i=disksize; i<memorysize; i++) buf[i] = 0;
3083 } else
3084 {
3085 for(i=disksize; i<memorysize; i++) buf[i] = (UCHAR1)0xFF;
3086 }
3087 for(i=0; i<memorysize; i++) ((UCHAR1 *)data)[i] = buf[i];
3088 }
3089 }
3090 }
3091 io_binindata.bytecount += disksize;
3092 if (io_verbose < 0 && io_binindata.filelength > 0 && io_inputprogressdialog != 0)
3093 {
3094 if (io_binindata.bytecount > io_binindata.reported + REPORTINC)
3095 {
3096 DiaSetProgress(io_inputprogressdialog, io_binindata.bytecount, io_binindata.filelength);
3097 io_binindata.reported = io_binindata.bytecount;
3098 }
3099 }
3100 }
3101
io_getstring(CLUSTER * cluster)3102 CHAR *io_getstring(CLUSTER *cluster)
3103 {
3104 INTBIG len;
3105 REGISTER INTBIG oldswapbytes;
3106 CHAR *name;
3107 REGISTER CHAR *tempstr;
3108
3109 if (SIZEOFCHAR != io_binindata.sizeofchar)
3110 {
3111 /* disk and memory don't match: read into temporary string */
3112 tempstr = io_gettempstring();
3113 if (allocstring(&name, tempstr, cluster)) return(0);
3114 } else
3115 {
3116 /* disk and memory match: read the data */
3117 io_getinbig(&len);
3118 name = (CHAR *)emalloc((len+1) * SIZEOFCHAR, cluster);
3119 if (name == 0) return(0);
3120 if (len != 0)
3121 {
3122 oldswapbytes = io_binindata.swap_bytes;
3123 io_binindata.swap_bytes = 0; /* prevent swapping */
3124 io_getin(name, len * SIZEOFCHAR, len * SIZEOFCHAR, FALSE);
3125 io_binindata.swap_bytes = oldswapbytes;
3126 }
3127 name[len] = 0;
3128 }
3129 return(name);
3130 }
3131
io_gettempstring(void)3132 CHAR *io_gettempstring(void)
3133 {
3134 INTBIG len;
3135 REGISTER INTBIG oldswapbytes, maxbytesperchar, i;
3136
3137 io_getinbig(&len);
3138 if (len+1 > io_tempstringlength)
3139 {
3140 if (io_tempstringlength != 0) efree((CHAR *)io_tempstring);
3141 io_tempstringlength = len+1;
3142 maxbytesperchar = maxi(SIZEOFCHAR, io_binindata.sizeofchar);
3143 io_tempstring = (CHAR1 *)emalloc(io_tempstringlength * maxbytesperchar, io_tool->cluster);
3144 if (io_tempstring == 0) { io_tempstringlength = 0; return(0); }
3145 }
3146 oldswapbytes = io_binindata.swap_bytes;
3147 if (io_binindata.swap_bytes != 0 && len != 0) io_binindata.swap_bytes = 0;
3148 if (len != 0) io_getin(io_tempstring, len * io_binindata.sizeofchar,
3149 len * io_binindata.sizeofchar, FALSE);
3150 io_binindata.swap_bytes = oldswapbytes;
3151 if (SIZEOFCHAR != io_binindata.sizeofchar)
3152 {
3153 /* size of strings on disk different than in memory: adjust */
3154 if (SIZEOFCHAR == 1)
3155 {
3156 /* disk has unicode, memory has 1-byte: reduce the data */
3157 for(i=0; i<len; i++)
3158 io_tempstring[i] = io_tempstring[i*2];
3159 io_tempstring[len] = 0;
3160 } else
3161 {
3162 /* disk has 1-byte, memory uses unicode: expand the data */
3163 for(i=len-1; i>=0; i--)
3164 ((CHAR *)io_tempstring)[i] = io_tempstring[i] & 0xFF;
3165 ((CHAR *)io_tempstring)[len] = 0;
3166 }
3167 } else
3168 {
3169 ((CHAR *)io_tempstring)[len] = 0;
3170 }
3171 return((CHAR *)io_tempstring);
3172 }
3173