#include #include "defs.h" #include "types.h" #include "exports.h" #define MAXCELLS 512 #define INFINITY ((Real) 2147483647) /* 2^31-1 */ #define NO_LAYER -1 #define SKIP_LAYER -2 private Cell cellTable[ MAXCELLS ]; private int cellSize; private Cell currCell; private Real currScale; private int currLayer; private Rect *currRects; private int currIndex; private Cell rootCell; public Call root; /* root of the call tree */ /* * Initialize or reset a cell */ public void ResetCell( c ) Cell c; { c->bBox.maxC.x = -INFINITY; c->bBox.maxC.y = -INFINITY; c->bBox.minC.x = INFINITY; c->bBox.minC.y = INFINITY; c->bigBox = c->bBox; c->name = NULL; c->calls = NULL; c->labels = NULL; c->inst = FALSE; { register int n; register LayerRects *r; for( n = nLayer, r = c->layers; n ; r++, n-- ) { r->rects = NULL; r->nRects = 0; } } } /* * Recursive undefinition routine */ public void UnDefCell( num ) int num; { register Cell c; int t; if (currCell != rootCell) LexError("Delete command inside of symbol"); for (t = 0; t < MAXCELLS; t++) { c = cellTable[ t ]; while( c ) { if( c->num >= num ) { /* effective deletion by redefinition */ if( c->inst == TRUE) c->num = -1; else ResetCell( c ); } c = c->next; } } } /* * Look for cell 'num' in the hash-table. If cell is not found, * create a new record for the cell. */ public Cell GetCell( num, def ) int num, def; { register Cell c; register int n; int t; n = num; t = n % MAXCELLS; c = cellTable[ t ]; while( c ) { if( c->num == n ) { if ((def == TRUE) && !((c->bBox.maxC.x < c->bBox.minC.x) && (c->calls == NULL))) { LexError( "Cell redefined without deletion", 0 ); UnDefCell( n ); } return( c ); } c = c->next; } if ((def == TRUE) || (currCell != rootCell)) { if(( (c = (Cell) Malloc( cellSize )) == NULL ) || (t == MAXCELLS)) Crash( "Out of memory for cells", 2 ); ResetCell( c ); c->num = n; c->next = cellTable[ t ]; cellTable[ t ] = c; return( c ); } else { LexError("Undefined cell called from root level", 0 ); return( rootCell ); } } #define Scale( a ) (a) * currScale /* * Start a new cell definition. */ public void DefineCell( cellNum, a, b ) { if( currCell != rootCell ) LexError( "DS within definition: closing current cell", 0 ); currCell = GetCell( cellNum, TRUE ); currScale = (Real) a / (Real) b; currLayer = NO_LAYER; } /* * Terminate a cell definition. */ public void CloseCell() { if( currCell == rootCell ) LexError( "No cell to close", 0 ); currCell = rootCell; currScale = 1.0; currLayer = NO_LAYER; } public void NameCell( name ) char *name; { if( (currCell->name = Malloc( strlen( name ) + 1 )) == NULL ) Crash( "Out of memory for cell names", 2 ); strcpy( currCell->name, name ); } /* * Change the current layer to 'name' provided this layer is not skipped . */ public void SetLayer( name ) char *name; { Layer lay; if( (lay = GetLayer( name, FALSE )) == NULL ) { LexError( "Unknown layer", 0 ); currLayer = SKIP_LAYER; } else if( currLayer != lay->num ) { if( not lay->skip ) { currLayer = lay->num; currIndex = currCell->layers[ currLayer ].nRects % RECTBUFF; currRects = &(currCell->layers[currLayer].rects->rect[currIndex]); } else currLayer = SKIP_LAYER; } } public void AddLabel( s, x, y ) char *s; int x, y; { Label lab; if( specialLayers.pointName ) { if( (lab = (Label) Malloc( sizeof( LabelRec ) + strlen( s ) + 1 )) == NULL ) Crash( "Out of memory for labels", 2 ); lab->pos.x = Scale( (Real) x ); lab->pos.y = Scale( (Real) y ); lab->lab = (char *) &(lab[1]); strcpy( lab->lab, s ); lab->next = currCell->labels; currCell->labels = lab; } } /* * Add a rectangle to the current cell, in the current layer. */ public void AddBox( length ,width ,centerX ,centerY ,dirX ,dirY ) int length ,width ,centerX ,centerY ,dirX ,dirY; { Point bot; Point top; RectLink newLink; Rect *r; if( currLayer == NO_LAYER ) LexError( "No layer set for rectangle", 0 ); if( dirX * dirY != 0 ) LexError( "Only 90 degree rectangles are supported", 0 ); if( dirY > dirX ) { dirX = length; /* rotate => swap length & width */ length = width; width = dirX; } bot.x = Scale( centerX - length * 0.5 ); bot.y = Scale( centerY - width * 0.5 ); top.x = Scale( centerX + length * 0.5 ); top.y = Scale( centerY + width * 0.5 ); MAX( currCell->bBox.maxC.x, top.x ) MAX( currCell->bBox.maxC.y, top.y ) MIN( currCell->bBox.minC.x, bot.x ) MIN( currCell->bBox.minC.y, bot.y ) if(( currLayer == SKIP_LAYER ) || ( currLayer == NO_LAYER )) return; if( currIndex == 0 ) { if( (newLink = (RectLink) Malloc( sizeof( RectPool ) )) == NULL ) Crash( "Out of memory for rectangles", 2 ); newLink->link = currCell->layers[ currLayer ].rects; currCell->layers[ currLayer ].rects = newLink; currRects = newLink->rect; } currRects->bot.x = bot.x; currRects->bot.y = bot.y; currRects->top.x = top.x; currRects->top.y = top.y; currRects++; ( currCell->layers[ currLayer ].nRects )++; currIndex = (++currIndex) % RECTBUFF; } /* * Mark a cell and its children as having been called from the * root level, and generate error if cell is empty. */ private void Instantiate( cell ) Cell cell; { Call c, prev; prev = NULL; for (c = cell->calls; c != NULL; c = c->next ) { c->cell->inst = TRUE; Instantiate ( c->cell ); /* Recursively instantiate */ /* Check for possibility that cell was not defined */ if ((c->cell->bBox.maxC.x < c->cell->bBox.minC.x) && (c->cell->calls == NULL)) { LexError( "Child cell was undefined or empty--removing", 0 ); if (prev == NULL) cell->calls = c->next; else prev->next = c->next; } prev = c; } } /* * Create a new node in the call-tree. Initialize its matrix to tm. */ public void CallCell( num, tm ) int num; Tmatrix tm; { Cell c; Call a, rcell; c = GetCell( num, FALSE ); if ( c != rootCell ) { tm[ 4 ] = Scale( tm[ 4 ] ); tm[ 5 ] = Scale( tm[ 5 ] ); if( (a = (Call) Malloc( sizeof( CallRec ) )) == NULL ) Crash( "Out of memory for cell calls", 2 ); a->cell = c; a->tm[0] = tm[0]; a->tm[1] = tm[1]; a->tm[2] = tm[2]; a->tm[3] = tm[3]; a->tm[4] = tm[4]; a->tm[5] = tm[5]; a->next = currCell->calls; currCell->calls = a; /* quick check for degenerate recursions */ for (rcell = currCell->calls; rcell != NULL; rcell = rcell->cell->calls) if (rcell->cell == currCell) { LexError("Cell has been called recursively", 0 ); currCell->calls = a->next; break; } /* instantiate the cell and its children if called from root level */ if ( currCell == rootCell ) { a->cell->inst = TRUE; Instantiate( a->cell ); } } } /* * Initialize the global root cells (calls). */ public void InitCells() { cellSize = sizeof( CellRec ) + (nLayer) * sizeof( LayerRects ); rootCell = (Cell) Malloc( cellSize ); rootCell->num = -1; rootCell->bBox.maxC.x = -INFINITY; rootCell->bBox.maxC.y = -INFINITY; rootCell->bBox.minC.x = INFINITY; rootCell->bBox.minC.y = INFINITY; rootCell->bigBox = rootCell->bBox; rootCell->name = NULL; rootCell->calls = NULL; rootCell->labels = NULL; rootCell->inst = FALSE; { register LayerRects *r; register int n; for( n = nLayer, r = rootCell->layers; n ; r++, n-- ) { r->rects = NULL; r->nRects = 0; } } root = (Call) Malloc( sizeof( CallRec ) ); root->cell = rootCell; root->next = NULL; currCell = rootCell; currScale = 1.0; currLayer = NO_LAYER; currRects = NULL; currIndex = 0; }