1 /* -*- tab-width: 4 -*-
2  *
3  * Electric(tm) VLSI Design System
4  *
5  * File: iocifpars.c
6  * CIF parsing
7  * Written by: Robert W. Hon, Schlumberger Palo Alto Research
8  *
9  * Copyright (c) 2000 Static Free Software.
10  *
11  * Electric(tm) is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  *
16  * Electric(tm) is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with Electric(tm); see the file COPYING.  If not, write to
23  * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
24  * Boston, Mass 02111-1307, USA.
25  *
26  * Static Free Software
27  * 4119 Alpine Road
28  * Portola Valley, California 94028
29  * info@staticfreesoft.com
30  */
31 
32 #include "config.h"
33 #include "global.h"
34 #include "eio.h"
35 #include "iocifpars.h"
36 #include "edialogs.h"
37 #include <math.h>
38 
39 /********************* interp.c: interpreter *********************/
40 
41 #define CONVERT 0					/* 1=> convert wires to boxes */
42 
43 /* global state for the interpreter */
44 static float io_cifscalefactor;		/* A/B from DS */
45 static stentry *io_cifcurrent;		/* current symbol being defined */
46 
47 static INTBIG io_cifinstance;		/* inst count for default names */
48 static INTBIG io_cifbinst;			/* inst count for default names */
49 static INTBIG io_cifstatesince;		/* # statements since 91 com */
50 static CHAR   io_cifnamepending;	/* 91 pending */
51 static CHAR   io_cifnamed;			/* symbol has been named */
52 static CHAR  *io_cifnstored;		/* name saved from 91 */
53 
54 static CHAR   io_cifdefinprog;		/* definition in progress flag */
55 static INTBIG io_cifignore;			/* ignore statements until DF */
56 static CHAR   io_cifendcom;			/* end command flag */
57 
58 static INTBIG io_cifcurlayer;		/* current layer */
59 static INTBIG io_cifbackuplayer;	/* place to save layer during def */
60 
61 static INTBIG io_nulllayererrors;	/* null layer errors encountered */
62 
63 typedef struct ite					/* items in item tree */
64 {
65 	INTBIG      it_type;			/* redundant indicator of obj type */
66 	struct ite *it_rel;				/* links for tree */
67 	struct ite *it_norel;			/* links for tree */
68 	struct ite *it_same;			/* links for tree */
69 	CHAR       *it_what;			/* pointer into symbol structure */
70 	INTBIG      it_level;			/* level of nest, from root (= 0) */
71 	INTBIG      it_context;			/* what trans context to use */
72 	INTBIG      it_left;			/* bb on chip */
73 	INTBIG      it_right;			/* bb on chip */
74 	INTBIG      it_bottom;			/* bb on chip */
75 	INTBIG      it_top;				/* bb on chip */
76 } itementry;
77 
78 static itementry *io_cifittop;		/* top of free stack */
79 static itementry *io_cifilist;		/* head of item list */
80 
81 static linkedpoint  *io_cifpfree;
82 static linkedtentry *io_ciftfree = NIL;
83 
84 /* prototypes for local routines */
85 static CHAR io_endseen(void);
86 static void io_idefstart(INTBIG, INTBIG, INTBIG);
87 static void io_idefend(void);
88 static void io_ideletedef(INTBIG);
89 static void io_ilayer(CHAR*);
90 static void io_icomment(CHAR*);
91 static void io_iusercommand(INTBIG, CHAR*);
92 static void io_iend(void);
93 static void io_iwire(INTBIG, CHAR*);
94 static void io_iwire(INTBIG, CHAR*);
95 static void io_iflash(INTBIG, point);
96 static void io_ipolygon(CHAR*);
97 static void io_scalepath(CHAR*, CHAR*);
98 static void io_ibox(INTBIG, INTBIG, point, INTBIG, INTBIG);
99 static void io_icall(INTBIG, CHAR*);
100 static void io_isymname(CHAR*);
101 static void io_iinstname(CHAR*);
102 static void io_igeoname(CHAR*, point, INTBIG);
103 static void io_ilabel(CHAR*, point);
104 static CHAR *io_makesymname(INTBIG);
105 static CHAR *io_makeinstname(INTBIG);
106 static void io_newstentry(stentry*, INTBIG);
107 static stentry *io_lookupsym(INTBIG);
108 static void io_freesymbols(void);
109 static void io_initmm(point);
110 static void io_donemm(void);
111 static void io_minmax(point);
112 static INTBIG io_minx(void);
113 static INTBIG io_miny(void);
114 static INTBIG io_maxx(void);
115 static INTBIG io_maxy(void);
116 static void io_findcallbb(symcall*);
117 static void io_findbb(stentry*);
118 static CHAR io_initutil(void);
119 static void io_freestorage(void);
120 static void io_freedef(objectptr);
121 static void io_clear(transform);
122 static BOOLEAN io_swapcontext(INTBIG);
123 static BOOLEAN io_increfcount(INTBIG);
124 static BOOLEAN io_decrefcount(INTBIG);
125 static void io_pushtrans(void);
126 static void io_poptrans(void);
127 static void io_matmult(transform, transform, transform);
128 static void io_mmult(transform, transform, transform);
129 static void io_applylocal(transform);
130 static void io_assign(transform, transform);
131 static void io_rotate(INTBIG, INTBIG);
132 static void io_translate(INTBIG, INTBIG);
133 static void io_mirror(CHAR);
134 static void io_dumpstack(void);
135 static void io_printmat(transform);
136 static void io_bbpolygon(INTBIG, path, INTBIG*, INTBIG*, INTBIG*, INTBIG*);
137 static void io_bbwire(INTBIG, INTBIG, path, INTBIG*, INTBIG*, INTBIG*, INTBIG*);
138 static CHAR io_inititems(void);
139 static BOOLEAN io_doneitems(void);
140 static itementry *io_newnode(void);
141 static void io_freenode(itementry*);
142 static void io_sendlist(itementry*);
143 static void io_dumpdef(stentry*);
144 static void io_shipcontents(stentry*);
145 static void io_outitem(itementry*);
146 static void io_item(objectptr);
147 static CHAR io_initinput(void);
148 static CHAR io_doneinput(void);
149 static CHAR io_getch(void);
150 static CHAR io_peek(void);
151 static CHAR io_endoffile(void);
152 static INTBIG io_flush(CHAR);
153 static void io_identify(void);
154 static CHAR io_inittypes(void);
155 static void io_freeciftfree(void);
156 static CHAR io_donetypes(void);
157 static linkedpoint *io_getpnode(void);
158 static void io_freepnode(linkedpoint*);
159 static void io_copypath(path, path);
160 static void io_freetlist(tlist);
161 static void io_dupetlist(tlist, tlist);
162 static linkedtentry *io_gettnode(void);
163 static void io_freetnode(linkedtentry*);
164 static void io_appendtentry(tlist, tentry);
165 static CHAR io_initerror(void);
166 static CHAR io_doneerror(void);
167 static void io_report(CHAR*, INTBIG);
168 static void io_blank(void);
169 static void io_sep(void);
170 static CHAR io_semi(void);
171 static CHAR io_sp(void);
172 static CHAR *io_utext(void);
173 static CHAR *io_name(void);
174 static INTBIG io_cardinal(void);
175 static INTBIG io_signed(void);
176 static void io_logit(INTBIG);
177 static point io_getpoint(void);
178 static void io_getpath(path);
179 static CHAR io_inittrans(void);
180 static CHAR io_donetrans(void);
181 static tmatrix io_getlocal(void);
182 static point io_transpoint(point);
183 static void io_freeonedef(struct cifhack *cur);
184 static CHAR *io_maketlist(void);
185 static INTBIG io_parsestatement(void);
186 
187 /*
188  * Routine to free all memory associated with this module.
189  */
io_freecifparsmemory(void)190 void io_freecifparsmemory(void)
191 {
192 	io_freeciftfree();
193 }
194 
io_initinterpreter(void)195 INTBIG io_initinterpreter(void)
196 {
197 	io_nulllayererrors = 0;
198 	io_cifdefinprog = 0;
199 	io_cifignore = 0;
200 	io_cifnamepending = 0;
201 	io_cifendcom = 0;
202 	io_cifcurlayer = -1;
203 	io_cifinstance = 1;
204 	return(io_initutil() || io_inititems() || io_inittrans());
205 }
206 
io_doneinterpreter(void)207 INTBIG io_doneinterpreter(void)
208 {
209 	if (io_nulllayererrors != 0)
210 	{
211 		io_report(_("output on null layer"), FATALSEMANTIC);
212 	}
213 
214 	io_freestorage();
215 	return(io_donetrans() || io_doneitems());
216 }
217 
io_endseen(void)218 CHAR io_endseen(void)
219 {
220 	return(io_cifendcom);
221 }
222 
io_idefstart(INTBIG symbol,INTBIG mtl,INTBIG div)223 void io_idefstart(INTBIG symbol,INTBIG mtl,INTBIG div)
224 {
225 	io_cifstatesince++;
226 	io_cifcurrent = io_lookupsym(symbol);
227 	if (io_cifcurrent->st_defined)
228 	{
229 		/* redefining this symbol */
230 		CHAR mess[300];
231 		(void)esnprintf(mess, 300, _("attempt to redefine symbol %lu (ignored)"), symbol);
232 		io_report(mess, ADVISORY);
233 		io_cifignore = 1;
234 		return;
235 	}
236 
237 	io_cifdefinprog = 1;
238 	if (mtl != 0 && div != 0) io_cifscalefactor = ((float) mtl)/((float) div); else
239 	{
240 		io_report(_("illegal scale factor, ignored"), ADVISORY);
241 		io_cifscalefactor = 1.0;
242 	}
243 	io_cifbackuplayer = io_cifcurlayer;	/* save current layer */
244 	io_cifbinst = io_cifinstance;		/* save instance count */
245 	io_cifcurlayer = -1;
246 	io_cifnamed = 0;					/* symbol not named */
247 	io_cifinstance = 0;					/* no calls in symbol yet */
248 }
249 
io_idefend(void)250 void io_idefend(void)
251 {
252 	CHAR *s;
253 
254 	io_cifstatesince++;
255 	if (io_cifignore)
256 	{
257 		io_cifignore = 0;
258 		return;
259 	}
260 	io_cifdefinprog = 0;
261 	io_cifcurlayer = io_cifbackuplayer;		/* restore old layer */
262 	io_cifinstance = io_cifbinst;
263 	if (!io_cifnamed)
264 	{
265 		s = io_makesymname(io_cifcurrent->st_symnumber);
266 		(void)allocstring(&io_cifcurrent->st_name, s, io_tool->cluster);
267 	}
268 	io_cifcurrent->st_defined = 1;
269 }
270 
271 
io_ideletedef(INTBIG n)272 void io_ideletedef(INTBIG n)
273 {
274 	io_cifstatesince++;
275 	io_report(_("DD not supported (ignored)"), ADVISORY);
276 }
277 
io_ilayer(CHAR * lname)278 void io_ilayer(CHAR *lname)
279 {
280 
281 	io_cifstatesince++;
282 	if (io_cifignore) return;
283 	io_cifcurlayer = io_findlayernum(lname);
284 }
285 
io_icomment(CHAR * contents)286 void io_icomment(CHAR *contents)
287 {
288 }
289 
io_iusercommand(INTBIG command,CHAR * text)290 void io_iusercommand(INTBIG command, CHAR *text)
291 {
292 	io_cifstatesince++;
293 	if (io_cifignore) return;
294 	io_outputusercommand(command, text);
295 }
296 
io_iend(void)297 void io_iend(void)
298 {
299 	io_cifstatesince++;
300 	io_cifendcom = 1;
301 	if (io_cifnamepending)
302 	{
303 		efree((CHAR *)io_cifnstored);
304 		io_report(_("no instance to match name command"), ADVISORY);
305 		io_cifnamepending = 0;
306 	}
307 }
308 
309 
310 #if CONVERT
311 /* convert wires to boxes and flashes */
312 
io_iwire(INTBIG width,CHAR * wpath)313 void io_iwire(INTBIG width, CHAR *wpath)
314 {
315 	INTBIG i, lim;
316 	INTBIG lt, rt, bm, tp;
317 	point prev, curr;
318 
319 	lim = io_pathlength((path)wpath);
320 	io_cifstatesince++;
321 	if (io_cifignore) return;
322 	if (io_cifcurlayer == -1)
323 	{
324 		io_nulllayererrors++;
325 		return;
326 	}
327 
328 	prev = io_removepoint((path)wpath);
329 	io_iflash(width, prev); io_cifstatesince--;
330 	for (i = 1; i < lim; i++)
331 	{
332 		INTBIG len, xr, yr;
333 		point center;
334 
335 		curr = io_removepoint((path)wpath);
336 		io_iflash(width, curr); io_cifstatesince--;
337 		xr = curr.x-prev.x;   yr = curr.y-prev.y;
338 		len = computedistance(0, 0, xr, yr);
339 		center.x = (curr.x+prev.x)/2;   center.y = (curr.y+prev.y)/2;
340 		io_ibox(len, width, center, xr, yr); io_cifstatesince--;
341 		prev = curr;
342 	}
343 }
344 
345 #else
346 /* regular wires */
347 
io_iwire(INTBIG width,CHAR * a)348 void io_iwire(INTBIG width, CHAR *a)
349 {
350 	wire *obj;
351 	INTBIG length = io_pathlength((path)a);
352 	CHAR *bbpath, *spath, *tpath;
353 	INTBIG i;
354 
355 	io_cifstatesince++;
356 	if (io_cifignore) return;
357 	if (io_cifcurlayer == -1)
358 	{
359 		io_nulllayererrors++;
360 		return;
361 	}
362 	obj = (wire *)emalloc((length-1)*sizeof(point)+sizeof(wire), io_tool->cluster);
363 	if (obj == NIL)
364 	{
365 		io_report(_("no space: io_iwire"), FATALINTERNAL);
366 		return;
367 	}
368 
369 	tpath = a;
370 	spath = NIL;			/* path in case of scaling */
371 	obj->wi_type = WIRE;
372 	obj->wi_layer = io_cifcurlayer;
373 	obj->wi_numpts = length;
374 	if (io_cifdefinprog && io_cifscalefactor != 1.0)
375 	{
376 		spath = io_makepath();		/* create a new path */
377 		io_scalepath(a, spath);		/* scale all points */
378 		width = (INTBIG)(io_cifscalefactor * (float)width);
379 		tpath = spath;
380 	}
381 	obj->wi_width = width;
382 
383 	bbpath = io_makepath();		/* get a new path for bb use */
384 	io_copypath((path)tpath, (path)bbpath);
385 	io_bbwire(io_cifcurlayer, width, (path)bbpath, &(obj->wi_bb.l), &(obj->wi_bb.r),
386 		&(obj->wi_bb.b), &(obj->wi_bb.t));
387 	io_freepath((path)bbpath);
388 	for (i = 0; i < length; i++) obj->wi_p[i] = io_removepoint((path)tpath);
389 
390 	if (io_cifdefinprog)
391 	{
392 		/* insert into symbol's guts */
393 		obj->wi_next = io_cifcurrent->st_guts;
394 		io_cifcurrent->st_guts = (objectptr) obj;
395 	} else io_item((objectptr)obj);		/* stick into item list */
396 
397 	if (spath != NIL) io_freepath((path)spath);
398 }
399 
400 #endif
401 
402 
io_iflash(INTBIG diameter,point center)403 void io_iflash(INTBIG diameter,point center)
404 {
405 	flash *obj;
406 
407 	io_cifstatesince++;
408 	if (io_cifignore) return;
409 	if (io_cifcurlayer == -1)
410 	{
411 		io_nulllayererrors++;
412 		return;
413 	}
414 	if (diameter == 0)
415 	{
416 		io_report(_("flash with null diamter, ignored"), ADVISORY);
417 		return;
418 	}
419 
420 	obj = (flash *)emalloc(sizeof(flash), io_tool->cluster);
421 	if (obj == NIL)
422 	{
423 		io_report(_("no space: io_iflash"), FATALINTERNAL);
424 		return;
425 	}
426 	obj->fl_type = FLASH;
427 	obj->fl_layer = io_cifcurlayer;
428 	if (io_cifdefinprog && io_cifscalefactor != 1.0)
429 	{
430 		diameter = (UINTBIG) (io_cifscalefactor * (float)diameter);
431 		center.x = (INTBIG) (io_cifscalefactor * (float)center.x);
432 		center.y = (INTBIG) (io_cifscalefactor * (float)center.y);
433 	}
434 	obj->fl_diameter = diameter;
435 	obj->fl_center = center;
436 
437 	io_bbflash(io_cifcurlayer, diameter, center, &(obj->fl_bb.l), &(obj->fl_bb.r),
438 		&(obj->fl_bb.b), &(obj->fl_bb.t));
439 
440 	if (io_cifdefinprog)
441 	{
442 		/* insert into symbol's guts */
443 		obj->fl_next = io_cifcurrent->st_guts;
444 		io_cifcurrent->st_guts = (objectptr) obj;
445 	} else io_item((objectptr)obj);		/* stick into item list */
446 }
447 
io_ipolygon(CHAR * a)448 void io_ipolygon(CHAR *a)
449 {
450 	polygon *obj;
451 	INTBIG length = io_pathlength((path)a);
452 	CHAR *bbpath,*spath,*tpath;
453 	INTBIG i;
454 
455 	io_cifstatesince++;
456 	if (io_cifignore) return;
457 	if (io_cifcurlayer == -1)
458 	{
459 		io_nulllayererrors++;
460 		return;
461 	}
462 	if (length < 3)
463 	{
464 		io_report(_("polygon with < 3 pts in path, ignored"), ADVISORY);
465 		return;
466 	}
467 
468 	obj = (polygon *)emalloc((length-1)*sizeof(point)+sizeof(polygon), io_tool->cluster);
469 	if (obj == NIL)
470 	{
471 		io_report(_("no space: io_ipolygon"), FATALINTERNAL);
472 		return;
473 	}
474 
475 	tpath = a;
476 	spath = NIL;			/* path in case of scaling */
477 	obj->po_type = POLY;
478 	obj->po_layer = io_cifcurlayer;
479 	obj->po_numpts = length;
480 	if (io_cifdefinprog && io_cifscalefactor != 1.0)
481 	{
482 		spath = io_makepath();		/* create a new path */
483 		io_scalepath(a, spath);		/* scale all points */
484 		tpath = spath;
485 	}
486 
487 	bbpath = io_makepath();		/* get a new path for bb use */
488 	io_copypath((path)tpath, (path)bbpath);
489 	io_bbpolygon(io_cifcurlayer, (path)bbpath, &(obj->po_bb.l), &(obj->po_bb.r),
490 		&(obj->po_bb.b), &(obj->po_bb.t));
491 	io_freepath((path)bbpath);
492 	for (i = 0; i < length; i++) obj->po_p[i] = io_removepoint((path)tpath);
493 
494 	if (io_cifdefinprog)
495 	{
496 		/* insert into symbol's guts */
497 		obj->po_next = io_cifcurrent->st_guts;
498 		io_cifcurrent->st_guts = (objectptr) obj;
499 	} else io_item((objectptr)obj);		/* stick into item list */
500 
501 	if (spath != NIL) io_freepath((path)spath);
502 }
503 
io_scalepath(CHAR * src,CHAR * dest)504 static void io_scalepath(CHAR *src, CHAR *dest)
505 {
506 	INTBIG i, limit;
507 
508 	limit = io_pathlength((path)src);
509 	for (i = 0; i < limit; i++)
510 	{
511 		point temp;
512 
513 		temp = io_removepoint((path)src);
514 
515 		temp.x = (INTBIG) (io_cifscalefactor*(float)temp.x);
516 		temp.y = (INTBIG) (io_cifscalefactor*(float)temp.y);
517 		if (io_appendpoint((path)dest, temp)) break;
518 	}
519 }
520 
io_ibox(INTBIG length,INTBIG width,point center,INTBIG xr,INTBIG yr)521 void io_ibox(INTBIG length, INTBIG width, point center, INTBIG xr, INTBIG yr)
522 {
523 	INTBIG tl, tr, tb, tt, halfw, halfl;
524 
525 	io_cifstatesince++;
526 	if (io_cifignore) return;
527 	if (io_cifcurlayer == -1)
528 	{
529 		io_nulllayererrors++;
530 		return;
531 	}
532 	if (length == 0 || width == 0)
533 	{
534 		io_report(_("box with null length or width specified, ignored"), ADVISORY);
535 		return;
536 	}
537 
538 	if (io_cifdefinprog && io_cifscalefactor != 1.0)
539 	{
540 		length = (INTBIG) (io_cifscalefactor * (float)length);
541 		width = (INTBIG) (io_cifscalefactor * (float)width);
542 		center.x = (INTBIG) (io_cifscalefactor * (float)center.x);
543 		center.y = (INTBIG) (io_cifscalefactor * (float)center.y);
544 	}
545 
546 	io_bbbox(io_cifcurlayer, length, width, center, xr, yr, &tl, &tr, &tb, &tt);
547 
548 	/* check for manhattan box */
549 	halfw = width/2; halfl = length/2;
550 	if (
551 		(yr == 0 && (length%2) == 0 && (width%2) == 0 &&
552 		(center.x-halfl) == tl && (center.x+halfl) == tr &&
553 		(center.y-halfw) == tb && (center.y+halfw) == tt)
554 		||
555 		(xr == 0 && (length%2) == 0 && (width%2) == 0 &&
556 		(center.x-halfw) == tl && (center.x+halfw) == tr &&
557 		(center.y-halfl) == tb && (center.y+halfl) == tt)
558 	)
559 	{
560 		mbox *obj;
561 		obj = (mbox *)emalloc(sizeof(mbox), io_tool->cluster);
562 		if (obj == NIL)
563 		{
564 			io_report(_("no space: io_ibox"), FATALINTERNAL);
565 			return;
566 		}
567 		obj->mb_type = MBOX;
568 		obj->mb_layer = io_cifcurlayer;
569 		if (yr == 0)
570 		{
571 			obj->mb_bb.l = tl;
572 			obj->mb_bb.r = tr;
573 			obj->mb_bb.b = tb;
574 			obj->mb_bb.t = tt;
575 		} else
576 		{
577 			/* this assumes that bb is unaffected by rotation */
578 			obj->mb_bb.l = center.x-halfw;
579 			obj->mb_bb.r = center.x+halfw;
580 			obj->mb_bb.b = center.y-halfl;
581 			obj->mb_bb.t = center.y+halfl;
582 		}
583 		if (io_cifdefinprog)
584 		{
585 			/* insert into symbol's guts */
586 			obj->mb_next = io_cifcurrent->st_guts;
587 			io_cifcurrent->st_guts = (objectptr) obj;
588 		} else io_item((objectptr)obj);		/* stick into item list */
589 	} else
590 	{
591 		box *obj;
592 
593 		obj = (box *)emalloc(sizeof(box), io_tool->cluster);
594 		if (obj == NIL)
595 		{
596 			io_report(_("no space: io_ibox"), FATALINTERNAL);
597 			return;
598 		}
599 		obj->bo_type = RECTANGLE;
600 		obj->bo_layer = io_cifcurlayer;
601 		obj->bo_length = length;
602 		obj->bo_width = width;
603 		obj->bo_center = center;
604 		obj->bo_xrot = xr;
605 		obj->bo_yrot = yr;
606 
607 		obj->bo_bb.l = tl;
608 		obj->bo_bb.r = tr;
609 		obj->bo_bb.b = tb;
610 		obj->bo_bb.t = tt;
611 		if (io_cifdefinprog)
612 		{
613 			/* insert into symbol's guts */
614 			obj->bo_next = io_cifcurrent->st_guts;
615 			io_cifcurrent->st_guts = (objectptr) obj;
616 		} else io_item((objectptr)obj);		/* stick into item list */
617 	}
618 }
619 
io_icall(INTBIG symbol,CHAR * list)620 void io_icall(INTBIG symbol, CHAR *list)
621 {
622 	INTBIG i,j;
623 	tentry temp;
624 	symcall *obj;		/* we need a new object */
625 	CHAR *newtlist;
626 
627 	if (io_cifignore) return;
628 	j = io_tlistlength((tlist)list);
629 	if (j == 0) newtlist = NIL; else
630 		newtlist = io_maketlist();
631 
632 	io_pushtrans();		/* get new frame of reference */
633 	for (i = 1; i <=j; i++)
634 	{
635 		/* build up incremental transformations */
636 		temp = io_removetentry((tlist)list);
637 		switch (temp.kind)
638 		{
639 			case MIRROR:
640 				io_mirror(temp.guts.mi.xcoord); break;
641 			case TRANSLATE:
642 				if (io_cifdefinprog && io_cifscalefactor != 1.0)
643 				{
644 					temp.guts.tr.xt = (INTBIG)(io_cifscalefactor*(float)temp.guts.tr.xt);
645 					temp.guts.tr.yt = (INTBIG)(io_cifscalefactor*(float)temp.guts.tr.yt);
646 				}
647 				io_translate(temp.guts.tr.xt, temp.guts.tr.yt);
648 				break;
649 		   case ROTATE:
650 				io_rotate(temp.guts.ro.xrot, temp.guts.ro.yrot); break;
651 		   default:
652 				io_report(_("interpreter: no such transformation"), FATALINTERNAL);
653 		}
654 		io_appendtentry((tlist)newtlist, temp);	/* copy the list */
655 	}
656 
657 	obj = (symcall *)emalloc(sizeof(symcall), io_tool->cluster);
658 	if (obj == NIL)
659 	{
660 		io_report(_("no space: io_icall"), FATALINTERNAL);
661 		io_poptrans();
662 		return;
663 	}
664 	obj->sy_type = CALL;
665 	obj->sy_tm = io_getlocal();
666 	io_poptrans();		/* return to previous state */
667 
668 	obj->sy_symnumber = symbol;
669 	obj->sy_unid = NIL;
670 	obj->sy_tlist = newtlist;
671 
672 	io_cifinstance++;		/* increment the instance count for names */
673 	if (io_cifnamepending)
674 	{
675 		if (io_cifstatesince != 0)
676 			io_report(_("statements between name and instance"), ADVISORY);
677 		obj->sy_name = io_cifnstored;
678 		io_cifnamepending = 0;
679 	} else
680 	{
681 		CHAR *s;
682 		s = io_makeinstname(io_cifinstance);
683 		(void)allocstring(&obj->sy_name, s, io_tool->cluster);
684 	}
685 	if (io_cifdefinprog)
686 	{
687 		/* insert into guts of symbol */
688 		obj->sy_next = io_cifcurrent->st_guts;
689 		io_cifcurrent->st_guts = (objectptr)obj;
690 		io_cifcurrent->st_ncalls++;
691 	} else io_item((objectptr)obj);
692 }
693 
io_isymname(CHAR * name)694 void io_isymname(CHAR *name)
695 {
696 	io_cifstatesince++;
697 	if (io_cifignore) return;
698 	if (!io_cifdefinprog)
699 	{
700 		io_report(_("no symbol to name"), FATALSEMANTIC);
701 		return;
702 	}
703 	if (*name == '\0')
704 	{
705 		io_report(_("null symbol name ignored"), ADVISORY);
706 		return;
707 	}
708 	if (io_cifnamed)
709 	{
710 		io_report(_("symbol is already named, new name ignored"), FATALSEMANTIC);
711 		return;
712 	}
713 	io_cifnamed = 1;
714 	(void)allocstring(&io_cifcurrent->st_name, name, io_tool->cluster);
715 }
716 
io_iinstname(CHAR * name)717 void io_iinstname(CHAR *name)
718 {
719 	if (io_cifignore) return;
720 	if (*name == '\0')
721 	{
722 		io_report(_("null instance name ignored"), ADVISORY);
723 		return;
724 	}
725 	if (io_cifnamepending)
726 	{
727 		efree((CHAR *)io_cifnstored);
728 		io_report(_("there is already a name pending, new name replaces it"), ADVISORY);
729 	}
730 	io_cifnamepending = 1;
731 	io_cifstatesince = 0;
732 	(void)allocstring(&io_cifnstored, name, io_tool->cluster);
733 }
734 
io_igeoname(CHAR * name,point pt,INTBIG lay)735 void io_igeoname(CHAR *name, point pt, INTBIG lay)
736 {
737 	gname *obj;
738 	point temp;
739 
740 	io_cifstatesince++;
741 	if (io_cifignore) return;
742 	if (*name == '\0')
743 	{
744 		io_report(_("null geometry name ignored"), ADVISORY);
745 		return;
746 	}
747 	obj = (gname *)emalloc(sizeof(gname), io_tool->cluster);
748 	if (obj == NIL)
749 	{
750 		io_report(_("no space: io_igeoname"), FATALINTERNAL);
751 		return;
752 	}
753 
754 	obj->gn_type = NAME;
755 	obj->gn_layer = lay;
756 	if (io_cifdefinprog && io_cifscalefactor != 1.0)
757 	{
758 		pt.x = (INTBIG)(io_cifscalefactor * (float)pt.x);
759 		pt.y = (INTBIG)(io_cifscalefactor * (float)pt.y);
760 	}
761 	obj->gn_pos = pt;
762 	(void)allocstring(&obj->gn_name, name, io_tool->cluster);
763 
764 	io_pushtrans();
765 	temp = io_transpoint(pt);
766 	io_poptrans();
767 	obj->gn_bb.l = temp.x;
768 	obj->gn_bb.r = temp.x;
769 	obj->gn_bb.b = temp.y;
770 	obj->gn_bb.t = temp.y;
771 
772 	if (io_cifdefinprog)
773 	{
774 		/* insert into symbol's guts */
775 		obj->gn_next = io_cifcurrent->st_guts;
776 		io_cifcurrent->st_guts = (objectptr) obj;
777 	} else io_item((objectptr)obj);		/* stick into item list */
778 }
779 
io_ilabel(CHAR * name,point pt)780 void io_ilabel(CHAR *name, point pt)
781 {
782 	label *obj;
783 	point temp;
784 
785 	io_cifstatesince++;
786 	if (io_cifignore) return;
787 	if (*name == '\0')
788 	{
789 		io_report(_("null label ignored"), ADVISORY);
790 		return;
791 	}
792 	obj = (label *)emalloc(sizeof(label), io_tool->cluster);
793 	if (obj == NIL)
794 	{
795 		io_report(_("no space: io_ilabel"), FATALINTERNAL);
796 		return;
797 	}
798 
799 	obj->la_type = LABEL;
800 	if (io_cifdefinprog && io_cifscalefactor != 1.0)
801 	{
802 		pt.x = (INTBIG)(io_cifscalefactor * (float)pt.x);
803 		pt.y = (INTBIG)(io_cifscalefactor * (float)pt.y);
804 	}
805 	obj->la_pos = pt;
806 	(void)allocstring(&obj->la_name, name, io_tool->cluster);
807 
808 	io_pushtrans();
809 	temp = io_transpoint(pt);
810 	io_poptrans();
811 	obj->la_bb.l = temp.x;
812 	obj->la_bb.r = temp.x;
813 	obj->la_bb.b = temp.y;
814 	obj->la_bb.t = temp.y;
815 
816 	if (io_cifdefinprog)
817 	{
818 		/* insert into symbol's guts */
819 		obj->la_next = io_cifcurrent->st_guts;
820 		io_cifcurrent->st_guts = (objectptr) obj;
821 	} else io_item((objectptr)obj);		/* stick into item list */
822 }
823 
824 /********************* util.c: storage manager begin *********************/
825 
io_makesymname(INTBIG n)826 CHAR *io_makesymname(INTBIG n)
827 {
828 	static CHAR s[50];
829 
830 	(void)esnprintf(s, 50, x_("SYM%lu"), n);
831 	return(s);
832 }
833 
io_makeinstname(INTBIG n)834 CHAR *io_makeinstname(INTBIG n)
835 {
836 	static CHAR s[50];
837 
838 	(void)esnprintf(s, 50, x_("INST<%lu>"), n);
839 	return(s);
840 }
841 
842 /********************* symbol table begin *********************/
843 
844 #define PRIME 199		/* hash table size */
845 #define hash(x) (x % PRIME)	/* hash function */
846 static stentry *io_cifstable[PRIME];	/* symbol table */
847 
848 /* initialize the entry pointed to by ptr */
io_newstentry(stentry * ptr,INTBIG num)849 static void io_newstentry(stentry *ptr, INTBIG num)
850 {
851 	ptr->st_symnumber = num;
852 	ptr->st_overflow = NIL;
853 	ptr->st_expanded = 0;
854 	ptr->st_frozen = 0;
855 	ptr->st_defined = 0;
856 	ptr->st_dumped = 0;		/* added for winstanley */
857 	ptr->st_ncalls = 0;		/* ditto */
858 	ptr->st_bbvalid = 0;
859 	ptr->st_name = NIL;
860 	ptr->st_guts = NIL;
861 }
862 
863 /* io_lookupsym(sym), if none, make
864  * a blank entry. return a pointer to whichever
865  */
io_lookupsym(INTBIG sym)866 stentry *io_lookupsym(INTBIG sym)
867 {
868 	stentry *cur, *old;
869 	INTBIG hadd = hash(sym);
870 
871 	if (io_cifstable[hadd] == NIL)
872 	{
873 		/* create a new entry */
874 		io_cifstable[hadd] = (stentry *)emalloc(sizeof(stentry), io_tool->cluster);
875 		if (io_cifstable[hadd] == NIL)
876 		{
877 			io_report(_("no space: io_lookupsym"), FATALINTERNAL);
878 			return(0);
879 		}
880 		io_newstentry(io_cifstable[hadd], sym);
881 		return(io_cifstable[hadd]);
882 	}
883 
884 	/* otherwise find stentry w/correct symbolnumber */
885 	cur = io_cifstable[hadd];
886 	while (cur != NIL)
887 		if (cur->st_symnumber == sym)
888 			return(cur);	/* found a match */
889 				else {old = cur; cur = cur->st_overflow;}
890 
891 	/* no matching symbol numbers, so create a new one */
892 	old->st_overflow = (stentry *)emalloc(sizeof(stentry), io_tool->cluster);
893 	if (old->st_overflow == NIL)
894 	{
895 		io_report(_("no space: io_lookupsym"), FATALINTERNAL);
896 		return(0);
897 	}
898 	io_newstentry(old->st_overflow, sym);
899 	return(old->st_overflow);
900 }
901 
io_freesymbols(void)902 void io_freesymbols(void)
903 {
904 	stentry *cur, *temp;
905 	INTBIG i;
906 
907 	for (i=0; i<PRIME; i++)
908 	{
909 		for (cur = io_cifstable[i]; cur != NIL; cur = temp)
910 		{
911 			temp = cur->st_overflow;
912 
913 			/* deallocate name string */
914 			if (cur->st_name != NIL) efree(cur->st_name);
915 			io_freedef(cur->st_guts);	/* deallocate contents */
916 			efree((CHAR *)cur);	/* deallocate this symbol table entry */
917 		}
918 	}
919 }
920 
921 /********************* some reentrant min-max stuff *********************/
922 
923 #define MAXMMSTACK 50		/* max depth of minmax stack */
924 static INTBIG io_cifmmleft[MAXMMSTACK];
925 static INTBIG io_cifmmright[MAXMMSTACK];
926 static INTBIG io_cifmmbottom[MAXMMSTACK];
927 static INTBIG io_cifmmtop[MAXMMSTACK];
928 static INTBIG io_cifmmptr;			/* stack pointer */
929 
io_initmm(point foo)930 void io_initmm(point foo)
931 {
932 	if (++io_cifmmptr >= MAXMMSTACK)
933 	{
934 		io_report(_("io_initmm: out of stack"), FATALINTERNAL);
935 		return;
936 	}
937 	io_cifmmleft[io_cifmmptr] = foo.x;   io_cifmmright[io_cifmmptr] = foo.x;
938 	io_cifmmbottom[io_cifmmptr] = foo.y; io_cifmmtop[io_cifmmptr] = foo.y;
939 }
940 
io_donemm(void)941 void io_donemm(void)
942 {
943 	if (io_cifmmptr < 0) io_report(_("io_donemm: pop from empty stack"), FATALINTERNAL);
944 		else io_cifmmptr--;
945 }
946 
io_minmax(point foo)947 void io_minmax(point foo)
948 {
949 	if (foo.x > io_cifmmright[io_cifmmptr]) io_cifmmright[io_cifmmptr] = foo.x;
950 		else {if (foo.x < io_cifmmleft[io_cifmmptr]) io_cifmmleft[io_cifmmptr] = foo.x;}
951 	if (foo.y > io_cifmmtop[io_cifmmptr]) io_cifmmtop[io_cifmmptr] = foo.y;
952 		else {if (foo.y < io_cifmmbottom[io_cifmmptr]) io_cifmmbottom[io_cifmmptr] = foo.y;}
953 }
954 
io_minx(void)955 INTBIG io_minx(void)
956 {
957 	return(io_cifmmleft[io_cifmmptr]);
958 }
959 
io_miny(void)960 INTBIG io_miny(void)
961 {
962 	return(io_cifmmbottom[io_cifmmptr]);
963 }
964 
io_maxx(void)965 INTBIG io_maxx(void)
966 {
967 	return(io_cifmmright[io_cifmmptr]);
968 }
969 
io_maxy(void)970 INTBIG io_maxy(void)
971 {
972 	return(io_cifmmtop[io_cifmmptr]);
973 }
974 
io_findcallbb(symcall * object)975 void io_findcallbb(symcall *object)		/* find the bb for this particular call */
976 {
977 	point temp;
978 	point comperror;	/* for compiler error */
979 	stentry *thisst;
980 
981 	thisst = io_lookupsym(object->sy_symnumber);
982 
983 	if (!thisst->st_defined)
984 	{
985 		CHAR mess[50];
986 		(void)esnprintf(mess, 50, _("call to undefined symbol %lu"), thisst->st_symnumber);
987 		io_report(mess, FATALSEMANTIC);
988 		return;
989 	}
990 	if (thisst->st_expanded)
991 	{
992 		CHAR mess[50];
993 		(void)esnprintf(mess, 50, _("recursive call on symbol %lu"), thisst->st_symnumber);
994 		io_report(mess, FATALSEMANTIC);
995 		return;
996 	} else thisst->st_expanded = 1;		/* mark as under expansion */
997 
998 	if (!thisst->st_frozen) thisst->st_frozen = 1;
999 
1000 	io_findbb(thisst);		/* get the bb of the symbol in its stentry */
1001 	object->sy_unid = thisst;	/* get this symbol's id */
1002 
1003 	io_pushtrans();			/* set up a new frame of reference */
1004 	io_applylocal(&(object->sy_tm));
1005 	temp.x = thisst->st_bb.l;   temp.y = thisst->st_bb.b;	/* ll */
1006 	comperror = io_transpoint(temp);
1007 	io_initmm(comperror);
1008 	temp.x = thisst->st_bb.r;
1009 	comperror = io_transpoint(temp);
1010 	io_minmax(comperror);
1011 	temp.y = thisst->st_bb.t;	/* ur */
1012 	comperror = io_transpoint(temp);
1013 	io_minmax(comperror);
1014 	temp.x = thisst->st_bb.l;
1015 	comperror = io_transpoint(temp);
1016 	io_minmax(comperror);
1017 
1018 	object->sy_bb.l = io_minx();   object->sy_bb.r = io_maxx();
1019 	object->sy_bb.b = io_miny();   object->sy_bb.t = io_maxy();
1020 	io_donemm();		/* object now has transformed bb of the symbol */
1021 	io_poptrans();
1022 
1023 	thisst->st_expanded = 0;
1024 }
1025 
io_findbb(stentry * sym)1026 static void io_findbb(stentry *sym)		/* find bb for sym */
1027 {
1028 	point temp;
1029 	CHAR first = 1;
1030 	struct cifhack *ob = (struct cifhack *)sym->st_guts;
1031 
1032 	if (sym->st_bbvalid) return;			/* already done */
1033 	if (ob == NIL)			/* empty symbol */
1034 	{
1035 		CHAR mess[100];
1036 		(void)esnprintf(mess, 100, _("symbol %lu has no geometry in it"),
1037 			sym->st_symnumber);
1038 		io_report(mess, ADVISORY);
1039 		sym->st_bb.l = 0;   sym->st_bb.r = 0;
1040 		sym->st_bb.b = 0;   sym->st_bb.t = 0;
1041 		sym->st_bbvalid = 1;
1042 		return;
1043 	}
1044 
1045 	while (ob != NIL)
1046 	{
1047 		/* find bb for symbol calls, all primitive are done already */
1048 		if (ob->kl_type == CALL) io_findcallbb((symcall *)ob);
1049 		temp.x = ob->kl_bb.l;   temp.y = ob->kl_bb.b;
1050 		if (first) {first = 0; io_initmm(temp);}
1051 			else io_minmax(temp);
1052 		temp.x = ob->kl_bb.r;   temp.y = ob->kl_bb.t;
1053 		io_minmax(temp);
1054 		ob = ob->kl_next;
1055 	}
1056 	sym->st_bb.l = io_minx();   sym->st_bb.r = io_maxx();
1057 	sym->st_bb.b = io_miny();   sym->st_bb.t = io_maxy();
1058 	sym->st_bbvalid = 1;
1059 	io_donemm();
1060 }
1061 
io_initutil(void)1062 CHAR io_initutil(void)
1063 {
1064 	INTBIG i;
1065 
1066 	for (i = 0; i < PRIME; i++) io_cifstable[i] = NIL;
1067 	io_cifmmptr = -1;			/* minmax stack pointer */
1068 	return(0);
1069 }
1070 
1071 /********************* storage deallocator begin **********/
1072 
io_freestorage(void)1073 void io_freestorage(void)
1074 {
1075 	io_freesymbols();		/* walk symbol table, free all definitions */
1076 }
1077 
io_freedef(objectptr head)1078 void io_freedef(objectptr head)
1079 {
1080 	struct cifhack *cur, *temp;
1081 
1082 	for(cur = (struct cifhack *)head; cur != NIL; cur = temp)
1083 	{
1084 		temp = cur->kl_next;
1085 		io_freeonedef(cur);
1086 	}
1087 }
1088 
io_freeonedef(struct cifhack * cur)1089 void io_freeonedef(struct cifhack *cur)
1090 {
1091 	switch (cur->kl_type)
1092 	{
1093 		case RECTANGLE:
1094 		case POLY:
1095 		case WIRE:
1096 		case MBOX:
1097 		case FLASH:
1098 			efree((CHAR *)cur);
1099 			break;
1100 		case CALL:
1101 			if (((symcall *)cur)->sy_tlist != 0)
1102 				io_freetlist((tlist) ((symcall *)cur)->sy_tlist);
1103 			efree(((symcall *)cur)->sy_name);
1104 			efree((CHAR *)cur);
1105 			break;
1106 		case NAME:
1107 			efree(((gname *)cur)->gn_name);
1108 			efree((CHAR *)cur);
1109 			break;
1110 		case LABEL:
1111 			efree(((label *)cur)->la_name);
1112 			efree((CHAR *)cur);
1113 			break;
1114 		default:
1115 			io_report(_("unknown def contents"), FATALSEMANTIC);
1116 	}
1117 }
1118 
1119 /********************* storage deallocator end ************/
1120 /********************* trans.c: begin *********************/
1121 
1122 #define TIDENT 0
1123 #define TROTATE 1
1124 #define TTRANSLATE 2
1125 #define TMIRROR 4
1126 
1127 #define CONTSIZE 50		/* initial number of contexts */
1128 
1129 typedef struct nba
1130 {
1131 	CHAR *sn_inst, *sn_sym;
1132 	struct nba *sn_prev, *sn_next;
1133 } snode;
1134 
1135 typedef struct
1136 {
1137 	transform base;				/* bottom of stack */
1138 	INTBIG    refcount;			/* not inuse if = 0 */
1139 	transform ctop;				/* current top */
1140 	snode     *nbase, *ntop;	/* name stack base,top */
1141 } context;
1142 
1143 static context  *io_cifcarray;		/* pointer to the first context */
1144 static INTBIG    io_cifclength;		/* length of context array */
1145 static INTBIG    io_cifcurcontext;	/* current context */
1146 static transform io_cifstacktop;	/* the top of stack */
1147 
io_inittrans(void)1148 CHAR io_inittrans(void)
1149 {
1150 	INTBIG i;
1151 
1152 	io_cifstacktop = (transform)emalloc(sizeof(tmatrix), io_tool->cluster);
1153 	if (io_cifstacktop == NIL)
1154 	{
1155 		io_report(_("no space: io_inittrans"), FATALINTERNAL);
1156 		return(1);
1157 	}
1158 	io_clear(io_cifstacktop);
1159 	io_cifstacktop->next = NIL;
1160 	io_cifstacktop->prev = NIL;
1161 	io_cifstacktop->multiplied = 1;
1162 
1163 	io_cifcarray = (context *)emalloc((CONTSIZE*sizeof(context)), io_tool->cluster);
1164 	if (io_cifcarray == NIL)
1165 	{
1166 		io_report(_("no space: intitrans"), FATALINTERNAL);
1167 		return(1);
1168 	}
1169 	io_cifcarray[0].base = io_cifstacktop;
1170 	io_cifcarray[0].refcount = 1;	/* this context will never go away */
1171 	io_cifcarray[0].ctop = io_cifstacktop;
1172 	io_cifcarray[0].nbase = NIL;
1173 	io_cifcarray[0].ntop = NIL;
1174 	io_cifclength = CONTSIZE;
1175 	for (i=1; i < CONTSIZE; i++)
1176 	{
1177 		io_cifcarray[i].base = NIL;
1178 		io_cifcarray[i].refcount = 0;
1179 		io_cifcarray[i].ctop = NIL;
1180 		io_cifcarray[i].nbase = NIL;
1181 		io_cifcarray[i].ntop = NIL;
1182 	}
1183 	io_cifcurcontext = 0;		/* where we are now */
1184 	return(0);
1185 }
1186 
io_donetrans(void)1187 CHAR io_donetrans(void)
1188 {
1189 	transform temp, old;
1190 
1191 	/* free all contexts, this version only uses one stack */
1192 	for (temp = io_cifstacktop->prev; temp != NIL; temp = old)
1193 	{
1194 		old = temp->prev;
1195 		efree((CHAR *)temp);
1196 	}
1197 	for (temp = io_cifstacktop->next; temp != NIL; temp = old)
1198 	{
1199 		old = temp->next;
1200 		efree((CHAR *)temp);
1201 	}
1202 	efree((CHAR *)io_cifstacktop);
1203 	efree((CHAR *)io_cifcarray);
1204 	return(0);
1205 }
1206 
1207 /**************** initialize a matrix, but don't reset links ****************/
1208 
io_clear(transform mat)1209 static void io_clear(transform mat)
1210 {
1211 	mat->a11 = 1.0;   mat->a12 = 0.0;
1212 	mat->a21 = 0.0;   mat->a22 = 1.0;
1213 	mat->a31 = 0.0;   mat->a32 = 0.0;   mat->a33 = 1.0;
1214 	mat->type = TIDENT;   mat->multiplied = 0;
1215 }
1216 
io_swapcontext(INTBIG id)1217 BOOLEAN io_swapcontext(INTBIG id)
1218 {
1219 	if (id >= io_cifclength || io_cifcarray[id].refcount == 0)
1220 	{
1221 		io_report(_("illegal swap context"), FATALINTERNAL);
1222 		return(TRUE);
1223 	}
1224 	if (io_cifcurcontext == id) return(FALSE);
1225 	io_cifcarray[io_cifcurcontext].ctop = io_cifstacktop;		/* save current context */
1226 	io_cifcurcontext = id;
1227 	io_cifstacktop = io_cifcarray[io_cifcurcontext].ctop;
1228 	return(FALSE);
1229 }
1230 
io_increfcount(INTBIG id)1231 BOOLEAN io_increfcount(INTBIG id)
1232 {
1233 	if (id >= io_cifclength)
1234 	{
1235 		io_report(_("illegal context: io_increfcount"), FATALINTERNAL);
1236 		return(TRUE);
1237 	}
1238 	io_cifcarray[id].refcount++;
1239 	return(FALSE);
1240 }
1241 
io_decrefcount(INTBIG id)1242 BOOLEAN io_decrefcount(INTBIG id)
1243 {
1244 	if (id >= io_cifclength || io_cifcarray[id].refcount == 0)
1245 	{
1246 		io_report(_("illegal context: io_decrefcount"), FATALINTERNAL);
1247 		return(TRUE);
1248 	}
1249 	io_cifcarray[id].refcount--;
1250 	return(FALSE);
1251 }
1252 
io_pushtrans(void)1253 void io_pushtrans(void)
1254 {
1255 	if (io_cifstacktop->next == NIL)
1256 	{
1257 		io_cifstacktop->next = (transform)emalloc(sizeof(tmatrix), io_tool->cluster);
1258 		if (io_cifstacktop->next == NIL)
1259 			io_report(_("no space: io_pushtrans"), FATALINTERNAL);
1260 		io_clear(io_cifstacktop->next);
1261 		io_cifstacktop->next->prev = io_cifstacktop;
1262 		io_cifstacktop = io_cifstacktop->next;
1263 		io_cifstacktop->next = NIL;
1264 	} else
1265 	{
1266 		io_cifstacktop = io_cifstacktop->next;
1267 		io_clear(io_cifstacktop);
1268 	}
1269 }
1270 
io_poptrans(void)1271 void io_poptrans(void)
1272 {
1273 	if (io_cifstacktop->prev != NIL) io_cifstacktop = io_cifstacktop->prev;
1274 		else io_report(_("pop, empty trans stack"), FATALINTERNAL);
1275 }
1276 
io_matmult(transform l,transform r,transform result)1277 static void io_matmult(transform l, transform r, transform result)
1278 {
1279 	if (l == NIL || r == NIL || result == NIL)
1280 		io_report(_("null arg to io_matmult"), FATALINTERNAL);
1281 	if (result->multiplied)
1282 	{
1283 		io_dumpstack();
1284 		io_report(_("can't re-mult tmatrix"), FATALINTERNAL);
1285 		return;
1286 	}
1287 	if (!r->multiplied)
1288 	{
1289 		tmatrix temp;
1290 
1291 		temp.multiplied = 0;
1292 		io_matmult(r, r->prev, &temp);
1293 		io_mmult(l, &temp, result);
1294 	} else io_mmult(l, r, result);
1295 }
1296 
io_mmult(transform l,transform r,transform result)1297 static void io_mmult(transform l,transform r,transform result)
1298 {
1299 	if (l == NIL || r == NIL || result == NIL)
1300 	{
1301 		io_report(_("null arg to io_mmult"), FATALINTERNAL);
1302 		return;
1303 	}
1304 	if (l->type == TIDENT) io_assign(r, result); else
1305 		if (r->type == TIDENT) io_assign(l, result); else
1306 	{
1307 		tmatrix temp;
1308 
1309 		temp.a11 = l->a11 * r->a11 + l->a12 * r->a21;
1310 		temp.a12 = l->a11 * r->a12 + l->a12 * r->a22;
1311 		temp.a21 = l->a21 * r->a11 + l->a22 * r->a21;
1312 		temp.a22 = l->a21 * r->a12 + l->a22 * r->a22;
1313 		temp.a31 = l->a31 * r->a11 + l->a32 * r->a21 + l->a33 * r->a31;
1314 		temp.a32 = l->a31 * r->a12 + l->a32 * r->a22 + l->a33 * r->a32;
1315 		temp.a33 = l->a33*r->a33;
1316 		temp.type = l->type | r->type;
1317 		io_assign(&temp,result);
1318 	}
1319 	if (result->a33 != 1.0)
1320 	{
1321 		/* divide by a33 */
1322 		result->a11 /= result->a33;
1323 		result->a12 /= result->a33;
1324 		result->a21 /= result->a33;
1325 		result->a22 /= result->a33;
1326 		result->a31 /= result->a33;
1327 		result->a32 /= result->a33;
1328 		result->a33 = 1.0;
1329 	}
1330 	result->multiplied = 1;
1331 }
1332 
io_getlocal(void)1333 tmatrix io_getlocal(void)
1334 {
1335 	return(*io_cifstacktop);
1336 }
1337 
io_applylocal(transform tm)1338 void io_applylocal(transform tm)
1339 {
1340 	io_assign(tm,io_cifstacktop);
1341 }
1342 
io_assign(transform src,transform dest)1343 static void io_assign(transform src,transform dest)
1344 {
1345 	dest->a11 = src->a11;
1346 	dest->a12 = src->a12;
1347 	dest->a21 = src->a21;
1348 	dest->a22 = src->a22;
1349 	dest->a31 = src->a31;
1350 	dest->a32 = src->a32;
1351 	dest->a33 = src->a33;
1352 	dest->type = src->type;
1353 	dest->multiplied = src->multiplied;
1354 }
1355 
io_rotate(INTBIG xrot,INTBIG yrot)1356 void io_rotate(INTBIG xrot,INTBIG yrot)
1357 {
1358 	float si = (float)yrot;
1359 	float co = (float)xrot;
1360 	float temp;
1361 
1362 	if (yrot == 0 && xrot >= 0) return;
1363 
1364 	io_cifstacktop->type |= TROTATE;
1365 	if (xrot == 0)
1366 	{
1367 		temp = io_cifstacktop->a11;
1368 		io_cifstacktop->a11 = -io_cifstacktop->a12;
1369 		io_cifstacktop->a12 = temp;
1370 
1371 		temp = io_cifstacktop->a21;
1372 		io_cifstacktop->a21 = -io_cifstacktop->a22;
1373 		io_cifstacktop->a22 = temp;
1374 
1375 		temp = io_cifstacktop->a31;
1376 		io_cifstacktop->a31 = -io_cifstacktop->a32;
1377 		io_cifstacktop->a32 = temp;
1378 		if (yrot < 0) io_cifstacktop->a33 = -io_cifstacktop->a33;
1379 	} else
1380 		if (yrot == 0) io_cifstacktop->a33 = -io_cifstacktop->a33;	/* xrot < 0 */
1381 	else
1382 	{
1383 		temp = io_cifstacktop->a11*co - io_cifstacktop->a12*si;
1384 		io_cifstacktop->a12 = io_cifstacktop->a11*si + io_cifstacktop->a12*co;
1385 		io_cifstacktop->a11 = temp;
1386 		temp = io_cifstacktop->a21*co - io_cifstacktop->a22*si;
1387 		io_cifstacktop->a22 = io_cifstacktop->a21*si + io_cifstacktop->a22*co;
1388 		io_cifstacktop->a21 = temp;
1389 		temp = io_cifstacktop->a31*co - io_cifstacktop->a32*si;
1390 		io_cifstacktop->a32 = io_cifstacktop->a31*si + io_cifstacktop->a32*co;
1391 		io_cifstacktop->a31 = temp;
1392 		io_cifstacktop->a33 = (float)computedistance(0, 0, (INTBIG)co, (INTBIG)si);
1393 	}
1394 }
1395 
io_translate(INTBIG xtrans,INTBIG ytrans)1396 void io_translate(INTBIG xtrans, INTBIG ytrans)
1397 {
1398 	if (xtrans != 0 || ytrans != 0)
1399 	{
1400 		io_cifstacktop->a31 += io_cifstacktop->a33*xtrans;
1401 		io_cifstacktop->a32 += io_cifstacktop->a33*ytrans;
1402 		io_cifstacktop->type |= TTRANSLATE;
1403 	}
1404 }
1405 
io_mirror(CHAR xcoord)1406 void io_mirror(CHAR xcoord)
1407 {
1408 	if (xcoord)
1409 	{
1410 		io_cifstacktop->a11 = -io_cifstacktop->a11;
1411 		io_cifstacktop->a21 = -io_cifstacktop->a21;
1412 		io_cifstacktop->a31 = -io_cifstacktop->a31;
1413 	} else
1414 	{
1415 		io_cifstacktop->a12 = -io_cifstacktop->a12;
1416 		io_cifstacktop->a22 = -io_cifstacktop->a22;
1417 		io_cifstacktop->a32 = -io_cifstacktop->a32;
1418 	}
1419 	io_cifstacktop->type |= TMIRROR;
1420 }
1421 
io_transpoint(point foo)1422 point io_transpoint(point foo)
1423 {
1424 	point ans;
1425 
1426 	if (!io_cifstacktop->multiplied)
1427 	{
1428 		io_matmult(io_cifstacktop,io_cifstacktop->prev,io_cifstacktop);
1429 	}
1430 	switch (io_cifstacktop->type)
1431 	{
1432 		case TIDENT:
1433 			return(foo);
1434 		case TTRANSLATE:
1435 			ans.x = roundfloat(io_cifstacktop->a31);
1436 			ans.y = roundfloat(io_cifstacktop->a32);
1437 			ans.x += foo.x;   ans.y += foo.y;
1438 			return(ans);
1439 		case TMIRROR:
1440 			ans.x = (io_cifstacktop->a11 < 0) ? -foo.x : foo.x;
1441 			ans.y = (io_cifstacktop->a22 < 0) ? -foo.y : foo.y;
1442 			return(ans);
1443 		case TROTATE:
1444 			ans.x = roundfloat(((float) foo.x)*io_cifstacktop->a11+((float) foo.y)*io_cifstacktop->a21);
1445 			ans.y = roundfloat(((float) foo.x)*io_cifstacktop->a12+((float) foo.y)*io_cifstacktop->a22);
1446 			return(ans);
1447 		default:
1448 			ans.x = roundfloat(io_cifstacktop->a31 + ((float) foo.x)*io_cifstacktop->a11+
1449 				((float) foo.y)*io_cifstacktop->a21);
1450 			ans.y = roundfloat(io_cifstacktop->a32 + ((float) foo.x)*io_cifstacktop->a12+
1451 				((float) foo.y)*io_cifstacktop->a22);
1452 	}
1453 	return(ans);
1454 }
1455 
io_dumpstack(void)1456 void io_dumpstack(void)
1457 {
1458 	transform foo = io_cifstacktop;
1459 	ttyputmsg(_("current context is %u"), io_cifcurcontext);
1460 	while (foo != NIL)
1461 	{
1462 		io_printmat(foo);
1463 		foo = foo->prev;
1464 	}
1465 }
1466 
io_printmat(transform t)1467 static void io_printmat(transform t)
1468 {
1469 	ttyputmsg(x_("type: %ld, mult: %d"), t->type, t->multiplied);
1470 	ttyputmsg(x_("%f %f"), t->a11, t->a12);
1471 	ttyputmsg(x_("%f %f"), t->a21, t->a22);
1472 	ttyputmsg(x_("%f %f %f"), t->a31, t->a32, t->a33);
1473 }
1474 
1475 /************ bbs.c: bounding box finder for primitive geometry ************/
1476 
io_bbflash(INTBIG lay,INTBIG diameter,point center,INTBIG * l,INTBIG * r,INTBIG * b,INTBIG * t)1477 void io_bbflash(INTBIG lay, INTBIG diameter, point center, INTBIG *l, INTBIG *r,
1478 	INTBIG *b, INTBIG *t)
1479 {
1480 	io_bbbox(lay, diameter, diameter, center, 1, 0, l, r, b, t);
1481 }
1482 
io_bbbox(INTBIG lay,INTBIG length,INTBIG width,point center,INTBIG xr,INTBIG yr,INTBIG * l,INTBIG * r,INTBIG * b,INTBIG * t)1483 void io_bbbox(INTBIG lay, INTBIG length, INTBIG width, point center, INTBIG xr,
1484 	INTBIG yr, INTBIG *l, INTBIG *r, INTBIG *b, INTBIG *t)
1485 {
1486 	INTBIG dx,dy;
1487 	point temp;
1488 
1489 	dx = length/2;
1490 	dy = width/2;
1491 
1492 	io_pushtrans();	/* newtrans */
1493 	io_rotate(xr, yr);
1494 	io_translate(center.x, center.y);
1495 	temp.x = dx;   temp.y = dy;
1496 	io_initmm(io_transpoint(temp));
1497 	temp.y = -dy;
1498 	io_minmax(io_transpoint(temp));
1499 	temp.x = -dx;
1500 	io_minmax(io_transpoint(temp));
1501 	temp.y = dy;
1502 	io_minmax(io_transpoint(temp));
1503 	io_poptrans();
1504 	*l = io_minx();
1505 	*r = io_maxx();
1506 	*b = io_miny();
1507 	*t = io_maxy();
1508 	io_donemm();
1509 }
1510 
io_bbpolygon(INTBIG lay,path ppath,INTBIG * l,INTBIG * r,INTBIG * b,INTBIG * t)1511 void io_bbpolygon(INTBIG lay, path ppath, INTBIG *l, INTBIG *r, INTBIG *b, INTBIG *t)
1512 {
1513 	INTBIG i, limit;
1514 
1515 	limit = io_pathlength(ppath);
1516 
1517 	io_pushtrans();	/* newtrans */
1518 	io_initmm(io_transpoint(io_removepoint(ppath)));
1519 	for (i = 1; i < limit; i++)
1520 	{
1521 		io_minmax(io_transpoint(io_removepoint(ppath)));
1522 	}
1523 	io_poptrans();
1524 	*l = io_minx();
1525 	*r = io_maxx();
1526 	*b = io_miny();
1527 	*t = io_maxy();
1528 	io_donemm();
1529 }
1530 
io_bbwire(INTBIG lay,INTBIG width,path ppath,INTBIG * l,INTBIG * r,INTBIG * b,INTBIG * t)1531 void io_bbwire(INTBIG lay, INTBIG width, path ppath, INTBIG *l, INTBIG *r,
1532 	INTBIG *b, INTBIG *t)
1533 {
1534 	INTBIG i, limit;
1535 	INTBIG half = (width+1)/2;
1536 
1537 	limit = io_pathlength(ppath);
1538 
1539 	io_pushtrans();	/* newtrans */
1540 	io_initmm(io_transpoint(io_removepoint(ppath)));
1541 	for (i = 1; i < limit; i++)
1542 	{
1543 		io_minmax(io_transpoint(io_removepoint(ppath)));
1544 	}
1545 	io_poptrans();
1546 	*l = io_minx()-half;
1547 	*r = io_maxx()+half;
1548 	*b = io_miny()-half;
1549 	*t = io_maxy()+half;
1550 	io_donemm();
1551 }
1552 
1553 /********************* items.c: item tree stuff *********************/
1554 
io_inititems(void)1555 CHAR io_inititems(void)
1556 {
1557 	io_cifittop = NIL;
1558 	io_cifilist = NIL;
1559 	return(0);
1560 }
1561 
io_doneitems(void)1562 BOOLEAN io_doneitems(void)
1563 {
1564 	itementry *cur, *next;
1565 
1566 	for (cur = io_cifittop; cur != NIL; cur = next)
1567 	{
1568 		next = cur->it_same;
1569 		io_freeonedef((struct cifhack *)cur->it_what);
1570 		efree((CHAR *)cur);
1571 	}
1572 	for (cur = io_cifilist; cur != NIL; cur = next)
1573 	{
1574 		next = cur->it_same;
1575 		io_freeonedef((struct cifhack *)cur->it_what);
1576 		efree((CHAR *)cur);
1577 	}
1578 	return(FALSE);
1579 }
1580 
1581 /*
1582  * allocate and free item nodes, come not from interpreter storage,
1583  * since they don't need to be saved with compiled stuff.
1584  */
io_newnode(void)1585 static itementry *io_newnode(void)		/* return a new itementry */
1586 {
1587 	itementry *ans;
1588 
1589 	if (io_cifittop == NIL)
1590 	{
1591 		ans = (itementry *)emalloc(sizeof(itementry), io_tool->cluster);
1592 		if (ans == NIL)
1593 		{
1594 			io_report(_("io_newnode: no space"), FATALINTERNAL);
1595 			return(NIL);
1596 		} else return(ans);
1597 	}
1598 	ans = io_cifittop;
1599 	io_cifittop = io_cifittop->it_same;
1600 	return(ans);
1601 }
1602 
io_freenode(itementry * ptr)1603 static void io_freenode(itementry *ptr)
1604 {
1605 	ptr->it_same = io_cifittop;
1606 	io_cifittop = ptr;
1607 }
1608 
io_sendlist(itementry * list)1609 static void io_sendlist(itementry *list)
1610 {
1611 	itementry *save, *h;
1612 
1613 	h = list;
1614 	while (h != NIL)
1615 	{
1616 		save = h->it_same;
1617 		io_outitem(h);
1618 		h = save;
1619 	}
1620 }
1621 
io_dumpdef(stentry * sym)1622 static void io_dumpdef(stentry *sym)
1623 {
1624 	struct cifhack *ro;
1625 
1626 	if (sym->st_dumped) return;		/* already done */
1627 	if (sym->st_ncalls > 0)			/* dump all children */
1628 	{
1629 		INTBIG count = sym->st_ncalls;
1630 
1631 		ro = (struct cifhack *) sym->st_guts;
1632 		while ((ro != NIL) && (count > 0))
1633 		{
1634 			if (ro->kl_type == CALL)
1635 			{
1636 				io_dumpdef(((symcall *) ro)->sy_unid);
1637 				count--;
1638 			}
1639 			ro = ro->kl_next;
1640 		}
1641 	}
1642 	io_shipcontents(sym);
1643 	sym->st_dumped = 1;
1644 }
1645 
io_shipcontents(stentry * sym)1646 static void io_shipcontents(stentry *sym)
1647 {
1648 	struct cifhack *ro;
1649 
1650 	ro = (struct cifhack *) sym->st_guts;
1651 	io_outputds(sym->st_symnumber, sym->st_name,
1652 		sym->st_bb.l, sym->st_bb.r, sym->st_bb.b, sym->st_bb.t);
1653 	while (ro != NIL)
1654 	{
1655 		switch (ro->kl_type)
1656 		{
1657 			CHAR *ppath, *t_list;
1658 			INTBIG length, i;
1659 			point temp;
1660 
1661 			case POLY:
1662 				length = ((polygon *)ro)->po_numpts;
1663 				ppath = io_makepath();
1664 				for (i = 0; i < length; i++)
1665 					if (io_appendpoint((path)ppath, ((polygon *)ro)->po_p[i])) return;
1666 				io_outputpolygon(((polygon *)ro)->po_layer, ppath);
1667 				io_freepath((path)ppath);
1668 				break;
1669 			case WIRE:
1670 				length = ((wire *)ro)->wi_numpts;
1671 				ppath = io_makepath();
1672 				for (i = 0; i < length; i++)
1673 					if (io_appendpoint((path)ppath, ((wire *)ro)->wi_p[i])) return;
1674 				io_outputwire(((wire *)ro)->wi_layer, ((wire *)ro)->wi_width,
1675 					ppath);
1676 				io_freepath((path)ppath);
1677 				break;
1678 			case FLASH:
1679 				io_outputflash(((flash *)ro)->fl_layer, ((flash *)ro)->fl_diameter,
1680 					((flash *)ro)->fl_center);
1681 				break;
1682 			case RECTANGLE:
1683 				io_outputbox(((box *)ro)->bo_layer, ((box *)ro)->bo_length,
1684 					((box *)ro)->bo_width, ((box *)ro)->bo_center,
1685 						((box *)ro)->bo_xrot, ((box *)ro)->bo_yrot);
1686 				break;
1687 			case MBOX:
1688 				temp.x = (((mbox *)ro)->mb_bb.r + ((mbox *) ro)->mb_bb.l)/2;
1689 				temp.y = (((mbox *)ro)->mb_bb.t + ((mbox *) ro)->mb_bb.b)/2;
1690 				io_outputbox(((mbox *)ro)->mb_layer,
1691 					((mbox *)ro)->mb_bb.r-((mbox *)ro)->mb_bb.l,
1692 						((mbox *)ro)->mb_bb.t-((mbox *)ro)->mb_bb.b, temp, 1, 0);
1693 				break;
1694 			case CALL:
1695 				t_list = io_maketlist();
1696 				io_dupetlist((tlist)((symcall *)ro)->sy_tlist, (tlist)t_list);
1697 				io_outputcall(((symcall *)ro)->sy_symnumber,
1698 					((symcall *)ro)->sy_unid->st_name, t_list);
1699 				io_freetlist((tlist)t_list);
1700 				break;
1701 			case NAME:
1702 				io_outputgeoname(((gname *)ro)->gn_name,
1703 					((gname *)ro)->gn_pos, ((gname *)ro)->gn_layer);
1704 				break;
1705 			case LABEL:
1706 				io_outputlabel(((label *)ro)->la_name, ((label *)ro)->la_pos);
1707 				break;
1708 		}
1709 		ro = ro->kl_next;
1710 	}
1711 	io_outputdf();
1712 }
1713 
io_iboundbox(INTBIG * l,INTBIG * r,INTBIG * b,INTBIG * t)1714 void io_iboundbox(INTBIG *l, INTBIG *r, INTBIG *b, INTBIG *t)
1715 {
1716 	itementry *h;
1717 	struct cifhack *obj;
1718 	point temp;
1719 	point comperror;	/* hack for compiler error */
1720 	CHAR first;
1721 
1722 	h = io_cifilist;
1723 	first = 1;
1724 
1725 	if (h == NIL)
1726 	{
1727 		io_report(_("item list is empty!"), ADVISORY);
1728 		return;
1729 	}
1730 
1731 	(void)io_swapcontext(0);
1732 	io_pushtrans();
1733 	while (h != NIL)
1734 	{
1735 		obj = (struct cifhack *)h->it_what;
1736 		temp.x = obj->kl_bb.l;
1737 		temp.y = obj->kl_bb.b;
1738 		comperror = io_transpoint(temp);
1739 		io_initmm(comperror);
1740 		temp.x = obj->kl_bb.r;
1741 		comperror = io_transpoint(temp);
1742 		io_minmax(comperror);
1743 		temp.y = obj->kl_bb.t;
1744 		comperror = io_transpoint(temp);
1745 		io_minmax(comperror);
1746 		temp.x = obj->kl_bb.l;
1747 		comperror = io_transpoint(temp);
1748 		io_minmax(comperror);
1749 
1750 		h->it_left = io_minx();
1751 		h->it_right = io_maxx();
1752 		h->it_bottom = io_miny();
1753 		h->it_top = io_maxy();
1754 		io_donemm();
1755 		temp.x = h->it_left;   temp.y = h->it_bottom;
1756 		if (first) {first = 0; io_initmm(temp);} else io_minmax(temp);
1757 		temp.x = h->it_right;   temp.y = h->it_top;
1758 		io_minmax(temp);
1759 		h = h->it_same;
1760 	}
1761 	*l = io_minx();
1762 	*r = io_maxx();
1763 	*b = io_miny();
1764 	*t = io_maxy();
1765 	io_donemm();
1766 	io_poptrans();
1767 	(void)io_swapcontext(0);		/* always leave in context 0 */
1768 }
1769 
io_createlist(void)1770 BOOLEAN io_createlist(void)
1771 {
1772 	if (!io_endseen()) ttyputmsg(_("missing End command, assumed"));
1773 	if (io_fatalerrors() > 0) return(TRUE);
1774 	io_sendlist(io_cifilist);		/* sendlist deletes nodes */
1775 	io_cifilist = NIL;
1776 	(void)io_swapcontext(0);
1777 	return(FALSE);
1778 }
1779 
io_outitem(itementry * thing)1780 static void io_outitem(itementry *thing)		/* spit out an item */
1781 {
1782 	switch (thing->it_type)
1783 	{
1784 		CHAR *ppath, *t_list;
1785 		INTBIG length, i;
1786 		point temp;
1787 
1788 		case POLY:
1789 			(void)io_swapcontext(thing->it_context);
1790 			length = ((polygon *) (thing->it_what))->po_numpts;
1791 			ppath = io_makepath();
1792 			for (i = 0; i < length; i++)
1793 				if (io_appendpoint((path)ppath, ((polygon *)(thing->it_what))->po_p[i])) return;
1794 			io_outputpolygon(((polygon *) (thing->it_what))->po_layer, ppath);
1795 			(void)io_decrefcount(thing->it_context);
1796 			io_freepath((path)ppath);
1797 			break;
1798 
1799 		case WIRE:
1800 			(void)io_swapcontext(thing->it_context);
1801 			length = ((wire *) (thing->it_what))->wi_numpts;
1802 			ppath = io_makepath();
1803 			for (i = 0; i < length; i++)
1804 				if (io_appendpoint((path)ppath, ((wire *) (thing->it_what))->wi_p[i])) return;
1805 			io_outputwire(((wire *) (thing->it_what))->wi_layer,
1806 				((wire *) (thing->it_what))->wi_width, ppath);
1807 			(void)io_decrefcount(thing->it_context);
1808 			io_freepath((path)ppath);
1809 			break;
1810 
1811 		case FLASH:
1812 			(void)io_swapcontext(thing->it_context);
1813 			io_outputflash(((flash *) (thing->it_what))->fl_layer,
1814 				((flash *) (thing->it_what))->fl_diameter, ((flash *) (thing->it_what))->fl_center);
1815 			(void)io_decrefcount(thing->it_context);
1816 			break;
1817 
1818 		case RECTANGLE:
1819 			(void)io_swapcontext(thing->it_context); /* get right frame of ref */
1820 			io_outputbox(((box *) (thing->it_what))->bo_layer,
1821 				((box *) (thing->it_what))->bo_length, ((box *) (thing->it_what))->bo_width,
1822 					((box *) (thing->it_what))->bo_center, ((box *) (thing->it_what))->bo_xrot,
1823 						((box *) (thing->it_what))->bo_yrot);
1824 			(void)io_decrefcount(thing->it_context);
1825 			break;
1826 
1827 		case MBOX:
1828 			(void)io_swapcontext(thing->it_context); /* get right frame of ref */
1829 			temp.x = (((mbox *) (thing->it_what))->mb_bb.r+
1830 				((mbox *) (thing->it_what))->mb_bb.l)/2;
1831 			temp.y = (((mbox *) (thing->it_what))->mb_bb.t+
1832 				((mbox *) (thing->it_what))->mb_bb.b)/2;
1833 			io_outputbox(
1834 				((mbox *) (thing->it_what))->mb_layer,
1835 				((mbox *) (thing->it_what))->mb_bb.r-
1836 				((mbox *) (thing->it_what))->mb_bb.l,
1837 				((mbox *) (thing->it_what))->mb_bb.t-
1838 				((mbox *) (thing->it_what))->mb_bb.b,
1839 				temp, 1, 0);
1840 			(void)io_decrefcount(thing->it_context);
1841 			break;
1842 
1843 		case CALL:
1844 			(void)io_swapcontext(thing->it_context);
1845 			io_pushtrans();
1846 			io_applylocal(&(((symcall *) (thing->it_what))->sy_tm));
1847 			t_list = io_maketlist();
1848 			io_dupetlist((tlist)((symcall *) (thing->it_what))->sy_tlist, (tlist)t_list);
1849 			io_dumpdef(((symcall *) (thing->it_what))->sy_unid);
1850 			io_outputcall(((symcall *) (thing->it_what))->sy_symnumber,
1851 				((symcall *) (thing->it_what))->sy_unid->st_name, t_list);
1852 			io_freetlist((tlist)t_list);
1853 			(void)io_swapcontext(thing->it_context);
1854 			io_poptrans();
1855 			(void)io_decrefcount(thing->it_context);
1856 			break;
1857 
1858 		case NAME:
1859 			(void)io_swapcontext(thing->it_context);
1860 			io_outputgeoname(((gname *) (thing->it_what))->gn_name,
1861 				((gname *) (thing->it_what))->gn_pos, ((gname *) (thing->it_what))->gn_layer);
1862 			(void)io_decrefcount(thing->it_context);
1863 			break;
1864 
1865 		case LABEL:
1866 			(void)io_swapcontext(thing->it_context);
1867 			io_outputlabel(((label *) (thing->it_what))->la_name,
1868 				((label *) (thing->it_what))->la_pos);
1869 			(void)io_decrefcount(thing->it_context);
1870 			break;
1871 	}
1872 	io_freenode(thing);
1873 }
1874 
io_item(objectptr object)1875 void io_item(objectptr object)		/* a bare item has been found */
1876 {
1877 	struct cifhack *obj;
1878 	itementry *newitem;
1879 
1880 	if (object == NIL)
1881 	{
1882 		io_report(_("item: null object"), FATALINTERNAL);
1883 		return;
1884 	}
1885 	obj = (struct cifhack *)object;
1886 
1887 	newitem = io_newnode();
1888 	newitem->it_type = obj->kl_type;
1889 	newitem->it_rel = NIL;
1890 	newitem->it_norel = NIL;
1891 	newitem->it_same = io_cifilist;		/* hook into linked list */
1892 	io_cifilist = newitem;
1893 	newitem->it_what = object;
1894 	newitem->it_level = 0;		/* bare item */
1895 	newitem->it_context = 0;		/* outermost context */
1896 	(void)io_increfcount(0);
1897 
1898 	/* symbol calls only */
1899 	if (obj->kl_type == CALL) io_findcallbb((symcall *)object);
1900 }
1901 
1902 /********************* parser.c: begin *********************/
1903 
1904 /*
1905  *	same as xp.c except removed
1906  *	efree()'s before realloc()'s
1907  *
1908  *	xp.c
1909  *	cif 2.0 parser
1910  *	experimental parser that includes names
1911  *	consists of 4 modules -- parser,error,types,input
1912  *
1913  *	exports:
1914  *		io_initparser()
1915  *		io_doneparser()
1916  *		io_parsestatement()
1917  *
1918  *		io_makepath()
1919  *		io_freepath(path)
1920  *		io_appendpoint(path,pt)
1921  *		io_copypath(path,path)
1922  *		io_removepoint(path)
1923  *		io_pathlength(path)
1924  *		io_maketlist()
1925  *		io_freetlist(tlist)
1926  *		io_appendtentry(tlist,tentry)
1927  *		io_removetentry(tlist)
1928  *		io_tlistlength(tlist)
1929  *		io_dupetlist(src,dest)
1930  *
1931  *		io_fatalerrors()
1932  *		io_report("message", kind)
1933  *
1934  *		io_infromfile(file)
1935  *
1936  *	inter-module routines:
1937  *		init/done types
1938  *		init/done error
1939  *		io_identify(), io_getch(), io_peek()
1940  *		ttyputmsg()
1941  *
1942  *	imports:
1943  *		io_idefstart(...)
1944  *		io_idefend()
1945  *		io_ideletedef(nsym)
1946  *		io_ilayer(...)
1947  *		io_iflash(...)
1948  *		io_ipolygon(...)
1949  *		io_ibox(...)
1950  *		io_icall(...)
1951  *		io_icomment(...)
1952  *		io_iusercommand(...)
1953  *		io_iend()
1954  *
1955  *		io_isymname(name)
1956  *		io_iinstname(name)
1957  *		io_igeoname(...)
1958  *		io_ilabel(...)
1959  *
1960  */
1961 
1962 /********************* input.c: input module *********************/
1963 
1964 #define LINELEN 200							/* max chars to save in line buffer */
1965 
1966 static FILE   *io_cifinfile;				/* input file */
1967 static INTBIG  io_ciffilelength;			/* file length */
1968 static INTBIG  io_cifcharsread;				/* characters read from file */
1969 static INTBIG  io_cifnextchar;				/* lookahead character */
1970 static INTBIG  io_ciflinecount;				/* line count */
1971 static CHAR    io_ciflinebuffer[LINELEN];	/* identify line buffer */
1972 static CHAR   *io_ciflineptr;				/* where we are in line buffer */
1973 static INTBIG  io_cifcharcount;				/* number of chars in buffer */
1974 static CHAR    io_cifresetbuffer;			/* flag to reset buffer */
1975 static void   *io_cifprogressdialog;		/* for showing input progress */
1976 
io_initinput(void)1977 static CHAR io_initinput(void)
1978 {
1979 	io_ciflinecount = 1;
1980 	io_cifcharcount = 0;
1981 	io_cifresetbuffer = 1;
1982 	return(0);
1983 }
1984 
io_doneinput(void)1985 static CHAR io_doneinput(void)
1986 {
1987 	xclose(io_cifinfile);
1988 	if (io_verbose < 0 && io_ciffilelength > 0) DiaDoneProgress(io_cifprogressdialog);
1989 	return(0);
1990 }
1991 
io_infromfile(FILE * file)1992 BOOLEAN io_infromfile(FILE *file)
1993 {
1994 	io_cifinfile = file;
1995 	if (io_verbose < 0)
1996 	{
1997 		io_ciffilelength = filesize(io_cifinfile);
1998 		if (io_ciffilelength > 0)
1999 		{
2000 			io_cifprogressdialog = DiaInitProgress(0, 0);
2001 			if (io_cifprogressdialog == 0) return(TRUE);
2002 			DiaSetProgress(io_cifprogressdialog, 0, io_ciffilelength);
2003 		}
2004 	} else io_ciffilelength = 0;
2005 	io_cifnextchar = xgetc(io_cifinfile);
2006 	io_cifcharsread = 1;
2007 	return(FALSE);
2008 }
2009 
io_getch(void)2010 static CHAR io_getch(void)
2011 {
2012 	REGISTER INTBIG c;
2013 
2014 	if (io_cifresetbuffer)
2015 	{
2016 		io_cifresetbuffer = 0;
2017 		io_ciflineptr = &io_ciflinebuffer[0];
2018 		io_cifcharcount = 0;
2019 	}
2020 
2021 	if ((c = io_cifnextchar) != EOF)
2022 	{
2023 		if (c == '\n') io_ciflinecount++;
2024 		if (io_cifcharcount < LINELEN-1)
2025 		{
2026 			if (c != '\n')
2027 			{
2028 				io_cifcharcount++; *io_ciflineptr++ = (CHAR)c; *io_ciflineptr = '\0';
2029 			} else io_cifresetbuffer = 1;
2030 		}
2031 		io_cifnextchar = xgetc(io_cifinfile);
2032 		io_cifcharsread++;
2033 		if (io_verbose < 0 && io_ciffilelength > 0 && (io_cifcharsread%2000) == 0)
2034 			DiaSetProgress(io_cifprogressdialog, io_cifcharsread, io_ciffilelength);
2035 	}
2036 	return((CHAR)c);
2037 }
2038 
io_peek(void)2039 static CHAR io_peek(void)
2040 {
2041 	return((CHAR)io_cifnextchar);
2042 }
2043 
io_endoffile(void)2044 CHAR io_endoffile(void)
2045 {
2046 	return(io_cifnextchar == EOF);
2047 }
2048 
io_flush(CHAR breakchar)2049 static INTBIG io_flush(CHAR breakchar)
2050 {
2051 	REGISTER INTBIG c;
2052 
2053 	while ((c = io_peek()) != EOF && c != breakchar) (void) io_getch();
2054 	return(c);
2055 }
2056 
io_identify(void)2057 static void io_identify(void)
2058 {
2059 	CHAR temp[200];
2060 
2061 	if (io_cifcharcount > 0)
2062 	{
2063 		(void)esnprintf(temp, 200, x_("line %ld: %s"), io_ciflinecount-io_cifresetbuffer, io_ciflinebuffer);
2064 		ttyputmsg(temp);
2065 	}
2066 }
2067 
2068 /********************* types.c: data types *********************/
2069 
io_freeciftfree(void)2070 static void io_freeciftfree(void)
2071 {
2072 	linkedtentry *ct;
2073 
2074 	while (io_ciftfree != 0)
2075 	{
2076 		ct = io_ciftfree;
2077 		io_ciftfree = io_ciftfree->tnext;
2078 		efree((CHAR *)ct);
2079 	}
2080 }
2081 
io_inittypes(void)2082 static CHAR io_inittypes(void)
2083 {
2084 	io_cifpfree = NIL;
2085 	io_freeciftfree();
2086 	return(0);
2087 }
2088 
io_donetypes(void)2089 static CHAR io_donetypes(void)
2090 {
2091 	while (io_cifpfree != NIL)
2092 	{
2093 		linkedpoint *temp;
2094 
2095 		temp = io_cifpfree->pnext;
2096 		efree((CHAR *)io_cifpfree);
2097 		io_cifpfree = temp;
2098 	}
2099 	while (io_ciftfree != NIL)
2100 	{
2101 		linkedtentry *temp;
2102 
2103 		temp = io_ciftfree->tnext;
2104 		efree((CHAR *)io_ciftfree);
2105 		io_ciftfree = temp;
2106 	}
2107 	return(0);
2108 }
2109 
io_makepath(void)2110 CHAR *io_makepath(void)
2111 {
2112 	path a;
2113 
2114 	a = (path)emalloc(sizeof(*a), io_tool->cluster);
2115 	if (a == NIL)
2116 	{
2117 		io_report(_("free storage exhausted"), FATALINTERNAL);
2118 		return(0);
2119 	}
2120 	a->pfirst = NIL;
2121 	a->plast = NIL;
2122 	a->plength = 0;
2123 	return((CHAR *)a);
2124 }
2125 
io_freepath(path a)2126 void io_freepath(path a)
2127 {
2128 	linkedpoint *node;
2129 
2130 	node = a->pfirst;
2131 	while (node != NIL)
2132 	{
2133 		linkedpoint *saved;
2134 		saved = node->pnext;
2135 		io_freepnode(node);
2136 		node = saved;
2137 	}
2138 	efree((CHAR *)a);		/* should change to avoid overhead */
2139 }
2140 
io_getpnode(void)2141 static linkedpoint *io_getpnode(void)
2142 {
2143 	linkedpoint *ans;
2144 
2145 	if (io_cifpfree == NIL)
2146 	{
2147 		return((linkedpoint *)emalloc(sizeof(linkedpoint), io_tool->cluster));
2148 	}
2149 	ans = io_cifpfree;
2150 	io_cifpfree = io_cifpfree->pnext;
2151 	return(ans);
2152 }
2153 
io_freepnode(linkedpoint * a)2154 static void io_freepnode(linkedpoint *a)
2155 {
2156 	a->pnext = io_cifpfree;
2157 	io_cifpfree = a;
2158 }
2159 
2160 /* returns nonzero on memory error */
io_appendpoint(path a,point p)2161 BOOLEAN io_appendpoint(path a, point p)
2162 {
2163 	linkedpoint *temp;
2164 
2165 	temp = a->plast;
2166 	a->plast = io_getpnode();
2167 	if (a->plast == 0) return(TRUE);
2168 	if (temp != NIL) temp->pnext = a->plast;
2169 	a->plast->pvalue = p;
2170 	a->plast->pnext = NIL;
2171 	if (a->pfirst == NIL) a->pfirst = a->plast;
2172 	a->plength += 1;
2173 	return(FALSE);
2174 }
2175 
io_copypath(path src,path dest)2176 void io_copypath(path src, path dest)
2177 {
2178 	linkedpoint *temp;
2179 
2180 	temp = src->pfirst;
2181 	if (src == dest) return;
2182 	while (temp != NIL)
2183 	{
2184 		if (io_appendpoint(dest, temp->pvalue)) break;
2185 		temp = temp->pnext;
2186 	}
2187 }
2188 
io_removepoint(path a)2189 point io_removepoint(path a)
2190 {
2191 	linkedpoint *temp;
2192 	point ans;
2193 
2194 	if (a->pfirst == NIL)
2195 	{
2196 		/* added code to initialize return value with dummy numbers */
2197 		ans.x = ans.y = 0;
2198 		return(ans);
2199 	}
2200 	temp = a->pfirst->pnext;
2201 	ans = a->pfirst->pvalue;
2202 	io_freepnode(a->pfirst);
2203 	a->pfirst = temp;
2204 	if (a->pfirst == NIL) a->plast = NIL;
2205 	a->plength -= 1;
2206 	return(ans);
2207 }
2208 
io_pathlength(path a)2209 INTBIG io_pathlength(path a)
2210 {
2211 	return(a->plength);
2212 }
2213 
io_maketlist(void)2214 CHAR *io_maketlist(void)
2215 {
2216 	tlist a;
2217 
2218 	a = (tlist)emalloc(sizeof(*a), io_tool->cluster);
2219 	if (a == NIL)
2220 	{
2221 		io_report(_("free storage exhausted"), FATALINTERNAL);
2222 		return(0);
2223 	}
2224 	a->tfirst = NIL;
2225 	a->tlast = NIL;
2226 	a->tlength = 0;
2227 	return((CHAR *) a);
2228 }
2229 
io_freetlist(tlist a)2230 void io_freetlist(tlist a)
2231 {
2232 	linkedtentry *node;
2233 
2234 	node = a->tfirst;
2235 	while (node != NIL)
2236 	{
2237 		linkedtentry *saved;
2238 		saved = node->tnext;
2239 		io_freetnode(node);
2240 		node = saved;
2241 	}
2242 	efree((CHAR *)a);		/* should change to avoid overhead */
2243 }
2244 
io_dupetlist(tlist src,tlist dest)2245 void io_dupetlist(tlist src, tlist dest)
2246 {
2247 	linkedtentry *node;
2248 
2249 	if (src == NIL || dest == NIL) return;
2250 	node = src->tfirst;
2251 	while (node != NIL)
2252 	{
2253 		io_appendtentry(dest, node->tvalue);
2254 		node = node->tnext;
2255 	}
2256 }
2257 
io_gettnode(void)2258 static linkedtentry *io_gettnode(void)
2259 {
2260 	linkedtentry *ans;
2261 
2262 	if (io_ciftfree == NIL)
2263 	{
2264 		ans = (linkedtentry *)emalloc(sizeof(linkedtentry), io_tool->cluster);
2265 		if (ans == 0) return(0);
2266 		return(ans);
2267 	}
2268 	ans = io_ciftfree;
2269 	io_ciftfree = io_ciftfree->tnext;
2270 	return(ans);
2271 }
2272 
io_freetnode(linkedtentry * a)2273 static void io_freetnode(linkedtentry *a)
2274 {
2275 	a->tnext = io_ciftfree;
2276 	io_ciftfree = a;
2277 }
2278 
io_appendtentry(tlist a,tentry p)2279 void io_appendtentry(tlist a, tentry p)
2280 {
2281 	linkedtentry *temp, *newt;
2282 
2283 	newt = io_gettnode();
2284 	if (newt == 0) return;
2285 
2286 	temp = a->tlast;
2287 	a->tlast = newt;
2288 	if (temp != NIL) temp->tnext = a->tlast;
2289 	a->tlast->tvalue = p;
2290 	a->tlast->tnext = NIL;
2291 	if (a->tfirst == NIL) a->tfirst = a->tlast;
2292 	a->tlength += 1;
2293 }
2294 
io_removetentry(tlist a)2295 tentry io_removetentry(tlist a)
2296 {
2297 	linkedtentry *temp;
2298 	tentry ans;
2299 
2300 	if (a->tfirst == NIL)
2301 	{
2302 		/* added extra code to initialize "ans" to a dummy value */
2303 		ans.kind = TRANSLATE;
2304 		ans.guts.tr.xt = ans.guts.tr.yt = 0;
2305 		return(ans);
2306 	}
2307 	temp = a->tfirst->tnext;
2308 	ans = a->tfirst->tvalue;
2309 	io_freetnode(a->tfirst);
2310 	a->tfirst = temp;
2311 	if (a->tfirst == NIL) a->tlast = NIL;
2312 	a->tlength -= 1;
2313 	return(ans);
2314 }
2315 
io_tlistlength(tlist a)2316 INTBIG io_tlistlength(tlist a)
2317 {
2318 	if (a == NIL) return(0);
2319 	return(a->tlength);
2320 }
2321 
2322 /********************* error.c: error reporter *********************/
2323 
2324 static INTBIG io_cifecounts[OTHER+1];
2325 
io_initerror(void)2326 static CHAR io_initerror(void)
2327 {
2328 	INTBIG i;
2329 
2330 	for (i = 0; i <= OTHER; i++) io_cifecounts[i] = 0;
2331 	return(0);
2332 }
2333 
io_doneerror(void)2334 static CHAR io_doneerror(void)
2335 {
2336 	return(0);
2337 }
2338 
io_fatalerrors(void)2339 INTBIG io_fatalerrors(void)
2340 {
2341 	return(io_cifecounts[FATALINTERNAL]+io_cifecounts[FATALSYNTAX]+
2342 		io_cifecounts[FATALSEMANTIC]+io_cifecounts[FATALOUTPUT]);
2343 }
2344 
io_report(CHAR * mess,INTBIG kind)2345 void io_report(CHAR *mess, INTBIG kind)
2346 {
2347 	io_identify();
2348 	io_cifecounts[kind]++;
2349 
2350 	switch (kind)
2351 	{
2352 		case FATALINTERNAL: ttyputmsg(_("Fatal internal error: %s"), mess);  break;
2353 		case FATALSYNTAX:   ttyputmsg(_("Syntax error: %s"), mess);          break;
2354 		case FATALSEMANTIC: ttyputmsg(_("Error: %s"), mess);                 break;
2355 		case FATALOUTPUT:   ttyputmsg(_("Output error: %s"), mess);          break;
2356 		case ADVISORY:      ttyputmsg(_("Warning: %s"), mess);               break;
2357 		default:            ttyputmsg(x_("%s"), mess);                        break;
2358 	}
2359 
2360 	if (kind == FATALINTERNAL) longjmp(io_filerror, 1);
2361 }
2362 
2363 
2364 /********************* parser.c: parser *********************/
2365 
2366 #define BIGSIGNED ((0X7FFFFFFF-9)/10)
2367 
2368 #define ERRORCHECK if (io_ciferrorfound) goto recover
2369 
2370 /*	specific syntax errors	*/
2371 
2372 #ifdef NOERROR
2373 #  undef NOERROR
2374 #endif
2375 #define NOERROR 100
2376 #define NUMTOOBIG 101
2377 #define NOUNSIGNED 102
2378 #define NOSIGNED 103
2379 #define NOSEMI 104
2380 #define NOPATH 105
2381 #define BADTRANS 106
2382 #define BADUSER 107
2383 #define BADCOMMAND 108
2384 #define INTERNAL 109
2385 #define BADDEF 110
2386 #define NOLAYER 111
2387 #define BADCOMMENT 112
2388 #define BADAXIS 113
2389 #define NESTDEF 114
2390 #define NESTDD 115
2391 #define NODEFSTART 116
2392 #define NESTEND 117
2393 #define NOSPACE 118
2394 #define NONAME 119
2395 
2396 static CHAR   io_ciferrorfound;			/* flag for error encountered */
2397 static INTBIG io_ciferrortype;			/* what it was */
2398 static CHAR   io_cifendisseen;			/* end command flag */
2399 
io_initparser(void)2400 INTBIG io_initparser(void)
2401 {
2402 	io_ciferrorfound = 0;
2403 	io_ciferrortype = NOERROR;
2404 	io_cifdefinprog = 0;
2405 	io_cifendisseen = 0;
2406 	return(io_initinput() || io_inittypes() || io_initerror());
2407 }
2408 
io_doneparser(void)2409 INTBIG io_doneparser(void)
2410 {
2411 	if (!io_cifendisseen) io_report(_("missing End command"), FATALSYNTAX);
2412 	return(io_doneinput() || io_donetypes() || io_doneerror());
2413 }
2414 
io_blank(void)2415 static void io_blank(void)
2416 {
2417 	REGISTER CHAR c;
2418 
2419 	for(;;)
2420 	{
2421 		switch (c = io_peek())
2422 		{
2423 			case '(':
2424 			case ')':
2425 			case ';':
2426 			case '-':
2427 			case EOF:
2428 				return;
2429 			default:
2430 				if (isdigit(c) || isupper(c)) return;
2431 					else (void) io_getch();
2432 		}
2433 	}
2434 }
2435 
io_sep(void)2436 static void io_sep(void)
2437 {
2438 	REGISTER CHAR c;
2439 
2440 	for(;;)
2441 	{
2442 		switch (c = io_peek())
2443 		{
2444 			case '(':
2445 			case ')':
2446 			case ';':
2447 			case '-':
2448 			case EOF:
2449 				return;
2450 			default:
2451 				if (isdigit(c)) return;
2452 					else (void) io_getch();
2453 		}
2454 	}
2455 }
2456 
io_semi(void)2457 static CHAR io_semi(void)
2458 {
2459 	CHAR ans = 0;
2460 
2461 	io_blank();
2462 	if (io_peek() == ';') {(void) io_getch(); ans = 1; io_blank();}
2463 	return(ans);
2464 }
2465 
io_sp(void)2466 static CHAR io_sp(void)
2467 {
2468 	CHAR ans = 0; CHAR c;
2469 
2470 	while ((c = io_peek()) == ' ' || c == '\t')
2471 	{
2472 		(void) io_getch();
2473 		ans = 1;
2474 	}
2475 	return(ans);
2476 }
2477 
io_utext(void)2478 static CHAR *io_utext(void)
2479 {
2480 	CHAR *user, *olduser;
2481 	INTBIG maxsize = 80;
2482 	INTBIG size = 0;
2483 
2484 	if ((user = (CHAR *)emalloc(maxsize * SIZEOFCHAR, io_tool->cluster)) == NIL)
2485 	{
2486 		io_report(_("free storage exhausted"), FATALINTERNAL);
2487 		return((CHAR *)0);
2488 	}
2489 	*user = '\0';
2490 	while (!io_endoffile() && io_peek() != ';')
2491 	{
2492 		*(user+size++) = io_getch();
2493 		if (size >= maxsize)
2494 		{
2495 			INTBIG i;
2496 			maxsize += 80;
2497 			olduser = user;
2498 			user = (CHAR *)emalloc(maxsize * SIZEOFCHAR, io_tool->cluster);
2499 			if (user == NIL)
2500 				io_report(_("free storage exhausted"), FATALINTERNAL);
2501 			for(i=0; i<maxsize-80; i++) user[i] = olduser[i];
2502 			efree(olduser);
2503 		}
2504 		*(user+size) = '\0';
2505 	}
2506 	return(user);
2507 }
2508 
io_name(void)2509 static CHAR *io_name(void)
2510 {
2511 	CHAR *ntext, *oldntext;
2512 	INTBIG maxsize = 80;
2513 	INTBIG size = 0;
2514 	CHAR c; CHAR nochar = 1;
2515 
2516 	if ((ntext = (CHAR *)emalloc(maxsize * SIZEOFCHAR, io_tool->cluster)) == NIL)
2517 	{
2518 		io_report(_("free storage exhausted"), FATALINTERNAL);
2519 		return((CHAR *) 0);
2520 	}
2521 	*ntext = '\0';
2522 	while (!io_endoffile() && (c = io_peek()) != ';' &&
2523 /*		(c < 'a' || c > 'z') &&       ...uncomment to disallow lowercase */
2524 		c != ' ' && c != '\t' && c != '{' && c != '}')
2525 	{
2526 		nochar = 0;
2527 /*		if (c >= 'a' && c <= 'z') c = (c-'a')+'A';      ...uncomment to make all names upper case */
2528 		(void) io_getch();
2529 		*(ntext+size++) = c;
2530 		if (size >= maxsize)
2531 		{
2532 			INTBIG i;
2533 			maxsize += 80;
2534 			oldntext = ntext;
2535 			if ((ntext = (CHAR *)emalloc(maxsize * SIZEOFCHAR, io_tool->cluster)) == NIL)
2536 				io_report(_("free storage exhausted"), FATALINTERNAL);
2537 			for(i=0; i<maxsize-80; i++) ntext[i] = oldntext[i];
2538 			efree(oldntext);
2539 		}
2540 		*(ntext+size) = '\0';
2541 	}
2542 	if (nochar) io_logit(NONAME);
2543 	return(ntext);
2544 }
2545 
io_cardinal(void)2546 static INTBIG io_cardinal(void)
2547 {
2548 	CHAR somedigit = 0;
2549 	REGISTER INTBIG ans = 0;
2550 	INTBIG c;
2551 
2552 	(void)io_sp();
2553 
2554 	while (ans < BIGSIGNED && (c = io_peek()) >= '0' && c <= '9')
2555 	{
2556 		ans *= 10; ans += io_getch() - '0';
2557 		somedigit = 1;
2558 	}
2559 
2560 	if (!somedigit)
2561 	{
2562 		io_logit(NOUNSIGNED);
2563 		return(0);
2564 	}
2565 	if ((c = io_peek()) >= '0' && c <= '9')
2566 	{
2567 		io_logit(NUMTOOBIG);
2568 		return(0XFFFFFFFF);
2569 	}
2570 	return(ans);
2571 }
2572 
io_signed(void)2573 static INTBIG io_signed(void)
2574 {
2575 	CHAR somedigit = 0;
2576 	CHAR sign = 0;
2577 	REGISTER INTBIG ans = 0;
2578 	CHAR c;
2579 
2580 	io_sep();
2581 
2582 	if (io_peek() == '-') {sign = 1; (void) io_getch();}
2583 
2584 	while (ans < BIGSIGNED && (c = io_peek()) >= '0' && c <= '9')
2585 	{
2586 		ans *= 10; ans += io_getch() - '0';
2587 		somedigit = 1;
2588 	}
2589 
2590 	if (!somedigit) {io_logit(NOSIGNED); return(0);}
2591 	if ((c = io_peek()) >= '0' && c <= '9')
2592 	{
2593 		io_logit(NUMTOOBIG);
2594 		return(sign ? -0X7FFFFFFF:0X7FFFFFFF);
2595 	}
2596 	return(sign ? -ans:ans);
2597 }
2598 
io_logit(INTBIG thing)2599 static void io_logit(INTBIG thing)
2600 {
2601 	io_ciferrorfound = 1;
2602 	io_ciferrortype = thing;
2603 }
2604 
io_getpoint(void)2605 static point io_getpoint(void)
2606 {
2607 	point ans;
2608 
2609 	ans.x = io_signed();
2610 	ans.y = io_signed();
2611 	return(ans);
2612 }
2613 
io_getpath(path a)2614 static void io_getpath(path a)
2615 {
2616 	CHAR c;
2617 	point temp;
2618 
2619 	io_sep();
2620 
2621 	while (((c = io_peek()) >= '0' && c <= '9') || c == '-')
2622 	{
2623 		temp = io_getpoint();	/* hack because of compiler error */
2624 		if (io_appendpoint(a, temp)) break;
2625 		io_sep();
2626 	}
2627 	if (io_pathlength(a) == 0) io_logit(NOPATH);
2628 }
2629 
io_parsestatement(void)2630 INTBIG io_parsestatement(void)
2631 {
2632 	CHAR curchar;
2633 	INTBIG command = NULLCOMMAND;
2634 	CHAR *curpath = NIL;
2635 	CHAR *curtlist = NIL;
2636 	INTBIG xrotate, yrotate;
2637 	point center;
2638 	INTBIG length, width;
2639 	INTBIG diameter;
2640 	CHAR lname[5], *oldcomment;
2641 	INTBIG symbolnumber, multiplier, divisor;
2642 	CHAR *comment = NIL;
2643 	CHAR *usertext = NIL;
2644 	CHAR *nametext = NIL;
2645 	INTBIG usercommand;
2646 	point namepoint;
2647 
2648 	io_blank();		/* flush initial junk */
2649 
2650 	switch (curchar = io_getch())
2651 	{
2652 		case 'P':
2653 			command = POLYCOM;
2654 			curpath = io_makepath();
2655 			io_getpath((path)curpath); ERRORCHECK;
2656 			break;
2657 
2658 		case 'B':
2659 			command = BOXCOM;
2660 			xrotate = 1; yrotate = 0;
2661 			length = io_cardinal(); ERRORCHECK;
2662 			width = io_cardinal(); ERRORCHECK;
2663 			center = io_getpoint(); ERRORCHECK; io_sep();
2664 			if (((curchar = io_peek()) >= '0' && curchar <= '9') || curchar == '-')
2665 			{
2666 				xrotate = io_signed(); ERRORCHECK;
2667 				yrotate = io_signed(); ERRORCHECK;
2668 			}
2669 			break;
2670 
2671 		case 'R':
2672 			command = FLASHCOM;
2673 			diameter = io_cardinal(); ERRORCHECK;
2674 			center = io_getpoint(); ERRORCHECK;
2675 			break;
2676 
2677 		case 'W':
2678 			command = WIRECOM;
2679 			width = io_cardinal(); ERRORCHECK;
2680 			curpath = io_makepath();
2681 			io_getpath((path)curpath); ERRORCHECK;
2682 			break;
2683 
2684 		case 'L':
2685 			{
2686 				INTBIG i;
2687 				command = LAYER;
2688 				io_blank();
2689 				for (i = 0; i<4; i++)
2690 					if (((curchar = io_peek()) >= 'A' && curchar <= 'Z') || isdigit(curchar))
2691 						lname[i] = io_getch();
2692 							else break;
2693 				lname[i] = '\0';
2694 				if (i == 0) {io_ciferrorfound = 1; io_ciferrortype = NOLAYER; goto recover;}
2695 			}
2696 			break;
2697 
2698 		case 'D':
2699 			io_blank();
2700 			switch (io_getch())
2701 			{
2702 				case 'S':
2703 					command = DEFSTART;
2704 					symbolnumber = io_cardinal(); ERRORCHECK;
2705 					io_sep(); multiplier = divisor = 1;
2706 					if (isdigit(io_peek()))
2707 					{
2708 						multiplier = io_cardinal(); ERRORCHECK;
2709 						divisor = io_cardinal(); ERRORCHECK;
2710 					}
2711 					if (io_cifdefinprog)
2712 					{
2713 						io_ciferrorfound = 1;
2714 						io_ciferrortype = NESTDEF;
2715 						goto recover;
2716 					}
2717 					io_cifdefinprog = 1;
2718 					break;
2719 				case 'F':
2720 					command = DEFEND;
2721 					if (!io_cifdefinprog)
2722 					{
2723 						io_ciferrorfound = 1;
2724 						io_ciferrortype = NODEFSTART;
2725 						goto recover;
2726 					}
2727 					io_cifdefinprog = 0;
2728 					break;
2729 				case 'D':
2730 					command = DELETEDEF;
2731 					symbolnumber = io_cardinal(); ERRORCHECK;
2732 					if (io_cifdefinprog)
2733 					{
2734 						io_ciferrorfound = 1;
2735 						io_ciferrortype = NESTDD;
2736 						goto recover;
2737 					}
2738 					break;
2739 				default:
2740 					io_ciferrorfound = 1;
2741 					io_ciferrortype = BADDEF;
2742 					goto recover;
2743 			}
2744 			break;
2745 
2746 		case 'C':
2747 			command = CALLCOM;
2748 			symbolnumber = io_cardinal(); ERRORCHECK;
2749 			io_blank();
2750 			curtlist = io_maketlist();
2751 			for(;;)
2752 			{
2753 				switch (io_peek())
2754 				{
2755 					tentry trans;
2756 
2757 					case 'T':
2758 						(void) io_getch();
2759 						trans.kind = TRANSLATE;
2760 						trans.guts.tr.xt = io_signed(); ERRORCHECK;
2761 						trans.guts.tr.yt = io_signed(); ERRORCHECK;
2762 						io_appendtentry((tlist)curtlist, trans);
2763 						break;
2764 
2765 					case 'M':
2766 						trans.kind = MIRROR;
2767 						(void) io_getch(); io_blank();
2768 						switch (io_getch())
2769 						{
2770 							case 'X': trans.guts.mi.xcoord = 1; break;
2771 							case 'Y': trans.guts.mi.xcoord = 0; break;
2772 							default:  io_ciferrorfound = 1; io_ciferrortype = BADAXIS; goto recover;
2773 						}
2774 						io_appendtentry((tlist)curtlist, trans);
2775 						break;
2776 
2777 					case 'R':
2778 						trans.kind = ROTATE;
2779 						(void) io_getch();
2780 						trans.guts.ro.xrot = io_signed(); ERRORCHECK;
2781 						trans.guts.ro.yrot = io_signed(); ERRORCHECK;
2782 						io_appendtentry((tlist)curtlist, trans);
2783 						break;
2784 
2785 					case ';':
2786 						goto localexit;
2787 
2788 					default:
2789 						io_ciferrorfound = 1; io_ciferrortype = BADTRANS; goto recover;
2790 				}
2791 				io_blank();		/* between transformation commands */
2792 			}	/* end of while (1) loop */
2793 			localexit:
2794 			break;
2795 
2796 		case '(':
2797 			{
2798 				INTBIG level = 1;
2799 				INTBIG maxsize = 80;
2800 				INTBIG size = 0;
2801 
2802 				command = COMMENT;
2803 				if ((comment = (CHAR *)emalloc(maxsize * SIZEOFCHAR, io_tool->cluster)) == NIL)
2804 				{
2805 					io_report(_("free storage exhausted"), FATALINTERNAL);
2806 					break;
2807 				}
2808 
2809 				*comment = '\0';
2810 				while (level)
2811 				{
2812 					switch (curchar = io_getch())
2813 					{
2814 						case '(':
2815 							level++;
2816 							*(comment+size++) = '(';
2817 							break;
2818 						case ')':
2819 							level--;
2820 							if (level) *(comment+size++) = ')';
2821 							break;
2822 						case EOF:
2823 							io_ciferrorfound = 1; io_ciferrortype = BADCOMMENT; goto recover;
2824 						default:
2825 							*(comment+size++) = curchar;
2826 					}
2827 					if (size >= maxsize)
2828 					{
2829 						INTBIG i;
2830 
2831 						maxsize += 80;
2832 						oldcomment = comment;
2833 						comment = (CHAR *)emalloc(maxsize * SIZEOFCHAR, io_tool->cluster);
2834 						if (comment == NIL)
2835 						{
2836 							io_report(_("free storage exhausted"), FATALINTERNAL);
2837 							break;
2838 						}
2839 						for(i=0; i<maxsize-80; i++) comment[i] = oldcomment[i];
2840 						efree(oldcomment);
2841 					}
2842 					*(comment+size) = '\0';
2843 				}
2844 			}
2845 			break;
2846 
2847 		case 'E':
2848 			command = END;
2849 			io_blank();
2850 			if (io_cifdefinprog)
2851 			{
2852 				io_ciferrorfound = 1;
2853 				io_ciferrortype = NESTEND;
2854 				goto recover;
2855 			}
2856 			if (!io_endoffile()) io_report(_("more text follows end command"), ADVISORY);
2857 			io_cifendisseen = 1;
2858 			io_iend();
2859 			goto alldone;
2860 
2861 		case ';':
2862 			command = NULLCOMMAND;
2863 			goto alldone;
2864 
2865 		case EOF:
2866 			command = ENDFILE;
2867 			goto alldone;
2868 
2869 		default:
2870 			if (isdigit(curchar))
2871 			{
2872 				if ((usercommand = curchar - '0') == 9 &&
2873 					((curchar = io_peek()) == ' ' || curchar == '\t' ||
2874 						curchar == '1' || curchar == '2' || curchar == '3'))
2875 							switch(io_getch())
2876 				{
2877 					case ' ':
2878 					case '\t':
2879 						(void) io_sp(); nametext = io_name(); ERRORCHECK;
2880 						command = SYMNAME;
2881 						break;
2882 					case '1':
2883 					case '2':
2884 					case '3':
2885 						if (!io_sp())
2886 						{
2887 							io_ciferrorfound = 1; io_ciferrortype = NOSPACE;
2888 							goto recover;
2889 						}
2890 						nametext = io_name(); ERRORCHECK;
2891 						switch(curchar)
2892 						{
2893 							case '1':
2894 								command = INSTNAME;
2895 								break;
2896 							case '2':
2897 							{
2898 								INTBIG i;
2899 
2900 								command = GEONAME;
2901 								namepoint = io_getpoint(); ERRORCHECK;
2902 								io_blank();
2903 								for (i = 0; i<4; i++)
2904 									if (((curchar = io_peek()) >= 'A' &&
2905 										curchar <= 'Z') || isdigit(curchar))
2906 											lname[i] = io_getch();
2907 												else break;
2908 								lname[i] = '\0';
2909 								break;
2910 							}
2911 							case '3':
2912 								command = LABELCOM;
2913 								namepoint = io_getpoint(); ERRORCHECK;
2914 								break;
2915 						}
2916 						break;
2917 				} else
2918 				{
2919 					command = USERS;
2920 					usertext = io_utext();
2921 					if (io_endoffile())
2922 					{
2923 						io_ciferrorfound = 1; io_ciferrortype = BADUSER; goto recover;
2924 					}
2925 				}
2926 			} else
2927 			{
2928 				io_ciferrorfound = 1;
2929 				io_ciferrortype = BADCOMMAND;
2930 				goto recover;
2931 			}
2932 	}
2933 
2934 	/*
2935 	 * by now we have a syntactically valid command
2936 	 * although it might be missing a semi-colon
2937 	 */
2938 	switch(command)
2939 	{
2940 		case WIRECOM:
2941 			io_iwire(width, curpath);
2942 			break;
2943 		case DEFSTART:
2944 			io_idefstart(symbolnumber, multiplier, divisor);
2945 			break;
2946 		case DEFEND:
2947 			io_idefend();
2948 			break;
2949 		case DELETEDEF:
2950 			io_ideletedef(symbolnumber);
2951 			break;
2952 		case CALLCOM:
2953 			io_icall(symbolnumber, curtlist);
2954 			break;
2955 		case LAYER:
2956 			io_ilayer(lname);
2957 			break;
2958 		case FLASHCOM:
2959 			io_iflash(diameter, center);
2960 			break;
2961 		case POLYCOM:
2962 			io_ipolygon(curpath);
2963 			break;
2964 		case BOXCOM:
2965 			io_ibox(length, width, center, xrotate, yrotate);
2966 			break;
2967 		case COMMENT:
2968 			io_icomment(comment);
2969 			break;
2970 		case USERS:
2971 			io_iusercommand(usercommand, usertext);
2972 			break;
2973 		case SYMNAME:
2974 			io_isymname(nametext);
2975 			break;
2976 		case INSTNAME:
2977 			io_iinstname(nametext);
2978 			break;
2979 		case GEONAME:
2980 			io_igeoname(nametext, namepoint, (INTBIG)lname);
2981 			break;
2982 		case LABELCOM:
2983 			io_ilabel(nametext, namepoint);
2984 			break;
2985 		default:
2986 			io_ciferrorfound = 1;
2987 			io_ciferrortype = INTERNAL;
2988 			goto recover;
2989 	}
2990 	if (!io_semi()) {io_ciferrorfound = 1; io_ciferrortype = NOSEMI; goto recover;}
2991 
2992 alldone:		/* everyone exits here */
2993 	if (curpath != NIL) io_freepath((path)curpath);
2994 	if (curtlist != NIL) io_freetlist((tlist)curtlist);
2995 	if (comment != NIL) efree((CHAR *) comment);
2996 	if (usertext != NIL) efree((CHAR *) usertext);
2997 	if (nametext != NIL) efree((CHAR *) nametext);
2998 	return(command);
2999 
3000 recover:		/* errors come here */
3001 	switch (io_ciferrortype)
3002 	{
3003 		case NUMTOOBIG:  io_report(_("number too large"), FATALSYNTAX); break;
3004 		case NOUNSIGNED: io_report(_("unsigned integer expected"), FATALSYNTAX); break;
3005 		case NOSIGNED:   io_report(_("signed integer expected"), FATALSYNTAX); break;
3006 		case NOSEMI:     io_report(_("missing ';' inserted"), FATALSYNTAX); break;
3007 		case NOPATH:     io_report(_("no points in path"), FATALSYNTAX); break;
3008 		case BADTRANS:   io_report(_("no such transformation command"), FATALSYNTAX); break;
3009 		case BADUSER:    io_report(_("end of file inside user command"), FATALSYNTAX); break;
3010 		case BADCOMMAND: io_report(_("unknown command encountered"), FATALSYNTAX); break;
3011 		case INTERNAL:   io_report(_("parser can't find i routine"), FATALINTERNAL); break;
3012 		case BADDEF:     io_report(_("no such define command"), FATALSYNTAX); break;
3013 		case NOLAYER:    io_report(_("layer name expected"), FATALSYNTAX); break;
3014 		case BADCOMMENT: io_report(_("end of file inside a comment"), FATALSYNTAX); break;
3015 		case BADAXIS:    io_report(_("no such axis in mirror command"), FATALSYNTAX); break;
3016 		case NESTDEF:    io_report(_("symbol definitions can't nest"), FATALSYNTAX); break;
3017 		case NODEFSTART: io_report(_("DF without DS"), FATALSYNTAX); break;
3018 		case NESTDD:     io_report(_("DD can't appear inside symbol definition"), FATALSYNTAX); break;
3019 		case NOSPACE:    io_report(_("missing space in name command"), FATALSYNTAX); break;
3020 		case NONAME:     io_report(_("no name in name command"), FATALSYNTAX); break;
3021 		case NESTEND:    io_report(_("End command inside symbol definition"), FATALSYNTAX); break;
3022 		case NOERROR:    io_report(_("error signaled but not reported"), FATALINTERNAL); break;
3023 		default:         io_report(_("uncaught error"), FATALSYNTAX);
3024 	}
3025 	if (io_ciferrortype != INTERNAL && io_ciferrortype != NOSEMI && io_flush(';') == EOF)
3026 		io_report(_("unexpected end of input file"), FATALSYNTAX);
3027 			else io_blank();
3028 	command = SYNTAXERROR;
3029 	io_ciferrorfound = 0;
3030 	io_ciferrortype = NOERROR;
3031 	goto alldone;
3032 }
3033 
io_parsefile(void)3034 INTBIG io_parsefile(void)
3035 {
3036 	INTBIG com;
3037 	INTBIG comcount = 1;
3038 
3039 	for(;;)
3040 	{
3041 		if (stopping(STOPREASONCIF)) break;
3042 		com = io_parsestatement();
3043 		if (com == END || com == ENDFILE) break;
3044 		comcount++;
3045 	}
3046 	return(comcount);
3047 }
3048