1 /* -*- tab-width: 4 -*-
2 *
3 * Electric(tm) VLSI Design System
4 *
5 * File: iogdsi.c
6 * Input/output tool: GDSII stream input
7 * Written by: Glen Lawson, S-MOS Systems, Inc.
8 *
9 * Copyright (c) 2000 Static Free Software.
10 *
11 * Electric(tm) is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * Electric(tm) is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with Electric(tm); see the file COPYING. If not, write to
23 * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
24 * Boston, Mass 02111-1307, USA.
25 *
26 * Static Free Software
27 * 4119 Alpine Road
28 * Portola Valley, California 94028
29 * info@staticfreesoft.com
30 */
31
32 /*
33 * Notes:
34 * Unsupported features and assumptions:
35 * Map layers with the IO_gds_layer_numbers variable on the current technology.
36 * The pure-layer node must have the HOLDSTRACE option, if not will CRASH
37 * for boundary types. Will map to the generic:DRC-node if not found.
38 * Case sensitive.
39 * SUBLAYERS or XXXTYPE fields are not supported, perhaps a variable
40 * could be attached to the object with this value.
41 * NODEs and TEXTNODEs - don't have an example
42 * PROPERTIES - could add as a variable to the structure.
43 * PATHTYPE 1 - rounded ends on paths, not supported
44 * Path dogears - no cleanup yet, simpler to map paths into arcs
45 * Absolute angle - ???
46 * REFLIBS - not supported.
47 * I have no BOX type examples.
48 *
49 * Nice to have:
50 * PATH-ARC mapping - should be done, problem is that any layer can
51 * be a path, only connection layers in electric are arcs.
52 * Someone could make a GDS mapping technology for this purpose,
53 * defaults could be taken from this technology.
54 * Misc. fields mapped to variables - should be done.
55 * AREFs - could build into a separate NODEPROTO, and instance, thus
56 * preserving the original intent and space. With a timestamp,
57 * can determine if the structure has been disturbed for output.
58 * MAG - no scaling is possible, must create a separate object for each
59 * value, don't scale. (TEXT does scale)
60 */
61
62 #include "config.h"
63 #include "global.h"
64 #include "egraphics.h"
65 #include "efunction.h"
66 #include "database.h"
67 #include "eio.h"
68 #include "usr.h"
69 #include "iogdsi.h"
70 #include "tech.h"
71 #include "tecgen.h"
72 #include "edialogs.h"
73 #include <math.h>
74
75 #define NEWPATH 1 /* path and cell caching optimizations */
76
77 /* electric specific globals */
78 static LIBRARY *io_gdslibrary = NOLIBRARY;
79 static jmp_buf io_gdsenv;
80 static NODEPROTO *io_gdsstructure = NONODEPROTO;
81 static NODEPROTO *io_gdssref = NONODEPROTO;
82 static NODEINST *io_gdsinstance = NONODEINST;
83 static NODEPROTO *io_gdslayernode = NONODEPROTO;
84 static NODEPROTO *io_gdslayernodes[MAXLAYERS];
85 static INTBIG io_gdslayertext[MAXLAYERS];
86 static INTBIG io_gdslayershape[MAXLAYERS];
87 static INTBIG io_gdslayerrect[MAXLAYERS];
88 static INTBIG io_gdslayerpath[MAXLAYERS];
89 static INTBIG io_gdslayerpoly[MAXLAYERS];
90 static BOOLEAN io_gdslayervisible[MAXLAYERS];
91 static BOOLEAN io_gdslayerused;
92 static INTBIG io_gdslayerwhich;
93 static INTBIG io_gdssrefcount;
94 static INTBIG io_gdsrecomputed;
95 static INTBIG *io_gdscurstate;
96 static void *io_gdsprogressdialog;
97
98 /* globals */
99 static STREAM io_gdsstream;
100 static INTBIG io_gdsbytesread;
101 static INTBIG io_gdsrecordcount;
102 static INTBIG io_gdsbufferindex;
103 static INTBIG io_gdsblockcount;
104 static gsymbol io_gdstoken;
105 static UINTSML io_gdstokenflags;
106 static INTSML io_gdstokenvalue16;
107 static INTBIG io_gdstokenvalue32;
108 static float io_gdsrealtokensp;
109 static double io_gdsrealtokendp;
110 static CHAR io_gdstokenstring[TEXTLINE+1];
111 static point_type io_gdsvertex[MAXPOINTS];
112 static point_type io_gdsboundarydelta[MAXPOINTS];
113 static INTBIG io_gdscurlayer, io_gdscursublayer;
114 static double io_gdsscale;
115 static INTBIG io_gdsfilesize;
116 static INTBIG *io_gdsIlayerlist;
117 static INTBIG io_gdsIlayerlisttotal = 0;
118
119
120 /* these are not really used */
121 static CHAR io_gdsversionstring[IDSTRING+1];
122 static CHAR io_gdslibraryname[IDSTRING+1];
123
124 static CHAR *io_gdsIerror_string[] =
125 {
126 N_("success"), /* 0 */
127 N_("Invalid GDS II datatype"), /* 1 */
128 N_("GDS II version number is not decipherable"), /* 2 */
129 N_("GDS II header statement is missing"), /* 3 */
130 N_("Library name is missing"), /* 4 */
131 N_("Begin library statement is missing"), /* 5 */
132 N_("Date value is not a valid number"), /* 6 */
133 N_("Libname statement is missing"), /* 7 */
134 N_("Generations value is invalid"), /* 8 */
135 N_("Units statement has invalid number format"), /* 9 */
136 N_("Units statement is missing"), /* 10 */
137 N_("Warning this structure is empty"), /* 11 */
138 N_("Structure name is missing"), /* 12 */
139 N_("Strname statement is missing"), /* 13 */
140 N_("Begin structure statement is missing"), /* 14 */
141 N_("Element end statement is missing"), /* 15 */
142 N_("Structure reference name is missing"), /* 16 */
143 N_("Structure reference has no translation value"), /* 17 */
144 N_("Boundary has no points"), /* 18 */
145 N_("Structure reference is missing its flags field"), /* 19 */
146 N_("Not enough points in the shape"), /* 20 */
147 N_("Too many points in the shape"), /* 21 */
148 N_("Invalid layer number"), /* 22 */
149 N_("Layer statement is missing"), /* 23 */
150 N_("No datatype field"), /* 24 */
151 N_("Path element has no points"), /* 25 */
152 N_("Text element has no reference point"), /* 26 */
153 N_("Array reference has no parameters"), /* 27 */
154 N_("Array reference name is missing"), /* 28 */
155 N_("Property has no value"), /* 29 */
156 N_("Array orientation oblique"), /* 30 */
157 N_("Failed to create AREF"), /* 31 */
158 N_("Failed to create RECTANGLE"), /* 32 */
159 N_("Failed to create POLYGON"), /* 33 */
160 N_("No memory"), /* 34 */
161 N_("Failed to create POLYGON points"), /* 35 */
162 N_("Could not create text marker"), /* 36 */
163 N_("Could not create text string"), /* 37 */
164 N_("Failed to create structure"), /* 38 */
165 N_("Failed to create cell center"), /* 39 */
166 N_("Failed to create NODE"), /* 40 */
167 N_("Failed to create box"), /* 41 */
168 N_("Failed to create outline"), /* 42 */
169 N_("Failed to create SREF proto"), /* 43 */
170 N_("Failed to create SREF") /* 44 */
171 };
172
173 static gsymbol io_gdsIoption_set[] =
174 {
175 GDS_ATTRTABLE,
176 GDS_REFLIBS,
177 GDS_FONTS,
178 GDS_GENERATIONS,
179 GDS_BADFIELD
180 };
181
182 static gsymbol io_gdsIshape_set[] =
183 {
184 GDS_AREF,
185 GDS_SREF,
186 GDS_BOUNDARY,
187 GDS_PATH,
188 GDS_NODE,
189 GDS_TEXTSYM,
190 GDS_BOX,
191 GDS_BADFIELD
192 };
193
194 static gsymbol io_gdsIgood_op_set[] =
195 {
196 GDS_HEADER,
197 GDS_BGNLIB,
198 GDS_LIBNAME,
199 GDS_UNITS,
200 GDS_ENDLIB,
201 GDS_BGNSTR,
202 GDS_STRNAME,
203 GDS_ENDSTR,
204 GDS_BOUNDARY,
205 GDS_PATH,
206 GDS_SREF,
207 GDS_AREF,
208 GDS_TEXTSYM,
209 GDS_LAYER,
210 GDS_DATATYPSYM,
211 GDS_WIDTH,
212 GDS_XY,
213 GDS_ENDEL,
214 GDS_SNAME,
215 GDS_COLROW,
216 GDS_TEXTNODE,
217 GDS_NODE,
218 GDS_TEXTTYPE,
219 GDS_PRESENTATION,
220 GDS_STRING,
221 GDS_STRANS,
222 GDS_MAG,
223 GDS_ANGLE,
224 GDS_REFLIBS,
225 GDS_FONTS,
226 GDS_PATHTYPE,
227 GDS_GENERATIONS,
228 GDS_ATTRTABLE,
229 GDS_NODETYPE,
230 GDS_PROPATTR,
231 GDS_PROPVALUE,
232 GDS_BOX,
233 GDS_BOXTYPE,
234 GDS_FORMAT,
235 GDS_MASK,
236 GDS_ENDMASKS,
237 GDS_BADFIELD
238 };
239
240 static gsymbol io_gdsIbackup_set[] =
241 {
242 GDS_UNITS,
243 GDS_REFLIBS,
244 GDS_FONTS,
245 GDS_ATTRTABLE,
246 GDS_BADFIELD
247 };
248
249 static gsymbol io_gdsImask_set[] =
250 {
251 GDS_DATATYPSYM,
252 GDS_TEXTTYPE,
253 GDS_BOXTYPE,
254 GDS_NODETYPE,
255 GDS_BADFIELD
256 };
257
258 static gsymbol io_gdsIunsupported_set[] =
259 {
260 GDS_ELFLAGS,
261 GDS_PLEX,
262 GDS_BADFIELD
263 };
264
265 static gsymbol io_gdsIrecovery_set[100];
266
267 /* prototypes for local routines */
268 static void io_gdsIappendset(gsymbol[], gsymbol);
269 static void io_gdsIattrtable(void);
270 static void io_gdsIbackup(void);
271 static void io_gdsIbeginstructure(void);
272 static void io_gdsIbox(INTBIG*);
273 static void io_gdsIcopyset(gsymbol[], gsymbol[]);
274 static void io_gdsIdetermine_aref(void);
275 static void io_gdsIdetermine_boundary(INTBIG, shape_type*, shape_type*);
276 static void io_gdsIdetermine_box(void);
277 static void io_gdsIdetermine_justification(INTBIG*, INTBIG*);
278 static void io_gdsIdetermine_layer(INTBIG*, INTBIG*);
279 static void io_gdsIdetermine_node(void);
280 static void io_gdsIdetermine_orientation(INTBIG*, INTBIG*, double*);
281 static void io_gdsIdetermine_path(void);
282 static void io_gdsIdetermine_points(INTBIG, INTBIG, INTBIG*);
283 static void io_gdsIdetermine_property(void);
284 static void io_gdsIdetermine_shape(void);
285 static void io_gdsIdetermine_sref(void);
286 static void io_gdsIdetermine_text(void);
287 static void io_gdsIdetermine_time(CHAR*);
288 static void io_gdsIelement(BOOLEAN*);
289 static void io_gdsIerror(INTBIG);
290 static NODEPROTO *io_gdsIfindproto(CHAR *name);
291 static void io_gdsIfonts(void);
292 static void io_gdsIgetdouble(double*);
293 static void io_gdsIgetfloat(float*);
294 static void io_gdsIgetinteger(INTBIG*);
295 static void io_gdsIgetproto(CHAR*);
296 static UCHAR1 io_gdsIgetrawbyte(void);
297 static gsymbol io_gdsIgetrecord(datatype_symbol*);
298 static datatype_symbol io_gdsIgetrecordtype(void);
299 static void io_gdsIgetstring(CHAR*);
300 static void io_gdsIgettoken(void);
301 static void io_gdsIgetword(UINTSML*);
302 static void io_gdsIheader(void);
303 static void io_gdsIinit(void);
304 static void io_gdsIitoa(CHAR*, INTBIG, INTBIG);
305 static void io_gdsIlibrary(void);
306 static BOOLEAN io_gdsIload(FILE*);
307 static BOOLEAN io_gdsImember(gsymbol, gsymbol[]);
308 static void io_gdsIOnceinit(void);
309 static void io_gdsIonlyone(gsymbol[], gsymbol);
310 static double io_gdsIpower(INTBIG, INTBIG);
311 static void io_gdsIrecompute(NODEPROTO*, INTBIG);
312 static void io_gdsIreflibs(void);
313 static void io_gdsIshape(INTBIG, shape_type, shape_type);
314 static void io_gdsIstep(INTBIG, INTBIG, INTBIG, INTBIG);
315 static void io_gdsIstructure(void);
316 static void io_gdsItext(CHAR*, INTBIG, INTBIG, INTBIG, INTBIG, double);
317 static void io_gdsItransform(point_type, INTBIG, INTBIG);
318 static void io_gdsItranslate(INTBIG*, INTBIG*, double, BOOLEAN);
319 static void io_gdsIunits(void);
320 static void io_gdsIunsupported(gsymbol[]);
321 static void io_gdsIparselayernumbers(CHAR *layernumbers, INTBIG **layers, INTBIG *total);
322
323 /* modules */
324
325 /*
326 * Routine to free all memory associated with this module.
327 */
io_freegdsinmemory(void)328 void io_freegdsinmemory(void)
329 {
330 if (io_gdsIlayerlisttotal > 0) efree((CHAR *)io_gdsIlayerlist);
331 }
332
io_gdsIpower(INTBIG val,INTBIG power)333 double io_gdsIpower(INTBIG val, INTBIG power)
334 {
335 double result;
336 REGISTER INTBIG count;
337
338 result = 1.0;
339 for(count=0; count<power; count++)
340 result *= (double)val;
341 return(result);
342 }
343
io_gdsImember(gsymbol tok,gsymbol set[])344 BOOLEAN io_gdsImember(gsymbol tok, gsymbol set[])
345 {
346 REGISTER gsymbol *ctok;
347
348 for (ctok = set; *ctok != GDS_BADFIELD; ctok++)
349 if (*ctok == tok) return(TRUE);
350 return(FALSE);
351 }
352
io_gdsIcopyset(gsymbol set1[],gsymbol set2[])353 void io_gdsIcopyset(gsymbol set1[], gsymbol set2[])
354 {
355 REGISTER gsymbol *item1, *item2;
356
357 for (item1 = set1, item2 = set2; *item1 != GDS_BADFIELD; item1++, item2++)
358 *item2 = *item1;
359 *item2 = GDS_BADFIELD;
360 }
361
io_gdsIonlyone(gsymbol set[],gsymbol item)362 void io_gdsIonlyone(gsymbol set[], gsymbol item)
363 {
364 set[0] = item;
365 set[1] = GDS_BADFIELD;
366 }
367
io_gdsIappendset(gsymbol set[],gsymbol item)368 void io_gdsIappendset(gsymbol set[], gsymbol item)
369 {
370 REGISTER gsymbol *pos;
371
372 pos = set;
373 while (*pos != GDS_BADFIELD) pos++;
374 *pos++ = item; *pos = GDS_BADFIELD;
375 }
376
io_gdsIgetrawbyte(void)377 UCHAR1 io_gdsIgetrawbyte(void)
378 {
379 if (io_gdsbufferindex >= BLOCKSIZE || io_gdsbufferindex < 0)
380 {
381 (void)xfread(io_gdsstream.buf, 1, BLOCKSIZE, io_gdsstream.fp);
382 io_gdsbufferindex = 0;
383 io_gdsblockcount = io_gdsblockcount + 1;
384 io_gdsbytesread += BLOCKSIZE;
385 if (io_gdsbytesread/5000 != (io_gdsbytesread-BLOCKSIZE)/5000)
386 {
387 if (io_verbose < 0 && io_gdsfilesize > 0)
388 DiaSetProgress(io_gdsprogressdialog, io_gdsbytesread, io_gdsfilesize); else
389 ttyputmsg(_("%ld bytes read (%ld%% done)"), io_gdsbytesread,
390 io_gdsbytesread*100/io_gdsfilesize);
391 }
392 }
393 io_gdsrecordcount = io_gdsrecordcount - 1;
394 return(io_gdsstream.buf[io_gdsbufferindex++]);
395 }
396
io_gdsIgetword(UINTSML * dataword)397 void io_gdsIgetword(UINTSML *dataword)
398 {
399 UINTSML lowbyte, highbyte;
400
401 highbyte = io_gdsIgetrawbyte() & 0xFF;
402 lowbyte = io_gdsIgetrawbyte() & 0xFF;
403 (*dataword) = (highbyte << 8) + lowbyte;
404 }
405
io_gdsIgetinteger(INTBIG * datavalue)406 void io_gdsIgetinteger(INTBIG *datavalue)
407 {
408 UINTSML lowword, highword;
409
410 io_gdsIgetword(&highword);
411 io_gdsIgetword(&lowword);
412 (*datavalue) = (highword << 16) + lowword;
413 }
414
io_gdsIgetstring(CHAR * streamstring)415 void io_gdsIgetstring(CHAR *streamstring)
416 {
417 CHAR letter, *pos;
418
419 pos = streamstring;
420 while (io_gdsrecordcount != 0)
421 {
422 letter = io_gdsIgetrawbyte();
423 *pos++ = letter;
424 }
425 *pos = '\0';
426 }
427
io_gdsIitoa(CHAR * nstring,INTBIG leng,INTBIG number)428 void io_gdsIitoa(CHAR *nstring, INTBIG leng, INTBIG number)
429 {
430 (void)esnprintf(nstring, leng, x_("%ld"), number);
431 }
432
io_gdsIgetfloat(float * realvalue)433 void io_gdsIgetfloat(float *realvalue)
434 {
435 unsigned long reg;
436 UINTSML dataword;
437 INTBIG sign;
438 INTBIG binary_exponent;
439 INTBIG shift_count;
440
441 reg = io_gdsIgetrawbyte() & 0xFF;
442 if (reg & 0x00000080) sign = -1;
443 else sign = 1;
444 reg = reg & 0x0000007F;
445
446 /* generate the exponent, currently in Excess-64 representation */
447 binary_exponent = (reg - 64) << 2;
448 reg = (unsigned long)(io_gdsIgetrawbyte() & 0xFF) << 16;
449 io_gdsIgetword(&dataword);
450 reg = reg + dataword;
451 shift_count = 0;
452
453 /* normalize the matissa */
454 while ((reg & 0x00800000) == 0)
455 {
456 reg = reg << 1;
457 shift_count++;
458 }
459
460 /* this is the exponent + normalize shift - precision of matissa */
461 /* binary_exponent = binary_exponent + shift_count - 24; */
462 binary_exponent = binary_exponent - shift_count - 24;
463
464 if (binary_exponent > 0)
465 {
466 (*realvalue) = (float)(sign * reg * io_gdsIpower(2, binary_exponent));
467 } else
468 {
469 if (binary_exponent < 0)
470 (*realvalue) = (float)(sign * reg / io_gdsIpower(2, -binary_exponent)); else
471 (*realvalue) = (float)(sign * reg);
472 }
473 }
474
io_gdsIgetdouble(double * realvalue)475 void io_gdsIgetdouble(double *realvalue)
476 {
477 UINTBIG register1, register2;
478 UINTSML dataword;
479 INTBIG exponent;
480 INTBIG long_integer;
481 static double twoto32;
482 static double twotoneg56;
483 static BOOLEAN init = TRUE;
484
485 if (init)
486 {
487 init = FALSE;
488 twoto32 = io_gdsIpower(2, 32);
489 twotoneg56 = 1.0 / io_gdsIpower (2, 56);
490 }
491
492 /* first byte is the exponent field (hex) */
493 register1 = io_gdsIgetrawbyte() & 0xFF;
494
495 /* plus sign bit */
496 if (register1 & 0x00000080) *realvalue = -1.0; else
497 *realvalue = 1.0;
498
499 /* the hex exponent is in excess 64 format */
500 register1 = register1 & 0x0000007F;
501 exponent = register1 - 64;
502
503 /* bytes 2-4 are the high ordered bits of the mantissa */
504 register1 = (UINTBIG)(io_gdsIgetrawbyte() & 0xFF) << 16;
505 io_gdsIgetword(&dataword);
506 register1 = register1 + dataword;
507
508 /* next word completes the matissa (1/16 to 1) */
509 io_gdsIgetinteger(&long_integer);
510 register2 = (UINTBIG)long_integer;
511
512 /* now normalize the value */
513 if (register1 || register2)
514 {
515 /* while ((register1 & 0x00800000) == 0) */
516 /* check for 0 in the high-order nibble */
517 while ((register1 & 0x00F00000) == 0)
518 {
519 /* register1 = register1 << 1; */
520 /* shift the 2 registers by 4 bits */
521 register1 = (register1 << 4) + (register2>>28);
522 register2 = register2 << 4;
523 exponent--;
524 }
525 } else
526 {
527 /* true 0 */
528 *realvalue = 0.0;
529 return;
530 }
531
532 /* now create the matissa (fraction between 1/16 to 1) */
533 *realvalue *= ((double) register1 * twoto32 + (double) register2) * twotoneg56;
534 if (exponent > 0)
535 {
536 *realvalue = (*realvalue) * io_gdsIpower(16, exponent);
537 } else
538 {
539 if (exponent < 0)
540 *realvalue = (*realvalue) / io_gdsIpower(16, -exponent);
541 }
542 }
543
io_gdsIgetrecordtype(void)544 datatype_symbol io_gdsIgetrecordtype(void)
545 {
546 switch (io_gdsIgetrawbyte())
547 {
548 case 0: return(GDS_NONE);
549 case 1: return(GDS_FLAGS);
550 case 2: return(GDS_SHORT_WORD);
551 case 3: return(GDS_LONG_WORD);
552 case 4: return(GDS_SHORT_REAL);
553 case 5: return(GDS_LONG_REAL);
554 case 6: return(GDS_ASCII_STRING);
555 default: return(GDS_ERR);
556 }
557 }
558
io_gdsIgetrecord(datatype_symbol * gds_type)559 gsymbol io_gdsIgetrecord(datatype_symbol *gds_type)
560 {
561 gsymbol temp;
562 UINTSML dataword, recordtype;
563
564 io_gdsIgetword(&dataword);
565 io_gdsrecordcount = dataword - 2;
566 recordtype = io_gdsIgetrawbyte() & 0xFF;
567 temp = GDS_NULLSYM;
568 switch (recordtype)
569 {
570 case 0: temp = GDS_HEADER; break;
571 case 1: temp = GDS_BGNLIB; break;
572 case 2: temp = GDS_LIBNAME; break;
573 case 3: temp = GDS_UNITS; break;
574 case 4: temp = GDS_ENDLIB; break;
575 case 5: temp = GDS_BGNSTR; break;
576 case 6: temp = GDS_STRNAME; break;
577 case 7: temp = GDS_ENDSTR; break;
578 case 8: temp = GDS_BOUNDARY; break;
579 case 9: temp = GDS_PATH; break;
580 case 10: temp = GDS_SREF; break;
581 case 11: temp = GDS_AREF; break;
582 case 12: temp = GDS_TEXTSYM; break;
583 case 13: temp = GDS_LAYER; break;
584 case 14: temp = GDS_DATATYPSYM; break;
585 case 15: temp = GDS_WIDTH; break;
586 case 16: temp = GDS_XY; break;
587 case 17: temp = GDS_ENDEL; break;
588 case 18: temp = GDS_SNAME; break;
589 case 19: temp = GDS_COLROW; break;
590 case 20: temp = GDS_TEXTNODE; break;
591 case 21: temp = GDS_NODE; break;
592 case 22: temp = GDS_TEXTTYPE; break;
593 case 23: temp = GDS_PRESENTATION; break;
594 case 24: temp = GDS_SPACING; break;
595 case 25: temp = GDS_STRING; break;
596 case 26: temp = GDS_STRANS; break;
597 case 27: temp = GDS_MAG; break;
598 case 28: temp = GDS_ANGLE; break;
599 case 29: temp = GDS_UINTEGER; break;
600 case 30: temp = GDS_USTRING; break;
601 case 31: temp = GDS_REFLIBS; break;
602 case 32: temp = GDS_FONTS; break;
603 case 33: temp = GDS_PATHTYPE; break;
604 case 34: temp = GDS_GENERATIONS; break;
605 case 35: temp = GDS_ATTRTABLE; break;
606 case 36: temp = GDS_STYPTABLE; break;
607 case 37: temp = GDS_STRTYPE; break;
608 case 38: temp = GDS_ELFLAGS; break;
609 case 39: temp = GDS_ELKEY; break;
610 case 40: temp = GDS_LINKTYPE; break;
611 case 41: temp = GDS_LINKKEYS; break;
612 case 42: temp = GDS_NODETYPE; break;
613 case 43: temp = GDS_PROPATTR; break;
614 case 44: temp = GDS_PROPVALUE; break;
615 case 45: temp = GDS_BOX; break;
616 case 46: temp = GDS_BOXTYPE; break;
617 case 47: temp = GDS_PLEX; break;
618 case 48: temp = GDS_BGNEXTN; break;
619 case 49: temp = GDS_ENDEXTN; break;
620 case 50: temp = GDS_TAPENUM; break;
621 case 51: temp = GDS_TAPECODE; break;
622 case 52: temp = GDS_STRCLASS; break;
623 case 53: temp = GDS_NUMTYPES; break;
624 case 54: temp = GDS_FORMAT; break;
625 case 55: temp = GDS_MASK; break;
626 case 56: temp = GDS_ENDMASKS; break;
627 default: temp = GDS_BADFIELD;
628 }
629 *gds_type = io_gdsIgetrecordtype();
630 return(temp);
631 }
632
io_gdsIerror(INTBIG n)633 void io_gdsIerror(INTBIG n)
634 {
635 ttyputerr(_("Error: %s, block %ld, index %ld"), TRANSLATE(io_gdsIerror_string[n]),
636 io_gdsblockcount, io_gdsbufferindex);
637 longjmp(io_gdsenv, 1);
638 }
639
io_gdsIgettoken(void)640 void io_gdsIgettoken(void)
641 {
642 static datatype_symbol valuetype;
643
644 if (io_gdsrecordcount == 0)
645 {
646 io_gdstoken = io_gdsIgetrecord(&valuetype);
647 } else
648 {
649 switch (valuetype)
650 {
651 case GDS_NONE:
652 break;
653 case GDS_FLAGS:
654 io_gdsIgetword(&io_gdstokenflags);
655 io_gdstoken = GDS_FLAGSYM;
656 break;
657 case GDS_SHORT_WORD:
658 io_gdsIgetword((UINTSML *)&io_gdstokenvalue16);
659 io_gdstoken = GDS_SHORT_NUMBER;
660 break;
661 case GDS_LONG_WORD:
662 io_gdsIgetinteger(&io_gdstokenvalue32);
663 io_gdstoken = GDS_NUMBER;
664 break;
665 case GDS_SHORT_REAL:
666 io_gdsIgetfloat(&io_gdsrealtokensp);
667 io_gdstoken = GDS_REALNUM;
668 break;
669 case GDS_LONG_REAL:
670 io_gdsIgetdouble(&io_gdsrealtokendp);
671 io_gdstoken = GDS_REALNUM;
672 break;
673 case GDS_ASCII_STRING:
674 io_gdsIgetstring(io_gdstokenstring);
675 io_gdstoken = GDS_IDENT;
676 break;
677 case GDS_ERR:
678 io_gdsIerror(1);
679 break;
680 }
681 }
682 }
683
io_gdsItranslate(INTBIG * ang,INTBIG * trans,double angle,BOOLEAN reflected)684 void io_gdsItranslate(INTBIG *ang, INTBIG *trans, double angle, BOOLEAN reflected)
685 {
686 *ang = rounddouble(angle) % 3600;
687 *trans = reflected ? 1 : 0;
688 if (*trans)
689 *ang = (2700 - *ang) % 3600;
690
691 /* should not happen...*/
692 if (*ang < 0) *ang = *ang + 3600;
693 }
694
io_gdsItransform(point_type delta,INTBIG angle,INTBIG trans)695 void io_gdsItransform(point_type delta, INTBIG angle, INTBIG trans)
696 {
697 XARRAY matrix;
698
699 makeangle(angle, trans, matrix);
700 xform(delta.px, delta.py, &delta.px, &delta.py, matrix);
701 }
702
io_gdsIstep(INTBIG nc,INTBIG nr,INTBIG angle,INTBIG trans)703 void io_gdsIstep(INTBIG nc, INTBIG nr, INTBIG angle, INTBIG trans)
704 {
705 point_type rowinterval, colinterval, ptc, pt;
706 INTBIG ic, ir;
707 INTBIG cx, cy, ox, oy;
708 XARRAY transform;
709
710 if (nc != 1)
711 {
712 colinterval.px = (io_gdsvertex[1].px - io_gdsvertex[0].px) / nc;
713 colinterval.py = (io_gdsvertex[1].py - io_gdsvertex[0].py) / nc;
714 io_gdsItransform(colinterval, angle, trans);
715 }
716 if (nr != 1)
717 {
718 rowinterval.px = (io_gdsvertex[2].px - io_gdsvertex[0].px) / nr;
719 rowinterval.py = (io_gdsvertex[2].py - io_gdsvertex[0].py) / nr;
720 io_gdsItransform(rowinterval, angle, trans);
721 }
722
723 /* create the node */
724 makeangle(angle, trans, transform);
725
726 /* now transform the center */
727 cx = (io_gdssref->highx + io_gdssref->lowx) / 2;
728 cy = (io_gdssref->highy + io_gdssref->lowy) / 2;
729 xform(cx, cy, &ox, &oy, transform);
730
731 /* calculate the offset from the original center */
732 ox -= cx; oy -= cy;
733
734 /* now generate the array */
735 ptc.px = io_gdsvertex[0].px; ptc.py = io_gdsvertex[0].py;
736 for (ic = 0; ic < nc; ic++)
737 {
738 pt = ptc;
739 for (ir = 0; ir < nr; ir++)
740 {
741 /* create the node */
742 if ((io_gdscurstate[0]&GDSINARRAYS) != 0 ||
743 (ir == 0 && ic == 0) ||
744 (ir == (nr-1) && ic == (nc-1)))
745 {
746 if ((io_gdsinstance = newnodeinst(io_gdssref, pt.px + io_gdssref->lowx + ox,
747 pt.px + io_gdssref->highx + ox, pt.py + io_gdssref->lowy + oy,
748 pt.py + io_gdssref->highy + oy, trans, angle,
749 io_gdsstructure)) == NONODEINST)
750 io_gdsIerror(31);
751 if ((io_gdscurstate[0] & GDSINEXPAND) != 0)
752 io_gdsinstance->userbits |= NEXPAND;
753 /* annotate the array info to this element */
754 }
755
756 /* add the row displacement */
757 pt.px += rowinterval.px; pt.py += rowinterval.py;
758 }
759
760 /* add displacement */
761 ptc.px += colinterval.px; ptc.py += colinterval.py;
762 }
763 }
764
io_gdsIdetermine_boundary(INTBIG npts,shape_type * perimeter,shape_type * oclass)765 void io_gdsIdetermine_boundary(INTBIG npts, shape_type *perimeter, shape_type *oclass)
766 {
767 BOOLEAN is90, is45;
768 REGISTER INTBIG i;
769
770 is90 = TRUE;
771 is45 = TRUE;
772 if (io_gdsvertex[0].px == io_gdsvertex[npts-1].px &&
773 io_gdsvertex[0].py == io_gdsvertex[npts-1].py)
774 (*perimeter) = GDS_CLOSED; else
775 (*perimeter) = GDS_LINE;
776
777 for (i=0; i<npts-1 && i<MAXPOINTS-1; i++)
778 {
779 io_gdsboundarydelta[i].px = io_gdsvertex[i+1].px - io_gdsvertex[i].px;
780 io_gdsboundarydelta[i].py = io_gdsvertex[i+1].py - io_gdsvertex[i].py;
781 }
782 for (i=0; i<npts-1 && i<MAXPOINTS-1; i++)
783 {
784 if (io_gdsboundarydelta[i].px != 0 && io_gdsboundarydelta[i].py != 0)
785 {
786 is90 = FALSE;
787 if (abs(io_gdsboundarydelta[i].px) != abs(io_gdsboundarydelta[i].py))
788 is45 = FALSE;
789 }
790 }
791 if ((*perimeter) == GDS_CLOSED && (is90 || is45))
792 (*oclass) = GDS_POLY; else
793 (*oclass) = GDS_OBLIQUE;
794 if (npts == 5 && is90 && (*perimeter) == GDS_CLOSED)
795 (*oclass) = GDS_RECTANGLE;
796 }
797
io_gdsIbox(INTBIG * npts)798 void io_gdsIbox(INTBIG *npts)
799 {
800 REGISTER INTBIG i, pxm, pym, pxs, pys;
801
802 pxm = io_gdsvertex[4].px;
803 pxs = io_gdsvertex[4].px;
804 pym = io_gdsvertex[4].py;
805 pys = io_gdsvertex[4].py;
806 for (i = 0; i<4; i++)
807 {
808 if (io_gdsvertex[i].px > pxm) pxm = io_gdsvertex[i].px;
809 if (io_gdsvertex[i].px < pxs) pxs = io_gdsvertex[i].px;
810 if (io_gdsvertex[i].py > pym) pym = io_gdsvertex[i].py;
811 if (io_gdsvertex[i].py < pys) pys = io_gdsvertex[i].py;
812 }
813 io_gdsvertex[0].px = pxs;
814 io_gdsvertex[0].py = pys;
815 io_gdsvertex[1].px = pxm;
816 io_gdsvertex[1].py = pym;
817 (*npts) = 2;
818 }
819
io_gdsIshape(INTBIG npts,shape_type perimeter,shape_type oclass)820 void io_gdsIshape(INTBIG npts, shape_type perimeter, shape_type oclass)
821 {
822 INTBIG lx, ly, hx, hy, cx, cy, i;
823 INTBIG *trace, *pt;
824 NODEINST *ni;
825
826 switch (oclass)
827 {
828 case GDS_RECTANGLE:
829 io_gdsIbox(&npts);
830
831 /* create the rectangle */
832 if (io_gdslayerused)
833 {
834 io_gdslayerrect[io_gdslayerwhich]++;
835 io_gdslayerpoly[io_gdslayerwhich]++;
836 if (newnodeinst(io_gdslayernode, io_gdsvertex[0].px,
837 io_gdsvertex[1].px, io_gdsvertex[0].py, io_gdsvertex[1].py, 0, 0,
838 io_gdsstructure) == NONODEINST)
839 io_gdsIerror(32);
840 }
841 break;
842
843 case GDS_OBLIQUE:
844 case GDS_POLY:
845 if (!io_gdslayerused) break;
846 io_gdslayershape[io_gdslayerwhich]++;
847 io_gdslayerpoly[io_gdslayerwhich]++;
848
849 /* determine the bounds of the polygon */
850 lx = hx = io_gdsvertex[0].px;
851 ly = hy = io_gdsvertex[0].py;
852 for (i=1; i<npts;i++)
853 {
854 if (lx > io_gdsvertex[i].px) lx = io_gdsvertex[i].px;
855 if (hx < io_gdsvertex[i].px) hx = io_gdsvertex[i].px;
856 if (ly > io_gdsvertex[i].py) ly = io_gdsvertex[i].py;
857 if (hy < io_gdsvertex[i].py) hy = io_gdsvertex[i].py;
858 }
859
860 /* now create the node */
861 if ((ni = newnodeinst(io_gdslayernode, lx, hx, ly, hy, 0, 0,
862 io_gdsstructure)) == NONODEINST)
863 io_gdsIerror(33);
864
865 /* now allocate the trace */
866 pt = trace = emalloc((npts*2*SIZEOFINTBIG), el_tempcluster);
867 if (trace == 0) io_gdsIerror(34);
868 cx = (hx + lx) / 2; cy = (hy + ly) / 2;
869 for (i=0; i<npts; i++)
870 {
871 *pt++ = io_gdsvertex[i].px - cx;
872 *pt++ = io_gdsvertex[i].py - cy;
873 }
874
875 /* store the trace information */
876 if (setvalkey((INTBIG)ni, VNODEINST, el_trace_key, (INTBIG)trace,
877 VINTEGER|VISARRAY|((npts*2)<<VLENGTHSH)) == NOVARIABLE)
878 io_gdsIerror(35);
879
880 /* free the polygon memory */
881 efree((CHAR *)trace);
882 break;
883 default:
884 break;
885 }
886 }
887
io_gdsItext(CHAR * charstring,INTBIG vjust,INTBIG hjust,INTBIG angle,INTBIG trans,double scale)888 void io_gdsItext(CHAR *charstring, INTBIG vjust, INTBIG hjust, INTBIG angle,
889 INTBIG trans, double scale)
890 {
891 NODEINST *ni;
892 VARIABLE *var;
893 INTBIG size;
894
895 /* no text */
896 if (!io_gdslayerused || !(io_gdscurstate[0]&GDSINTEXT)) return;
897 io_gdslayertext[io_gdslayerwhich]++;
898
899 io_gdsvertex[1].px = io_gdsvertex[0].px + MINFONTWIDTH * estrlen(charstring);
900 io_gdsvertex[1].py = io_gdsvertex[0].py + MINFONTHEIGHT;
901
902 /* create a holding node */
903 ni = newnodeinst(io_gdslayernode, io_gdsvertex[0].px, io_gdsvertex[0].px,
904 io_gdsvertex[0].py, io_gdsvertex[0].py, trans, angle, io_gdsstructure);
905 if (ni == NONODEINST) io_gdsIerror(36);
906
907 /* now add the text */
908 var = setvalkey((INTBIG)ni, VNODEINST, el_node_name_key, (INTBIG)charstring,
909 VSTRING|VDISPLAY);
910 if (var == NOVARIABLE) io_gdsIerror(37);
911
912 /* set the text size and orientation */
913 size = rounddouble(scale);
914 if (size <= 0) size = 8;
915 if (size > TXTMAXPOINTS) size = TXTMAXPOINTS;
916 TDSETSIZE(var->textdescript, size);
917
918 /* determine the presentation */
919 TDSETPOS(var->textdescript, VTPOSCENT);
920 switch (vjust)
921 {
922 case 1: /* top */
923 switch (hjust)
924 {
925 case 1: TDSETPOS(var->textdescript, VTPOSUPRIGHT); break;
926 case 2: TDSETPOS(var->textdescript, VTPOSUPLEFT); break;
927 default: TDSETPOS(var->textdescript, VTPOSUP); break;
928 }
929 break;
930
931 case 2: /* bottom */
932 switch (hjust)
933 {
934 case 1: TDSETPOS(var->textdescript, VTPOSDOWNRIGHT); break;
935 case 2: TDSETPOS(var->textdescript, VTPOSDOWNLEFT); break;
936 default: TDSETPOS(var->textdescript, VTPOSDOWN); break;
937 }
938 break;
939
940 default: /* centered */
941 switch (hjust)
942 {
943 case 1: TDSETPOS(var->textdescript, VTPOSRIGHT); break;
944 case 2: TDSETPOS(var->textdescript, VTPOSLEFT); break;
945 default: TDSETPOS(var->textdescript, VTPOSCENT); break;
946 }
947 }
948 }
949
950 /*
951 * This routine rewritten by Steven Rubin to be more robust in finding
952 * pure-layer nodes associated with the GDS layer numbers.
953 */
io_gdsIOnceinit(void)954 void io_gdsIOnceinit(void)
955 {
956 INTBIG i, j, k, count, which, *layers, numlayers, fakelayer[1];
957 VARIABLE *var;
958 static POLYGON *poly = NOPOLYGON;
959 REGISTER NODEINST *ni;
960 NODEINST node;
961 REGISTER NODEPROTO *np;
962
963 /* create the polygon */
964 (void)needstaticpolygon(&poly, 4, io_tool->cluster);
965
966 /* run through the node prototypes in this technology */
967 ni = &node; initdummynode(ni);
968
969 /* create the layer mapping table */
970 for (i=0; i<MAXLAYERS; i++)
971 {
972 io_gdslayernodes[i] = NONODEPROTO;
973 io_gdslayertext[i] = 0;
974 io_gdslayershape[i] = 0;
975 io_gdslayerrect[i] = 0;
976 io_gdslayerpath[i] = 0;
977 io_gdslayerpoly[i] = 0;
978 io_gdslayervisible[i] = TRUE;
979 }
980 var = getval((INTBIG)el_curtech, VTECHNOLOGY, -1, x_("IO_gds_layer_numbers"));
981 if (var != NOVARIABLE && (var->type&VISARRAY) == 0) var = NOVARIABLE;
982 if (var != NOVARIABLE)
983 {
984 count = getlength(var);
985 for (i=0; i<count; i++)
986 {
987 if ((var->type&VTYPE) == VSTRING)
988 {
989 io_gdsIparselayernumbers(((CHAR **)var->addr)[i], &layers, &numlayers);
990 } else
991 {
992 fakelayer[0] = ((INTBIG *)var->addr)[i];
993 layers = fakelayer;
994 if (fakelayer[0] < 0) numlayers = 0; else
995 numlayers = 1;
996 }
997 for(k=0; k<numlayers; k++)
998 {
999 which = layers[k];
1000 if (which < 0) continue;
1001 if (which >= MAXLAYERS)
1002 {
1003 ttyputmsg(_("GDS layer %ld is too large (limit is %ld)"), which, MAXLAYERS-1);
1004 continue;
1005 }
1006 for(np = el_curtech->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
1007 {
1008 if (((np->userbits&NFUNCTION)>>NFUNCTIONSH) != NPNODE) continue;
1009 ni->proto = np;
1010 ni->lowx = np->lowx;
1011 ni->highx = np->highx;
1012 ni->lowy = np->lowy;
1013 ni->highy = np->highy;
1014 j = nodepolys(ni, 0, NOWINDOWPART);
1015 if (j != 1) continue;
1016 shapenodepoly(ni, 0, poly);
1017 if (i == poly->layer)
1018 {
1019 /* ignore if this layer is not to be drawn */
1020 if ((poly->desc->colstyle&INVISIBLE) != 0)
1021 io_gdslayervisible[which] = FALSE;
1022 break;
1023 }
1024 }
1025 if (np != NONODEPROTO)
1026 {
1027 io_gdslayernodes[which] = np;
1028 continue;
1029 }
1030 }
1031 }
1032 } else ttyputmsg(_("Technology has no GDSII layer numbers"));
1033 }
1034
1035 /*
1036 * Routine to parse a string of layer numbers in "layernumbers" and return those layers
1037 * in the array "layers", with the size of the array in "total".
1038 */
io_gdsIparselayernumbers(CHAR * layernumbers,INTBIG ** layers,INTBIG * total)1039 void io_gdsIparselayernumbers(CHAR *layernumbers, INTBIG **layers, INTBIG *total)
1040 {
1041 REGISTER CHAR *pt;
1042 REGISTER INTBIG count, i, newtotal, *newlist, number;
1043
1044 count = 0;
1045 pt = layernumbers;
1046 for(;;)
1047 {
1048 while (*pt == ' ') pt++;
1049 if (*pt == 0) break;
1050 number = myatoi(pt);
1051 if (count >= io_gdsIlayerlisttotal)
1052 {
1053 newtotal = io_gdsIlayerlisttotal * 2;
1054 if (count >= newtotal) newtotal = count+5;
1055 newlist = (INTBIG *)emalloc(newtotal * SIZEOFINTBIG, io_tool->cluster);
1056 if (newlist == 0) return;
1057 for(i=0; i<count; i++)
1058 newlist[i] = io_gdsIlayerlist[i];
1059 if (io_gdsIlayerlisttotal > 0) efree((CHAR *)io_gdsIlayerlist);
1060 io_gdsIlayerlist = newlist;
1061 io_gdsIlayerlisttotal = newtotal;
1062 }
1063 io_gdsIlayerlist[count++] = number;
1064 while (*pt != 0 && *pt != ',') pt++;
1065 if (*pt == ',') pt++;
1066 }
1067 *layers = io_gdsIlayerlist;
1068 *total = count;
1069 }
1070
1071 /*
1072 * Routine to initialize the input of a GDS file
1073 */
io_gdsIinit(void)1074 void io_gdsIinit(void)
1075 {
1076 io_gdsbufferindex = -1;
1077 io_gdsrecordcount = 0;
1078 io_gdsblockcount = 1;
1079 io_gdscurlayer = io_gdscursublayer = 0;
1080 }
1081
io_gdsIdetermine_time(CHAR * time_string)1082 void io_gdsIdetermine_time(CHAR *time_string)
1083 {
1084 REGISTER INTBIG i;
1085 CHAR time_array[7][IDSTRING+1];
1086
1087 for (i = 0; i < 6; i++)
1088 {
1089 if (io_gdstoken == GDS_SHORT_NUMBER)
1090 {
1091 if (i == 0 && io_gdstokenvalue16 < 1900)
1092 {
1093 /* handle Y2K date issues */
1094 if (io_gdstokenvalue16 > 60) io_gdstokenvalue16 += 1900; else
1095 io_gdstokenvalue16 += 2000;
1096 }
1097 (void)esnprintf(time_array[i], IDSTRING+1, x_("%02d"), io_gdstokenvalue16);
1098 io_gdsIgettoken();
1099 } else
1100 {
1101 io_gdsIonlyone(io_gdsIrecovery_set, GDS_SHORT_NUMBER);
1102 io_gdsIerror(6);
1103 }
1104 }
1105 (void)esnprintf(time_string, IDSTRING+1, x_("%s-%s-%s at %s:%s:%s"), time_array[1], time_array[2],
1106 time_array[0], time_array[3], time_array[4], time_array[5]);
1107 }
1108
io_gdsIheader(void)1109 void io_gdsIheader(void)
1110 {
1111 if (io_gdstoken == GDS_HEADER)
1112 {
1113 io_gdsIgettoken();
1114 if (io_gdstoken == GDS_SHORT_NUMBER)
1115 {
1116 io_gdsIitoa(io_gdsversionstring, 129, io_gdstokenvalue16);
1117 } else
1118 {
1119 io_gdsIonlyone(io_gdsIrecovery_set, GDS_BGNLIB);
1120 io_gdsIerror(2);
1121 }
1122 } else
1123 {
1124 io_gdsIonlyone(io_gdsIrecovery_set, GDS_BGNLIB);
1125 io_gdsIerror(3);
1126 }
1127 }
1128
io_gdsIlibrary(void)1129 void io_gdsIlibrary(void)
1130 {
1131 CHAR mod_time[IDSTRING+1], create_time[IDSTRING+1];
1132
1133 if (io_gdstoken == GDS_BGNLIB)
1134 {
1135 io_gdsIgettoken();
1136 io_gdsIdetermine_time(create_time);
1137 io_gdsIdetermine_time(mod_time);
1138 if (io_gdstoken == GDS_LIBNAME)
1139 {
1140 io_gdsIgettoken();
1141 if (io_gdstoken == GDS_IDENT)
1142 {
1143 (void)estrcpy(io_gdslibraryname, io_gdstokenstring);
1144 } else
1145 {
1146 io_gdsIonlyone(io_gdsIrecovery_set, GDS_UNITS);
1147 io_gdsIerror(4);
1148 }
1149 } else
1150 {
1151 io_gdsIonlyone(io_gdsIrecovery_set, GDS_UNITS);
1152 }
1153 } else
1154 {
1155 io_gdsIonlyone(io_gdsIrecovery_set, GDS_UNITS);
1156 io_gdsIerror(5);
1157 }
1158 }
1159
io_gdsIreflibs(void)1160 void io_gdsIreflibs(void)
1161 {
1162 io_gdsIgettoken();
1163 io_gdsIgettoken();
1164 }
1165
io_gdsIfonts(void)1166 void io_gdsIfonts(void)
1167 {
1168 io_gdsIgettoken();
1169 io_gdsIgettoken();
1170 }
1171
io_gdsIbackup(void)1172 void io_gdsIbackup(void)
1173 {
1174 CHAR backup_string[IDSTRING+1];
1175
1176 io_gdsIgettoken();
1177 if (io_gdstoken == GDS_SHORT_NUMBER)
1178 {
1179 io_gdsIitoa(backup_string, 129, io_gdstokenvalue16);
1180 } else
1181 {
1182 io_gdsIcopyset(io_gdsIbackup_set, io_gdsIrecovery_set);
1183 io_gdsIerror(8);
1184 }
1185 io_gdsIgettoken();
1186 }
1187
io_gdsIattrtable(void)1188 void io_gdsIattrtable(void)
1189 {
1190 io_gdsIgettoken();
1191 if (io_gdstoken == GDS_IDENT)
1192 {
1193 io_gdsIgettoken();
1194 }
1195 }
1196
io_gdsIunits(void)1197 void io_gdsIunits(void)
1198 {
1199 double meter_unit, db_unit;
1200 double microns_per_user_unit;
1201 CHAR realstring[IDSTRING+1];
1202
1203 if (io_gdstoken == GDS_UNITS)
1204 {
1205 io_gdsIgettoken();
1206 if (io_gdstoken == GDS_REALNUM)
1207 {
1208 db_unit = io_gdsrealtokendp;
1209 /* io_gdstechnologyscalefactor = rounddouble(1.0 / io_gdsrealtokendp); */
1210 io_gdsIgettoken();
1211 meter_unit = io_gdsrealtokendp;
1212 microns_per_user_unit = (meter_unit / db_unit) * 1.0e6;
1213 (void)esnprintf(realstring, IDSTRING+1, x_("%6.3f"), microns_per_user_unit);
1214
1215 /* don't change the cast in this equation - roundoff error! */
1216 io_gdsscale = meter_unit * (double)(1000000 * scalefromdispunit(1.0, DISPUNITMIC));
1217 } else
1218 {
1219 io_gdsIonlyone(io_gdsIrecovery_set, GDS_BGNSTR);
1220 io_gdsIerror(9);
1221 }
1222 } else
1223 {
1224 io_gdsIonlyone(io_gdsIrecovery_set, GDS_BGNSTR);
1225 io_gdsIerror(10);
1226 }
1227 }
1228
io_gdsIunsupported(gsymbol bad_op_set[])1229 void io_gdsIunsupported(gsymbol bad_op_set[])
1230 {
1231 if (io_gdsImember(io_gdstoken, bad_op_set))
1232 do
1233 {
1234 io_gdsIgettoken();
1235 } while (!io_gdsImember(io_gdstoken, io_gdsIgood_op_set));
1236 }
1237
io_gdsIdetermine_points(INTBIG min_points,INTBIG max_points,INTBIG * point_counter)1238 void io_gdsIdetermine_points(INTBIG min_points, INTBIG max_points, INTBIG *point_counter)
1239 {
1240 (*point_counter) = 0;
1241 while (io_gdstoken == GDS_NUMBER)
1242 {
1243 io_gdsvertex[*point_counter].px = rounddouble((double)io_gdstokenvalue32 * io_gdsscale);
1244 io_gdsIgettoken();
1245 io_gdsvertex[*point_counter].py = rounddouble((double)io_gdstokenvalue32 * io_gdsscale);
1246 (*point_counter)++;
1247 if (*point_counter > max_points)
1248 {
1249 ttyputmsg(_("Found %ld points"), *point_counter);
1250 io_gdsIerror(21);
1251 }
1252 io_gdsIgettoken();
1253 }
1254 if (*point_counter < min_points)
1255 {
1256 ttyputmsg(_("Found %ld points"), *point_counter);
1257 io_gdsIerror(20);
1258 }
1259 }
1260
io_gdsIdetermine_orientation(INTBIG * angle,INTBIG * trans,double * scale)1261 void io_gdsIdetermine_orientation(INTBIG *angle, INTBIG *trans, double *scale)
1262 {
1263 BOOLEAN mirror_x;
1264 double anglevalue;
1265
1266 anglevalue = 0.0;
1267 *scale = 1.0;
1268 mirror_x = FALSE;
1269 io_gdsIgettoken();
1270 if (io_gdstoken == GDS_FLAGSYM)
1271 {
1272 if ((io_gdstokenflags&0100000) != 0) mirror_x = TRUE;
1273 io_gdsIgettoken();
1274 } else
1275 {
1276 io_gdsIonlyone(io_gdsIrecovery_set, GDS_XY);
1277 io_gdsIerror(19);
1278 }
1279 if (io_gdstoken == GDS_MAG)
1280 {
1281 io_gdsIgettoken();
1282 *scale = io_gdsrealtokendp;
1283 io_gdsIgettoken();
1284 }
1285 if (io_gdstoken == GDS_ANGLE)
1286 {
1287 io_gdsIgettoken();
1288 anglevalue = io_gdsrealtokendp * 10;
1289 io_gdsIgettoken();
1290 }
1291 io_gdsItranslate(angle, trans, anglevalue, mirror_x);
1292 }
1293
io_gdsIdetermine_layer(INTBIG * layer,INTBIG * sublayer)1294 void io_gdsIdetermine_layer(INTBIG *layer, INTBIG *sublayer)
1295 {
1296 *layer = io_gdscurlayer;
1297 *sublayer = io_gdscursublayer;
1298 if (io_gdstoken == GDS_LAYER)
1299 {
1300 io_gdsIgettoken();
1301 if (io_gdstoken == GDS_SHORT_NUMBER)
1302 {
1303 io_gdscurlayer = *layer = io_gdstokenvalue16;
1304 if (io_gdscurlayer >= MAXLAYERS)
1305 {
1306 ttyputmsg(_("GDS layer %ld is too high (limit is %d)"),
1307 io_gdscurlayer, MAXLAYERS-1);
1308 io_gdscurlayer = MAXLAYERS-1;
1309 }
1310 if (io_gdslayernodes[io_gdscurlayer] == NONODEPROTO)
1311 {
1312 if ((io_gdscurstate[0]&GDSINIGNOREUKN) == 0)
1313 {
1314 ttyputmsg(_("GDS layer %ld unknown, using Generic:DRC"),
1315 io_gdscurlayer);
1316 } else
1317 {
1318 ttyputmsg(_("GDS layer %ld unknown, ignoring it"),
1319 io_gdscurlayer);
1320 }
1321 io_gdslayernodes[io_gdscurlayer] = gen_drcprim;
1322 }
1323 io_gdslayernode = io_gdslayernodes[io_gdscurlayer];
1324 if (io_gdslayernode == gen_drcprim &&
1325 (io_gdscurstate[0]&GDSINIGNOREUKN) != 0)
1326 {
1327 io_gdslayerused = FALSE;
1328 } else
1329 {
1330 io_gdslayerused = io_gdslayervisible[io_gdscurlayer];
1331 }
1332 io_gdslayerwhich = io_gdscurlayer;
1333
1334 io_gdsIgettoken();
1335 if (io_gdsImember(io_gdstoken, io_gdsImask_set))
1336 {
1337 io_gdsIgettoken();
1338 if (io_gdstokenvalue16 != 0)
1339 {
1340 io_gdscursublayer = *sublayer = io_gdstokenvalue16;
1341 }
1342 } else
1343 {
1344 io_gdsIonlyone(io_gdsIrecovery_set, GDS_XY);
1345 io_gdsIerror(24);
1346 }
1347 } else
1348 {
1349 io_gdsIonlyone(io_gdsIrecovery_set, GDS_XY);
1350 io_gdsIerror(22);
1351 }
1352 } else
1353 {
1354 io_gdsIonlyone(io_gdsIrecovery_set, GDS_XY);
1355 io_gdsIerror(23);
1356 }
1357 }
1358
io_gdsIfindproto(CHAR * name)1359 NODEPROTO *io_gdsIfindproto(CHAR *name)
1360 {
1361 REGISTER NODEPROTO *np;
1362
1363 for(np = io_gdslibrary->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
1364 if (namesame(name, np->protoname) == 0) return(np);
1365 return(NONODEPROTO);
1366 }
1367
io_gdsIbeginstructure(void)1368 void io_gdsIbeginstructure(void)
1369 {
1370 CHAR create_time[IDSTRING+1], mod_time[IDSTRING+1];
1371 REGISTER void *infstr;
1372
1373 if (io_gdstoken == GDS_BGNSTR)
1374 {
1375 io_gdsIgettoken();
1376 io_gdsIdetermine_time(create_time);
1377 io_gdsIdetermine_time(mod_time);
1378 if (io_gdstoken == GDS_STRNAME)
1379 {
1380 io_gdsIgettoken();
1381 if (io_gdstoken == GDS_IDENT)
1382 {
1383 /* look for this nodeproto */
1384 io_gdsstructure = io_gdsIfindproto(io_gdstokenstring);
1385 if (io_gdsstructure == NONODEPROTO)
1386 {
1387 /* create the proto */
1388 io_gdsstructure = us_newnodeproto(io_gdstokenstring, io_gdslibrary);
1389 if (io_gdsstructure == NONODEPROTO)
1390 io_gdsIerror(38);
1391 if (io_verbose < 0 && io_gdsfilesize > 0)
1392 {
1393 infstr = initinfstr();
1394 formatinfstr(infstr, _("Reading %s"), io_gdstokenstring);
1395 DiaSetTextProgress(io_gdsprogressdialog, returninfstr(infstr));
1396 } else if (io_verbose != 0) ttyputmsg(_("Reading %s"), io_gdstokenstring);
1397 if (io_gdslibrary->curnodeproto == NONODEPROTO)
1398 io_gdslibrary->curnodeproto = io_gdsstructure;
1399 }
1400 } else
1401 {
1402 io_gdsIcopyset(io_gdsIshape_set, io_gdsIrecovery_set);
1403 io_gdsIappendset(io_gdsIrecovery_set, GDS_ENDSTR);
1404 io_gdsIerror(12);
1405 }
1406 } else
1407 {
1408 io_gdsIcopyset(io_gdsIshape_set, io_gdsIrecovery_set);
1409 io_gdsIappendset(io_gdsIrecovery_set, GDS_ENDSTR);
1410 io_gdsIerror(13);
1411 }
1412 } else
1413 {
1414 io_gdsIcopyset(io_gdsIshape_set, io_gdsIrecovery_set);
1415 io_gdsIappendset(io_gdsIrecovery_set, GDS_ENDSTR);
1416 io_gdsIerror(14);
1417 }
1418 }
1419
io_gdsIdetermine_property(void)1420 void io_gdsIdetermine_property(void)
1421 {
1422 CHAR propvalue[IDSTRING+1];
1423
1424 io_gdsIgettoken();
1425 io_gdsIgettoken();
1426 if (io_gdstoken == GDS_PROPVALUE)
1427 {
1428 io_gdsIgettoken();
1429 (void)estrcpy(propvalue, io_gdstokenstring);
1430
1431 /* add to the current structure as a variable? */
1432 io_gdsIgettoken();
1433 } else
1434 {
1435 io_gdsIonlyone(io_gdsIrecovery_set, GDS_ENDEL);
1436 io_gdsIerror(29);
1437 }
1438 /* close Attribute */
1439 }
1440
1441 /* need more info ... */
io_gdsIdetermine_node(void)1442 void io_gdsIdetermine_node(void)
1443 {
1444 INTBIG n;
1445
1446 io_gdsIgettoken();
1447 io_gdsIunsupported(io_gdsIunsupported_set);
1448 if (io_gdstoken == GDS_LAYER)
1449 {
1450 io_gdsIgettoken();
1451 if (io_gdstoken == GDS_SHORT_NUMBER)
1452 {
1453 io_gdscurlayer = io_gdstokenvalue16;
1454 if (io_gdscurlayer >= MAXLAYERS)
1455 {
1456 ttyputmsg(_("GDS layer %ld is too high (limit is %d)"),
1457 io_gdscurlayer, MAXLAYERS-1);
1458 io_gdscurlayer = MAXLAYERS-1;
1459 }
1460 if (io_gdslayernodes[io_gdscurlayer] == NONODEPROTO)
1461 {
1462 ttyputmsg(_("GDS layer %ld unknown, using Generic:DRC"),
1463 io_gdscurlayer);
1464 io_gdslayernodes[io_gdscurlayer] = gen_drcprim;
1465 }
1466 io_gdslayernode = io_gdslayernodes[io_gdscurlayer];
1467
1468 io_gdsIgettoken();
1469 }
1470 } else
1471 {
1472 io_gdsIonlyone(io_gdsIrecovery_set, GDS_ENDEL);
1473 io_gdsIerror(18);
1474 }
1475
1476 /* should do something with node type??? */
1477 if (io_gdstoken == GDS_NODETYPE)
1478 {
1479 io_gdsIgettoken();
1480 io_gdsIgettoken();
1481 }
1482
1483 /* make a dot */
1484 if (io_gdstoken == GDS_XY)
1485 {
1486 io_gdsIgettoken();
1487 io_gdsIdetermine_points(1, 1, &n);
1488
1489 /* create the node */
1490 if (newnodeinst(io_gdslayernode, io_gdsvertex[0].px,
1491 io_gdsvertex[0].px, io_gdsvertex[0].py, io_gdsvertex[0].py, 0, 0,
1492 io_gdsstructure) == NONODEINST)
1493 io_gdsIerror(40);
1494 } else
1495 {
1496 io_gdsIonlyone(io_gdsIrecovery_set, GDS_ENDEL);
1497 io_gdsIerror(18);
1498 }
1499 }
1500
1501 /* untested feature, I don't have a box type */
io_gdsIdetermine_box(void)1502 void io_gdsIdetermine_box(void)
1503 {
1504 INTBIG n, layer, sublayer;
1505
1506 io_gdsIgettoken();
1507 io_gdsIunsupported(io_gdsIunsupported_set);
1508 io_gdsIdetermine_layer(&layer, &sublayer);
1509 if (io_gdstoken == GDS_XY)
1510 {
1511 io_gdsIgettoken();
1512 io_gdsIdetermine_points(2, MAXPOINTS, &n);
1513 if (io_gdslayerused)
1514 {
1515 /* create the box */
1516 io_gdslayerrect[io_gdslayerwhich]++;
1517 io_gdslayerpoly[io_gdslayerwhich]++;
1518 if (newnodeinst(io_gdslayernode, io_gdsvertex[0].px, io_gdsvertex[1].px,
1519 io_gdsvertex[0].py, io_gdsvertex[1].py , 0, 0,
1520 io_gdsstructure) == NONODEINST)
1521 io_gdsIerror(41);
1522 }
1523 } else
1524 {
1525 io_gdsIonlyone(io_gdsIrecovery_set, GDS_ENDEL);
1526 io_gdsIerror(18);
1527 }
1528 }
1529
io_gdsIdetermine_shape(void)1530 void io_gdsIdetermine_shape(void)
1531 {
1532 INTBIG n, layer, sublayer;
1533 shape_type perimeter, oclass;
1534
1535 io_gdsIgettoken();
1536 io_gdsIunsupported(io_gdsIunsupported_set);
1537 io_gdsIdetermine_layer(&layer, &sublayer);
1538 io_gdsIgettoken();
1539 if (io_gdstoken == GDS_XY)
1540 {
1541 io_gdsIgettoken();
1542 io_gdsIdetermine_points(3, MAXPOINTS, &n);
1543 io_gdsIdetermine_boundary(n, &perimeter, &oclass);
1544 io_gdsIshape(n, perimeter, oclass);
1545 } else
1546 {
1547 io_gdsIonlyone(io_gdsIrecovery_set, GDS_ENDEL);
1548 io_gdsIerror(18);
1549 }
1550 }
1551
io_gdsIdetermine_path(void)1552 void io_gdsIdetermine_path(void)
1553 {
1554 INTBIG endcode, n, layer, sublayer, off[8], thisAngle, lastAngle, nextAngle,
1555 bgnextend, endextend, fextend, textend, ang;
1556 INTBIG width, length, lx, ly, hx, hy, i, j, fx, fy, tx, ty, cx, cy;
1557 REGISTER NODEINST *ni;
1558 static POLYGON *poly = NOPOLYGON;
1559
1560 endcode = 0;
1561 io_gdsIgettoken();
1562 io_gdsIunsupported(io_gdsIunsupported_set);
1563 io_gdsIdetermine_layer(&layer, &sublayer);
1564 io_gdsIgettoken();
1565 if (io_gdstoken == GDS_PATHTYPE)
1566 {
1567 io_gdsIgettoken();
1568 endcode = io_gdstokenvalue16;
1569 io_gdsIgettoken();
1570 }
1571 if (io_gdstoken == GDS_WIDTH)
1572 {
1573 io_gdsIgettoken();
1574 width = rounddouble((double)io_gdstokenvalue32 * io_gdsscale);
1575 io_gdsIgettoken();
1576 } else
1577 {
1578 width = 0;
1579 }
1580 #ifdef NEWPATH
1581 bgnextend = endextend = (endcode == 0 || endcode == 4 ? 0 : width/2);
1582 if (io_gdstoken == GDS_BGNEXTN)
1583 {
1584 io_gdsIgettoken();
1585 if (endcode == 4)
1586 bgnextend = rounddouble((double)io_gdstokenvalue32 * io_gdsscale);
1587 io_gdsIgettoken();
1588 }
1589 if (io_gdstoken == GDS_ENDEXTN)
1590 {
1591 io_gdsIgettoken();
1592 if (endcode == 4)
1593 endextend = rounddouble((double)io_gdstokenvalue32 * io_gdsscale);
1594 io_gdsIgettoken();
1595 }
1596 #endif
1597 if (io_gdstoken == GDS_XY)
1598 {
1599 io_gdsIgettoken();
1600 io_gdsIdetermine_points(2, MAXPOINTS, &n);
1601 if (io_gdslayerused)
1602 io_gdslayerpath[io_gdslayerwhich]++;
1603
1604 /* construct the path */
1605 for (i=0; i < n-1; i++)
1606 {
1607 fx = io_gdsvertex[i].px; fy = io_gdsvertex[i].py;
1608 tx = io_gdsvertex[i+1].px; ty = io_gdsvertex[i+1].py;
1609
1610 /* determine whether either end needs to be shrunk */
1611 fextend = textend = width / 2;
1612 thisAngle = figureangle(fx, fy, tx, ty);
1613 if (i > 0)
1614 {
1615 lastAngle = figureangle(io_gdsvertex[i-1].px, io_gdsvertex[i-1].py,
1616 io_gdsvertex[i].px, io_gdsvertex[i].py);
1617 if (abs(thisAngle-lastAngle) % 900 != 0)
1618 {
1619 ang = abs(thisAngle-lastAngle) / 10;
1620 if (ang > 180) ang = 360 - ang;
1621 if (ang > 90) ang = 180 - ang;
1622 fextend = tech_getextendfactor(width, ang);
1623 }
1624 #ifdef NEWPATH
1625 } else
1626 {
1627 fextend = bgnextend;
1628 #endif
1629 }
1630 if (i+1 < n-1)
1631 {
1632 nextAngle = figureangle(io_gdsvertex[i+1].px, io_gdsvertex[i+1].py,
1633 io_gdsvertex[i+2].px, io_gdsvertex[i+2].py);
1634 if (abs(thisAngle-nextAngle) % 900 != 0)
1635 {
1636 ang = abs(thisAngle-nextAngle) / 10;
1637 if (ang > 180) ang = 360 - ang;
1638 if (ang > 90) ang = 180 - ang;
1639 textend = tech_getextendfactor(width, ang);
1640 }
1641 #ifdef NEWPATH
1642 } else
1643 {
1644 textend = endextend;
1645 #endif
1646 }
1647
1648 /* handle arbitrary angle path segment */
1649 if (io_gdslayerused)
1650 {
1651 io_gdslayerpoly[io_gdslayerwhich]++;
1652
1653 /* get polygon */
1654 (void)needstaticpolygon(&poly, 4, io_tool->cluster);
1655
1656 /* determine shape of segment */
1657 length = computedistance(fx, fy, tx, ty);
1658 #ifndef NEWPATH
1659 if (endcode == 0) fextend = textend = 0;
1660 #endif
1661 j = figureangle(fx, fy, tx, ty);
1662 tech_makeendpointpoly(length, width, j, fx, fy, fextend,
1663 tx, ty, textend, poly);
1664
1665 /* make the node for this segment */
1666 if (isbox(poly, &lx, &hx, &ly, &hy))
1667 {
1668 if (newnodeinst(io_gdslayernode, lx, hx, ly, hy, 0, 0,
1669 io_gdsstructure) == NONODEINST)
1670 io_gdsIerror(42);
1671 } else
1672 {
1673 getbbox(poly, &lx, &hx, &ly, &hy);
1674 ni = newnodeinst(io_gdslayernode, lx, hx, ly, hy, 0, 0, io_gdsstructure);
1675 if (ni == NONODEINST)
1676 io_gdsIerror(42);
1677
1678 /* set the shape into the node */
1679 cx = (lx + hx) / 2;
1680 cy = (ly + hy) / 2;
1681 for(j=0; j<4; j++)
1682 {
1683 off[j*2] = poly->xv[j] - cx;
1684 off[j*2+1] = poly->yv[j] - cy;
1685 }
1686 (void)setvalkey((INTBIG)ni, VNODEINST, el_trace_key, (INTBIG)off,
1687 VINTEGER|VISARRAY|(8<<VLENGTHSH));
1688 }
1689 }
1690 }
1691 } else
1692 {
1693 io_gdsIonlyone(io_gdsIrecovery_set, GDS_ENDEL);
1694 io_gdsIerror(25);
1695 }
1696 }
1697
io_gdsIgetproto(CHAR * name)1698 void io_gdsIgetproto(CHAR *name)
1699 {
1700 NODEPROTO *np;
1701 REGISTER void *infstr;
1702
1703 /* scan for this proto */
1704 np = io_gdsIfindproto(name);
1705 if (np == NONODEPROTO)
1706 {
1707 /* FILO order, create this nodeproto */
1708 if ((np = us_newnodeproto(io_gdstokenstring, io_gdslibrary)) == NONODEPROTO)
1709 io_gdsIerror(43);
1710 if (io_verbose < 0 && io_gdsfilesize > 0)
1711 {
1712 infstr = initinfstr();
1713 formatinfstr(infstr, _("Reading %s"), io_gdstokenstring);
1714 DiaSetTextProgress(io_gdsprogressdialog, returninfstr(infstr));
1715 } else if (io_verbose != 0) ttyputmsg(_("Reading %s"), io_gdstokenstring);
1716 }
1717
1718 /* set the reference node proto */
1719 io_gdssref = np;
1720 }
1721
io_gdsIdetermine_sref(void)1722 void io_gdsIdetermine_sref(void)
1723 {
1724 INTBIG n, angle, trans, cx, cy, ox, oy;
1725 XARRAY transform;
1726 double scale;
1727
1728 io_gdsIgettoken();
1729 io_gdsIunsupported(io_gdsIunsupported_set);
1730 if (io_gdstoken == GDS_SNAME)
1731 {
1732 io_gdsIgettoken();
1733 io_gdsIgetproto(io_gdstokenstring);
1734 io_gdsIgettoken();
1735 if (io_gdstoken == GDS_STRANS)
1736 io_gdsIdetermine_orientation(&angle, &trans, &scale);
1737 else
1738 {
1739 angle = 0; trans = 0;
1740 scale = 1.0;
1741 }
1742 if (io_gdstoken == GDS_XY)
1743 {
1744 io_gdsIgettoken();
1745 io_gdsIdetermine_points(1, 1, &n);
1746 /* close Translate */
1747 } else
1748 {
1749 io_gdsIonlyone(io_gdsIrecovery_set, GDS_ENDEL);
1750 io_gdsIerror(17);
1751 }
1752
1753 /* create the node */
1754 makeangle(angle, trans, transform);
1755
1756 /* now transform the center */
1757 cx = (io_gdssref->highx + io_gdssref->lowx) / 2;
1758 cy = (io_gdssref->highy + io_gdssref->lowy) / 2;
1759 xform(cx, cy, &ox, &oy, transform);
1760
1761 /* calculate the offset from the original center */
1762 ox -= cx; oy -= cy;
1763
1764 if ((io_gdsinstance = newnodeinst(io_gdssref,
1765 io_gdsvertex[0].px + io_gdssref->lowx + ox,
1766 io_gdsvertex[0].px + io_gdssref->highx + ox,
1767 io_gdsvertex[0].py + io_gdssref->lowy + oy,
1768 io_gdsvertex[0].py + io_gdssref->highy + oy,
1769 trans, angle, io_gdsstructure)) == NONODEINST)
1770 io_gdsIerror(44);
1771 if (io_gdscurstate[0]&GDSINEXPAND)
1772 io_gdsinstance->userbits |= NEXPAND;
1773 io_gdssrefcount++;
1774 } else
1775 {
1776 io_gdsIonlyone(io_gdsIrecovery_set, GDS_ENDEL);
1777 io_gdsIerror(16);
1778 }
1779 }
1780
io_gdsIdetermine_aref(void)1781 void io_gdsIdetermine_aref(void)
1782 {
1783 INTBIG n, ncols, nrows, angle, trans;
1784 double scale;
1785
1786 io_gdsIgettoken();
1787 io_gdsIunsupported(io_gdsIunsupported_set);
1788 if (io_gdstoken == GDS_SNAME)
1789 {
1790 io_gdsIgettoken();
1791
1792 /* get this nodeproto */
1793 io_gdsIgetproto(io_gdstokenstring);
1794 io_gdsIgettoken();
1795 if (io_gdstoken == GDS_STRANS)
1796 io_gdsIdetermine_orientation(&angle, &trans, &scale);
1797 else
1798 {
1799 angle = trans = 0;
1800 scale = 1.0;
1801 }
1802 if (io_gdstoken == GDS_COLROW)
1803 {
1804 io_gdsIgettoken();
1805 ncols = io_gdstokenvalue16;
1806 io_gdsIgettoken();
1807 nrows = io_gdstokenvalue16;
1808 io_gdsIgettoken();
1809 }
1810 if (io_gdstoken == GDS_XY)
1811 {
1812 io_gdsIgettoken();
1813 io_gdsIdetermine_points(3, 3, &n);
1814 io_gdsIstep(ncols, nrows, angle, trans);
1815 } else
1816 {
1817 io_gdsIonlyone(io_gdsIrecovery_set, GDS_ENDEL);
1818 io_gdsIerror(27);
1819 }
1820 } else
1821 {
1822 io_gdsIonlyone(io_gdsIrecovery_set, GDS_ENDEL);
1823 io_gdsIerror(28);
1824 }
1825 }
1826
io_gdsIdetermine_justification(INTBIG * vert_just,INTBIG * horiz_just)1827 void io_gdsIdetermine_justification(INTBIG *vert_just, INTBIG *horiz_just)
1828 {
1829 INTBIG font_libno;
1830
1831 io_gdsIgettoken();
1832 if (io_gdstoken == GDS_FLAGSYM)
1833 {
1834 font_libno = io_gdstokenflags & 0x0030;
1835 font_libno = font_libno >> 4;
1836 (*vert_just) = io_gdstokenflags & 0x000C;
1837 (*vert_just) = (*vert_just) >> 2;
1838 (*horiz_just) = io_gdstokenflags & 0x0003;
1839 io_gdsIgettoken();
1840 } else
1841 {
1842 io_gdsIonlyone(io_gdsIrecovery_set, GDS_XY);
1843 io_gdsIerror(27);
1844 }
1845 }
1846
io_gdsIdetermine_text(void)1847 void io_gdsIdetermine_text(void)
1848 {
1849 INTBIG vert_just, horiz_just, layer, sublayer;
1850 CHAR textstring[TEXTLINE+1];
1851 INTBIG n, angle, trans;
1852 double scale;
1853
1854 io_gdsIgettoken();
1855 io_gdsIunsupported(io_gdsIunsupported_set);
1856 io_gdsIdetermine_layer(&layer, &sublayer);
1857 io_gdsIgettoken();
1858 vert_just = -1;
1859 horiz_just = -1;
1860 if (io_gdstoken == GDS_PRESENTATION)
1861 io_gdsIdetermine_justification(&vert_just, &horiz_just);
1862 if (io_gdstoken == GDS_PATHTYPE)
1863 {
1864 io_gdsIgettoken();
1865 /* pathcode = io_gdstokenvalue16; */
1866 io_gdsIgettoken();
1867 }
1868 if (io_gdstoken == GDS_WIDTH)
1869 {
1870 io_gdsIgettoken();
1871 /* pathwidth = rounddouble((double)io_gdstokenvalue32 * io_gdsscale); */
1872 io_gdsIgettoken();
1873 }
1874 angle = trans = 0;
1875 scale = 1.0;
1876 for(;;)
1877 {
1878 if (io_gdstoken == GDS_STRANS)
1879 {
1880 io_gdsIdetermine_orientation(&angle, &trans, &scale);
1881 continue;
1882 }
1883 if (io_gdstoken == GDS_XY)
1884 {
1885 io_gdsIgettoken();
1886 io_gdsIdetermine_points(1, 1, &n);
1887 continue;
1888 }
1889 if (io_gdstoken == GDS_ANGLE)
1890 {
1891 io_gdsIgettoken();
1892 angle = (INTBIG)(io_gdsrealtokendp * 10.0);
1893 io_gdsIgettoken();
1894 continue;
1895 }
1896 if (io_gdstoken == GDS_STRING)
1897 {
1898 if (io_gdsrecordcount == 0) textstring[0] = '\0'; else
1899 {
1900 io_gdsIgettoken();
1901 (void)estrcpy(textstring, io_gdstokenstring);
1902 }
1903 io_gdsIgettoken();
1904 break;
1905 }
1906 if (io_gdstoken == GDS_MAG)
1907 {
1908 io_gdsIgettoken();
1909 io_gdsIgettoken();
1910 continue;
1911 }
1912 io_gdsIonlyone(io_gdsIrecovery_set, GDS_ENDEL);
1913 io_gdsIerror(26);
1914 break;
1915 }
1916 io_gdsItext(textstring, vert_just, horiz_just, angle, trans, scale);
1917 }
1918
io_gdsIelement(BOOLEAN * empty_structure)1919 void io_gdsIelement(BOOLEAN *empty_structure)
1920 {
1921 while (io_gdsImember(io_gdstoken, io_gdsIshape_set))
1922 {
1923 switch (io_gdstoken)
1924 {
1925 case GDS_AREF: io_gdsIdetermine_aref(); break;
1926 case GDS_SREF: io_gdsIdetermine_sref(); break;
1927 case GDS_BOUNDARY: io_gdsIdetermine_shape(); break;
1928 case GDS_PATH: io_gdsIdetermine_path(); break;
1929 case GDS_NODE: io_gdsIdetermine_node(); break;
1930 case GDS_TEXTSYM: io_gdsIdetermine_text(); break;
1931 case GDS_BOX: io_gdsIdetermine_box(); break;
1932 default: break;
1933 }
1934 }
1935
1936 while (io_gdstoken == GDS_PROPATTR)
1937 io_gdsIdetermine_property();
1938 if (io_gdstoken != GDS_ENDEL)
1939 {
1940 io_gdsIonlyone(io_gdsIrecovery_set, GDS_BGNSTR);
1941 io_gdsIerror(15);
1942 }
1943 (*empty_structure) = FALSE;
1944 }
1945
io_gdsIstructure(void)1946 void io_gdsIstructure(void)
1947 {
1948 BOOLEAN empty_structure;
1949
1950 io_gdsIbeginstructure();
1951 empty_structure = TRUE;
1952 io_gdsIgettoken();
1953 while (io_gdstoken != GDS_ENDSTR)
1954 {
1955 io_gdsIelement(&empty_structure);
1956 io_gdsIgettoken();
1957 }
1958 if (empty_structure)
1959 {
1960 ttyputmsg(x_("%s"), TRANSLATE(io_gdsIerror_string[11]));
1961 ttyputerr(_("Error at block number %5d and offset %4d"),
1962 io_gdsblockcount, io_gdsbufferindex);
1963 return;
1964 }
1965
1966 db_boundcell(io_gdsstructure, &io_gdsstructure->lowx, &io_gdsstructure->highx,
1967 &io_gdsstructure->lowy, &io_gdsstructure->highy);
1968 }
1969
io_gdsIload(FILE * input)1970 BOOLEAN io_gdsIload(FILE *input)
1971 {
1972 io_gdsIinit();
1973 io_gdsIgettoken();
1974 io_gdsIheader();
1975 io_gdsIgettoken();
1976 io_gdsIlibrary();
1977 io_gdsIgettoken();
1978 while (io_gdsImember(io_gdstoken, io_gdsIoption_set))
1979 switch (io_gdstoken)
1980 {
1981 case GDS_REFLIBS:
1982 io_gdsIreflibs(); break;
1983 case GDS_FONTS:
1984 io_gdsIfonts(); break;
1985 case GDS_ATTRTABLE:
1986 io_gdsIattrtable(); break;
1987 case GDS_GENERATIONS:
1988 io_gdsIbackup(); break;
1989 default: break;
1990 }
1991 while (io_gdstoken != GDS_UNITS)
1992 io_gdsIgettoken();
1993 io_gdsIunits();
1994 io_gdsIgettoken();
1995 while (io_gdstoken != GDS_ENDLIB)
1996 {
1997 io_gdsIstructure();
1998 io_gdsIgettoken();
1999 }
2000 return(FALSE);
2001 }
2002
2003 /* module: io_readgdslibrary
2004 * function: Electric entry-point in gdsII stream library read.
2005 * inputs:
2006 * lib - the library to read
2007 * position: 0 for single-file input,
2008 * 1 for first of series
2009 * 2 for midseriese
2010 * 3 for end of series
2011 * returns false on success, true on error
2012 */
io_readgdslibrary(LIBRARY * lib,INTBIG position)2013 BOOLEAN io_readgdslibrary(LIBRARY *lib, INTBIG position)
2014 {
2015 FILE *input;
2016 BOOLEAN err;
2017 INTBIG i;
2018 INTBIG count;
2019 CHAR *filename;
2020 NODEPROTO *np;
2021
2022 io_gdslibrary = lib;
2023
2024 /* get current state of I/O tool */
2025 io_gdscurstate = io_getstatebits();
2026
2027 /* get the gds file */
2028 if ((input = xopen(io_gdslibrary->libfile, io_filetypegds, x_(""), &filename)) == NULL)
2029 {
2030 ttyputerr(_("File %s not found"), io_gdslibrary->libfile);
2031 return(TRUE);
2032 }
2033
2034 io_gdsstream.fp = input;
2035 io_gdsfilesize = filesize(input);
2036 if (io_verbose < 0 && io_gdsfilesize > 0)
2037 {
2038 io_gdsprogressdialog = DiaInitProgress(0, 0);
2039 if (io_gdsprogressdialog == 0)
2040 {
2041 xclose(input);
2042 return(TRUE);
2043 }
2044 DiaSetProgress(io_gdsprogressdialog, 0, io_gdsfilesize);
2045 }
2046 io_gdsbytesread = 0;
2047
2048 /* setup the error return location */
2049 if (setjmp(io_gdsenv) != 0)
2050 {
2051 xclose(input);
2052 if (io_verbose < 0 && io_gdsfilesize > 0) DiaDoneProgress(io_gdsprogressdialog);
2053 return(TRUE);
2054 }
2055
2056 /* set default objects */
2057 io_gdslayernode = gen_drcprim;
2058 if (position == 0 || position == 1)
2059 {
2060 io_gdsIOnceinit();
2061 io_gdssrefcount = 0;
2062 }
2063
2064 err = io_gdsIload(input);
2065
2066 /* output layer use table */
2067 if (io_verbose == 1)
2068 {
2069 if (position == 0 || position == 3)
2070 {
2071 if (position == 0)
2072 ttyputmsg(_("%s information:"), skippath(io_gdslibrary->libfile)); else
2073 ttyputmsg(_("Summary information:"));
2074 ttyputmsg(x_(" %ld %s"), io_gdssrefcount, makeplural(x_("SREF"), io_gdssrefcount));
2075 for (i = 0; i < MAXLAYERS; i++)
2076 {
2077 if (io_gdslayertext[i] || io_gdslayerpoly[i])
2078 {
2079 if (i < el_curtech->layercount)
2080 {
2081 ttyputmsg(_(" %ld objects on layer %ld (%s)"),
2082 io_gdslayerpoly[i]+io_gdslayertext[i], i,
2083 describenodeproto(io_gdslayernodes[i]));
2084 } else
2085 {
2086 ttyputmsg(_(" %ld objects on layer %ld"),
2087 io_gdslayerpoly[i]+io_gdslayertext[i], i);
2088 }
2089 }
2090 }
2091 }
2092 }
2093
2094 /* finish up */
2095 xclose(input);
2096
2097 if (position == 0 || position == 3)
2098 {
2099 if (io_verbose < 0 && io_gdsfilesize > 0)
2100 {
2101 DiaSetTextProgress(io_gdsprogressdialog, _("Cleaning up..."));
2102 DiaSetProgress(io_gdsprogressdialog, 0, io_gdssrefcount);
2103 }
2104
2105 /* determine which cells need to be recomputed */
2106 count = io_gdssrefcount;
2107 for (i = 0; i < MAXLAYERS; i++)
2108 count += io_gdslayertext[i] + io_gdslayerpoly[i];
2109 for(np = io_gdslibrary->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
2110 np->temp1 = 0;
2111 io_gdsrecomputed = 0;
2112 for(np = io_gdslibrary->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
2113 if (np->temp1 == 0)
2114 io_gdsIrecompute(np, count);
2115
2116 }
2117 if (io_verbose < 0 && io_gdsfilesize > 0) DiaDoneProgress(io_gdsprogressdialog);
2118 return(err);
2119 }
2120
io_gdsIrecompute(NODEPROTO * np,INTBIG count)2121 void io_gdsIrecompute(NODEPROTO *np, INTBIG count)
2122 {
2123 REGISTER INTBIG cx, cy;
2124 CHAR numsofar[50];
2125 INTBIG ox, oy;
2126 XARRAY trans;
2127 REGISTER NODEINST *ni;
2128
2129 /* rebuild the geometry database, note that this is faster then
2130 just updating the SREF info */
2131 /* first clear the geometry structure */
2132 db_freertree(np->rtree);
2133 (void)geomstructure(np);
2134 for(ni = np->firstnodeinst; ni != NONODEINST; ni = ni->nextnodeinst)
2135 {
2136 if (ni->proto->primindex == 0)
2137 {
2138 if (ni->proto->temp1 == 0)
2139 io_gdsIrecompute(ni->proto, count);
2140 if ((ni->highx-ni->lowx) != (ni->proto->highx-ni->proto->lowx) ||
2141 (ni->highy-ni->lowy) != (ni->proto->highy-ni->proto->lowy))
2142 {
2143 makeangle(ni->rotation, ni->transpose, trans);
2144
2145 /* now transform the center */
2146 cx = (ni->proto->highx + ni->proto->lowx) / 2;
2147 cy = (ni->proto->highy + ni->proto->lowy) / 2;
2148 xform(cx, cy, &ox, &oy, trans);
2149
2150 /* calculate the offset from the original center */
2151 ox -= cx; oy -= cy;
2152 ni->lowx += (ni->proto->lowx + ox);
2153 ni->highx += (ni->proto->highx + ox);
2154 ni->lowy += (ni->proto->lowy + oy);
2155 ni->highy += (ni->proto->highy + oy);
2156 boundobj(ni->geom, &(ni->geom->lowx), &(ni->geom->highx),
2157 &(ni->geom->lowy), &(ni->geom->highy));
2158 }
2159 }
2160
2161 /* now link into the geometry list */
2162 linkgeom(ni->geom, np);
2163
2164 io_gdsrecomputed++;
2165 if ((io_gdsrecomputed%1000) == 0 && io_verbose < 0 && io_gdsfilesize > 0)
2166 {
2167 (void)esnprintf(numsofar, 50, _("Cleaned up %ld instances..."), io_gdsrecomputed);
2168 DiaSetTextProgress(io_gdsprogressdialog, numsofar);
2169 if (count > 0)
2170 DiaSetProgress(io_gdsprogressdialog, io_gdsrecomputed, count);
2171 }
2172 }
2173
2174 db_boundcell(np, &np->lowx, &np->highx, &np->lowy, &np->highy);
2175 np->temp1 = 1;
2176 }
2177