1 /***************************************************************************
2 SCED - Schematic Capture Editor
3 JSPICE3 adaptation of Spice3e2 - Copyright (c) Stephen R. Whiteley 1992
4 Copyright 1990 Regents of the University of California. All rights reserved.
5 Authors: 1981 Giles C. Billingsley (parts of KIC layout editor)
6 1992 Stephen R. Whiteley
7 ****************************************************************************/
8
9 /* changes:
10 * 1. The DX and DY parameters used in CDCall(), CDBeginMakeCall() and
11 * elsewhere now refer to center-to-center spacing. Previously,
12 * edge to adjacent edge spacing was used. This creates problems
13 * when converting from GDSII, and also means that cell placement
14 * changes if cell size changes. Now, arrayed cells stay put if the
15 * BB's change. There may be compatibility problems with files
16 * which use the old scheme.
17 *
18 * 2. Hooks have been added for manipulation of the property strings
19 * for use by a schematic layout program. See the notes in
20 * CDBeginMakeCall() and CDEndMakeCall().
21 *
22 * 3. A routine for searching libraries has been added to POpen() in
23 * paths.c. See the note there concerning use.
24 *
25 * 4. A callback to a user supplied routine
26 * void CDLabelBB(struct o *Pointer,long *L,long *B, long *R, long *T)
27 * has been added. This routine returns the effective window of
28 * of the label, which depends on font size, etc, This routine
29 * is called by the generators, not CDBB(), as the BB is window
30 * dependent.
31 * 5. Labels are always put in the residual bin, so the generator
32 * can find them if the origin is out of the AOI.
33 *
34 * 6. CDInit() now calls malloc() to set up arrays for CDDesc. The
35 * return value is True if malloc fails, False if OK.
36 *
37 * Two routines need to be supplied externally for 2,3,4 above. If the
38 * features are not used, add the following to the external code:
39 * void UpdateProperties() {}
40 * FILE *OpenDevice() {return NULL;}
41 * void CDLabelBB(whatever)
42 *
43 */
44
45 /* call to extern HYdeleteReference() in CDDelete() */
46 /* calls to SteTransform(), TPop() in CDPatchInstance() */
47 /* calls to IsCellInLib() in CDReflect(), CDPatchInstances() */
48
49 /*======================================================================*
50 * *
51 * CCCCCC DDDDDDD *
52 * CC CC DD DD *
53 * CC CC DD DD *
54 * CC DD DD *
55 * CC DD DD *
56 * CC CC DD DD *
57 * CC CC DD DD *
58 * CCCCCC DDDDDDD *
59 * *
60 * *
61 * CD package code. *
62 * *
63 * *
64 *======================================================================*/
65
66 #include "spice.h"
67 #include "cddefs.h"
68 #include "cdparser.h"
69 #include <string.h>
70
71 #define LARGEBUFFERSIZE 400
72 struct bu *CDSymbolTable[CDNUMLAYERS+1];
73 struct d CDDesc;
74 struct l CDLayer[CDNUMLAYERS+1];
75 int CDStatusInt;
76 static char CDDiagnosticString[LARGEBUFFERSIZE];
77 char *CDStatusString = CDDiagnosticString;
78
79 /*
80 * The following is the policy for handling errors in CD:
81 * When a routine encounters difficulty, it will set CDStatusInt
82 * to some identifying value, copy a diagnostic string into
83 * CDStatusString, and return a 'False'. Otherwise, the routine
84 * will return 'True' and not alter the value of CDStatusInt.
85 * Every routine that uses malloc will test the returned value
86 * and return False via CDError() if malloc fails.
87 */
88
89
90 /*===========================================================================*
91 * *
92 * III N N III TTTTT III A L III ZZZZZ A TTTTT III OOO N N *
93 * I NN N I T I A A L I Z A A T I O O NN N *
94 * I N N N I T I A A L I Z A A T I O O N N N *
95 * I N NN I T I AAAAA L I Z AAAAA T I O O N NN *
96 * III N N III T III A A LLLLL III ZZZZZ A A T III OOO N N *
97 * *
98 * RRRR OOO U U TTTTT III N N EEEEE SSSS *
99 * R R O O U U T I NN N E S *
100 * RRRR O O U U T I N N N EEE SSS *
101 * R R O O U U T I N NN E S *
102 * R R OOO UUU T III N N EEEEE SSSS *
103 * *
104 * *
105 * *
106 * CDInit() *
107 * CDPath(Path) *
108 * CDSetLayer(Layer,Tech,Mask) *
109 * CDDebug(Flag) *
110 * *
111 *===========================================================================*/
112
113 int
CDInit()114 CDInit()
115 {
116 /*
117 * This must be the first CD routine called. It initializes
118 * the layer table, search path, symbol table, and transform
119 * stack. Returns True if error, False otherwise.
120 */
121 int Layer,Int1;
122 char *c,*PGetPath();
123
124 CDStatusString = CDDiagnosticString;
125 for (Int1 = 0;Int1 < CDNUMLAYERS;++Int1)
126 CDSymbolTable[Int1] = NULL;
127 for (Layer = 1;Layer <= CDNUMLAYERS;++Layer) {
128 CDLayer[Layer].lTechnology = ' ';
129 CDLayer[Layer].lMask[0] = ' ';
130 CDLayer[Layer].lMask[1] = ' ';
131 CDLayer[Layer].lMask[2] = ' ';
132 CDLayer[Layer].lCDFrom = False;
133 }
134 c = PGetPath();
135 if (*c == '\0')
136 CDPath(".");
137 CDDebug(False);
138 CDDesc.dPrptyList = NULL;
139 CDDesc.dNumSymbolsAllocated = 0;
140
141 /* Vanilla operation. */
142 CDDesc.dControl = DCONTROLVANILLA;
143
144 /* Alocate arrays if not already done */
145 if (CDDesc.dSymTabNames == NULL) {
146 CDDesc.dSymTabNames = (char(*)[FILENAMESIZE])
147 tmalloc(CDNUMREMEMBER*FILENAMESIZE);
148 if (CDDesc.dSymTabNames == NULL) {
149 CDStatusInt = CDError(CDMALLOCFAILED);
150 return True;
151 }
152 CDDesc.dSymTabNumbers = (int *) tmalloc(CDNUMREMEMBER*sizeof(int));
153 if (CDDesc.dSymTabNumbers == NULL) {
154 CDStatusInt = CDError(CDMALLOCFAILED);
155 return True;
156 }
157 }
158 TInit();
159 return False;
160 }
161
162
163 int
CDPath(Path)164 CDPath(Path)
165 char *Path;
166 {
167 /*
168 * Sets search rules for symbol name resolution.
169 * Path is a list of directory names to search separated by blanks.
170 * csh-style names are understood.
171 * False is returned if the search path argument is invalid.
172 */
173 if (PSetPath(Path))
174 return (CDError(CDBADPATH));
175 else
176 return (True);
177 }
178
179
180 void
CDSetLayer(Layer,Technology,Mask)181 CDSetLayer(Layer,Technology,Mask)
182 int Layer;
183 char Technology,Mask[];
184 {
185 /*
186 * This routine sets the layer Layer to the name 'TechnologyMask'.
187 * There is no returned value.
188 */
189 CDLayer[Layer].lTechnology = Technology;
190 CDLayer[Layer].lMask[0] = Mask[0];
191 CDLayer[Layer].lMask[1] = Mask[1];
192 CDLayer[Layer].lMask[2] = Mask[2];
193 }
194
195
196 void
CDDebug(Debug)197 CDDebug(Debug)
198 int Debug;
199 {
200 /*
201 * If Debug is true, then CD will run in debug mode. There is
202 * no returned value.
203 */
204 CDDesc.dDebug = Debug;
205 }
206
207
208
209
210 /*======================================================================*
211 * *
212 * SSSS Y Y M M BBBB OOO L *
213 * S Y Y MM MM B B O O L *
214 * SSS Y M M M BBBB O O L *
215 * S Y M M B B O O L *
216 * SSSS Y M M BBBB OOO LLLLL *
217 * *
218 * M M A N N A GGG EEEEE M M EEEEE N N TTTTT *
219 * MM MM A A NN N A A G E MM MM E NN N T *
220 * M M M A A N N N A A G GGG EEE M M M EEE N N N T *
221 * M M AAAAA N NN AAAAA G G E M M E N NN T *
222 * M M A A N N A A GGG EEEEE M M EEEEE N N T *
223 * *
224 * *
225 * *
226 * CDOpen(SymbolName,SymbolDesc,Access) *
227 * CDSymbol(SymbolName,SymbolDesc) *
228 * CDClose(SymbolDesc) *
229 * CDReflect(SymbolDesc) *
230 * CDPatchInstances(SymbolDesc,MasterName) *
231 * *
232 *======================================================================*/
233
234 int
CDOpen(SymbolName,SymbolDesc,Access)235 CDOpen(SymbolName,SymbolDesc,Access)
236 char *SymbolName;
237 struct s **SymbolDesc;
238 char Access;
239 {
240 /*
241 * Open symbol and return desc for it.
242 *
243 * CDOpen returns False if parse failed or out of memory. When CDOpen
244 * returns, CDStatusInt assumes one of the following values:
245 * (FATAL)-CDPARSEFAILED if parser failed or out of memory.
246 * CDOLDSYMBOL if success and symbol already exists in memory.
247 * CDNEWSYMBOL if success and symbol is a new (empty) one.
248 * CDSUCCEEDED if no problem was encountered.
249 * If the return is fatal, CDStatusString contains a diagnostic message.
250 * Only CDPARSEFAILED is returned as a fatal error; this simplifies
251 * the diagnostic test.
252 *
253 * If Access == 'w', then create the cell if it doesn't already exist.
254 * In other words, open cell for writing. This solves the following
255 * problem: if the user tries to create an instance of a cell that
256 * doesn't exist, it will not be created in the database. If the cell
257 * was added to the database, a second attempt to place the cell that
258 * doesn't exist would succeed. Bad News!
259 *
260 * If Access == 'n', then create a new cell if it doesn't already exist
261 * in the database. Unlike Access == 'w', the cell will not be parsed
262 * if it exists in the current search path.
263 */
264
265 char *StatusString;
266 char *cp;
267 FILE *FDesc;
268 struct bu *Bucket;
269 struct m *MasterListDesc;
270 struct s *MasterSymbolDesc;
271 struct s *NewDesc;
272 struct prpty PrptyCopy;
273 int Key,Int1,Int2;
274 int Layer;
275 int StatusInt;
276 int ret;
277 unsigned size;
278 static int RecursionLevel = 0;
279
280 #ifdef DEBUGREFLECT
281 printf("Begin CDOpen of symbol %s.\n",SymbolName);
282 #endif
283
284 if (SymbolName == NULL Or *SymbolName == '\0') {
285 CDStatusInt = CDPARSEFAILED;
286 sprintf(CDStatusString,"Null symbol name encountered.");
287 return (False);
288 }
289 CDDesc.dControl = DCONTROLCDOPEN;
290 ++RecursionLevel;
291
292 /* Is symbol open already? */
293
294 Key = 0;
295 *SymbolDesc = NULL;
296 Int2 = strlen(SymbolName);
297 for (Int1 = 0; Int1 < Int2; ++Int1)
298 Key += SymbolName[Int1];
299 Bucket = CDSymbolTable[Key % CDNUMLAYERS];
300 while (Bucket != NULL) {
301 if (strcmp(Bucket->buSymbolDesc->sName,SymbolName) == 0) {
302 *SymbolDesc = Bucket->buSymbolDesc;
303 break;
304 }
305 Bucket = Bucket->buSucc;
306 }
307 if (*SymbolDesc != NULL) {
308 CDStatusInt = CDOLDSYMBOL;
309 *CDStatusString = '\0';
310 }
311 else {
312 /* first, try to allocate memory */
313 if ((NewDesc = alloc(s)) == NULL) {
314 CDStatusInt = CDError(CDMALLOCFAILED);
315 CDStatusInt = CDPARSEFAILED;
316 ret = False;
317 goto done;
318 }
319 size = Int2 + 2;
320 if ((cp = tmalloc(size)) == NULL) {
321 CDStatusInt = CDError(CDMALLOCFAILED);
322 CDStatusInt = CDPARSEFAILED;
323 ret = False;
324 goto done;
325 }
326 if ((Bucket = alloc(bu)) == NULL) {
327 CDStatusInt = CDError(CDMALLOCFAILED);
328 CDStatusInt = CDPARSEFAILED;
329 ret = False;
330 goto done;
331 }
332 if (Access != 'n' And (FDesc = POpen(SymbolName,"r",
333 (char **)NULL)) != NULL) {
334 /*
335 * Symbol already exists, so user probably intends
336 * to edit it or just read it.
337 */
338
339 /* put symbol into symbol table */
340 *SymbolDesc = CDDesc.dSymbolDesc = NewDesc;
341 ++CDDesc.dNumSymbolsAllocated;
342 for (Layer = 0;Layer <= CDNUMLAYERS;++Layer)
343 CDDesc.dSymbolDesc->sBin[Layer] = (struct o ***)NULL;
344 CDDesc.dSymbolDesc->sName = cp;
345 strcpy(CDDesc.dSymbolName,SymbolName);
346 strcpy(CDDesc.dSymbolDesc->sName,CDDesc.dSymbolName);
347 CDDesc.dNumX = CDDesc.dNumY = 1;
348 CDDesc.dDX = CDDesc.dDY = 0;
349 CDDesc.dSymbolDesc->sA = 1;
350 CDDesc.dSymbolDesc->sB = 1;
351 CDDesc.dSymbolDesc->sBBValid = True;
352 CDDesc.dSymbolDesc->sLeft = CDDesc.dSymbolDesc->sBottom =CDINFINITY;
353 CDDesc.dSymbolDesc->sRight = CDDesc.dSymbolDesc->sTop = -CDINFINITY;
354 CDDesc.dSymbolDesc->sInfo = 0;
355 CDDesc.dSymbolDesc->sMasterList = NULL;
356 CDDesc.dSymbolDesc->sPrptyList = NULL;
357 /* add property list information */
358 while (CDDesc.dPrptyList != NULL) {
359 if (Not CDAddProperty(CDDesc.dSymbolDesc,(struct o *)NULL,
360 CDDesc.dPrptyList->prpty_Value,
361 CDDesc.dPrptyList->prpty_String)) {
362 CDStatusInt = CDError(CDMALLOCFAILED);
363 CDStatusInt = CDPARSEFAILED;
364 ret = False;
365 goto done;
366 }
367 /* free storage of CDDesc.dPrptyList */
368 PrptyCopy = *CDDesc.dPrptyList;
369 tfree(CDDesc.dPrptyList->prpty_String);
370 tfree(CDDesc.dPrptyList);
371 CDDesc.dPrptyList = PrptyCopy.prpty_Succ;
372 }
373 /*
374 * Insert symbol desc in symbol table.
375 * The hash table 'Key' was computed above.
376 */
377 if (CDSymbolTable[Key % CDNUMLAYERS] != NULL)
378 CDSymbolTable[Key % CDNUMLAYERS]->buPred = Bucket;
379 Bucket->buPred = NULL;
380 Bucket->buSucc = CDSymbolTable[Key % CDNUMLAYERS];
381 Bucket->buSymbolDesc = *SymbolDesc;
382 CDSymbolTable[Key % CDNUMLAYERS] = Bucket;
383 fclose(FDesc);
384 PCIF(SymbolName,&StatusString,&StatusInt);
385 if (StatusInt == PSUCCEEDED)
386 CDStatusInt = CDOLDSYMBOL;
387 else{
388 CDStatusInt = CDPARSEFAILED;
389 strcpy(CDStatusString,StatusString);
390
391 /* SRW ** so CDGen() doesn't puke */
392 for (Layer = 0;Layer <= CDNUMLAYERS;++Layer)
393 CDDesc.dSymbolDesc->sBin[Layer] = (struct o ***)NULL;
394
395 ret = False;
396 goto done;
397 }
398 /*
399 * Now, the master list descs and instance descs, if any, have
400 * to be filled in. See the discussion in CDBeginMakeCall for
401 * why this wasn't done earlier.
402 */
403 MasterListDesc = CDDesc.dSymbolDesc->sMasterList;
404 while (MasterListDesc != NULL) {
405 /*
406 * This recursive call is safe, because PCIF has done its work.
407 * Because StatusInt is checked, we ignore the returned value.
408 */
409 CDOpen(MasterListDesc->mName,&MasterSymbolDesc,'r');
410 if (CDStatusInt == CDNEWSYMBOL Or CDStatusInt == CDPARSEFAILED) {
411 if (CDStatusInt == CDNEWSYMBOL) {
412 CDStatusInt = CDPARSEFAILED;
413 sprintf(CDStatusString,
414 "Master %s doesn't seem to be around.\n",
415 MasterListDesc->mName);
416 }
417 ret = False;
418 goto done;
419 }
420 if (Not CDReflect(MasterSymbolDesc)) {
421 CDStatusInt = CDPARSEFAILED;
422 ret = False;
423 goto done;
424 }
425 MasterListDesc = MasterListDesc->mSucc;
426 }
427 CDStatusInt = CDSUCCEEDED;
428 }
429 else {
430 if (Access == 'w' Or Access == 'n') {
431 /* create cell in database */
432 CDDesc.dSymbolDesc = NewDesc;
433 ++CDDesc.dNumSymbolsAllocated;
434 for (Layer = 0;Layer <= CDNUMLAYERS;++Layer)
435 CDDesc.dSymbolDesc->sBin[Layer] = (struct o ***)NULL;
436 CDDesc.dSymbolDesc->sName = cp;
437 strcpy(CDDesc.dSymbolName,SymbolName);
438 strcpy(CDDesc.dSymbolDesc->sName,CDDesc.dSymbolName);
439 CDDesc.dNumX = CDDesc.dNumY = 1;
440 CDDesc.dDX = CDDesc.dDY = 0;
441 CDDesc.dSymbolDesc->sA = 1;
442 CDDesc.dSymbolDesc->sB = 1;
443 CDDesc.dSymbolDesc->sBBValid = True;
444 CDDesc.dSymbolDesc->sLeft
445 = CDDesc.dSymbolDesc->sBottom = CDINFINITY;
446 CDDesc.dSymbolDesc->sRight
447 = CDDesc.dSymbolDesc->sTop = -CDINFINITY;
448 CDDesc.dSymbolDesc->sInfo = 0;
449 CDDesc.dSymbolDesc->sMasterList = NULL;
450 CDDesc.dSymbolDesc->sPrptyList = NULL;
451 /* add property list information */
452 while (CDDesc.dPrptyList != NULL) {
453 if (Not CDAddProperty(CDDesc.dSymbolDesc,(struct o *)NULL,
454 CDDesc.dPrptyList->prpty_Value,
455 CDDesc.dPrptyList->prpty_String)) {
456 CDStatusInt = CDError(CDMALLOCFAILED);
457 CDStatusInt = CDPARSEFAILED;
458 ret = False;
459 goto done;
460 }
461 /* free storage of CDDesc.dPrptyList */
462 PrptyCopy = *CDDesc.dPrptyList;
463 tfree(CDDesc.dPrptyList->prpty_String);
464 tfree(CDDesc.dPrptyList);
465 CDDesc.dPrptyList = PrptyCopy.prpty_Succ;
466 }
467 /*
468 * Insert symbol desc in symbol table.
469 * The hash table 'Key' was computed above.
470 */
471 *SymbolDesc = CDDesc.dSymbolDesc;
472 if (CDSymbolTable[Key % CDNUMLAYERS] != NULL)
473 CDSymbolTable[Key % CDNUMLAYERS]->buPred = Bucket;
474 Bucket->buSucc = CDSymbolTable[Key % CDNUMLAYERS];
475 Bucket->buSymbolDesc = *SymbolDesc;
476 Bucket->buPred = NULL;
477 CDSymbolTable[Key % CDNUMLAYERS] = Bucket;
478 }
479 else {
480 *SymbolDesc = NULL;
481 /* free the previously allocated memory. It's not needed */
482 tfree(NewDesc);
483 tfree(Bucket);
484 tfree(cp);
485 }
486 CDStatusInt = CDNEWSYMBOL;
487 }
488 }
489 ret = True;
490 done:
491
492 --RecursionLevel;
493 if (RecursionLevel == 0 And CDDesc.dControl != DCONTROLPCIF)
494 CDDesc.dControl = DCONTROLVANILLA;
495
496 #ifdef DEBUGREFLECT
497 printf("End CDOpen of symbol %s.\n",SymbolName);
498 #endif
499
500 return (ret);
501 }
502
503
504 void
CDSymbol(SymbolName,SymbolDesc)505 CDSymbol(SymbolName,SymbolDesc)
506 char *SymbolName;
507 struct s **SymbolDesc;
508 {
509 /*
510 * Returns symbol desc if any for symbol.
511 * If SymbolName is not in symbol table, the pointer SymbolDesc
512 * is returned NULL.
513 */
514 int Key,Int1,Int2;
515 struct bu *Bucket;
516
517 Key = 0;
518 *SymbolDesc = NULL;
519 if (SymbolName == NULL)
520 return;
521 Int2 = strlen(SymbolName);
522 for (Int1 = 0;Int1 < Int2;++Int1)
523 Key += SymbolName[Int1];
524 Bucket = CDSymbolTable[Key % CDNUMLAYERS];
525 while (Bucket != NULL) {
526 if (strcmp(Bucket->buSymbolDesc->sName,SymbolName) == 0) {
527 *SymbolDesc = Bucket->buSymbolDesc;
528 return;
529 }
530 Bucket = Bucket->buSucc;
531 }
532 }
533
534
535 int
CDClose(SymbolDesc)536 CDClose(SymbolDesc)
537 struct s *SymbolDesc;
538 {
539 /*
540 * Close symbol. Free SymbolDesc.
541 * If malloc fails, False is returned. Otherwise, True is returned.
542 */
543 struct bu *Bucket;
544 struct g *GenDesc;
545 struct o *Pointer;
546 int Key,Int1,Int2;
547 int Layer;
548
549 /*
550 * Delete symbol desc from symbol table.
551 */
552 Key = 0;
553 Int2 = strlen(SymbolDesc->sName);
554 for (Int1 = 0; Int1 < Int2; ++Int1)
555 Key += SymbolDesc->sName[Int1];
556 Bucket = CDSymbolTable[Key % CDNUMLAYERS];
557 while (Bucket != NULL) {
558 if (strcmp(Bucket->buSymbolDesc->sName,SymbolDesc->sName) == 0)
559 break;
560 Bucket = Bucket->buSucc;
561 }
562 if (Bucket == NULL)
563 return (True);
564 if (Bucket->buPred == NULL And Bucket->buSucc == NULL) {
565 /*
566 * Only desc--has no pred or succ.
567 */
568 CDSymbolTable[Key % CDNUMLAYERS] = NULL;
569 }
570 elif (Bucket->buPred == NULL) {
571 /*
572 * First desc. Has a succ, but no pred.
573 */
574 CDSymbolTable[Key % CDNUMLAYERS] = Bucket->buSucc;
575 Bucket->buSucc->buPred = NULL;
576 }
577 elif (Bucket->buSucc == NULL) {
578 /*
579 * Last desc--has a pred, but no succ.
580 */
581 Bucket->buPred->buSucc = NULL;
582 }
583 else {
584 /*
585 * Vanilla desc has a pred and a succ.
586 */
587 Bucket->buSucc->buPred = Bucket->buPred;
588 Bucket->buPred->buSucc = Bucket->buSucc;
589 }
590 /*
591 * Free storage taken up by symbol.
592 */
593 for (Layer = 0;Layer <= CDNUMLAYERS;++Layer) {
594 if (Not CDInitGen(SymbolDesc,Layer,-CDINFINITY,-CDINFINITY,
595 CDINFINITY,CDINFINITY,&GenDesc))
596 return (CDError(CDMALLOCFAILED));
597 loop {
598 CDGen(SymbolDesc,GenDesc,&Pointer);
599 if (Pointer == NULL)
600 break;
601 else{
602 CDDelete(SymbolDesc,Pointer);
603 }
604 }
605 }
606 /*
607 * Free storage of property list;
608 */
609 CDPrptyListFree(SymbolDesc->sPrptyList);
610
611 tfree(SymbolDesc->sHY);
612
613 tfree(Bucket->buSymbolDesc);
614 tfree(Bucket);
615 return (True);
616 }
617
618
619 int
CDReflect(SymbolDesc)620 CDReflect(SymbolDesc)
621 struct s *SymbolDesc;
622 {
623 /*
624 * This routine must be invoked at certain times by the CD user.
625 * All bounding box information must be up-to-date if the indexing
626 * method is to work.
627 *
628 * CDReflect will return False if malloc fails. Otherwise, True is
629 * returned.
630 *
631 * Here's the problem.
632 * Suppose we have a symbol called Load and there is an instance
633 * of it in NAND. Then, there is a master list desc for Load in
634 * NAND's master list. Suppose Load is edited and its BB changes.
635 * Then, the instance desc for the instance of Load in NAND will be wrong.
636 * Calling CDReflect(Load) reflects the change to Load's BB to all
637 * symbols that DIRECTLY or INDIRECTLY reference it.
638 *
639 * In one sentence, here is when you must invoke CDReflect:
640 * You have opened a symbol and edited it so that its bounding box
641 * has changed and you are done editing it for the time being.
642 */
643 int Int1;
644 long L,B,R,T;
645 struct bu *Bucket;
646 struct m *MasterListDesc;
647
648 /*
649 * Here's the algorithm.
650 * Let the name of the symbol we are reflecting be S.
651 *
652 * Recompute BB of S.
653 * CDUpdate does this.
654 *
655 * For each symbol named i, i != S, in CD's hash table of symbol descs,
656 * do the following.
657 *
658 * For each master named M, if any, in master list of i, do the following.
659 * If M == S and M's BB != S's BB, do the following.
660 * M's BB = S's BB.
661 * Patch up i's instance descs that reference M.
662 * Update i's BB.
663 * Invoke Reflect(i) recursively.
664 */
665
666 #ifdef DEBUGREFLECT
667 printf("Begin Reflect(%s).\n",SymbolDesc->sName);
668 printf(" Old BB is %d %d %d %d.\n",SymbolDesc->sLeft,SymbolDesc->sBottom,
669 SymbolDesc->sRight,SymbolDesc->sTop);
670 #endif
671
672 /*
673 * Recompute BB of S.
674 */
675 if (Not CDBB(SymbolDesc,(struct o *)NULL,&L,&B,&R,&T))
676 return (False);
677
678 #ifdef DEBUGREFLECT
679 printf(" New BB is %d %d %d %d.\n",SymbolDesc->sLeft,SymbolDesc->sBottom,
680 SymbolDesc->sRight,SymbolDesc->sTop);
681 #endif
682
683 for (Int1 = 0;Int1 < CDNUMLAYERS;++Int1) {
684 Bucket = CDSymbolTable[Int1];
685 loop {
686 if (Bucket == NULL)
687 break;
688 /*
689 * SymbolDesc is the desc for S.
690 * Bucket->buSymbolDesc is the desc for i.
691 */
692 elif (strcmp(Bucket->buSymbolDesc->sName,SymbolDesc->sName) == 0)
693 Bucket = Bucket->buSucc;
694 else {
695
696 #ifdef DEBUGREFLECT
697 printf(" Begin traversing master list of %s.\n",Bucket->buSymbolDesc->sName);
698 #endif
699
700 MasterListDesc = Bucket->buSymbolDesc->sMasterList;
701 loop {
702 if (MasterListDesc == NULL) {
703
704 #ifdef DEBUGREFLECT
705 printf(" End traversing master list of %s.\n",Bucket->buSymbolDesc->sName);
706 #endif
707
708 break;
709 }
710 else {
711 /*
712 * MasterListDesc->mName is M.
713 */
714
715 #ifdef DEBUGREFLECT
716 printf("Considering %s.\n",MasterListDesc->mName);
717 printf("BB is %d %d %d %d.\n",MasterListDesc->mLeft,MasterListDesc->mBottom,
718 MasterListDesc->mRight,MasterListDesc->mTop);
719 #endif
720
721 if (! strcmp(MasterListDesc->mName,SymbolDesc->sName)
722 And ((MasterListDesc->mLeft != SymbolDesc->sLeft Or
723 MasterListDesc->mBottom != SymbolDesc->sBottom Or
724 MasterListDesc->mRight != SymbolDesc->sRight Or
725 MasterListDesc->mTop != SymbolDesc->sTop)
726 Or !IsCellInLib(MasterListDesc->mName))) {
727
728 #ifdef DEBUGREFLECT
729 printf("BB conflict.\n");
730 #endif
731
732 MasterListDesc->mLeft = SymbolDesc->sLeft;
733 MasterListDesc->mBottom = SymbolDesc->sBottom;
734 MasterListDesc->mRight = SymbolDesc->sRight;
735 MasterListDesc->mTop = SymbolDesc->sTop;
736 /*
737 * Patch up instance descs.
738 * A very big loop.
739 * Warrants its own routine.
740 */
741 if (Not CDPatchInstances(Bucket->buSymbolDesc,
742 MasterListDesc->mName))
743 return (False);
744 /*
745 * Recompute i's BB.
746 */
747 Bucket->buSymbolDesc->sBBValid = False;
748 if (Not CDBB(Bucket->buSymbolDesc,(struct o *)NULL,
749 &L,&B,&R,&T)) return (False);
750 /*
751 * Reflect changes up the hierarchy of
752 * instance references.
753 */
754 if (Not CDReflect(Bucket->buSymbolDesc))
755 return (False);
756 }
757 MasterListDesc = MasterListDesc->mSucc;
758 };
759 }
760 Bucket = Bucket->buSucc;
761 }
762 }
763 }
764
765 #ifdef DEBUGREFLECT
766 printf("End Reflect(%s).\n",SymbolDesc->sName);
767 #endif
768
769 return (True);
770 }
771
772 int
CDPatchInstances(SymbolDesc,MasterName)773 CDPatchInstances(SymbolDesc,MasterName)
774 struct s *SymbolDesc;
775 char *MasterName;
776 {
777 /* SRW ** modified for SCED */
778 /*
779 * This routine will replace all instances of MasterName in the symbol
780 * pointed to by SymbolDesc. The result is to reflect any change in
781 * the BB of MasterName in the symbol. It also updates the SCED
782 * properties, which is necessary if, for example, one changes the
783 * location of a terminal in a subedit.
784 *
785 * CDPatchInstances will return False if malloc fails.
786 * Otherwise, True is returned.
787 */
788
789 struct g *GenDesc;
790 struct o *OldPntr,*NewPntr,tmp;
791 struct t *TGen;
792 struct s *MasterDesc = NULL;
793 struct prpty *PrptyDesc;
794 char *SymbolName;
795 char Type;
796 int NumX,NumY;
797 long X,Y;
798 long DX,DY;
799 long NewL,NewB,NewR,NewT;
800
801 #ifdef DEBUGREFLECT
802 printf("Begin patching instances of master %s for symbol %s.\n",MasterName,SymbolDesc->sName);
803 #endif
804
805 if (MasterName == NULL || *MasterName == '\0')
806 return (True);
807 if (Not CDInitGen(SymbolDesc,0,-CDINFINITY,-CDINFINITY,CDINFINITY,
808 CDINFINITY,&GenDesc)) return (CDError(CDMALLOCFAILED));
809 if (!IsCellInLib(MasterName))
810 CDSymbol(MasterName,&MasterDesc);
811 loop {
812 CDGen(SymbolDesc,GenDesc,&OldPntr);
813 if (OldPntr == NULL)
814 break;
815 CDCall(OldPntr,&SymbolName,&NumX,&DX,&NumY,&DY);
816 if (SymbolName == NULL)
817 continue;
818 if (strcmp(SymbolName,MasterName) != 0)
819 continue;
820
821 /* SRW ** horrible way to get BB */
822 /* we can assume here that the only error is CDMALLOCFAILED */
823 if (Not CDBeginMakeCall(SymbolDesc,SymbolName,
824 NumX,DX,NumY,DY,&NewPntr))
825 if (CDStatusInt == CDMALLOCFAILED)
826 return (CDError(CDMALLOCFAILED));
827 CDInitTGen(OldPntr,&TGen);
828 loop {
829 CDTGen(&TGen,&Type,&X,&Y);
830 if (TGen == NULL)
831 break;
832 else
833 if (Not CDT(NewPntr,Type,X,Y))
834 return (CDError(CDMALLOCFAILED));
835 }
836 if (Not CDEndMakeCall(SymbolDesc,NewPntr))
837 return (CDError(CDMALLOCFAILED));
838
839 /* update the property list */
840 if (MasterDesc && CDDesc.dControl != DCONTROLVANILLA) {
841 CDProperty(MasterDesc,(struct o *)NULL,&PrptyDesc);
842 while (PrptyDesc) {
843 CDCopyProperty(SymbolDesc,NewPntr,PrptyDesc);
844 PrptyDesc = PrptyDesc->prpty_Succ;
845 }
846 SetTransform(NewPntr);
847 UpdateProperties(NewPntr);
848 TPop();
849 }
850 else {
851 CDProperty(SymbolDesc,OldPntr,&PrptyDesc);
852 while (PrptyDesc) {
853 CDCopyProperty(SymbolDesc,NewPntr,PrptyDesc);
854 PrptyDesc = PrptyDesc->prpty_Succ;
855 }
856 }
857 CDDelete(SymbolDesc,OldPntr);
858
859
860
861 #ifdef notdef
862 CDSymbol(SymbolName,&MasterDesc);
863
864 for (il = Ilst; il; il = il1) {
865 il1 = il->next;
866 OldPntr = il->pointer;
867 tfree(il);
868
869 CDCall(OldPntr,&SymbolName,&NumX,&DX,&NumY,&DY);
870
871 /* we can assume here that the only error is CDMALLOCFAILED */
872 if (Not CDBeginMakeCall(SymbolDesc,SymbolName,NumX,DX,NumY,DY,&NewPntr))
873 if (CDStatusInt == CDMALLOCFAILED)
874 return (CDError(CDMALLOCFAILED));
875 CDInitTGen(OldPntr,&TGen);
876 loop {
877 CDTGen(&TGen,&Type,&X,&Y);
878 if (TGen == NULL)
879 break;
880 else
881 if (Not CDT(NewPntr,Type,X,Y))
882 return (CDError(CDMALLOCFAILED));
883 }
884 if (Not CDEndMakeCall(SymbolDesc,NewPntr))
885 return (CDError(CDMALLOCFAILED));
886
887 /* update the property list */
888 if (MasterDesc && CDDesc.dControl != DCONTROLVANILLA) {
889 CDProperty(MasterDesc,(struct o *)NULL,&PrptyDesc);
890 while (PrptyDesc) {
891 CDCopyProperty(SymbolDesc,NewPntr,PrptyDesc);
892 PrptyDesc = PrptyDesc->prpty_Succ;
893 }
894 SetTransform(NewPntr);
895 UpdateProperties(NewPntr);
896 TPop();
897 }
898 CDProperty(SymbolDesc,OldPntr,&PrptyDesc);
899 while (PrptyDesc != NULL) {
900 switch (PrptyDesc->prpty_Value) {
901 case P_MODEL:
902 case P_VALUE:
903 case P_INITC:
904 case P_OTHER:
905 if (Not CDCopyProperty(SymbolDesc,NewPntr,PrptyDesc))
906 return (CDError(CDMALLOCFAILED));
907 break;
908 case P_NODE:
909 case P_NAME:
910 case P_MUT:
911 case P_BRANCH:
912 if (MasterDesc && CDDesc.dControl != DCONTROLVANILLA)
913 break;
914 if (Not CDCopyProperty(SymbolDesc,NewPntr,PrptyDesc))
915 return (CDError(CDMALLOCFAILED));
916 }
917 PrptyDesc = PrptyDesc->prpty_Succ;
918 }
919 CDDelete(SymbolDesc,OldPntr);
920 #endif
921 }
922
923 #ifdef DEBUGREFLECT
924 printf("End patching instances of master %s for symbol %s.\n",MasterName,SymbolDesc->sName);
925 #endif
926
927 return (True);
928 }
929
930
931
932 /*======================================================================*
933 * *
934 * OOO BBBB J EEEEE CCCC TTTTT *
935 * O O B B J E C T *
936 * O O BBBB J EEE C T *
937 * O O B B J J E C T *
938 * OOO BBBB JJJ EEEEE CCCC T *
939 * *
940 * CCCC RRRR EEEEE A TTTTT III OOO N N *
941 * C R R E A A T I O O NN N *
942 * C RRRR EEE A A T I O O N N N *
943 * C R R E AAAAA T I O O N NN *
944 * CCCC R R EEEEE A A T III OOO N N *
945 * *
946 * *
947 * *
948 * CDMakeBox(SymbolDesc,Layer,Length,Width,X,Y,Pointer) *
949 * CDMakeLabel(SymbolDesc,Layer,Label,X,Y,Xform,Pointer) *
950 * CDMakePolygon(SymbolDesc,Layer,Path,Pointer) *
951 * CDMakeWire(SymbolDesc,Layer,Width,Path,Pointer) *
952 * CDMakeRoundFlash(SymbolDesc,Layer,Width,X,Y,Pointer) *
953 * CDBeginMakeCall(SymbolDesc,SymbolName,NumX,DX,NumY,DY,Pointer) *
954 * CDEndMakeCall(SymbolDesc,Pointer) *
955 * CDInsertObjectDesc(SymbolDesc,ObjectDesc) *
956 * CDCheckPath(Path) *
957 * *
958 *======================================================================*/
959
960 int
961 CDMakeBox(SymbolDesc,Layer,Length,Width,X,Y,Pointer)
962 struct s *SymbolDesc;
963 int Layer;
964 long Length,Width,X,Y;
965 struct o **Pointer;
966 {
967 struct o *ObjectDesc;
968 if (Length == 0 Or Width == 0)
969 return (CDError(CDBADBOX));
970 if ((ObjectDesc = alloc(o)) == NULL)
971 return (CDError(CDMALLOCFAILED));
972 Length = Abs(Length);
973 Width = Abs(Width);
974 ObjectDesc->oRep = NULL;
975 ObjectDesc->oPrptyList = NULL;
976 ObjectDesc->oInfo = 0;
977 ObjectDesc->oType = CDBOX;
978 ObjectDesc->oLayer = Layer;
979 ObjectDesc->oLeft = X-Length/2;
980 ObjectDesc->oBottom = Y-Width/2;
981 ObjectDesc->oRight = X+Length/2;
982 ObjectDesc->oTop = Y+Width/2;
983 *Pointer = ObjectDesc;
984 if (Not CDInsertObjectDesc(SymbolDesc,ObjectDesc))
985 return (False);
986 return (True);
987 }
988
989
990 int
991 CDMakeLabel(SymbolDesc,Layer,Label,X,Y,Xform,Pointer)
992 struct s *SymbolDesc;
993 int Layer;
994 char *Label;
995 long X,Y;
996 char Xform;
997 struct o **Pointer;
998 {
999 struct la *LabelDesc;
1000 struct o *ObjectDesc;
1001 unsigned long size;
1002
1003 if ((LabelDesc = alloc(la)) == NULL)
1004 return (CDError(CDMALLOCFAILED));
1005 if ((ObjectDesc = alloc(o)) == NULL)
1006 return (CDError(CDMALLOCFAILED));
1007 size = strlen(Label) + 2;
1008 if ((LabelDesc->laLabel = tmalloc(size)) == NULL)
1009 return (CDError(CDMALLOCFAILED));
1010 strcpy(LabelDesc->laLabel,Label);
1011 LabelDesc->laX = X;
1012 LabelDesc->laY = Y;
1013 LabelDesc->laXform = Xform;
1014 ObjectDesc->oRep = (struct o *)LabelDesc;
1015 ObjectDesc->oPrptyList = NULL;
1016 ObjectDesc->oInfo = 0;
1017 ObjectDesc->oType = CDLABEL;
1018 ObjectDesc->oLayer = Layer;
1019
1020 /* give label a small BB */
1021 ObjectDesc->oLeft = X;
1022 ObjectDesc->oRight = X + 400;
1023 ObjectDesc->oBottom = Y;
1024 ObjectDesc->oTop = Y + 200;
1025 /*
1026 ObjectDesc->oLeft = ObjectDesc->oRight = X;
1027 ObjectDesc->oBottom = ObjectDesc->oTop = Y;
1028 */
1029
1030 *Pointer = ObjectDesc;
1031 if (Not CDInsertObjectDesc(SymbolDesc,ObjectDesc))
1032 return (False);
1033 return (True);
1034 }
1035
1036
1037 int
1038 CDMakePolygon(SymbolDesc,Layer,Path,Pointer)
1039 struct s *SymbolDesc;
1040 int Layer;
1041 struct p *Path;
1042 struct o **Pointer;
1043 {
1044 struct po *PolygonDesc;
1045 struct o *ObjectDesc;
1046 struct p *Pair;
1047
1048 if ((PolygonDesc = alloc(po)) == NULL)
1049 return (CDError(CDMALLOCFAILED));
1050 if ((ObjectDesc = alloc(o)) == NULL)
1051 return (CDError(CDMALLOCFAILED));
1052 CDCheckPath(Path);
1053 PolygonDesc->poPath = Path;
1054 ObjectDesc->oRep = (struct o *)PolygonDesc;
1055 ObjectDesc->oPrptyList = NULL;
1056 ObjectDesc->oInfo = 0;
1057 ObjectDesc->oType = CDPOLYGON;
1058 ObjectDesc->oLayer = Layer;
1059 ObjectDesc->oLeft = ObjectDesc->oBottom = CDINFINITY;
1060 ObjectDesc->oRight = ObjectDesc->oTop = -CDINFINITY;
1061 Pair = Path;
1062 while (Pair != NULL) {
1063 if (ObjectDesc->oLeft > Pair->pX)
1064 ObjectDesc->oLeft = Pair->pX;
1065 if (ObjectDesc->oRight < Pair->pX)
1066 ObjectDesc->oRight = Pair->pX;
1067 if (ObjectDesc->oBottom > Pair->pY)
1068 ObjectDesc->oBottom = Pair->pY;
1069 if (ObjectDesc->oTop < Pair->pY)
1070 ObjectDesc->oTop = Pair->pY;
1071 Pair = Pair->pSucc;
1072 }
1073 *Pointer = ObjectDesc;
1074 if (Not CDInsertObjectDesc(SymbolDesc,ObjectDesc))
1075 return (False);
1076 return (True);
1077 }
1078
1079
1080 int
1081 CDMakeWire(SymbolDesc,Layer,Width,Path,Pointer)
1082 struct s *SymbolDesc;
1083 int Layer;
1084 long Width;
1085 struct p *Path;
1086 struct o **Pointer;
1087 {
1088 struct w *WireDesc;
1089 struct o *ObjectDesc;
1090 struct p *Pair;
1091
1092 if ((WireDesc = alloc(w)) == NULL)
1093 return (CDError(CDMALLOCFAILED));
1094 if ((ObjectDesc = alloc(o)) == NULL)
1095 return (CDError(CDMALLOCFAILED));
1096 CDCheckPath(Path);
1097 if (Width < 0) Width = -Width;
1098 WireDesc->wWidth = Width;
1099 WireDesc->wPath = Path;
1100 ObjectDesc->oRep = (struct o *)WireDesc;
1101 ObjectDesc->oPrptyList = NULL;
1102 ObjectDesc->oInfo = 0;
1103 ObjectDesc->oType = CDWIRE;
1104 ObjectDesc->oLayer = Layer;
1105 ObjectDesc->oLeft = ObjectDesc->oBottom = CDINFINITY;
1106 ObjectDesc->oRight = ObjectDesc->oTop = -CDINFINITY;
1107 Pair = Path;
1108 while (Pair != NULL) {
1109 if (ObjectDesc->oLeft > Pair->pX-Width/2)
1110 ObjectDesc->oLeft = Pair->pX-Width/2;
1111 if (ObjectDesc->oRight < Pair->pX+Width/2)
1112 ObjectDesc->oRight = Pair->pX+Width/2;
1113 if (ObjectDesc->oBottom > Pair->pY-Width/2)
1114 ObjectDesc->oBottom = Pair->pY-Width/2;
1115 if (ObjectDesc->oTop < Pair->pY+Width/2)
1116 ObjectDesc->oTop = Pair->pY+Width/2;
1117 Pair = Pair->pSucc;
1118 }
1119 *Pointer = ObjectDesc;
1120 if (Not CDInsertObjectDesc(SymbolDesc,ObjectDesc))
1121 return (False);
1122 return (True);
1123 }
1124
1125
1126 int
1127 CDMakeRoundFlash(SymbolDesc,Layer,Width,X,Y,Pointer)
1128 struct s *SymbolDesc;
1129 int Layer;
1130 long Width,X,Y;
1131 struct o **Pointer;
1132 {
1133 struct r *RoundFlashDesc;
1134 struct o *ObjectDesc;
1135
1136 if ((RoundFlashDesc = alloc(r)) == NULL)
1137 return (CDError(CDMALLOCFAILED));
1138 if ((ObjectDesc = alloc(o)) == NULL)
1139 return (CDError(CDMALLOCFAILED));
1140 RoundFlashDesc->rWidth = Width;
1141 RoundFlashDesc->rX = X;
1142 RoundFlashDesc->rY = Y;
1143 ObjectDesc->oRep = (struct o *)RoundFlashDesc;
1144 ObjectDesc->oPrptyList = NULL;
1145 ObjectDesc->oInfo = 0;
1146 ObjectDesc->oType = CDROUNDFLASH;
1147 ObjectDesc->oLayer = Layer;
1148 ObjectDesc->oLeft = X-Width/2;
1149 ObjectDesc->oBottom = Y-Width/2;
1150 ObjectDesc->oRight = X+Width/2;
1151 ObjectDesc->oTop = Y+Width/2;
1152 *Pointer = ObjectDesc;
1153 if (Not CDInsertObjectDesc(SymbolDesc,ObjectDesc))
1154 return (False);
1155 return (True);
1156 }
1157
1158 int
1159 CDBeginMakeCall(SymbolDesc,SymbolName,NumX,DX,NumY,DY,Pointer)
1160 struct s *SymbolDesc;
1161 char *SymbolName;
1162 int NumX,NumY;
1163 long DX,DY;
1164 struct o **Pointer;
1165 {
1166 /*
1167 * CDBeginMakeCall will return False if a CDMALLOCFAILED error
1168 * occurs or if CDOpen fails. Possible values for CDStatusInt
1169 * upon return are:
1170 * (Fatal)-CDPARSEFAILED - Syntax error
1171 * (Fatal)-CDMALLOCFAILED - Out of memory
1172 * (Fatal)-CDNEWSYMBOL - symbol does not exist
1173 * CDOLDSYMBOL - successful return, symbol exists
1174 * Only CDOLDSYMBOL is not a fatal return (i.e., CDBeginMakeCall
1175 * returns True).
1176 */
1177 struct c *CallDesc;
1178 struct o *ObjectDesc;
1179 struct m *MasterListDesc;
1180 struct s *MasterSymbolDesc;
1181 struct prpty *PrptyDesc;
1182 unsigned int size;
1183
1184 /* The symbol call is inserted into the database CDEndMakeCall */
1185 if ((CallDesc = alloc(c)) == NULL)
1186 return (CDError(CDMALLOCFAILED));
1187 if ((ObjectDesc = alloc(o)) == NULL)
1188 return (CDError(CDMALLOCFAILED));
1189 CallDesc->cNumX = NumX;
1190 CallDesc->cDX = DX;
1191 CallDesc->cNumY = NumY;
1192 CallDesc->cT = NULL;
1193 CallDesc->cDY = DY;
1194 ObjectDesc->oRep = (struct o *)CallDesc;
1195 ObjectDesc->oPrptyList = NULL;
1196 ObjectDesc->oInfo = 0;
1197 ObjectDesc->oType = CDSYMBOLCALL;
1198 ObjectDesc->oLayer = 0;
1199 *Pointer = ObjectDesc;
1200 MasterListDesc = SymbolDesc->sMasterList;
1201 /*
1202 * Search masterList for an instance of SymbolName.
1203 * If not found, insert into the masterList (which is a linked list).
1204 * An entry in the master list contains the symbol name, the bounding
1205 * box, and the number of references.
1206 */
1207 loop{
1208 if (MasterListDesc == NULL) {
1209 /*
1210 * Insert into list
1211 * Firstly, try to allocate memory
1212 */
1213 if ((MasterListDesc = alloc(m)) == NULL)
1214 return (CDError(CDMALLOCFAILED));
1215 size = strlen(SymbolName) + 2;
1216 if ((MasterListDesc->mName = tmalloc(size)) == NULL)
1217 return (CDError(CDMALLOCFAILED));
1218 /* insert new instance at end of (linked) masterList */
1219 if (SymbolDesc->sMasterList != NULL)
1220 SymbolDesc->sMasterList->mPred = MasterListDesc;
1221 MasterListDesc->mSucc = SymbolDesc->sMasterList;
1222 MasterListDesc->mPred = NULL;
1223 SymbolDesc->sMasterList = MasterListDesc;
1224 MasterListDesc->mReferenceCount = 0;
1225 strcpy(MasterListDesc->mName,SymbolName);
1226 if (CDDesc.dControl == DCONTROLVANILLA) {
1227 /*
1228 * DCONTROLVANILLA tells us that CDOpen is safe to call here.
1229 * Because StatusInt is checked, we ignore the returned value.
1230 */
1231 CDOpen(MasterListDesc->mName,&MasterSymbolDesc,'r');
1232 if (CDStatusInt == CDPARSEFAILED Or CDStatusInt == CDNEWSYMBOL) {
1233 /* CDOpen failed -- Don't put bad master in MasterList */
1234 if (CDStatusInt == CDNEWSYMBOL)
1235 sprintf(CDStatusString,"Symbol %s not found.",
1236 MasterListDesc->mName);
1237 if (SymbolDesc->sMasterList != NULL)
1238 SymbolDesc->sMasterList->mPred = NULL;
1239 strcpy(MasterListDesc->mName,"");
1240 SymbolDesc->sMasterList = MasterListDesc->mSucc;
1241 tfree(MasterListDesc);
1242 return (False);
1243 }
1244 if (Not CDBB(MasterSymbolDesc,(struct o *)NULL,
1245 &(MasterListDesc->mLeft),&(MasterListDesc->mBottom),
1246 &(MasterListDesc->mRight),&(MasterListDesc->mTop)))
1247 return (False);
1248 }
1249 elif (CDDesc.dControl == DCONTROLCDOPEN Or
1250 CDDesc.dControl == DCONTROLPCIF) {
1251 /*
1252 * We CANNOT invoke CDBB here, because if the master symbol
1253 * hasn't already been mapped into main memory via CDOpen,
1254 * CDBB will invoke CDOpen which will then invoke PCIF and
1255 * since PCIF CANNOT be invoked recursively, all of PCIF's
1256 * state will be broken. The solution is to defer filling
1257 * in the bounding box information for master list descs and
1258 * instance descs until PCIF has returned in CDOpen. Why not
1259 * write PCIF so it can be invoked recursively? For a deep
1260 * hierarchy, we might exceed the limit on open file
1261 * descriptors and we clearly don't want to limit hierarchy
1262 * depth.
1263 */
1264 MasterListDesc->mLeft = MasterListDesc->mBottom =
1265 MasterListDesc->mRight = MasterListDesc->mTop = 0;
1266 }
1267 break;
1268 }
1269 elif (strcmp(SymbolName,MasterListDesc->mName) == 0) {
1270 /*
1271 * A match! This symbol is already in memory.
1272 */
1273
1274 /* SRW */
1275 if (CDDesc.dControl == DCONTROLVANILLA)
1276 CDSymbol(MasterListDesc->mName,&MasterSymbolDesc);
1277
1278 CDStatusInt = CDOLDSYMBOL;
1279 *CDStatusString = '\0';
1280 break;
1281 }
1282 else
1283 MasterListDesc = MasterListDesc->mSucc;
1284 }
1285 CallDesc->cMaster = MasterListDesc;
1286 MasterListDesc->mReferenceCount++;
1287
1288 /* SRW
1289 * This version of CD is used for a schematic editor, in which
1290 * connectivity is established by maintaining terminal coordinates
1291 * in property strings. As we add a cell (DCONTROLVANILLA set),
1292 * the property strings contain connection nodes with coordinates
1293 * relative to the cell. These coordinates are transformed to be
1294 * relative to the parent cell by a routine called in
1295 * CDEndMakeCall().
1296 */
1297 if (CDDesc.dControl == DCONTROLVANILLA) {
1298 CDProperty(MasterSymbolDesc,(struct o *)NULL,&PrptyDesc);
1299 while (PrptyDesc) {
1300 CDCopyProperty(SymbolDesc,ObjectDesc,PrptyDesc);
1301 PrptyDesc = PrptyDesc->prpty_Succ;
1302 }
1303 }
1304
1305 return (True);
1306 }
1307
1308
1309 int
1310 CDT(Pointer,Type,X,Y)
1311 struct o *Pointer;
1312 char Type;
1313 long X,Y;
1314 {
1315 /*
1316 * After invoking BeginMakeCall, invoke T for each transformation in
1317 * the call. The transformation is a linked list of transformation
1318 * descs headed by the ct field of the call desc. Finally, invoke
1319 * EndMakeCall.
1320 */
1321 struct c *CDesc;
1322 struct t *TDesc;
1323
1324 CDesc = (struct c *)Pointer->oRep;
1325 TDesc = CDesc->cT;
1326 if (TDesc == NULL) {
1327 if ((CDesc->cT = TDesc = alloc(t)) == NULL)
1328 return (CDError(CDMALLOCFAILED));
1329 TDesc->tSucc = NULL;
1330 TDesc->tX = X;
1331 TDesc->tY = Y;
1332 TDesc->tType = Type;
1333 return (True);
1334 }
1335 while (TDesc->tSucc != NULL)
1336 TDesc = TDesc->tSucc;
1337 if ((TDesc = TDesc->tSucc = alloc(t)) == NULL)
1338 return (CDError(CDMALLOCFAILED));
1339 TDesc->tSucc = NULL;
1340 TDesc->tX = X;
1341 TDesc->tY = Y;
1342 TDesc->tType = Type;
1343 return (True);
1344 }
1345
1346
1347 int
1348 CDEndMakeCall(SymbolDesc,Pointer)
1349 struct s *SymbolDesc;
1350 struct o *Pointer;
1351 {
1352 struct c *CallDesc;
1353 struct o *ObjectDesc;
1354 struct m *MasterListDesc;
1355 struct t *TGen;
1356 long X,Y;
1357 char Type;
1358
1359 ObjectDesc = Pointer;
1360 CallDesc = (struct c *)ObjectDesc->oRep;
1361 MasterListDesc = CallDesc->cMaster;
1362 if (TFull())
1363 return (CDError(CDXFORMSTACKFULL));
1364 TPush();
1365 TIdentity();
1366 CDInitTGen(Pointer,&TGen);
1367 loop {
1368 CDTGen(&TGen,&Type,&X,&Y);
1369 if (TGen == NULL)
1370 break;
1371 if (Type == CDROTATE)
1372 TRotate(X,Y);
1373 elif (Type == CDTRANSLATE)
1374 TTranslate(X,Y);
1375 elif (Type == CDMIRRORX)
1376 TMX();
1377 elif (Type == CDMIRRORY)
1378 TMY();
1379 }
1380
1381 #ifdef DEBUGREFLECT
1382 printf("Making call of master %s in symbol %s.\n",MasterListDesc->mName,
1383 SymbolDesc->sName);
1384 printf("Untransformed (master's) BB is %d %d %d %d.\n",
1385 MasterListDesc->mLeft,MasterListDesc->mBottom,
1386 MasterListDesc->mRight,MasterListDesc->mTop);
1387 #endif
1388
1389 ObjectDesc->oLeft = MasterListDesc->mLeft;
1390 ObjectDesc->oBottom = MasterListDesc->mBottom;
1391 TPoint(&(ObjectDesc->oLeft),&(ObjectDesc->oBottom));
1392 ObjectDesc->oRight = MasterListDesc->mRight;
1393 ObjectDesc->oTop = MasterListDesc->mTop;
1394
1395 #ifdef DEBUGREFLECT
1396 TPoint(&(ObjectDesc->oRight),&(ObjectDesc->oTop));
1397 if (ObjectDesc->oRight < ObjectDesc->oLeft)
1398 SwapInts(ObjectDesc->oLeft,ObjectDesc->oRight);
1399 if (ObjectDesc->oTop < ObjectDesc->oBottom)
1400 SwapInts(ObjectDesc->oBottom,ObjectDesc->oTop);
1401 printf("Transformed, unarrayed BB is %d %d %d %d.\n",
1402 ObjectDesc->oLeft,ObjectDesc->oBottom,
1403 ObjectDesc->oRight,ObjectDesc->oTop);
1404 #endif
1405
1406 ObjectDesc->oRight += (CallDesc->cNumX-1)*CallDesc->cDX;
1407 ObjectDesc->oTop += (CallDesc->cNumY-1)*CallDesc->cDY;
1408 TPoint(&(ObjectDesc->oRight),&(ObjectDesc->oTop));
1409 if (ObjectDesc->oRight < ObjectDesc->oLeft)
1410 SwapInts(ObjectDesc->oLeft,ObjectDesc->oRight);
1411 if (ObjectDesc->oTop < ObjectDesc->oBottom)
1412 SwapInts(ObjectDesc->oBottom,ObjectDesc->oTop);
1413
1414 #ifdef DEBUGREFLECT
1415 printf("Transformed, arrayed BB is %d %d %d %d.\n",
1416 ObjectDesc->oLeft,ObjectDesc->oBottom,
1417 ObjectDesc->oRight,ObjectDesc->oTop);
1418 #endif
1419
1420 /* SRW **
1421 * UpdateProperties() must be supplied externally. The intended
1422 * purpose of this routine is to update properties that require as
1423 * input the transformed coordinates of points within the cell.
1424 * The property strings may not be present unless DCONTROLVANILLA.
1425 * See the note in CDBeginMakeCall().
1426 */
1427 if (CDDesc.dControl == DCONTROLVANILLA)
1428 UpdateProperties(ObjectDesc);
1429
1430 TPop();
1431 if (Not CDInsertObjectDesc(SymbolDesc,ObjectDesc))
1432 return (False);
1433 return (True);
1434 }
1435
1436
1437 void
1438 CDCheckPath(Path)
1439 struct p *Path;
1440 {
1441 /*
1442 * Check to see that the path does not have two identical and
1443 * adjacent vertices.
1444 */
1445 struct p *Pair;
1446 struct p *Copy;
1447 Pair = Path;
1448 while (Pair->pSucc != NULL) {
1449 if (Pair->pX == Pair->pSucc->pX And Pair->pY == Pair->pSucc->pY) {
1450 Copy = Pair->pSucc;
1451 Pair->pSucc = Copy->pSucc;
1452 tfree(Copy);
1453 }
1454 else
1455 Pair = Pair->pSucc;
1456 }
1457 }
1458
1459
1460 int
1461 CDInsertObjectDesc(SymbolDesc,ObjectDesc)
1462 struct s *SymbolDesc;
1463 struct o *ObjectDesc;
1464 {
1465 int Int1,Int2,Layer;
1466 long X,Y;
1467 long BeginX,EndX,BeginY,EndY;
1468
1469 CDIntersect(ObjectDesc->oLeft,ObjectDesc->oBottom,ObjectDesc->oRight,
1470 ObjectDesc->oTop,&BeginX,&EndX,&BeginY,&EndY);
1471 /* SRW ** always put labels in residual bin, since the size is
1472 * not known.
1473 */
1474 if (BeginX != EndX Or BeginY != EndY Or ObjectDesc->oType == CDLABEL)
1475 X = Y = 0;
1476 else {
1477 X = BeginX;
1478 Y = BeginY;
1479 }
1480 Layer = ObjectDesc->oLayer;
1481 if (SymbolDesc->sBin[Layer] == (struct o ***)NULL) {
1482 /* allocate Bin */
1483 if ((SymbolDesc->sBin[Layer] = (struct o ***)
1484 tmalloc(sizeof(char*) * (CDNUMBINS+1))) == NULL)
1485 return (CDError(CDMALLOCFAILED));
1486 for (Int1 = 0; Int1 <= CDNUMBINS; ++Int1) {
1487 if ((SymbolDesc->sBin[Layer][Int1] = (struct o **)
1488 tmalloc(sizeof(char*) * (CDNUMBINS+1))) == NULL)
1489 return (CDError(CDMALLOCFAILED));
1490 for (Int2 = 0; Int2 <= CDNUMBINS; ++Int2) {
1491 if ((SymbolDesc->sBin[Layer][Int1][Int2] = (struct o *)
1492 tmalloc(sizeof(char*))) == NULL)
1493 return (CDError(CDMALLOCFAILED));
1494 SymbolDesc->sBin[Layer][Int1][Int2] = (struct o *)NULL;
1495 }
1496 }
1497 }
1498 elif (SymbolDesc->sBin[Layer][X][Y] != NULL)
1499 SymbolDesc->sBin[Layer][X][Y]->oPred = ObjectDesc;
1500 ObjectDesc->oSucc = SymbolDesc->sBin[Layer][X][Y];
1501 SymbolDesc->sBin[Layer][X][Y] = ObjectDesc;
1502 ObjectDesc->oPred = NULL;
1503 SymbolDesc->sLeft = Min(SymbolDesc->sLeft,ObjectDesc->oLeft);
1504 SymbolDesc->sBottom = Min(SymbolDesc->sBottom,ObjectDesc->oBottom);
1505 SymbolDesc->sRight = Max(SymbolDesc->sRight,ObjectDesc->oRight);
1506 SymbolDesc->sTop = Max(SymbolDesc->sTop,ObjectDesc->oTop);
1507
1508 #ifdef DEBUGGEN
1509 if (X == 0 And Y == 0)
1510 printf("Inserting a desc on layer %d in residual bin.\n",Layer);
1511 else
1512 printf("Inserting a desc on layer %d in bin (%d,%d).\n",Layer,X,Y);
1513 #endif
1514
1515 #ifdef DEBUGREFLECT
1516 if (X == 0 And Y == 0)
1517 printf("Inserting a desc on layer %d in residual bin.\n",Layer);
1518 else
1519 printf("Inserting a desc on layer %d in bin (%d,%d).\n",Layer,X,Y);
1520 #endif
1521
1522 return (True);
1523 }
1524
1525
1526
1527
1528 /*======================================================================*
1529 * *
1530 * OOO BBBB J EEEEE CCCC TTTTT *
1531 * O O B B J E C T *
1532 * O O BBBB J EEE C T *
1533 * O O B B J J E C T *
1534 * OOO BBBB JJJ EEEEE CCCC T *
1535 * *
1536 * DDDD EEEEE L EEEEE TTTTT III OOO N N *
1537 * D D E L E T I O O NN N *
1538 * D D EEE L EEE T I O O N N N *
1539 * D D E L E T I O O N NN *
1540 * DDDD EEEEE LLLLL EEEEE T III OOO N N *
1541 * *
1542 * *
1543 * *
1544 * CDDeleteObjectDesc(SymbolDesc,ObjectDesc) *
1545 * *
1546 *======================================================================*/
1547
1548 void
1549 CDDeleteObjectDesc(SymbolDesc,ObjectDesc)
1550 struct s *SymbolDesc;
1551 struct o *ObjectDesc;
1552 {
1553 int Layer;
1554 long X,Y;
1555 long BeginX,EndX,BeginY,EndY;
1556 struct p PCopy;
1557 struct t TCopy;
1558
1559 /* we should test the descriptors as valid pointers */
1560 Layer = ObjectDesc->oLayer;
1561 /* is the Bin allocated? */
1562 if (SymbolDesc->sBin[Layer] == NULL Or ObjectDesc == NULL)
1563 return;
1564 CDIntersect(ObjectDesc->oLeft,ObjectDesc->oBottom,ObjectDesc->oRight,
1565 ObjectDesc->oTop,&BeginX,&EndX,&BeginY,&EndY);
1566 /* SRW ** labels are always in residual bin */
1567 if (BeginX != EndX Or BeginY != EndY Or ObjectDesc->oType == CDLABEL)
1568 X = Y = 0;
1569 else {
1570 X = BeginX;
1571 Y = BeginY;
1572 }
1573 if (SymbolDesc->sBin[Layer][X][Y] == NULL)
1574 /* Something's rotten */
1575 return;
1576 elif (ObjectDesc->oPred == NULL And ObjectDesc->oSucc == NULL)
1577 /* Only desc--has no pred or succ */
1578 SymbolDesc->sBin[Layer][X][Y] = NULL;
1579 elif (ObjectDesc->oPred == NULL) {
1580 /* First desc. Has a succ, but no pred */
1581 SymbolDesc->sBin[Layer][X][Y] = ObjectDesc->oSucc;
1582 ObjectDesc->oSucc->oPred = NULL;
1583 }
1584 elif (ObjectDesc->oSucc == NULL)
1585 /* Last desc--has a pred, but no succ */
1586 ObjectDesc->oPred->oSucc = NULL;
1587 else {
1588 /* Vanilla desc has a pred and a succ */
1589 ObjectDesc->oSucc->oPred = ObjectDesc->oPred;
1590 ObjectDesc->oPred->oSucc = ObjectDesc->oSucc;
1591 }
1592 /*
1593 * Invalidate BB.
1594 */
1595 SymbolDesc->sBBValid = False;
1596
1597 /*
1598 * Free storage of property list;
1599 */
1600 CDPrptyListFree(ObjectDesc->oPrptyList);
1601
1602 /* SRW ** delete any hypertext reference to ObjectDesc (for SCED) */
1603 HYdeleteReference(ObjectDesc);
1604
1605 /*
1606 * Free storage of oRep;
1607 */
1608 if (ObjectDesc->oType == CDROUNDFLASH)
1609 tfree(ObjectDesc->oRep);
1610 elif (ObjectDesc->oType == CDSYMBOLCALL) {
1611 struct c *CallDesc;
1612 struct t *TDesc;
1613
1614 CallDesc = (struct c *)ObjectDesc->oRep;
1615 /* SRW ** reduce the master reference count */
1616 if (CallDesc->cMaster)
1617 CallDesc->cMaster->mReferenceCount --;
1618 TDesc = CallDesc->cT;
1619 while (TDesc != NULL) {
1620 TCopy = *TDesc;
1621 tfree(TDesc);
1622 TDesc = TCopy.tSucc;
1623 }
1624 tfree(CallDesc);
1625 }
1626 elif (ObjectDesc->oType == CDPOLYGON) {
1627 struct po *PolygonDesc;
1628 struct p *Pair;
1629
1630 PolygonDesc = (struct po *)ObjectDesc->oRep;
1631 Pair = PolygonDesc->poPath;
1632 while (Pair != NULL) {
1633 PCopy = *Pair;
1634 tfree(Pair);
1635 Pair = PCopy.pSucc;
1636 }
1637 tfree(PolygonDesc);
1638 }
1639 elif (ObjectDesc->oType == CDWIRE) {
1640 struct w *WireDesc;
1641 struct p *Pair;
1642
1643 WireDesc = (struct w *)ObjectDesc->oRep;
1644 Pair = WireDesc->wPath;
1645 while (Pair != NULL) {
1646 PCopy = *Pair;
1647 tfree(Pair);
1648 Pair = PCopy.pSucc;
1649 }
1650 tfree(WireDesc);
1651 }
1652 tfree(ObjectDesc);
1653
1654 #ifdef DEBUGGEN
1655 printf("Deleting a desc on layer %d in bin (%d,%d)\n.",Layer,X,Y);
1656 #endif
1657
1658 }
1659
1660
1661
1662 /*======================================================================*
1663 * *
1664 * A CCCC CCCC EEEEE SSSS SSSS III N N GGGG *
1665 * A A C C E S S I NN N G *
1666 * A A C C EEE SSS SSS I N N N G GGG *
1667 * AAAAA C C E S S I N NN G G *
1668 * A A CCCC CCCC EEEEE SSSS SSSS III N N GGG *
1669 * *
1670 * OOO BBBB J EEEEE CCCC TTTTT SSSS *
1671 * O O B B J E C T S *
1672 * O O BBBB J EEE C T SSS *
1673 * O O B B J J E C T S *
1674 * OOO BBBB JJJ EEEEE CCCC T SSSS *
1675 * *
1676 * *
1677 * *
1678 * CDCall(Pointer,SymbolName,NumX,DX,NumY,DY) *
1679 * CDBox(Pointer,Layer,Length,Width,X,Y) *
1680 * CDLabel(Pointer,Layer,Label,X,Y,xform) *
1681 * CDPolygon(Pointer,Layer,Path) *
1682 * CDWire(Pointer,Layer,Width,Path) *
1683 * CDRoundFlash(Pointer,Layer,Width,X,Y) *
1684 * *
1685 *======================================================================*/
1686
1687 void
1688 CDCall(Pointer,SymbolName,NumX,DX,NumY,DY)
1689 struct o *Pointer;
1690 char **SymbolName;
1691 int *NumX,*NumY;
1692 long *DX,*DY;
1693 {
1694 struct c *CallDesc;
1695 struct s *MasterDesc;
1696
1697 if (Pointer == NULL)
1698 return;
1699 if (Pointer->oType != CDSYMBOLCALL) {
1700 *SymbolName = NULL;
1701 *NumX = 0;
1702 *DX = 0;
1703 *NumY = 0;
1704 *DY = 0;
1705 }
1706 else {
1707 CallDesc = (struct c *)Pointer->oRep;
1708 *SymbolName = CallDesc->cMaster->mName;
1709 *NumX = CallDesc->cNumX;
1710 *DX = CallDesc->cDX;
1711 *NumY = CallDesc->cNumY;
1712 *DY = CallDesc->cDY;
1713 }
1714 }
1715
1716 void
1717 CDBox(Pointer,Layer,Length,Width,X,Y)
1718 struct o *Pointer;
1719 int *Layer;
1720 long *Length,*Width,*X,*Y;
1721 {
1722
1723 if (Pointer == NULL)
1724 return;
1725 if (Pointer->oType != CDBOX)
1726 *Layer = *Length = *Width = *X = *Y = 0;
1727 else {
1728 *Layer = Pointer->oLayer;
1729 *Length = Pointer->oRight - Pointer->oLeft;
1730 *Width = Pointer->oTop - Pointer->oBottom;
1731 *X = Pointer->oLeft + (*Length >> 1);
1732 *Y = Pointer->oBottom + (*Width >> 1);
1733 }
1734 }
1735
1736
1737 void
1738 CDLabel(Pointer,Layer,Label,X,Y,Xform)
1739 struct o *Pointer;
1740 int *Layer;
1741 char **Label;
1742 long *X,*Y;
1743 char *Xform;
1744 {
1745 struct la *LabelDesc;
1746
1747 if (Pointer == NULL)
1748 return;
1749 if (Pointer->oType != CDLABEL) {
1750 *Layer = *X = *Y = 0;
1751 *Label = NULL;
1752 *Xform = (char)0;
1753 }
1754 else {
1755 *Layer = Pointer->oLayer;
1756 LabelDesc = (struct la *)Pointer->oRep;
1757 *Label = LabelDesc->laLabel;
1758 *X = LabelDesc->laX;
1759 *Y = LabelDesc->laY;
1760 *Xform = LabelDesc->laXform;
1761 }
1762 }
1763
1764
1765 void
1766 CDPolygon(Pointer,Layer,Path)
1767 struct o *Pointer;
1768 int *Layer;
1769 struct p **Path;
1770 {
1771 struct po *PolygonDesc;
1772
1773 if (Pointer == NULL)
1774 return;
1775 if (Pointer->oType != CDPOLYGON) {
1776 *Layer = 0;
1777 *Path = NULL;
1778 }
1779 else {
1780 *Layer = Pointer->oLayer;
1781 PolygonDesc = (struct po *)Pointer->oRep;
1782 *Path = PolygonDesc->poPath;
1783 }
1784 }
1785
1786
1787 void
1788 CDWire(Pointer,Layer,Width,Path)
1789 struct o *Pointer;
1790 int *Layer;
1791 long *Width;
1792 struct p **Path;
1793 {
1794 struct w *WireDesc;
1795
1796 if (Pointer == NULL)
1797 return;
1798 if (Pointer->oType != CDWIRE) {
1799 *Layer = *Width = 0;
1800 *Path = NULL;
1801 }
1802 else {
1803 *Layer = Pointer->oLayer;
1804 WireDesc = (struct w *)Pointer->oRep;
1805 *Width = WireDesc->wWidth;
1806 *Path = WireDesc->wPath;
1807 }
1808 }
1809
1810
1811 void
1812 CDRoundFlash(Pointer,Layer,Width,X,Y)
1813 struct o *Pointer;
1814 int *Layer;
1815 long *Width,*X,*Y;
1816 {
1817 struct r *RoundFlashDesc;
1818
1819 if (Pointer == NULL)
1820 return;
1821 if (Pointer->oType != CDROUNDFLASH)
1822 return;
1823 *Layer = Pointer->oLayer;
1824 RoundFlashDesc = (struct r *)Pointer->oRep;
1825 *Width = RoundFlashDesc->rWidth;
1826 *X = RoundFlashDesc->rX;
1827 *Y = RoundFlashDesc->rY;
1828 }
1829
1830
1831
1832
1833 /*======================================================================*
1834 * *
1835 * A CCCC CCCC EEEEE SSSS SSSS III N N GGGG *
1836 * A A C C E S S I NN N G *
1837 * A A C C EEE SSS SSS I N N N G GGG *
1838 * AAAAA C C E S S I N NN G G *
1839 * A A CCCC CCCC EEEEE SSSS SSSS III N N GGG *
1840 * *
1841 * III N N FFFFF OOO RRRR M M A TTTTT III OOO N N *
1842 * I NN N F O O R R MM MM A A T I O O NN N *
1843 * I N N N FFF O O RRRR M M M A A T I O O N N N *
1844 * I N NN F O O R R M M AAAAA T I O O N NN *
1845 * III N N F OOO R R M M A A T III OOO N N *
1846 * *
1847 * *
1848 * *
1849 * CDInfo(SymbolDesc,Pointer,Info) *
1850 * CDSetInfo(SymbolDesc,Pointer,Info) *
1851 * CDType(Pointer,Type) *
1852 * CDBB(SymbolDesc,Pointer,Left,Bottom,Right,Top) *
1853 * CDIntersect(Left,Bottom,Right,Top,BeginX,EndX,BeginY,EndY) *
1854 * *
1855 *======================================================================*/
1856
1857 void
1858 CDInfo(SymbolDesc,Pointer,Info)
1859 struct s *SymbolDesc;
1860 struct o *Pointer;
1861 int *Info;
1862 {
1863 /*
1864 * Return info field of object.
1865 * If Pointer == NULL, object is symbol itself.
1866 */
1867 if (Pointer == NULL)
1868 *Info = SymbolDesc->sInfo;
1869 else
1870 *Info = Pointer->oInfo;
1871 }
1872
1873
1874 void
1875 CDSetInfo(SymbolDesc,Pointer,Info)
1876 struct s *SymbolDesc;
1877 struct o *Pointer;
1878 int Info;
1879 {
1880 /*
1881 * Set info field of object.
1882 * If Pointer == NULL, object is symbol itself.
1883 */
1884 if (Pointer == NULL)
1885 SymbolDesc->sInfo = Info;
1886 else
1887 Pointer->oInfo = Info;
1888 }
1889
1890
1891 void
1892 CDType(Pointer,Type)
1893 struct o *Pointer;
1894 char *Type;
1895 {
1896 /*
1897 * Returns type of object pointed to by Pointer.
1898 */
1899 *Type = Pointer->oType;
1900 }
1901
1902
1903 int
1904 CDBB(SymbolDesc,Pointer,Left,Bottom,Right,Top)
1905 struct s *SymbolDesc;
1906 struct o *Pointer;
1907 long *Left,*Bottom,*Right,*Top;
1908 {
1909 /*
1910 * Return BB of object pointed to by Pointer.
1911 * If Pointer == NULL, return BB of symbol itself.
1912 * Basically, we CAN'T afford to recompute the BB of the symbol each time
1913 * CDDelete or an object creation routine is invoked.
1914 *
1915 * If malloc fails, CDBB will return False via CDError. Otherwise, True
1916 * is returned.
1917 */
1918 struct g *GenDesc;
1919 int Layer;
1920
1921 if (Pointer == NULL And SymbolDesc->sBBValid) {
1922 *Left = SymbolDesc->sLeft;
1923 *Bottom = SymbolDesc->sBottom;
1924 *Right = SymbolDesc->sRight;
1925 *Top = SymbolDesc->sTop;
1926
1927 #ifdef DEBUGREFLECT
1928 printf("CDBB1(%s,%d,%d,%d,%d)\n",SymbolDesc->sName,*Left,*Bottom,*Right,*Top);
1929 #endif
1930
1931 #ifdef DEBUGGEN
1932 printf("CDBB1(%s,%d,%d,%d,%d)\n",SymbolDesc->sName,*Left,*Bottom,*Right,*Top);
1933 #endif
1934
1935 return (True);
1936 }
1937 elif (Pointer != NULL) {
1938 *Left = Pointer->oLeft;
1939 *Bottom = Pointer->oBottom;
1940 *Right = Pointer->oRight;
1941 *Top = Pointer->oTop;
1942
1943 #ifdef DEBUGREFLECT
1944 printf("CDBB2(%s,%d,%d,%d,%d)\n",SymbolDesc->sName,*Left,*Bottom,*Right,*Top);
1945 #endif
1946
1947 #ifdef DEBUGGEN
1948 printf("CDBB2(%s,%d,%d,%d,%d)\n",SymbolDesc->sName,*Left,*Bottom,*Right,*Top);
1949 #endif
1950
1951 return (True);
1952 }
1953 SymbolDesc->sLeft = SymbolDesc->sBottom = CDINFINITY;
1954 SymbolDesc->sRight = SymbolDesc->sTop = -CDINFINITY;
1955 if (Not CDInitGen(SymbolDesc,0,-CDINFINITY,-CDINFINITY,CDINFINITY,
1956 CDINFINITY,&GenDesc)) return (CDError(CDMALLOCFAILED));
1957 loop {
1958 CDGen(SymbolDesc,GenDesc,&Pointer);
1959 if (Pointer == NULL)
1960 break;
1961 SymbolDesc->sLeft = Min(SymbolDesc->sLeft,Pointer->oLeft);
1962 SymbolDesc->sBottom = Min(SymbolDesc->sBottom,Pointer->oBottom);
1963 SymbolDesc->sRight = Max(SymbolDesc->sRight,Pointer->oRight);
1964 SymbolDesc->sTop = Max(SymbolDesc->sTop,Pointer->oTop);
1965 }
1966 for (Layer = 1;Layer <= CDNUMLAYERS;++Layer) {
1967 if (Not CDInitGen(SymbolDesc,Layer,-CDINFINITY,-CDINFINITY,
1968 CDINFINITY,CDINFINITY,&GenDesc))
1969 return (CDError(CDMALLOCFAILED));
1970 CDGen(SymbolDesc,GenDesc,&Pointer);
1971 if (Pointer == NULL)
1972 continue;
1973 loop {
1974 SymbolDesc->sLeft = Min(SymbolDesc->sLeft,Pointer->oLeft);
1975 SymbolDesc->sBottom = Min(SymbolDesc->sBottom,Pointer->oBottom);
1976 SymbolDesc->sRight = Max(SymbolDesc->sRight,Pointer->oRight);
1977 SymbolDesc->sTop = Max(SymbolDesc->sTop,Pointer->oTop);
1978 CDGen(SymbolDesc,GenDesc,&Pointer);
1979 if (Pointer == NULL)
1980 break;
1981 }
1982 }
1983 if (SymbolDesc->sLeft == CDINFINITY)
1984 SymbolDesc->sLeft = SymbolDesc->sBottom = SymbolDesc->sRight =
1985 SymbolDesc->sTop = 0;
1986 SymbolDesc->sBBValid = True;
1987 *Left = SymbolDesc->sLeft;
1988 *Bottom = SymbolDesc->sBottom;
1989 *Right = SymbolDesc->sRight;
1990 *Top = SymbolDesc->sTop;
1991
1992 #ifdef DEBUGGEN
1993 printf("CDBB3(%s,%d,%d,%d,%d)\n",SymbolDesc->sName,*Left,*Bottom,*Right,*Top);
1994 #endif
1995
1996 #ifdef DEBUGREFLECT
1997 printf("CDBB3(%s,%d,%d,%d,%d)\n",SymbolDesc->sName,*Left,*Bottom,*Right,*Top);
1998 #endif
1999
2000 return (True);
2001 }
2002
2003
2004 /*
2005 * Test code for CDIntersect.
2006 * main()
2007 * {
2008 * int Left,Bottom,Right,Top,BeginX,EndX,BeginY,EndY;
2009 *
2010 * printf("BB?");
2011 * scanf("%d%d%d%d",&Left,&Bottom,&Right,&Top);
2012 * CDIntersect(Left,Bottom,Right,Top,&BeginX,&EndX,&BeginY,&EndY);
2013 * printf("Bin[.][%d..%d][%d..%d]\n",BeginX,EndX,BeginY,EndY);
2014 * }
2015 */
2016
2017 void
2018 CDIntersect(Left,Bottom,Right,Top,BeginX,EndX,BeginY,EndY)
2019 long Left,Bottom,Right,Top;
2020 long *BeginX,*EndX,*BeginY,*EndY;
2021 {
2022 /*
2023 * Returns which bins overlap the AOI
2024 * The residual bin is always searched
2025 * Runs in constant time
2026 */
2027 #ifdef FLOAT
2028 *BeginX = (int)((float)(Left-CDBINMINX) * (float)(CDNUMBINS)/(float)(CDBINMAXX-CDBINMINX) + 1);
2029 if (*BeginX > CDNUMBINS)
2030 *BeginX = CDNUMBINS;
2031 elif (*BeginX < 1)
2032 *BeginX = 1;
2033 *EndX = (int)((float)(Right-CDBINMINX) * (float)(CDNUMBINS)/(float)(CDBINMAXX-CDBINMINX) + 1);
2034 if (*EndX > CDNUMBINS)
2035 *EndX = CDNUMBINS;
2036 elif (*EndX < 1)
2037 *EndX = 1;
2038 *BeginY = (int)((float)(Bottom-CDBINMINY) * (float)(CDNUMBINS)/(float)(CDBINMAXY-CDBINMINY) + 1);
2039 if (*BeginY > CDNUMBINS)
2040 *BeginY = CDNUMBINS;
2041 elif (*BeginY < 1)
2042 *BeginY = 1;
2043 *EndY = (int)((float)(Top-CDBINMINY) * (float)(CDNUMBINS)/(float)(CDBINMAXY-CDBINMINY) + 1);
2044 if (*EndY > CDNUMBINS)
2045 *EndY = CDNUMBINS;
2046 elif (*EndY < 1)
2047 *EndY = 1;
2048 #else
2049 *BeginX = ((Left-CDBINMINX) * (CDNUMBINS)/(CDBINMAXX-CDBINMINX) + 1);
2050 if (*BeginX > CDNUMBINS)
2051 *BeginX = CDNUMBINS;
2052 elif (*BeginX < 1)
2053 *BeginX = 1;
2054 *EndX = ((Right-CDBINMINX) * (CDNUMBINS)/(CDBINMAXX-CDBINMINX) + 1);
2055 if (*EndX > CDNUMBINS)
2056 *EndX = CDNUMBINS;
2057 elif (*EndX < 1)
2058 *EndX = 1;
2059 *BeginY = ((Bottom-CDBINMINY) * (CDNUMBINS)/(CDBINMAXY-CDBINMINY) + 1);
2060 if (*BeginY > CDNUMBINS)
2061 *BeginY = CDNUMBINS;
2062 elif (*BeginY < 1)
2063 *BeginY = 1;
2064 *EndY = ((Top-CDBINMINY) * (CDNUMBINS)/(CDBINMAXY-CDBINMINY) + 1);
2065 if (*EndY > CDNUMBINS)
2066 *EndY = CDNUMBINS;
2067 elif (*EndY < 1)
2068 *EndY = 1;
2069 #endif
2070 }
2071
2072
2073
2074
2075 /*======================================================================*
2076 * *
2077 * GGGG EEEEE N N EEEEE RRRR A TTTTT OOO RRRR SSSS *
2078 * G E NN N E R R A A T O O R R S *
2079 * G GGG EEE N N N EEE RRRR A A T O O RRRR SSS *
2080 * G G E N NN E R R AAAAA T O O R R S *
2081 * GGG EEEEE N N EEEEE R R A A T OOO R R SSSS *
2082 * *
2083 * *
2084 * *
2085 * CDInitGen(SymbolDesc,Layer,Left,Bottom,Right,Top,GenDesc) *
2086 * CDGen(SymbolDesc,GenDesc,Pointer) *
2087 * CDInitTGen(Pointer,TGen) *
2088 * CDTGen(TGen,Type,X,Y) *
2089 * *
2090 *======================================================================*/
2091
2092 int
2093 CDInitGen(SymbolDesc,Layer,Left,Bottom,Right,Top,GenDesc)
2094 struct s *SymbolDesc;
2095 int Layer;
2096 long Left,Bottom,Right,Top;
2097 struct g **GenDesc;
2098 {
2099 /*
2100 * Returns a pointer to a generator desc.
2101 * Layer == 0 denotes calls.
2102 */
2103 long BeginX,BeginY,EndX,EndY;
2104
2105 #ifdef DEBUGGEN
2106 printf("Begin initializing generator to search symbol %s.\n",SymbolDesc->sName);
2107 printf("Untransformed AOI is %ld %ld %ld %ld.\n",Left,Bottom,Right,Top);
2108 #endif
2109
2110 /*
2111 * Apply inverse of current transformation to AOI.
2112 */
2113 TInverse();
2114 TInversePoint(&Left,&Bottom);
2115 TInversePoint(&Right,&Top);
2116 if (Right < Left)
2117 SwapInts(Left,Right);
2118 if (Top < Bottom)
2119 SwapInts(Bottom,Top);
2120
2121 #ifdef DEBUGGEN
2122 printf("Transformed AOI is %ld %ld %ld %ld.\n",Left,Bottom,Right,Top);
2123 #endif
2124
2125 CDIntersect(Left,Bottom,Right,Top,&BeginX,&EndX,&BeginY,&EndY);
2126
2127 #ifdef DEBUGGEN
2128 printf("Initialized generator to search bins %ld..%ld,%ld..%ld on layer %d.\n",
2129 BeginX,EndX,BeginY,EndY,Layer);
2130 #endif
2131
2132 if ((*GenDesc = alloc(g)) == NULL)
2133 return (CDError(CDMALLOCFAILED));
2134 (*GenDesc)->gLeft = Left;
2135 (*GenDesc)->gBottom = Bottom;
2136 (*GenDesc)->gRight = Right;
2137 (*GenDesc)->gTop = Top;
2138 (*GenDesc)->gLayer = Layer;
2139 (*GenDesc)->gX = (*GenDesc)->gBeginX = BeginX;
2140 (*GenDesc)->gY = (*GenDesc)->gBeginY = EndY;
2141 (*GenDesc)->gEndX = EndX;
2142 (*GenDesc)->gEndY = BeginY;
2143 /*
2144 * CDGen will ALWAYS search the residual bin FIRST.
2145 * The vanilla bins will be searched in the order
2146 * for Y = EndY..BeginY
2147 * for X = BeginX..EndX
2148 * ...
2149 * so that redisplays will flow top down.
2150 */
2151 if (SymbolDesc->sBin[Layer] == NULL)
2152 (*GenDesc)->gPointer = NULL;
2153 else
2154 (*GenDesc)->gPointer = SymbolDesc->sBin[Layer][0][0];
2155
2156 #ifdef DEBUGGEN
2157 printf("End initializing generator to search symbol %s.\n",SymbolDesc->sName);
2158 #endif
2159
2160 return (True);
2161 }
2162
2163
2164 void
2165 CDGen(SymbolDesc,GenDesc,Pointer)
2166 struct s *SymbolDesc;
2167 struct g *GenDesc;
2168 struct o **Pointer;
2169 {
2170 /*
2171 * Returns pointer to next object.
2172 * You should invoke CDType to access object's type and dispatch off
2173 * of type. See traversal code in CDUpdate. Pointer == NULL if last
2174 * object at which time GenDesc is freed.
2175 */
2176 int i;
2177 long L,B,R,T;
2178
2179 loop {
2180 if (GenDesc->gPointer != NULL) {
2181 /*
2182 * gPointer points to an object desc. Is it in the AOI?
2183 * This test is necessary, because of the granularity of the bins.
2184 * Suppose AOI lies entirely within one bin.
2185 * Then there may, in general, be descs in the bin whose BBs lie
2186 * outside the AOI.
2187 */
2188
2189 /* callback to user supplied routine */
2190 if (GenDesc->gPointer->oType == CDLABEL)
2191 CDLabelBB(GenDesc->gPointer,&L,&B,&R,&T);
2192 else {
2193 L = GenDesc->gPointer->oLeft;
2194 B = GenDesc->gPointer->oBottom;
2195 R = GenDesc->gPointer->oRight;
2196 T = GenDesc->gPointer->oTop;
2197 }
2198
2199 #ifdef DEBUGGEN
2200 printf("Generator intersecting %ld %ld %ld %ld to AOI.\n",L,B,R,T);
2201 #endif
2202
2203 if (L > GenDesc->gRight Or B > GenDesc->gTop Or
2204 R < GenDesc->gLeft Or T < GenDesc->gBottom) {
2205 /*
2206 * Object isn't visible, so consider the next one, if any, in
2207 * the bin currently being searched.
2208 */
2209 GenDesc->gPointer = GenDesc->gPointer->oSucc;
2210
2211 #ifdef DEBUGGEN
2212 printf("Invisible.\n");
2213 #endif
2214
2215 }
2216 else {
2217
2218 #ifdef DEBUGGEN
2219 printf("Visible.\n");
2220 #endif
2221
2222 /*
2223 * Object is visible, so return object desc.
2224 */
2225 *Pointer = GenDesc->gPointer;
2226 GenDesc->gPointer = GenDesc->gPointer->oSucc;
2227 return;
2228 }
2229 }
2230 else {
2231 if (GenDesc->gY < GenDesc->gEndY) {
2232 /* The generator is done */
2233 tfree(GenDesc);
2234 *Pointer = NULL;
2235 return;
2236 }
2237 /*
2238 * Consider first object in next bin.
2239 * If the bin is empty, we will pass through the loop again.
2240 */
2241 i = GenDesc->gLayer;
2242 if (SymbolDesc->sBin[i] == NULL) {
2243 /* The generator is done */
2244 tfree(GenDesc);
2245 *Pointer = NULL;
2246 return;
2247 }
2248 GenDesc->gPointer = SymbolDesc->sBin[i][GenDesc->gX][GenDesc->gY];
2249 ++(GenDesc->gX);
2250 if (GenDesc->gX > GenDesc->gEndX) {
2251 GenDesc->gX = GenDesc->gBeginX;
2252 --(GenDesc->gY);
2253 }
2254 }
2255 }
2256 }
2257
2258
2259 void
2260 CDInitTGen(Pointer,TGen)
2261 struct o *Pointer;
2262 struct t **TGen;
2263 {
2264 struct c *CallDesc;
2265
2266 if (Pointer == NULL)
2267 return;
2268 if (Pointer->oType != CDSYMBOLCALL)
2269 return;
2270 CallDesc = (struct c *)Pointer->oRep;
2271 *TGen = CallDesc->cT;
2272 }
2273
2274
2275 void
2276 CDTGen(TGen,Type,X,Y)
2277 struct t **TGen;
2278 char *Type;
2279 long *X,*Y;
2280 {
2281 static FirstDesc = True;
2282
2283 if (*TGen == NULL)
2284 return;
2285 elif (FirstDesc) {
2286 FirstDesc = False;
2287 *X = (*TGen)->tX;
2288 *Y = (*TGen)->tY;
2289 *Type = (*TGen)->tType;
2290 }
2291 else {
2292 *TGen = (*TGen)->tSucc;
2293 if (*TGen == NULL) {
2294 FirstDesc = True;
2295 return;
2296 }
2297 *X = (*TGen)->tX;
2298 *Y = (*TGen)->tY;
2299 *Type = (*TGen)->tType;
2300 }
2301 }
2302
2303
2304
2305
2306 /*======================================================================*
2307 * *
2308 * CCCC III FFFFF *
2309 * C I F *
2310 * C I FFFF *
2311 * C I F *
2312 * CCCC III F *
2313 * *
2314 * TTTTT RRRR A N N SSSS L A TTTTT III OOO N N *
2315 * T R R A A NN N S L A A T I O O NN N *
2316 * T RRRR A A N N N SSS L A A T I O O N N N *
2317 * T R R AAAAA N NN S L AAAAA T I O O N NN *
2318 * T R R A A N N SSSS LLLLL A A T III OOO N N *
2319 * *
2320 * *
2321 * *
2322 * CDUpdate(SymbolDesc,SymbolFile) *
2323 * CDGenCIF(FileDesc,SymbolDesc,SymbolNum,A,B) *
2324 * CDTo(CIFFile,Root,A,B,Program) *
2325 * CDFrom(Root,CIFFile,A,B,Layers,NumLayers,Program) *
2326 * CDUnmark(SymbolDesc) *
2327 * *
2328 *======================================================================*/
2329
2330 int
2331 CDUpdate(SymbolDesc,SymbolFile)
2332 struct s *SymbolDesc;
2333 char *SymbolFile;
2334 {
2335 /*
2336 * Update symbol to symbol file.
2337 * If SymbolFile == NULL, update to file SymbolDesc->sName.
2338 * Returns True if success, else returns False.
2339 */
2340 FILE *FileDesc;
2341 struct g *GenDesc;
2342 struct o *Pointer;
2343 struct t *TGen;
2344 struct p *Path;
2345 struct prpty *PrptyDesc;
2346 char *Label;
2347 char *SymbolName;
2348 int Layer;
2349 long X,Y,Length,Width;
2350 int NumX,NumY;
2351 long DX,DY;
2352 char Type,Xform;
2353
2354 if (SymbolFile == NULL) {
2355 if ((FileDesc = POpen(SymbolDesc->sName,"w",(char **)NULL))
2356 == NULL) return (False);
2357 fprintf(FileDesc,"(Symbol %s);\n",SymbolDesc->sName);
2358 }
2359 else {
2360 char *s;
2361 int i;
2362
2363 if ((FileDesc = POpen(SymbolFile,"w",(char **)NULL))
2364 == NULL) return (False);
2365 /* SRW strip off path prefix */
2366 s = strrchr(SymbolFile,DIR_TERM);
2367 if (s) {
2368 *s = 0;
2369 for (i = 0, s++; *s; i++, s++)
2370 SymbolFile[i] = *s;
2371 SymbolFile[i] = '\0';
2372 }
2373 fprintf(FileDesc,"(Symbol %s);\n",SymbolFile);
2374 }
2375 fprintf(FileDesc,"9 %s;\n",SymbolDesc->sName);
2376
2377 /* add property list info */
2378 CDProperty(SymbolDesc,(struct o *)NULL,&PrptyDesc);
2379 CDPrptyListPrint(FileDesc,PrptyDesc);
2380
2381 GenBeginSymbol(FileDesc,0,1L,1L);
2382 SymbolDesc->sLeft = SymbolDesc->sBottom = CDINFINITY;
2383 SymbolDesc->sRight = SymbolDesc->sTop = -CDINFINITY;
2384 if (Not CDInitGen(SymbolDesc,0,-CDINFINITY,-CDINFINITY,CDINFINITY,
2385 CDINFINITY,&GenDesc)) return (CDError(CDMALLOCFAILED));
2386 loop {
2387 CDGen(SymbolDesc,GenDesc,&Pointer);
2388 if (Pointer == NULL)
2389 break;
2390 CDCall(Pointer,&SymbolName,&NumX,&DX,&NumY,&DY);
2391 /* add symbol name extension */
2392 fprintf(FileDesc,"9 %s;\n",SymbolName);
2393
2394 /* add property list info */
2395 CDProperty(SymbolDesc,Pointer,&PrptyDesc);
2396 CDPrptyListPrint(FileDesc,PrptyDesc);
2397
2398 /* add symbol array extension */
2399 if (NumX != 1 Or NumY != 1)
2400 fprintf(FileDesc,"1 Array %d %ld %d %ld;\n",NumX,DX,NumY,DY);
2401 fprintf(FileDesc,"C 0");
2402 CDInitTGen(Pointer,&TGen);
2403 loop {
2404 CDTGen(&TGen,&Type,&X,&Y);
2405 if (TGen == NULL) {
2406 fprintf(FileDesc,";\n");
2407 break;
2408 }
2409 elif (Type == CDROTATE)
2410 fprintf(FileDesc," R %ld %ld",X,Y);
2411 elif (Type == CDTRANSLATE)
2412 fprintf(FileDesc," T %ld %ld",X,Y);
2413 elif (Type == CDMIRRORX)
2414 fprintf(FileDesc," MX");
2415 elif (Type == CDMIRRORY)
2416 fprintf(FileDesc," MY");
2417 }
2418 SymbolDesc->sLeft = Min(SymbolDesc->sLeft,Pointer->oLeft);
2419 SymbolDesc->sBottom = Min(SymbolDesc->sBottom,Pointer->oBottom);
2420 SymbolDesc->sRight = Max(SymbolDesc->sRight,Pointer->oRight);
2421 SymbolDesc->sTop = Max(SymbolDesc->sTop,Pointer->oTop);
2422 }
2423 for (Layer = 1;Layer <= CDNUMLAYERS;++Layer) {
2424 if (Not CDInitGen(SymbolDesc,Layer,-CDINFINITY,-CDINFINITY,
2425 CDINFINITY,CDINFINITY,&GenDesc))
2426 return (CDError(CDMALLOCFAILED));
2427 CDGen(SymbolDesc,GenDesc,&Pointer);
2428 if (Pointer == NULL)
2429 continue;
2430 GenLayer(FileDesc,CDLayer[Layer].lTechnology,CDLayer[Layer].lMask);
2431 loop{
2432 CDProperty(SymbolDesc,Pointer,&PrptyDesc);
2433 CDPrptyListPrint(FileDesc,PrptyDesc);
2434
2435 CDType(Pointer,&Type);
2436 if (Type == CDWIRE) {
2437 CDWire(Pointer,&Layer,&Width,&Path);
2438 GenWire(FileDesc,Width,Path);
2439 }
2440 elif (Type == CDPOLYGON) {
2441 CDPolygon(Pointer,&Layer,&Path);
2442 GenPolygon(FileDesc,Path);
2443 }
2444 elif (Type == CDLABEL) {
2445 CDLabel(Pointer,&Layer,&Label,&X,&Y,&Xform);
2446 fprintf(FileDesc,"94 %s %ld %ld %d",Label,X,Y,Xform);
2447 fprintf(FileDesc,";\n");
2448 }
2449 elif (Type == CDBOX) {
2450 CDBox(Pointer,&Layer,&Length,&Width,&X,&Y);
2451 GenBox(FileDesc,Length,Width,X,Y,1,0);
2452 }
2453 SymbolDesc->sLeft = Min(SymbolDesc->sLeft,Pointer->oLeft);
2454 SymbolDesc->sBottom = Min(SymbolDesc->sBottom,Pointer->oBottom);
2455 SymbolDesc->sRight = Max(SymbolDesc->sRight,Pointer->oRight);
2456 SymbolDesc->sTop = Max(SymbolDesc->sTop,Pointer->oTop);
2457 CDGen(SymbolDesc,GenDesc,&Pointer);
2458 if (Pointer == NULL)
2459 break;
2460 }
2461 }
2462 if (SymbolDesc->sLeft == CDINFINITY)
2463 SymbolDesc->sLeft = SymbolDesc->sBottom = SymbolDesc->sRight =
2464 SymbolDesc->sTop = 0;
2465 GenEndSymbol(FileDesc);
2466 GenEnd(FileDesc);
2467 fclose(FileDesc);
2468 CDDesc.dSymbolDesc->sBBValid = True;
2469 return (True);
2470 }
2471
2472
2473 int
2474 CDGenCIF(FileDesc,SymbolDesc,SymbolNum,A,B,Program)
2475 FILE *FileDesc;
2476 struct s *SymbolDesc;
2477 int *SymbolNum;
2478 long A,B;
2479 char Program;
2480 {
2481 struct g *GenDesc;
2482 struct o *Pointer;
2483 struct s *MasterDesc;
2484 struct p *Pair,*Path;
2485 struct t *TGen;
2486 struct prpty *PrptyDesc;
2487 char *SymbolName;
2488 char *Label;
2489 int Layer;
2490 long X,Y,Length,Width;
2491 int NumX,NumY;
2492 long DX,DY;
2493 int Info;
2494 int i,j,FirstT;
2495 long Left,Bottom,Right,Top;
2496 int OutputLayer;
2497 char Type,Xform;
2498
2499 *SymbolNum += 1;
2500 /*
2501 * Mark symbol associated withSymbolDesc as visited by storing
2502 * its symbol # in its info field. VERY NICE.
2503 */
2504 CDSetInfo(SymbolDesc,(struct o *)NULL,*SymbolNum);
2505
2506 /*
2507 * First write to the CIF file any symbol definitions below
2508 * the symbol associated with SymbolDesc.
2509 */
2510 if (Not CDInitGen(SymbolDesc,0,-CDINFINITY,-CDINFINITY,CDINFINITY,
2511 CDINFINITY,&GenDesc)) return (CDError(CDMALLOCFAILED));
2512 loop {
2513 CDGen(SymbolDesc,GenDesc,&Pointer);
2514 if (Pointer == NULL)
2515 break;
2516 CDCall(Pointer,&SymbolName,&NumX,&DX,&NumY,&DY);
2517 if (Not CDOpen(SymbolName,&MasterDesc,'w'))
2518 return (False);
2519 CDInfo(MasterDesc,(struct o *)NULL,&Info);
2520 if (Info == 0)
2521 /* Write master's definition to CIF file. */
2522 if (Not CDGenCIF(FileDesc,MasterDesc,SymbolNum,A,B,Program))
2523 return (False);
2524 }
2525
2526 /*
2527 * Write to the CIF file the definition of the symbol associated with
2528 * SymbolDesc. Instance calls first--then geometries.
2529 */
2530 if (Program == 'e') {
2531 CDProperty(SymbolDesc,(struct o *)NULL,&PrptyDesc);
2532 CDPrptyListPrint(FileDesc,PrptyDesc);
2533 }
2534 CDInfo(SymbolDesc,(struct o *)NULL,&Info);
2535 fprintf(FileDesc,"DS %d 1 1;\n",Info);
2536 /* write symbol rename extension */
2537 if (Program == 'b' Or Program == 'a') /* NCA/Stanford CIF */
2538 fprintf(FileDesc,"( %s );\n",SymbolDesc->sName);
2539 elif (Program == 'i') /* Icarus style CIF */
2540 fprintf(FileDesc,"( 9 %s );\n",SymbolDesc->sName);
2541 elif (Program == 's') /* SIF style CIF */
2542 fprintf(FileDesc,"( Name: %s );\n",SymbolDesc->sName);
2543 else /* KIC/CD default */
2544 fprintf(FileDesc,"9 %s;\n",SymbolDesc->sName);
2545 if (Not CDInitGen(SymbolDesc,0,-CDINFINITY,-CDINFINITY,CDINFINITY,
2546 CDINFINITY,&GenDesc)) return (CDError(CDMALLOCFAILED));
2547 loop {
2548 CDGen(SymbolDesc,GenDesc,&Pointer);
2549 if (Pointer == NULL)
2550 break;
2551 CDCall(Pointer,&SymbolName,&NumX,&DX,&NumY,&DY);
2552 if (Not CDOpen(SymbolName,&MasterDesc,'w'))
2553 return (False);
2554 CDInfo(MasterDesc,(struct o *)NULL,&Info);
2555 if (Not CDBB(MasterDesc,(struct o *)NULL,&Left,&Bottom,&Right,&Top))
2556 return (False);
2557 for (i = 1;i <= NumY;++i) {
2558 for (j = 1;j <= NumX;++j) {
2559 /* write property list extension */
2560 if (Program == 'e') {
2561 CDProperty(SymbolDesc,Pointer,&PrptyDesc);
2562 CDPrptyListPrint(FileDesc,PrptyDesc);
2563 }
2564 fprintf(FileDesc,"C %d",Info);
2565 FirstT = True;
2566 CDInitTGen(Pointer,&TGen);
2567 loop {
2568 CDTGen(&TGen,&Type,&X,&Y);
2569 if (TGen == NULL) {
2570 fprintf(FileDesc,";\n");
2571 break;
2572 }
2573 elif (Type == CDROTATE)
2574 fprintf(FileDesc," R %ld %ld",X,Y);
2575 elif (Type == CDTRANSLATE And FirstT) {
2576 fprintf(FileDesc," T %ld %ld",
2577 (X+(j-1)*DX)*A/B,(Y+(i-1)*DY)*A/B);
2578 FirstT = False;
2579 }
2580 elif (Type == CDTRANSLATE)
2581 fprintf(FileDesc," T %ld %ld",X*A/B,Y*A/B);
2582 elif (Type == CDMIRRORX)
2583 fprintf(FileDesc," MX");
2584 elif (Type == CDMIRRORY)
2585 fprintf(FileDesc," MY");
2586 }
2587 }
2588 }
2589 }
2590 for (Layer = 1;Layer <= CDNUMLAYERS;++Layer) {
2591 if (CDLayer[Layer-1].lCDFrom) {
2592 if (Program == 'b') /* NCA style CIF */
2593 fprintf(FileDesc,"L %d;\n",Layer);
2594 else
2595 GenLayer(FileDesc,CDLayer[Layer].lTechnology,
2596 CDLayer[Layer].lMask);
2597 OutputLayer = True;
2598 }
2599 else
2600 OutputLayer = False;
2601 if (Not CDInitGen(SymbolDesc,Layer,-CDINFINITY,-CDINFINITY,
2602 CDINFINITY,CDINFINITY,&GenDesc))
2603 return (CDError(CDMALLOCFAILED));
2604 loop {
2605 CDGen(SymbolDesc,GenDesc,&Pointer);
2606 if (Pointer == NULL)
2607 break;
2608 /* write property list extension */
2609 if (Program == 'e') {
2610 CDProperty(SymbolDesc,Pointer,&PrptyDesc);
2611 CDPrptyListPrint(FileDesc,PrptyDesc);
2612 }
2613 CDType(Pointer,&Type);
2614 if (!OutputLayer && Type != CDLABEL) {
2615 /* output all labels */
2616 }
2617 elif (Type == CDBOX) {
2618 CDBox(Pointer,&Layer,&Length,&Width,&X,&Y);
2619 GenBox(FileDesc,Length*A/B,Width*A/B,X*A/B,Y*A/B,1,0);
2620 }
2621 elif (Type == CDWIRE) {
2622 CDWire(Pointer,&Layer,&Width,&Path);
2623 if (Path->pSucc == NULL)
2624 fprintf(FileDesc,"W %d %d %d",Width*A/B,
2625 Path->pX*A/B,Path->pY*A/B);
2626 else {
2627 fprintf(FileDesc,"W %d",Width*A/B);
2628 Pair = Path;
2629 while (Pair != NULL) {
2630 fprintf(FileDesc," %ld %ld",Pair->pX*A/B,Pair->pY*A/B);
2631 Pair = Pair->pSucc;
2632 }
2633 }
2634 fprintf(FileDesc,";\n");
2635 }
2636 elif (Type == CDPOLYGON) {
2637 CDPolygon(Pointer,&Layer,&Path);
2638 fprintf(FileDesc,"P");
2639 Pair = Path;
2640 while (Pair != NULL) {
2641 fprintf(FileDesc," %ld %ld",Pair->pX*A/B,Pair->pY*A/B);
2642 Pair = Pair->pSucc;
2643 }
2644 fprintf(FileDesc,";\n");
2645 }
2646 elif (Type == CDLABEL) {
2647 CDLabel(Pointer,&Layer,&Label,&X,&Y,&Xform);
2648 if (Program == 'k' Or Program == 'e') /* KIC/CD label */
2649 fprintf(FileDesc,"94 %s %ld %ld %d;\n",
2650 Label,X*A/B,Y*A/B,(char)Xform);
2651 elif (Program == 'b') /* NCA label */
2652 fprintf(FileDesc,"94 %s %ld %ld %d;\n",
2653 Label,X*A/B,Y*A/B,Layer);
2654 elif (Program == 'm') { /* mextra label */
2655 fprintf(FileDesc,"94 %s %ld %ld",Label,X*A/B,Y*A/B);
2656 if (CDLayer[Layer].lTechnology != ' ') {
2657 fprintf(FileDesc," %c",CDLayer[Layer].lTechnology);
2658 i = 0;
2659 while (i < 3 And CDLayer[Layer].lMask[i] > 040) {
2660 fprintf(FileDesc,"%c",CDLayer[Layer].lMask[i]);
2661 i++;
2662 }
2663 }
2664 fprintf(FileDesc,";\n");
2665 }
2666 }
2667 }
2668 }
2669 GenEndSymbol(FileDesc);
2670 return (True);
2671 }
2672
2673
2674 int
2675 CDTo(CIFFile,Root,A,B,Program)
2676 char *CIFFile,*Root;
2677 long A,B;
2678 char Program;
2679 {
2680 /*
2681 * Translate from CIF file into symbol files.
2682 * Each time we see a symbol definition, we write it in its own file.
2683 * The problem is that commands may be in the file that aren't part of a
2684 * symbol definition. The solution is to have a file named Root for
2685 * the commands.
2686 */
2687 int Int1;
2688 int StatusInt;
2689 char *StatusString;
2690 CDDesc.dControl = DCONTROLCDTO;
2691
2692 /*
2693 * On the first pass, we just fill the symbol name table.
2694 */
2695 CDDesc.dFirstPass = True;
2696 CDDesc.dNumSymbolTable = 0;
2697 if ((CDDesc.dProgram = Program) != 'n') {
2698 for (Int1 = 0;Int1 < CDNUMREMEMBER;++Int1) {
2699 CDDesc.dSymTabNames[Int1][0] = EOS;
2700 CDDesc.dSymTabNumbers[Int1] = -1;
2701 }
2702 PCIF(CIFFile,&StatusString,&StatusInt);
2703 if (StatusInt == PFAILED) {
2704 CDStatusInt = CDPARSEFAILED;
2705 strcpy(CDStatusString,StatusString);
2706 return (False);
2707 }
2708 }
2709 /*
2710 * On the second pass, we do the sequential translation.
2711 */
2712 CDDesc.dFirstPass = False;
2713 CDDesc.dPrptyList = NULL;
2714 CDDesc.dA = A;
2715 CDDesc.dB = B;
2716 CDDesc.dDSA = CDDesc.dDSB = 1;
2717 CDDesc.dRoot = True;
2718 if ((CDDesc.dRootFileDesc = POpen(Root,"w",(char **)NULL))
2719 == NULL) {
2720 sprintf(CDStatusString,"Can't open file Root.");
2721 CDStatusInt = CDPARSEFAILED;
2722 return (False);
2723 }
2724 fprintf(CDDesc.dRootFileDesc,"(Symbol %s.);\n",Root);
2725 fprintf(CDDesc.dRootFileDesc,"(Microns/lambda = %d/%d);\n",A,B);
2726 fprintf(CDDesc.dRootFileDesc,"9 %s;\n",Root);
2727 GenBeginSymbol(CDDesc.dRootFileDesc,0,1,1);
2728 PCIF(CIFFile,&StatusString,&StatusInt);
2729 if (StatusInt == PFAILED) {
2730 CDStatusInt = CDPARSEFAILED;
2731 strcpy(CDStatusString,StatusString);
2732 return (False);
2733 }
2734 else
2735 CDStatusInt = CDSUCCEEDED;
2736 GenEndSymbol(CDDesc.dRootFileDesc);
2737 GenEnd(CDDesc.dRootFileDesc);
2738 fclose(CDDesc.dRootFileDesc);
2739 CDDesc.dControl = DCONTROLVANILLA;
2740 return (True);
2741 }
2742
2743
2744 int
2745 CDFrom(Root,CIFFile,A,B,Layers,NumLayers,Program)
2746 char *Root,*CIFFile,Program;
2747 long A,B;
2748 int Layers[],NumLayers;
2749 {
2750 /*
2751 * Translate symbol hierarchy rooted with symbol named Root into
2752 * CIF file named CIFFile.
2753 */
2754 struct s *SymbolDesc;
2755 FILE *FileDesc;
2756 int SymbolNum = 0;
2757 int Info;
2758 int Layer;
2759
2760 for (Layer = 0;Layer < NumLayers;++Layer)
2761 if (Layers[Layer])
2762 CDLayer[Layer].lCDFrom = True;
2763 else
2764 CDLayer[Layer].lCDFrom = False;
2765 if ((FileDesc = POpen(CIFFile,"w",(char **)NULL)) == NULL) {
2766 CDStatusInt = CDPARSEFAILED;
2767 sprintf(CDStatusString,"Can't open CIF file.");
2768 return (False);
2769 }
2770 if (Not CDOpen(Root,&SymbolDesc,'r')) {
2771 CDStatusInt = CDPARSEFAILED;
2772 return (False);
2773 }
2774 if (CDStatusInt == CDNEWSYMBOL) {
2775 sprintf(CDStatusString,"Can't open file %s.",Root);
2776 return (False);
2777 }
2778 fprintf(FileDesc,"(CIF file of symbol hierarchy rooted at %s);\n",Root);
2779 if (Not CDGenCIF(FileDesc,SymbolDesc,&SymbolNum,A,B,Program))
2780 return (False);
2781 CDInfo(SymbolDesc,(struct o *)NULL,&Info);
2782 fprintf(FileDesc,"C %d;\nE\n",Info);
2783 fclose(FileDesc);
2784 /*
2785 * Really should set all of the info fields in all symbol descs to 0.
2786 * CDUnmark(SymbolDesc);
2787 */
2788 return (True);
2789 }
2790
2791
2792 int
2793 CDParseCIF(Root,CIFFile,Program)
2794 char *Root,*CIFFile,Program;
2795 {
2796 /*
2797 * Construct CD database from a CIF file rather than a hierarchy
2798 * of cell files.
2799 */
2800 struct m *MasterListDesc1;
2801 struct m *MasterListDesc2;
2802 struct s *MasterSymbolDesc1;
2803 struct s *MasterSymbolDesc2;
2804 char *StatusString;
2805 int StatusInt;
2806 int Int1;
2807
2808 CDDesc.dProgram = Program;
2809 CDDesc.dA = CDDesc.dB = 1;
2810 CDDesc.dDSA = CDDesc.dDSB = 1;
2811 CDDesc.dRoot = True;
2812 CDDesc.dControl = DCONTROLPCIF;
2813 CDDesc.dSymbolDesc = CDDesc.dRootCellDesc;
2814 if (Not CDOpen(Root,&CDDesc.dRootCellDesc,'n')) {
2815 CDStatusInt = CDMALLOCFAILED;
2816 return (False);
2817 }
2818 CDDesc.dControl = DCONTROLPCIF;
2819
2820 /*
2821 * On the first pass, we just fill the symbol name table.
2822 */
2823 CDDesc.dFirstPass = True;
2824 CDDesc.dNumSymbolTable = 0;
2825 for (Int1 = 0;Int1 < CDNUMREMEMBER;++Int1) {
2826 CDDesc.dSymTabNames[Int1][0] = EOS;
2827 CDDesc.dSymTabNumbers[Int1] = -1;
2828 }
2829 PCIF(CIFFile,&StatusString,&StatusInt);
2830 if (StatusInt == PFAILED) {
2831 CDStatusInt = CDPARSEFAILED;
2832 strcpy(CDStatusString,StatusString);
2833 return (False);
2834 }
2835
2836 /*
2837 * On the second pass, we do the sequential translation.
2838 */
2839 CDDesc.dFirstPass = False;
2840 PCIF(CIFFile,&StatusString,&StatusInt);
2841 if (StatusInt == PFAILED) {
2842 CDStatusInt = CDPARSEFAILED;
2843 strcpy(CDStatusString,StatusString);
2844 return (False);
2845 }
2846 MasterListDesc1 = CDDesc.dRootCellDesc->sMasterList;
2847 while (MasterListDesc1 != NULL) {
2848 CDOpen(MasterListDesc1->mName,&MasterSymbolDesc1,'r');
2849 if (CDStatusInt == CDNEWSYMBOL Or CDStatusInt == CDPARSEFAILED) {
2850 if (CDStatusInt == CDNEWSYMBOL) {
2851 CDStatusInt = CDPARSEFAILED;
2852 sprintf(CDStatusString,"Master %s doesn't seem to be around.\n",
2853 MasterListDesc1->mName);
2854 }
2855 return (False);
2856 }
2857 MasterListDesc2 = MasterSymbolDesc1->sMasterList;
2858 while (MasterListDesc2 != NULL) {
2859 CDOpen(MasterListDesc2->mName,&MasterSymbolDesc2,'r');
2860 if (CDStatusInt == CDNEWSYMBOL Or CDStatusInt == CDPARSEFAILED) {
2861 if (CDStatusInt == CDNEWSYMBOL) {
2862 CDStatusInt = CDPARSEFAILED;
2863 sprintf(CDStatusString,
2864 "Master %s doesn't seem to be around.\n",
2865 MasterListDesc2->mName);
2866 }
2867 return (False);
2868 }
2869 if (Not CDReflect(MasterSymbolDesc2)) {
2870 CDStatusInt = CDPARSEFAILED;
2871 return (CDError(CDMALLOCFAILED));
2872 }
2873 MasterListDesc2 = MasterListDesc2->mSucc;
2874 }
2875 if (Not CDReflect(MasterSymbolDesc1)) {
2876 CDStatusInt = CDPARSEFAILED;
2877 return (CDError(CDMALLOCFAILED));
2878 }
2879 MasterListDesc1 = MasterListDesc1->mSucc;
2880 }
2881 if (Not CDReflect(CDDesc.dRootCellDesc)) {
2882 CDStatusInt = CDPARSEFAILED;
2883 return (CDError(CDMALLOCFAILED));
2884 }
2885 return (True);
2886 }
2887
2888
2889 int
2890 CDUnmark(SymbolDesc)
2891 struct s *SymbolDesc;
2892 {
2893 struct g *GenDesc;
2894 struct o *Pointer;
2895 char *SymbolName;
2896 int NumX,NumY;
2897 long DX,DY;
2898 int Info;
2899 int Layer;
2900 struct s *MasterDesc;
2901
2902 if (Not CDInitGen(SymbolDesc,0,-CDINFINITY,-CDINFINITY,CDINFINITY,
2903 CDINFINITY,&GenDesc)) return (CDError(CDMALLOCFAILED));
2904 #ifdef DEBUG_CDUNMARK
2905 fprintf(stderr,"\n\n");
2906 fprintf(stderr,"1CDUnmark: Inititialezed generator on instance layer.\n\n");
2907 #endif
2908 loop {
2909 CDGen(SymbolDesc,GenDesc,&Pointer);
2910 if (Pointer == NULL)
2911 break;
2912
2913 #ifdef DEBUG_CDUNMARK
2914 fprintf(stderr,"2CDUnmark: CDGen found instance: Pointer = 0x%x\n\n",Pointer);
2915 #endif
2916
2917 CDCall(Pointer,&SymbolName,&NumX,&DX,&NumY,&DY);
2918
2919 #ifdef DEBUG_CDUNMARK
2920 fprintf(stderr,"3CDUnmark: instance name = %s\n\n",SymbolName);
2921 #endif
2922
2923 /*
2924 * Cell has already been mapped into memory. Therefore,
2925 * we can assume that CDOpen does not fail in the parse.
2926 */
2927 if (Not CDOpen(SymbolName,&MasterDesc,'r'))
2928 return (CDError(CDMALLOCFAILED));
2929
2930 #ifdef DEBUG_CDUNMARK
2931 fprintf(stderr,"4CDUnmark: CDOpen returned MasterDesc = 0x%x\n\n",MasterDesc);
2932 #endif
2933
2934 CDInfo(MasterDesc,(struct o *)NULL,&Info);
2935 if (Info != 0) {
2936 /* Unmark master */
2937 CDSetInfo(MasterDesc,(struct o *)NULL,0);
2938 if (Not CDUnmark(MasterDesc))
2939 return (False);
2940 }
2941 }
2942 for (Layer = 1; Layer <= CDNUMLAYERS; ++Layer) {
2943 if (Not CDInitGen(SymbolDesc,Layer,-CDINFINITY,-CDINFINITY,
2944 CDINFINITY,CDINFINITY,&GenDesc))
2945 return (CDError(CDMALLOCFAILED));
2946
2947 #ifdef DEBUG_CDUNMARK
2948 fprintf(stderr,"5CDUnmark: Inititialezed generator on layer %d.\n\n",Layer);
2949 #endif
2950
2951 loop{
2952 CDGen(SymbolDesc,GenDesc,&Pointer);
2953 if (Pointer == NULL)
2954 break;
2955
2956 #ifdef DEBUG_CDUNMARK
2957 fprintf(stderr,"6CDUnmark: CDGen found instance: Pointer = 0x%x\n\n",Pointer);
2958 #endif
2959
2960 CDInfo(SymbolDesc,(struct o *)NULL,&Info);
2961 if (Info != 0) {
2962 /* Unmark geometry */
2963 CDSetInfo(SymbolDesc,Pointer,0);
2964 }
2965 }
2966 }
2967 return (True);
2968 }
2969
2970
2971
2972 /*======================================================================*
2973 * *
2974 * EEEEE RRRR RRRR OOO RRRR *
2975 * E R R R R O O R R *
2976 * EEE RRRR RRRR O O RRRR *
2977 * E R R R R O O R R *
2978 * EEEEE R R R R OOO R R *
2979 * *
2980 * RRRR OOO U U TTTTT III N N EEEEE SSSS *
2981 * R R O O U U T I NN N E S *
2982 * RRRR O O U U T I N N N EEE SSS *
2983 * R R O O U U T I N NN E S *
2984 * R R OOO UUU T III N N EEEEE SSSS *
2985 * *
2986 * *
2987 * *
2988 * CDError(ID) *
2989 * *
2990 *======================================================================*/
2991
2992 int
2993 CDError(ID)
2994 int ID;
2995 {
2996 CDStatusInt = ID;
2997 switch(ID) {
2998
2999 case CDMALLOCFAILED:
3000 sprintf(CDStatusString,"CD Out of memory.");
3001 return (False);
3002
3003 case CDBADBOX:
3004 sprintf(CDStatusString,"Can't allow a zero width box.");
3005 /* not a fatal error */
3006 return (True);
3007
3008 case CDXFORMSTACKFULL:
3009 sprintf(CDStatusString,"Transform stack is full.");
3010 return (False);
3011
3012 case CDBADPATH:
3013 sprintf(CDStatusString,"Can't set search path.");
3014 return (False);
3015
3016 default:
3017 sprintf(CDStatusString,"Unknown Error.");
3018 return (False);
3019
3020 }
3021 }
3022
3023