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