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