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