2017-04-25 14:41:48 +02:00
|
|
|
/* CIFreadcell.c -
|
|
|
|
|
*
|
|
|
|
|
* This file contains more routines to parse CIF files. In
|
|
|
|
|
* particular, it contains the routines to handle cells,
|
|
|
|
|
* both definitions and calls, and user-defined features
|
|
|
|
|
* like labels.
|
|
|
|
|
*
|
2020-05-23 23:13:14 +02:00
|
|
|
* *********************************************************************
|
|
|
|
|
* * Copyright (C) 1985, 1990 Regents of the University of California. *
|
|
|
|
|
* * Permission to use, copy, modify, and distribute this *
|
|
|
|
|
* * software and its documentation for any purpose and without *
|
|
|
|
|
* * fee is hereby granted, provided that the above copyright *
|
|
|
|
|
* * notice appear in all copies. The University of California *
|
|
|
|
|
* * makes no representations about the suitability of this *
|
|
|
|
|
* * software for any purpose. It is provided "as is" without *
|
|
|
|
|
* * express or implied warranty. Export of this software outside *
|
|
|
|
|
* * of the United States of America may require an export license. *
|
2017-04-25 14:41:48 +02:00
|
|
|
* *********************************************************************
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#ifndef lint
|
2024-10-04 12:37:02 +02:00
|
|
|
static const char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/cif/CIFrdcl.c,v 1.5 2010/08/25 17:33:55 tim Exp $";
|
2017-04-25 14:41:48 +02:00
|
|
|
#endif /* not lint */
|
|
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
#include <ctype.h>
|
|
|
|
|
|
|
|
|
|
#include "utils/magic.h"
|
|
|
|
|
#include "utils/malloc.h"
|
|
|
|
|
#include "utils/geometry.h"
|
|
|
|
|
#include "tiles/tile.h"
|
|
|
|
|
#include "utils/hash.h"
|
|
|
|
|
#include "utils/undo.h"
|
|
|
|
|
#include "database/database.h"
|
|
|
|
|
#include "cif/CIFint.h"
|
|
|
|
|
#include "cif/CIFread.h"
|
|
|
|
|
#include "cif/cif.h"
|
|
|
|
|
#include "calma/calma.h"
|
|
|
|
|
#include "utils/utils.h"
|
|
|
|
|
#include "windows/windows.h"
|
|
|
|
|
#include "dbwind/dbwind.h"
|
|
|
|
|
#include "utils/main.h"
|
|
|
|
|
#include "drc/drc.h"
|
|
|
|
|
|
|
|
|
|
/* The following variable is made available to the outside world,
|
|
|
|
|
* and is the cell definition currently being modified.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
CellDef *cifReadCellDef;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* The following hash table is used internally to keep track of
|
|
|
|
|
* of all the cells we've seen definitions for or calls on.
|
|
|
|
|
* The hash table entries contain pointers to cellDefs, and
|
|
|
|
|
* are indexed by CIF cell number. If the CDAVAILABLE bit is
|
|
|
|
|
* set it means we've read the cell's contents. If not set, it
|
|
|
|
|
* means that the cell has been called but not yet defined.
|
|
|
|
|
*/
|
|
|
|
|
HashTable CifCellTable;
|
|
|
|
|
|
|
|
|
|
/* The following variable is used to save and restore current
|
|
|
|
|
* paint layer information so that we can resume the correct
|
|
|
|
|
* layer after a subcell definition.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
Plane *cifOldReadPlane = NULL;
|
|
|
|
|
|
|
|
|
|
/* The following boolean is TRUE if a subcell definition is being
|
|
|
|
|
* read. FALSE means we're working on the EditCell.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
bool cifSubcellBeingRead;
|
|
|
|
|
|
|
|
|
|
/* The following two collections of planes are used to hold CIF
|
|
|
|
|
* information while cells are being read in (one set for the
|
|
|
|
|
* outermost, unnamed cell, and one for the current subcell).
|
|
|
|
|
* When a cell is complete, then geometrical operations are
|
|
|
|
|
* performed on the layers and stuff is painted into Magic.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
Plane *cifEditCellPlanes[MAXCIFRLAYERS];
|
|
|
|
|
Plane *cifSubcellPlanes[MAXCIFRLAYERS];
|
|
|
|
|
Plane **cifCurReadPlanes = cifEditCellPlanes; /* Set of planes currently
|
|
|
|
|
* in force.
|
|
|
|
|
*/
|
|
|
|
|
TileType cifCurLabelType = TT_SPACE; /* Magic layer on which to put '94'
|
|
|
|
|
* labels that aren't identified by
|
|
|
|
|
* type.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/* Structure used when flattening the CIF hierarchy on read-in */
|
|
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
|
Plane *plane;
|
|
|
|
|
Transform *trans;
|
|
|
|
|
} CIFCopyRec;
|
|
|
|
|
|
|
|
|
|
/* The following variable is used to hold a subcell id between
|
|
|
|
|
* the 91 statement and the (immediately-following?) call statement.
|
|
|
|
|
* The string this points to is dynamically allocated, so it must
|
|
|
|
|
* also be freed explicitly.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
char *cifSubcellId = NULL;
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
/*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* CIFReadCellInit --
|
|
|
|
|
*
|
|
|
|
|
* This procedure initializes the data structures in this
|
|
|
|
|
* module just prior to reading a CIF file.
|
|
|
|
|
*
|
|
|
|
|
* If ptrkeys is 0, the keys used in this hash table will
|
|
|
|
|
* be strings; if it is 1, the keys will be CIF numbers.
|
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* None.
|
|
|
|
|
*
|
|
|
|
|
* Side effects:
|
|
|
|
|
* The cell hash table is initialized, and things are set up
|
|
|
|
|
* to put information in the EditCell first.
|
|
|
|
|
*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
void
|
K&R: cif/*.c bulk function implementation conversion
Beware of the MISMATCH with the prototype found in original
source, with the type declaration below.
External call sites checked to confirm argument order is
correct with the argument name order.
// nedges <> dir
bool
cifOrient(edges, nedges, dir)
CIFPath *edges[], /* Array of edges to be categorized. */
int dir[], /* Array to hold directions. */
int nedges) /* Size of arrays. */
// spacing <> border
int
CIFGetContactSize(type, edge, spacing, border)
TileType type,
int *edge,
int *border,
int *spacing)
K&R obsolete syntax removal for C23 compatibility series
2024-10-04 12:34:19 +02:00
|
|
|
CIFReadCellInit(
|
|
|
|
|
int ptrkeys)
|
2017-04-25 14:41:48 +02:00
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
HashInit(&CifCellTable, 32, ptrkeys);
|
|
|
|
|
cifReadCellDef = EditCellUse->cu_def;
|
|
|
|
|
cifSubcellBeingRead = FALSE;
|
|
|
|
|
cifCurReadPlanes = cifEditCellPlanes;
|
|
|
|
|
for (i = 0; i < MAXCIFRLAYERS; i += 1)
|
|
|
|
|
{
|
|
|
|
|
if (cifEditCellPlanes[i] == NULL)
|
|
|
|
|
cifEditCellPlanes[i] = DBNewPlane((ClientData) TT_SPACE);
|
|
|
|
|
if (cifSubcellPlanes[i] == NULL)
|
|
|
|
|
cifSubcellPlanes[i] = DBNewPlane((ClientData) TT_SPACE);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* cifForgetCell --
|
|
|
|
|
*
|
|
|
|
|
* This local procedure is used to find a cell in the subcell
|
2020-05-23 23:13:14 +02:00
|
|
|
* table and remove its CellDef entry.
|
2017-04-25 14:41:48 +02:00
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* FALSE if no such entry was found, otherwise TRUE.
|
|
|
|
|
*
|
|
|
|
|
* Side effects:
|
|
|
|
|
* Mucks with the CIF cell name hash table.
|
|
|
|
|
*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
bool
|
K&R: cif/*.c bulk function implementation conversion
Beware of the MISMATCH with the prototype found in original
source, with the type declaration below.
External call sites checked to confirm argument order is
correct with the argument name order.
// nedges <> dir
bool
cifOrient(edges, nedges, dir)
CIFPath *edges[], /* Array of edges to be categorized. */
int dir[], /* Array to hold directions. */
int nedges) /* Size of arrays. */
// spacing <> border
int
CIFGetContactSize(type, edge, spacing, border)
TileType type,
int *edge,
int *border,
int *spacing)
K&R obsolete syntax removal for C23 compatibility series
2024-10-04 12:34:19 +02:00
|
|
|
cifForgetCell(
|
|
|
|
|
int cifNum)
|
2017-04-25 14:41:48 +02:00
|
|
|
{
|
|
|
|
|
HashEntry *h;
|
|
|
|
|
|
|
|
|
|
h = HashLookOnly(&CifCellTable, (char *)(spointertype)cifNum);
|
|
|
|
|
if (h == NULL)
|
|
|
|
|
return FALSE;
|
|
|
|
|
else if (HashGetValue(h) == 0)
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
HashSetValue(h, 0);
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* cifUniqueCell --
|
|
|
|
|
*
|
|
|
|
|
* Attempt to find a cell in the CIF subcell name hash table.
|
|
|
|
|
* If one exists, rename its definition so that it will not
|
|
|
|
|
* be overwritten when the cell is redefined.
|
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* None.
|
|
|
|
|
*
|
|
|
|
|
* Side effects:
|
|
|
|
|
* None.
|
|
|
|
|
*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
void
|
K&R: cif/*.c bulk function implementation conversion
Beware of the MISMATCH with the prototype found in original
source, with the type declaration below.
External call sites checked to confirm argument order is
correct with the argument name order.
// nedges <> dir
bool
cifOrient(edges, nedges, dir)
CIFPath *edges[], /* Array of edges to be categorized. */
int dir[], /* Array to hold directions. */
int nedges) /* Size of arrays. */
// spacing <> border
int
CIFGetContactSize(type, edge, spacing, border)
TileType type,
int *edge,
int *border,
int *spacing)
K&R obsolete syntax removal for C23 compatibility series
2024-10-04 12:34:19 +02:00
|
|
|
cifUniqueCell(
|
|
|
|
|
int cifNum)
|
2017-04-25 14:41:48 +02:00
|
|
|
{
|
|
|
|
|
HashEntry *h;
|
|
|
|
|
CellDef *def, *testdef;
|
|
|
|
|
char name[17];
|
|
|
|
|
int reused = 0;
|
|
|
|
|
|
|
|
|
|
h = HashLookOnly(&CifCellTable, (char *)(spointertype)cifNum);
|
|
|
|
|
|
|
|
|
|
if ((h == NULL) || HashGetValue(h) == 0)
|
|
|
|
|
{
|
|
|
|
|
/* Cell was deleted with "DD". Don't rename anything */
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sprintf(name, "%d", cifNum);
|
|
|
|
|
def = DBCellLookDef(name);
|
|
|
|
|
if (def == (CellDef *)NULL)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
/* Cell may have been called but not yet defined---this is okay. */
|
|
|
|
|
else if ((def->cd_flags & CDAVAILABLE) == 0)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
testdef = def;
|
|
|
|
|
while (testdef != NULL)
|
|
|
|
|
{
|
|
|
|
|
sprintf(name, "%d_%d", cifNum, ++reused);
|
|
|
|
|
testdef = DBCellLookDef(name);
|
|
|
|
|
}
|
|
|
|
|
DBCellRenameDef(def, name);
|
|
|
|
|
|
|
|
|
|
h = HashFind(&CifCellTable, (char *)(spointertype)cifNum);
|
|
|
|
|
HashSetValue(h, 0);
|
|
|
|
|
|
|
|
|
|
CIFReadError("Warning: cell definition %d reused.\n", cifNum);
|
|
|
|
|
}
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
/*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* cifFindCell --
|
|
|
|
|
*
|
|
|
|
|
* This local procedure is used to find a cell in the subcell
|
|
|
|
|
* table, and create a new subcell if there isn't already
|
|
|
|
|
* one there. If a new subcell is created, its CDAVAILABLE
|
|
|
|
|
* is left FALSE.
|
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* The return value is a pointer to the definition for the
|
|
|
|
|
* cell whose CIF number is cifNum.
|
|
|
|
|
*
|
|
|
|
|
* Side effects:
|
|
|
|
|
* A new CellDef may be created.
|
|
|
|
|
*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
CellDef *
|
K&R: cif/*.c bulk function implementation conversion
Beware of the MISMATCH with the prototype found in original
source, with the type declaration below.
External call sites checked to confirm argument order is
correct with the argument name order.
// nedges <> dir
bool
cifOrient(edges, nedges, dir)
CIFPath *edges[], /* Array of edges to be categorized. */
int dir[], /* Array to hold directions. */
int nedges) /* Size of arrays. */
// spacing <> border
int
CIFGetContactSize(type, edge, spacing, border)
TileType type,
int *edge,
int *border,
int *spacing)
K&R obsolete syntax removal for C23 compatibility series
2024-10-04 12:34:19 +02:00
|
|
|
cifFindCell(
|
|
|
|
|
int cifNum) /* The CIF number of the desired cell. */
|
2017-04-25 14:41:48 +02:00
|
|
|
{
|
|
|
|
|
HashEntry *h;
|
|
|
|
|
CellDef *def, *testdef;
|
|
|
|
|
int reused;
|
|
|
|
|
|
|
|
|
|
h = HashFind(&CifCellTable, (char *)(spointertype)cifNum);
|
|
|
|
|
|
|
|
|
|
if (HashGetValue(h) == 0)
|
|
|
|
|
{
|
|
|
|
|
char name[15];
|
|
|
|
|
|
|
|
|
|
sprintf(name, "%d", cifNum);
|
|
|
|
|
def = DBCellLookDef(name);
|
|
|
|
|
if (def == NULL)
|
|
|
|
|
{
|
2020-03-21 17:40:35 +01:00
|
|
|
def = DBCellNewDef(name);
|
2017-04-25 14:41:48 +02:00
|
|
|
|
|
|
|
|
/* Tricky point: call DBReComputeBbox here to make SURE
|
|
|
|
|
* that the cell has a valid bounding box. Otherwise,
|
|
|
|
|
* if the cell is used in a parent before being defined
|
|
|
|
|
* then it will cause a core dump.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
DBReComputeBbox(def);
|
|
|
|
|
}
|
|
|
|
|
HashSetValue(h, def);
|
|
|
|
|
}
|
|
|
|
|
return (CellDef *) HashGetValue(h);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* CIFScalePlanes --
|
|
|
|
|
*
|
|
|
|
|
* Scale all of the CIF planes by the amount (scalen / scaled)
|
|
|
|
|
*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
void
|
K&R: cif/*.c bulk function implementation conversion
Beware of the MISMATCH with the prototype found in original
source, with the type declaration below.
External call sites checked to confirm argument order is
correct with the argument name order.
// nedges <> dir
bool
cifOrient(edges, nedges, dir)
CIFPath *edges[], /* Array of edges to be categorized. */
int dir[], /* Array to hold directions. */
int nedges) /* Size of arrays. */
// spacing <> border
int
CIFGetContactSize(type, edge, spacing, border)
TileType type,
int *edge,
int *border,
int *spacing)
K&R obsolete syntax removal for C23 compatibility series
2024-10-04 12:34:19 +02:00
|
|
|
CIFScalePlanes(
|
|
|
|
|
int scalen,
|
|
|
|
|
int scaled,
|
|
|
|
|
Plane **planearray)
|
2017-04-25 14:41:48 +02:00
|
|
|
{
|
|
|
|
|
int pNum;
|
|
|
|
|
Plane *newplane;
|
|
|
|
|
|
|
|
|
|
for (pNum = 0; pNum < MAXCIFRLAYERS; pNum++)
|
|
|
|
|
{
|
|
|
|
|
if (planearray[pNum] != NULL)
|
|
|
|
|
{
|
|
|
|
|
newplane = DBNewPlane((ClientData) TT_SPACE);
|
|
|
|
|
DBClearPaintPlane(newplane);
|
|
|
|
|
dbScalePlane(planearray[pNum], newplane, pNum,
|
|
|
|
|
scalen, scaled, TRUE);
|
|
|
|
|
DBFreePaintPlane(planearray[pNum]);
|
|
|
|
|
TiFreePlane(planearray[pNum]);
|
|
|
|
|
planearray[pNum] = newplane;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* CIFInputRescale --
|
|
|
|
|
*
|
|
|
|
|
* Scale all CIF distances by n / d. Normally, rescaling is done in
|
|
|
|
|
* the upward direction (n > 1, d = 1) in response to a value in the
|
|
|
|
|
* CIF input that does not divide evenly into the database units of
|
|
|
|
|
* the CIF planes. Currently there is no call to CIFInputRescale
|
|
|
|
|
* with d > 1, but it is left for the possibility that scalefactors
|
|
|
|
|
* could be restored after finishing a subcell definition, possibly
|
|
|
|
|
* preventing integer overflow in large designs.
|
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* None.
|
|
|
|
|
*
|
|
|
|
|
* Side effects:
|
|
|
|
|
* Many. Adjusts the CIF input style scalefactor (CIF vs. magic
|
|
|
|
|
* units), multiplier (CIF units vs. centimicrons), distances of all
|
|
|
|
|
* CIF boolean operations, and the scale of all existing planes in
|
|
|
|
|
* the current CIF database.
|
|
|
|
|
*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*/
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
void
|
K&R: cif/*.c bulk function implementation conversion
Beware of the MISMATCH with the prototype found in original
source, with the type declaration below.
External call sites checked to confirm argument order is
correct with the argument name order.
// nedges <> dir
bool
cifOrient(edges, nedges, dir)
CIFPath *edges[], /* Array of edges to be categorized. */
int dir[], /* Array to hold directions. */
int nedges) /* Size of arrays. */
// spacing <> border
int
CIFGetContactSize(type, edge, spacing, border)
TileType type,
int *edge,
int *border,
int *spacing)
K&R obsolete syntax removal for C23 compatibility series
2024-10-04 12:34:19 +02:00
|
|
|
CIFInputRescale(
|
|
|
|
|
int n,
|
|
|
|
|
int d)
|
2017-04-25 14:41:48 +02:00
|
|
|
{
|
|
|
|
|
CIFReadStyle *istyle = cifCurReadStyle;
|
|
|
|
|
CIFReadLayer *cl;
|
|
|
|
|
CIFOp *op;
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
/* 2-step process for efficiency */
|
|
|
|
|
|
|
|
|
|
if (n > 1)
|
|
|
|
|
{
|
|
|
|
|
istyle->crs_scaleFactor *= n;
|
|
|
|
|
istyle->crs_multiplier *= n;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < istyle->crs_nLayers; i++)
|
|
|
|
|
{
|
|
|
|
|
cl = istyle->crs_layers[i];
|
|
|
|
|
for (op = cl->crl_ops; op != NULL; op = op->co_next)
|
|
|
|
|
if (op->co_distance)
|
|
|
|
|
op->co_distance *= n;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (d > 1)
|
|
|
|
|
{
|
|
|
|
|
istyle->crs_scaleFactor /= d;
|
|
|
|
|
istyle->crs_multiplier /= d;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < istyle->crs_nLayers; i++)
|
|
|
|
|
{
|
|
|
|
|
cl = istyle->crs_layers[i];
|
|
|
|
|
for (op = cl->crl_ops; op != NULL; op = op->co_next)
|
|
|
|
|
if (op->co_distance)
|
|
|
|
|
op->co_distance /= d;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-01-25 21:05:05 +01:00
|
|
|
CIFScalePlanes(n, d, cifCurReadPlanes);
|
|
|
|
|
if (cifCurReadPlanes != cifEditCellPlanes)
|
|
|
|
|
CIFScalePlanes(n, d, cifEditCellPlanes);
|
2024-10-04 18:10:48 +02:00
|
|
|
if ((const Plane*)cifEditCellPlanes != (const Plane*)cifSubcellPlanes && cifCurReadPlanes != cifSubcellPlanes)
|
2017-04-25 14:41:48 +02:00
|
|
|
CIFScalePlanes(n, d, cifSubcellPlanes);
|
|
|
|
|
|
|
|
|
|
CIFReadWarning("CIF style %s: units rescaled by factor of %d / %d\n",
|
|
|
|
|
istyle->crs_name, n, d);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* CIFParseStart --
|
|
|
|
|
*
|
|
|
|
|
* Parse the beginning of a symbol (cell) definition.
|
|
|
|
|
* ds ::= D { blank } S integer [ sep integer sep integer ]
|
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* TRUE is returned if the parse completed successfully, and
|
|
|
|
|
* FALSE is returned otherwise.
|
|
|
|
|
*
|
|
|
|
|
* Side effects:
|
|
|
|
|
* Set up information for the new cell, including the CIF
|
|
|
|
|
* planes and creating a Magic cell (if one doesn't exist
|
|
|
|
|
* already).
|
|
|
|
|
*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
bool
|
K&R: cif/*.c bulk function implementation conversion
Beware of the MISMATCH with the prototype found in original
source, with the type declaration below.
External call sites checked to confirm argument order is
correct with the argument name order.
// nedges <> dir
bool
cifOrient(edges, nedges, dir)
CIFPath *edges[], /* Array of edges to be categorized. */
int dir[], /* Array to hold directions. */
int nedges) /* Size of arrays. */
// spacing <> border
int
CIFGetContactSize(type, edge, spacing, border)
TileType type,
int *edge,
int *border,
int *spacing)
K&R obsolete syntax removal for C23 compatibility series
2024-10-04 12:34:19 +02:00
|
|
|
CIFParseStart(void)
|
2017-04-25 14:41:48 +02:00
|
|
|
{
|
|
|
|
|
int number;
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
if (cifSubcellBeingRead)
|
|
|
|
|
{
|
|
|
|
|
CIFReadError("definition start inside other definition; ignored.\n");
|
|
|
|
|
CIFSkipToSemi();
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
if (cifSubcellId != NULL)
|
|
|
|
|
{
|
|
|
|
|
CIFReadError("pending call identifier %s discarded.\n", cifSubcellId);
|
|
|
|
|
(void) StrDup(&cifSubcellId, (char *) NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Take the `S'. */
|
|
|
|
|
|
|
|
|
|
TAKE();
|
|
|
|
|
if (!CIFParseInteger(&number))
|
|
|
|
|
{
|
|
|
|
|
CIFReadError("definition start, but no symbol number; ignored.\n");
|
|
|
|
|
CIFSkipToSemi();
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
else if (number < 0)
|
|
|
|
|
{
|
|
|
|
|
CIFReadError("illegal negative symbol number; definition ignored.\n");
|
|
|
|
|
CIFSkipToSemi();
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!CIFParseInteger(&cifReadScale1))
|
|
|
|
|
{
|
|
|
|
|
cifReadScale1 = 1;
|
|
|
|
|
cifReadScale2 = 1;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
cifReadScale1 *= cifCurReadStyle->crs_multiplier; /* Units not centimicrons */
|
|
|
|
|
|
|
|
|
|
if (!CIFParseInteger(&cifReadScale2))
|
|
|
|
|
{
|
|
|
|
|
CIFReadError(
|
|
|
|
|
"only one of two scale factors given; ignored.\n");
|
|
|
|
|
cifReadScale1 = 1;
|
|
|
|
|
cifReadScale2 = 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (cifReadScale1 <= 0 || cifReadScale2 <= 0)
|
|
|
|
|
{
|
|
|
|
|
CIFReadError("Illegal scale %d / %d changed to 1 / 1\n",
|
|
|
|
|
cifReadScale1, cifReadScale2);
|
|
|
|
|
cifReadScale1 = 1;
|
|
|
|
|
cifReadScale2 = 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Set up the cell definition.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
cifUniqueCell(number);
|
|
|
|
|
cifReadCellDef = cifFindCell(number);
|
|
|
|
|
DBCellClearDef(cifReadCellDef);
|
|
|
|
|
DBCellSetAvail(cifReadCellDef);
|
|
|
|
|
|
|
|
|
|
cifOldReadPlane = cifReadPlane;
|
|
|
|
|
cifReadPlane = (Plane *) NULL;
|
|
|
|
|
cifSubcellBeingRead = TRUE;
|
|
|
|
|
cifCurReadPlanes = cifSubcellPlanes;
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
* cifCheckPaintFunc ---
|
|
|
|
|
*
|
|
|
|
|
* Callback function for checking if any paint has been generated
|
|
|
|
|
* on the CIF target plane for a "copyup" layer.
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
K&R: cif/*.c bulk function implementation conversion
Beware of the MISMATCH with the prototype found in original
source, with the type declaration below.
External call sites checked to confirm argument order is
correct with the argument name order.
// nedges <> dir
bool
cifOrient(edges, nedges, dir)
CIFPath *edges[], /* Array of edges to be categorized. */
int dir[], /* Array to hold directions. */
int nedges) /* Size of arrays. */
// spacing <> border
int
CIFGetContactSize(type, edge, spacing, border)
TileType type,
int *edge,
int *border,
int *spacing)
K&R obsolete syntax removal for C23 compatibility series
2024-10-04 12:34:19 +02:00
|
|
|
int cifCheckPaintFunc(
|
|
|
|
|
Tile *tile,
|
|
|
|
|
ClientData clientData)
|
2017-04-25 14:41:48 +02:00
|
|
|
{
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Callback function for copying paint from one CIF cell into another */
|
|
|
|
|
|
|
|
|
|
int
|
K&R: cif/*.c bulk function implementation conversion
Beware of the MISMATCH with the prototype found in original
source, with the type declaration below.
External call sites checked to confirm argument order is
correct with the argument name order.
// nedges <> dir
bool
cifOrient(edges, nedges, dir)
CIFPath *edges[], /* Array of edges to be categorized. */
int dir[], /* Array to hold directions. */
int nedges) /* Size of arrays. */
// spacing <> border
int
CIFGetContactSize(type, edge, spacing, border)
TileType type,
int *edge,
int *border,
int *spacing)
K&R obsolete syntax removal for C23 compatibility series
2024-10-04 12:34:19 +02:00
|
|
|
cifCopyPaintFunc(
|
|
|
|
|
Tile *tile,
|
|
|
|
|
CIFCopyRec *cifCopyRec)
|
2017-04-25 14:41:48 +02:00
|
|
|
{
|
|
|
|
|
int pNum;
|
2017-08-02 04:14:42 +02:00
|
|
|
TileType dinfo;
|
2017-04-25 14:41:48 +02:00
|
|
|
Rect sourceRect, targetRect;
|
|
|
|
|
Transform *trans = cifCopyRec->trans;
|
|
|
|
|
Plane *plane = cifCopyRec->plane;
|
|
|
|
|
|
2017-08-02 04:14:42 +02:00
|
|
|
dinfo = TiGetTypeExact(tile);
|
|
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
if (trans)
|
|
|
|
|
{
|
|
|
|
|
TiToRect(tile, &sourceRect);
|
|
|
|
|
GeoTransRect(trans, &sourceRect, &targetRect);
|
2017-08-02 04:14:42 +02:00
|
|
|
if (IsSplit(tile))
|
|
|
|
|
dinfo = DBTransformDiagonal(TiGetTypeExact(tile), trans);
|
2017-04-25 14:41:48 +02:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
TiToRect(tile, &targetRect);
|
|
|
|
|
|
2017-08-02 04:14:42 +02:00
|
|
|
DBNMPaintPlane(plane, dinfo, &targetRect, CIFPaintTable,
|
2017-04-25 14:41:48 +02:00
|
|
|
(PaintUndoInfo *)NULL);
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2022-01-21 03:50:13 +01:00
|
|
|
/*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* cifMaskHintFunc --
|
|
|
|
|
*
|
|
|
|
|
* For each tile in the scanned plane, convert the tile into a coordinate
|
|
|
|
|
* string by appending the coordinates to the list passed as clientData.
|
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* Return 0 to keep the search going.
|
|
|
|
|
*
|
|
|
|
|
* Side effects:
|
|
|
|
|
* Allocates memory for and seeds a linked rect entry
|
|
|
|
|
*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
int
|
K&R: cif/*.c bulk function implementation conversion
Beware of the MISMATCH with the prototype found in original
source, with the type declaration below.
External call sites checked to confirm argument order is
correct with the argument name order.
// nedges <> dir
bool
cifOrient(edges, nedges, dir)
CIFPath *edges[], /* Array of edges to be categorized. */
int dir[], /* Array to hold directions. */
int nedges) /* Size of arrays. */
// spacing <> border
int
CIFGetContactSize(type, edge, spacing, border)
TileType type,
int *edge,
int *border,
int *spacing)
K&R obsolete syntax removal for C23 compatibility series
2024-10-04 12:34:19 +02:00
|
|
|
cifMaskHintFunc(
|
|
|
|
|
Tile *tile,
|
|
|
|
|
LinkedRect **lrecp)
|
2022-01-21 03:50:13 +01:00
|
|
|
{
|
|
|
|
|
Rect r;
|
|
|
|
|
LinkedRect *newlr;
|
|
|
|
|
|
|
|
|
|
newlr = (LinkedRect *)mallocMagic(sizeof(LinkedRect));
|
|
|
|
|
newlr->r_next = *lrecp;
|
|
|
|
|
(*lrecp) = newlr;
|
|
|
|
|
|
|
|
|
|
TiToRect(tile, &newlr->r_r);
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
/*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* CIFPaintCurrent --
|
|
|
|
|
*
|
|
|
|
|
* This procedure does geometrical processing on the current
|
|
|
|
|
* set of CIF planes, and paints the results into the current
|
|
|
|
|
* CIF cell.
|
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* Return 0
|
|
|
|
|
*
|
|
|
|
|
* Side effects:
|
|
|
|
|
* Lots of information gets added to the current Magic cell.
|
|
|
|
|
*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
int
|
2024-10-04 12:44:01 +02:00
|
|
|
CIFPaintCurrent(
|
|
|
|
|
int filetype)
|
2017-04-25 14:41:48 +02:00
|
|
|
{
|
2024-10-04 12:26:58 +02:00
|
|
|
extern int cifMakeBoundaryFunc(Tile *tile, ClientData clientdata); /* Forward declaration. */
|
|
|
|
|
extern int cifPaintCurrentFunc(Tile *tile, TileType type); /* Forward declaration. */
|
2019-06-05 21:03:51 +02:00
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
Plane *plane, *swapplane;
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < cifCurReadStyle->crs_nLayers; i++)
|
|
|
|
|
{
|
|
|
|
|
TileType type;
|
|
|
|
|
CIFOp *op;
|
|
|
|
|
|
|
|
|
|
plane = CIFGenLayer(cifCurReadStyle->crs_layers[i]->crl_ops,
|
2020-11-12 16:34:27 +01:00
|
|
|
&TiPlaneRect, (CellDef *)NULL, (CellDef *)NULL,
|
|
|
|
|
cifCurReadPlanes, FALSE, (ClientData)NULL);
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
/* Generate a paint/erase table, then paint from the CIF
|
|
|
|
|
* plane into the current Magic cell.
|
|
|
|
|
*/
|
|
|
|
|
type = cifCurReadStyle->crs_layers[i]->crl_magicType;
|
|
|
|
|
|
|
|
|
|
if (cifCurReadStyle->crs_layers[i]->crl_flags & CIFR_TEMPLAYER)
|
|
|
|
|
{
|
|
|
|
|
op = cifCurReadStyle->crs_layers[i]->crl_ops;
|
|
|
|
|
while (op)
|
|
|
|
|
{
|
|
|
|
|
if (op->co_opcode == CIFOP_COPYUP) break;
|
|
|
|
|
op = op->co_next;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Quick check to see if anything was generated */
|
|
|
|
|
/* on this layer. */
|
|
|
|
|
|
|
|
|
|
if (op && (DBSrPaintArea((Tile *)NULL, plane, &TiPlaneRect,
|
|
|
|
|
&DBAllButSpaceBits, cifCheckPaintFunc,
|
|
|
|
|
(ClientData)NULL) == 1))
|
|
|
|
|
{
|
|
|
|
|
/* Copy-up function */
|
|
|
|
|
|
|
|
|
|
int pNum;
|
|
|
|
|
Plane *newplane;
|
|
|
|
|
Plane **parray;
|
|
|
|
|
extern char *(cifReadLayers[MAXCIFRLAYERS]);
|
|
|
|
|
|
2020-11-21 01:56:41 +01:00
|
|
|
/* NOTE: The condition cd_client == 0 when CDFLATGDS
|
|
|
|
|
* indicates that the cell was already in memory when the
|
|
|
|
|
* GDS was read. This condition should be properly caught
|
|
|
|
|
* and handled.
|
2018-10-23 14:44:04 +02:00
|
|
|
*/
|
2020-05-23 23:13:14 +02:00
|
|
|
if ((cifReadCellDef->cd_flags & CDFLATGDS) &&
|
2020-11-21 01:56:41 +01:00
|
|
|
(cifReadCellDef->cd_client != (ClientData)0))
|
2017-04-25 14:41:48 +02:00
|
|
|
parray = (Plane **)cifReadCellDef->cd_client;
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
parray = (Plane **)mallocMagic(MAXCIFRLAYERS * sizeof(Plane *));
|
|
|
|
|
cifReadCellDef->cd_flags |= CDFLATGDS;
|
|
|
|
|
cifReadCellDef->cd_flags &= ~CDFLATTENED;
|
|
|
|
|
cifReadCellDef->cd_client = (ClientData)parray;
|
|
|
|
|
for (pNum = 0; pNum < MAXCIFRLAYERS; pNum++)
|
|
|
|
|
parray[pNum] = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (pNum = 0; pNum < MAXCIFRLAYERS; pNum++)
|
|
|
|
|
{
|
|
|
|
|
if (TTMaskHasType(&op->co_cifMask, pNum))
|
|
|
|
|
{
|
|
|
|
|
CIFCopyRec cifCopyRec;
|
|
|
|
|
|
2017-08-02 04:14:42 +02:00
|
|
|
newplane = parray[pNum];
|
|
|
|
|
if (newplane == NULL)
|
|
|
|
|
{
|
|
|
|
|
newplane = DBNewPlane((ClientData) TT_SPACE);
|
|
|
|
|
DBClearPaintPlane(newplane);
|
|
|
|
|
}
|
2017-04-25 14:41:48 +02:00
|
|
|
|
|
|
|
|
cifCopyRec.plane = newplane;
|
|
|
|
|
cifCopyRec.trans = NULL;
|
|
|
|
|
|
|
|
|
|
DBSrPaintArea((Tile *)NULL, plane, &TiPlaneRect,
|
|
|
|
|
&DBAllButSpaceBits, cifCopyPaintFunc,
|
|
|
|
|
&cifCopyRec);
|
|
|
|
|
|
|
|
|
|
parray[pNum] = newplane;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-06-05 21:03:51 +02:00
|
|
|
else if (op == NULL)
|
|
|
|
|
{
|
|
|
|
|
/* Handle boundary layer */
|
|
|
|
|
|
|
|
|
|
op = cifCurReadStyle->crs_layers[i]->crl_ops;
|
|
|
|
|
while (op)
|
|
|
|
|
{
|
|
|
|
|
if (op->co_opcode == CIFOP_BOUNDARY) break;
|
|
|
|
|
op = op->co_next;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (op && (DBSrPaintArea((Tile *)NULL, plane, &TiPlaneRect,
|
|
|
|
|
&DBAllButSpaceBits, cifCheckPaintFunc,
|
|
|
|
|
(ClientData)NULL) == 1))
|
|
|
|
|
DBSrPaintArea((Tile *) NULL, plane, &TiPlaneRect,
|
2024-10-21 10:13:23 +02:00
|
|
|
&CIFSolidBits, cifMakeBoundaryFunc, INT2CD(filetype));
|
2019-06-05 21:03:51 +02:00
|
|
|
}
|
2017-04-25 14:41:48 +02:00
|
|
|
|
|
|
|
|
/* Swap planes */
|
|
|
|
|
swapplane = cifCurReadPlanes[type];
|
|
|
|
|
cifCurReadPlanes[type] = plane;
|
|
|
|
|
plane = swapplane;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
DBSrPaintArea((Tile *) NULL, plane, &TiPlaneRect,
|
|
|
|
|
&CIFSolidBits, cifPaintCurrentFunc,
|
2024-10-21 10:13:23 +02:00
|
|
|
INT2CD(type));
|
2020-05-23 23:13:14 +02:00
|
|
|
}
|
2019-06-05 21:03:51 +02:00
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
/* Recycle the plane, which was dynamically allocated. */
|
|
|
|
|
|
|
|
|
|
DBFreePaintPlane(plane);
|
|
|
|
|
TiFreePlane(plane);
|
|
|
|
|
}
|
|
|
|
|
|
2022-01-21 03:50:13 +01:00
|
|
|
/* If mask hints were requested, then for each GDS/CIF layer in the */
|
|
|
|
|
/* input, if the layer has a corresponding output layer and the */
|
|
|
|
|
/* output layer has a mask hints operator, then generate the output */
|
|
|
|
|
/* plane for that layer, compare to the input plane, and create */
|
|
|
|
|
/* mask hint properties to make the output the same as the input. */
|
|
|
|
|
|
2022-01-21 20:48:59 +01:00
|
|
|
if ((CalmaMaskHints != NULL) && (!TTMaskIsZero(CalmaMaskHints)))
|
2022-01-21 03:50:13 +01:00
|
|
|
{
|
|
|
|
|
int j;
|
|
|
|
|
CIFOp *op, newop, subop;
|
|
|
|
|
Plane *presult;
|
|
|
|
|
TileTypeBitMask genMask;
|
|
|
|
|
int *in_out_map;
|
|
|
|
|
extern char *(cifReadLayers[MAXCIFRLAYERS]);
|
|
|
|
|
|
|
|
|
|
TTMaskZero(&genMask);
|
|
|
|
|
in_out_map = (int *)mallocMagic(cifNReadLayers * sizeof(int));
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < cifNReadLayers; i++)
|
|
|
|
|
{
|
2022-01-21 20:48:59 +01:00
|
|
|
if (!TTMaskHasType(CalmaMaskHints, i)) continue;
|
|
|
|
|
|
2022-01-21 03:50:13 +01:00
|
|
|
/* Does the input layer have a corresponding output layer? */
|
|
|
|
|
in_out_map[i] = -1;
|
|
|
|
|
for (j = 0; j < CIFCurStyle->cs_nLayers; j++)
|
|
|
|
|
{
|
|
|
|
|
if (!strcmp(CIFCurStyle->cs_layers[j]->cl_name, cifReadLayers[i]))
|
|
|
|
|
{
|
|
|
|
|
/* Does the layer have a mask-hints operator? */
|
|
|
|
|
for (op = CIFCurStyle->cs_layers[j]->cl_ops; op; op = op->co_next)
|
|
|
|
|
if (op->co_opcode == CIFOP_MASKHINTS)
|
|
|
|
|
{
|
|
|
|
|
TTMaskSetType(&genMask, j);
|
|
|
|
|
in_out_map[i] = j;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (in_out_map[i] >= 0) break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Multiply input planes to the same scale as the generated output */
|
2022-12-19 22:05:38 +01:00
|
|
|
CIFScalePlanes(CIFCurStyle->cs_scaleFactor, cifCurReadStyle->crs_scaleFactor,
|
|
|
|
|
cifCurReadPlanes);
|
2022-01-21 03:50:13 +01:00
|
|
|
|
|
|
|
|
/* Generate the output for these layers from the cell contents */
|
|
|
|
|
CIFClearPlanes(CIFPlanes);
|
|
|
|
|
|
|
|
|
|
/* TO-DO: Replace DBAllTypeBits with genMask. Requires that genMask */
|
|
|
|
|
/* be expanded to include all dependent layers. */
|
|
|
|
|
CIFGen(cifReadCellDef, cifReadCellDef, &TiPlaneRect, CIFPlanes, &DBAllTypeBits,
|
|
|
|
|
TRUE, FALSE, FALSE, (ClientData)NULL);
|
|
|
|
|
|
|
|
|
|
/* Set up double operator for OR and ANDNOT functions */
|
|
|
|
|
newop.co_opcode = CIFOP_OR;
|
|
|
|
|
newop.co_distance = 0;
|
|
|
|
|
newop.co_next = &subop;
|
|
|
|
|
newop.co_client = (ClientData)NULL;
|
|
|
|
|
TTMaskZero(&newop.co_paintMask);
|
|
|
|
|
|
|
|
|
|
subop.co_opcode = CIFOP_ANDNOT;
|
|
|
|
|
subop.co_distance = 0;
|
|
|
|
|
subop.co_next = NULL;
|
|
|
|
|
subop.co_client = (ClientData)NULL;
|
|
|
|
|
TTMaskZero(&subop.co_paintMask);
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < cifNReadLayers; i++)
|
|
|
|
|
{
|
|
|
|
|
LinkedRect *lrec = NULL;
|
|
|
|
|
char *propstr = NULL;
|
|
|
|
|
char locstr[512];
|
|
|
|
|
Plane *tempp;
|
|
|
|
|
|
2022-01-21 20:48:59 +01:00
|
|
|
if (!TTMaskHasType(CalmaMaskHints, i)) continue;
|
|
|
|
|
|
2022-01-21 03:50:13 +01:00
|
|
|
j = in_out_map[i];
|
|
|
|
|
if (j < 0) continue;
|
|
|
|
|
|
|
|
|
|
TTMaskSetOnlyType(&subop.co_cifMask, j);
|
|
|
|
|
|
|
|
|
|
/* Replace last layer + 1 on CIFPlanes with input layer i */
|
|
|
|
|
|
|
|
|
|
tempp = CIFPlanes[CIFCurStyle->cs_nLayers];
|
|
|
|
|
TTMaskSetOnlyType(&newop.co_cifMask, CIFCurStyle->cs_nLayers);
|
|
|
|
|
CIFPlanes[CIFCurStyle->cs_nLayers] = cifCurReadPlanes[i];
|
|
|
|
|
CIFCurStyle->cs_nLayers++;
|
|
|
|
|
|
|
|
|
|
/* Compute result (i AND-NOT j), which will be all the areas of
|
|
|
|
|
* the input on layer i that are not generated by writing output
|
|
|
|
|
* layer j.
|
|
|
|
|
*/
|
|
|
|
|
presult = CIFGenLayer(&newop, &TiPlaneRect, (CellDef *)NULL,
|
|
|
|
|
(CellDef *)NULL, CIFPlanes, FALSE, (ClientData)NULL);
|
|
|
|
|
|
|
|
|
|
/* Scan the resulting plane and generate linked Rect structures for
|
|
|
|
|
* each shape found.
|
|
|
|
|
*/
|
|
|
|
|
DBSrPaintArea((Tile *)NULL, presult, &TiPlaneRect, &CIFSolidBits,
|
|
|
|
|
cifMaskHintFunc, (ClientData)&lrec);
|
|
|
|
|
|
|
|
|
|
if (lrec != NULL)
|
|
|
|
|
{
|
|
|
|
|
char *propname;
|
|
|
|
|
|
|
|
|
|
propname = (char *)mallocMagic(11 + strlen(cifReadLayers[i]));
|
|
|
|
|
sprintf(propname, "MASKHINTS_%s", cifReadLayers[i]);
|
|
|
|
|
|
|
|
|
|
propstr = (char *)NULL;
|
|
|
|
|
|
|
|
|
|
/* Turn all linked Rects into a mask-hints property in the
|
|
|
|
|
* target cell.
|
|
|
|
|
*/
|
|
|
|
|
while (lrec != NULL)
|
|
|
|
|
{
|
|
|
|
|
char *newstr;
|
|
|
|
|
sprintf(locstr, "%d %d %d %d",
|
|
|
|
|
lrec->r_r.r_xbot / CIFCurStyle->cs_scaleFactor,
|
|
|
|
|
lrec->r_r.r_ybot / CIFCurStyle->cs_scaleFactor,
|
|
|
|
|
lrec->r_r.r_xtop / CIFCurStyle->cs_scaleFactor,
|
|
|
|
|
lrec->r_r.r_ytop / CIFCurStyle->cs_scaleFactor);
|
|
|
|
|
if (propstr == NULL)
|
|
|
|
|
{
|
|
|
|
|
newstr = (char *)mallocMagic(strlen(locstr) + 1);
|
|
|
|
|
sprintf(newstr, "%s", locstr);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
newstr = (char *)mallocMagic(strlen(locstr)
|
|
|
|
|
+ strlen(propstr) + 2);
|
|
|
|
|
sprintf(newstr, "%s %s", propstr, locstr);
|
|
|
|
|
freeMagic(propstr);
|
|
|
|
|
}
|
|
|
|
|
propstr = newstr;
|
|
|
|
|
freeMagic(lrec);
|
|
|
|
|
lrec = lrec->r_next;
|
|
|
|
|
}
|
|
|
|
|
/* NOTE: propstr is transferred to the CellDef and should
|
|
|
|
|
* not be free'd here.
|
|
|
|
|
*/
|
|
|
|
|
DBPropPut(cifReadCellDef, propname, propstr);
|
|
|
|
|
freeMagic(propname);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Delete the generated plane */
|
|
|
|
|
DBFreePaintPlane(presult);
|
|
|
|
|
TiFreePlane(presult);
|
|
|
|
|
|
|
|
|
|
/* Replace the input plane that was shuffled out */
|
|
|
|
|
CIFCurStyle->cs_nLayers--;
|
|
|
|
|
CIFPlanes[CIFCurStyle->cs_nLayers] = tempp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Free up the planes used to create the output */
|
|
|
|
|
CIFClearPlanes(CIFPlanes);
|
|
|
|
|
|
|
|
|
|
freeMagic((char *)in_out_map);
|
|
|
|
|
}
|
|
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
/* Now go through all the current planes and zero them out. */
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < MAXCIFRLAYERS; i++)
|
|
|
|
|
DBClearPaintPlane(cifCurReadPlanes[i]);
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2019-06-05 21:03:51 +02:00
|
|
|
/* Use CIF layer geometry to define a fixed bounding box for the current cell */
|
|
|
|
|
|
|
|
|
|
int
|
K&R: cif/*.c bulk function implementation conversion
Beware of the MISMATCH with the prototype found in original
source, with the type declaration below.
External call sites checked to confirm argument order is
correct with the argument name order.
// nedges <> dir
bool
cifOrient(edges, nedges, dir)
CIFPath *edges[], /* Array of edges to be categorized. */
int dir[], /* Array to hold directions. */
int nedges) /* Size of arrays. */
// spacing <> border
int
CIFGetContactSize(type, edge, spacing, border)
TileType type,
int *edge,
int *border,
int *spacing)
K&R obsolete syntax removal for C23 compatibility series
2024-10-04 12:34:19 +02:00
|
|
|
cifMakeBoundaryFunc(
|
|
|
|
|
Tile *tile, /* Tile of CIF information. */
|
|
|
|
|
ClientData clientdata) /* Pass the file type (CIF or CALMA) */
|
2019-06-05 21:03:51 +02:00
|
|
|
{
|
|
|
|
|
/* It is assumed that there is one rectangle for the boundary. */
|
|
|
|
|
/* If there are multiple rectangles defined with the boundary */
|
|
|
|
|
/* layer, then the last one defines the FIXED_BBOX property. */
|
|
|
|
|
|
|
|
|
|
Rect area;
|
|
|
|
|
char propertyvalue[128], *storedvalue;
|
2019-07-09 02:36:48 +02:00
|
|
|
int savescale;
|
2025-01-06 17:24:57 +01:00
|
|
|
int filetype = (int)CD2INT(clientdata);
|
2019-06-05 21:03:51 +02:00
|
|
|
|
|
|
|
|
TiToRect(tile, &area);
|
2019-07-09 02:36:48 +02:00
|
|
|
area.r_xtop = CIFScaleCoord(area.r_xtop, COORD_EXACT);
|
|
|
|
|
savescale = cifCurReadStyle->crs_scaleFactor;
|
|
|
|
|
area.r_ytop = CIFScaleCoord(area.r_ytop, COORD_EXACT);
|
|
|
|
|
if (savescale != cifCurReadStyle->crs_scaleFactor)
|
|
|
|
|
{
|
|
|
|
|
area.r_xtop *= (savescale / cifCurReadStyle->crs_scaleFactor);
|
|
|
|
|
savescale = cifCurReadStyle->crs_scaleFactor;
|
|
|
|
|
}
|
|
|
|
|
area.r_xbot = CIFScaleCoord(area.r_xbot, COORD_EXACT);
|
|
|
|
|
if (savescale != cifCurReadStyle->crs_scaleFactor)
|
|
|
|
|
{
|
|
|
|
|
area.r_xtop *= (savescale / cifCurReadStyle->crs_scaleFactor);
|
|
|
|
|
area.r_ytop *= (savescale / cifCurReadStyle->crs_scaleFactor);
|
|
|
|
|
savescale = cifCurReadStyle->crs_scaleFactor;
|
|
|
|
|
}
|
|
|
|
|
area.r_ybot = CIFScaleCoord(area.r_ybot, COORD_EXACT);
|
|
|
|
|
if (savescale != cifCurReadStyle->crs_scaleFactor)
|
|
|
|
|
{
|
|
|
|
|
area.r_xtop *= (savescale / cifCurReadStyle->crs_scaleFactor);
|
|
|
|
|
area.r_ytop *= (savescale / cifCurReadStyle->crs_scaleFactor);
|
|
|
|
|
area.r_xbot *= (savescale / cifCurReadStyle->crs_scaleFactor);
|
|
|
|
|
}
|
2019-06-05 21:03:51 +02:00
|
|
|
|
|
|
|
|
if (cifReadCellDef->cd_flags & CDFIXEDBBOX)
|
2019-07-23 14:45:42 +02:00
|
|
|
{
|
|
|
|
|
char *propvalue;
|
|
|
|
|
bool found;
|
|
|
|
|
|
|
|
|
|
/* Only flag a warning if the redefined boundary was */
|
|
|
|
|
/* different from the original. */
|
|
|
|
|
|
|
|
|
|
propvalue = (char *)DBPropGet(cifReadCellDef, "FIXED_BBOX", &found);
|
|
|
|
|
if (found)
|
|
|
|
|
{
|
|
|
|
|
Rect bbox;
|
|
|
|
|
if (sscanf(propvalue, "%d %d %d %d", &bbox.r_xbot, &bbox.r_ybot,
|
|
|
|
|
&bbox.r_xtop, &bbox.r_ytop) == 4)
|
|
|
|
|
{
|
|
|
|
|
if ((bbox.r_xbot != area.r_xbot) ||
|
|
|
|
|
(bbox.r_ybot != area.r_ybot) ||
|
|
|
|
|
(bbox.r_xtop != area.r_xtop) ||
|
|
|
|
|
(bbox.r_ytop != area.r_ytop))
|
|
|
|
|
{
|
|
|
|
|
if (filetype == FILE_CIF)
|
|
|
|
|
CIFReadError("Warning: Cell %s boundary was redefined.\n",
|
|
|
|
|
cifReadCellDef->cd_name);
|
|
|
|
|
else
|
2019-07-25 22:29:12 +02:00
|
|
|
CalmaReadError("Warning: Cell %s boundary was redefined.\n",
|
2019-07-23 14:45:42 +02:00
|
|
|
cifReadCellDef->cd_name);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-06-05 21:03:51 +02:00
|
|
|
|
|
|
|
|
sprintf(propertyvalue, "%d %d %d %d",
|
|
|
|
|
area.r_xbot, area.r_ybot, area.r_xtop, area.r_ytop);
|
|
|
|
|
storedvalue = StrDup((char **)NULL, propertyvalue);
|
|
|
|
|
DBPropPut(cifReadCellDef, "FIXED_BBOX", storedvalue);
|
|
|
|
|
cifReadCellDef->cd_flags |= CDFIXEDBBOX;
|
2019-07-09 02:36:48 +02:00
|
|
|
return 0;
|
2019-06-05 21:03:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Paint CIF layer geometry into the current cell def as magic layer "type" */
|
2017-04-25 14:41:48 +02:00
|
|
|
|
|
|
|
|
int
|
K&R: cif/*.c bulk function implementation conversion
Beware of the MISMATCH with the prototype found in original
source, with the type declaration below.
External call sites checked to confirm argument order is
correct with the argument name order.
// nedges <> dir
bool
cifOrient(edges, nedges, dir)
CIFPath *edges[], /* Array of edges to be categorized. */
int dir[], /* Array to hold directions. */
int nedges) /* Size of arrays. */
// spacing <> border
int
CIFGetContactSize(type, edge, spacing, border)
TileType type,
int *edge,
int *border,
int *spacing)
K&R obsolete syntax removal for C23 compatibility series
2024-10-04 12:34:19 +02:00
|
|
|
cifPaintCurrentFunc(
|
|
|
|
|
Tile *tile, /* Tile of CIF information. */
|
|
|
|
|
TileType type) /* Magic type to be painted. */
|
2017-04-25 14:41:48 +02:00
|
|
|
{
|
|
|
|
|
Rect area;
|
|
|
|
|
int pNum;
|
|
|
|
|
int savescale;
|
|
|
|
|
bool snap_type = COORD_EXACT;
|
|
|
|
|
|
|
|
|
|
/* Contact types are allowed to be on half-lambda spacing, and are */
|
|
|
|
|
/* snapped to the nearest magic coordinate if the result is a */
|
|
|
|
|
/* fractional magic coordinate. */
|
|
|
|
|
|
|
|
|
|
if (DBIsContact(type)) snap_type = COORD_HALF_U;
|
|
|
|
|
|
|
|
|
|
/* Compute the area of the CIF tile, then scale it into
|
|
|
|
|
* Magic coordinates.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
TiToRect(tile, &area);
|
|
|
|
|
area.r_xtop = CIFScaleCoord(area.r_xtop, snap_type);
|
|
|
|
|
savescale = cifCurReadStyle->crs_scaleFactor;
|
|
|
|
|
area.r_ytop = CIFScaleCoord(area.r_ytop, snap_type);
|
|
|
|
|
if (snap_type == COORD_HALF_U) snap_type = COORD_HALF_L;
|
|
|
|
|
if (savescale != cifCurReadStyle->crs_scaleFactor)
|
|
|
|
|
{
|
|
|
|
|
area.r_xtop *= (savescale / cifCurReadStyle->crs_scaleFactor);
|
|
|
|
|
savescale = cifCurReadStyle->crs_scaleFactor;
|
|
|
|
|
}
|
|
|
|
|
area.r_xbot = CIFScaleCoord(area.r_xbot, snap_type);
|
|
|
|
|
if (savescale != cifCurReadStyle->crs_scaleFactor)
|
|
|
|
|
{
|
|
|
|
|
area.r_xtop *= (savescale / cifCurReadStyle->crs_scaleFactor);
|
|
|
|
|
area.r_ytop *= (savescale / cifCurReadStyle->crs_scaleFactor);
|
|
|
|
|
savescale = cifCurReadStyle->crs_scaleFactor;
|
|
|
|
|
}
|
|
|
|
|
area.r_ybot = CIFScaleCoord(area.r_ybot, snap_type);
|
|
|
|
|
if (savescale != cifCurReadStyle->crs_scaleFactor)
|
|
|
|
|
{
|
|
|
|
|
area.r_xtop *= (savescale / cifCurReadStyle->crs_scaleFactor);
|
|
|
|
|
area.r_ytop *= (savescale / cifCurReadStyle->crs_scaleFactor);
|
|
|
|
|
area.r_xbot *= (savescale / cifCurReadStyle->crs_scaleFactor);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Check for degenerate areas (from rescale limiting) before painting */
|
|
|
|
|
if ((area.r_xbot == area.r_xtop) || (area.r_ybot == area.r_ytop))
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
for (pNum = PL_PAINTBASE; pNum < DBNumPlanes; pNum++)
|
|
|
|
|
if (DBPaintOnPlane(type, pNum))
|
|
|
|
|
{
|
|
|
|
|
DBNMPaintPlane(cifReadCellDef->cd_planes[pNum], TiGetTypeExact(tile),
|
|
|
|
|
&area, DBStdPaintTbl(type, pNum), (PaintUndoInfo *) NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0; /* To keep the search alive. */
|
|
|
|
|
}
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
/*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* CIFParseFinish --
|
|
|
|
|
*
|
|
|
|
|
* This procedure is called at the end of a cell definition.
|
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* TRUE is returned if the parse completed successfully, and
|
|
|
|
|
* FALSE is returned otherwise.
|
|
|
|
|
*
|
|
|
|
|
* Side effects:
|
|
|
|
|
* Process the CIF planes and paint the results into the Magic
|
|
|
|
|
* cell.
|
|
|
|
|
*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
bool
|
K&R: cif/*.c bulk function implementation conversion
Beware of the MISMATCH with the prototype found in original
source, with the type declaration below.
External call sites checked to confirm argument order is
correct with the argument name order.
// nedges <> dir
bool
cifOrient(edges, nedges, dir)
CIFPath *edges[], /* Array of edges to be categorized. */
int dir[], /* Array to hold directions. */
int nedges) /* Size of arrays. */
// spacing <> border
int
CIFGetContactSize(type, edge, spacing, border)
TileType type,
int *edge,
int *border,
int *spacing)
K&R obsolete syntax removal for C23 compatibility series
2024-10-04 12:34:19 +02:00
|
|
|
CIFParseFinish(void)
|
2017-04-25 14:41:48 +02:00
|
|
|
{
|
|
|
|
|
if (!cifSubcellBeingRead)
|
|
|
|
|
{
|
|
|
|
|
CIFReadError("definition finish without definition start; ignored.\n");
|
|
|
|
|
CIFSkipToSemi();
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
2020-05-23 23:13:14 +02:00
|
|
|
if (cifSubcellId != NULL)
|
2017-04-25 14:41:48 +02:00
|
|
|
{
|
|
|
|
|
CIFReadError("pending call identifier %s discarded.\n", cifSubcellId);
|
|
|
|
|
(void) StrDup(&cifSubcellId, (char *) NULL);
|
|
|
|
|
}
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
/* Take the `F'. */
|
|
|
|
|
|
|
|
|
|
TAKE();
|
|
|
|
|
|
|
|
|
|
/* Do the geometrical processing and paint this material back into
|
|
|
|
|
* the appropriate cell of the database. Then restore the saved
|
|
|
|
|
* layer info.
|
|
|
|
|
*/
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2019-07-23 14:45:42 +02:00
|
|
|
CIFPaintCurrent(FILE_CIF);
|
2017-04-25 14:41:48 +02:00
|
|
|
|
|
|
|
|
DBAdjustLabels(cifReadCellDef, &TiPlaneRect);
|
|
|
|
|
DBReComputeBbox(cifReadCellDef);
|
|
|
|
|
cifReadCellDef = EditCellUse->cu_def;
|
|
|
|
|
cifReadPlane = cifOldReadPlane;
|
|
|
|
|
cifReadScale1 = 1;
|
|
|
|
|
cifReadScale2 = 1;
|
|
|
|
|
cifSubcellBeingRead = FALSE;
|
|
|
|
|
cifCurReadPlanes = cifEditCellPlanes;
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
/*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* CIFParseDelete --
|
|
|
|
|
*
|
|
|
|
|
* This procedure is called to handle delete-symbol statements.
|
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* TRUE is returned if the parse completed successfully, and
|
|
|
|
|
* FALSE is returned otherwise.
|
|
|
|
|
*
|
|
|
|
|
* Side effects:
|
|
|
|
|
* The mapping between numbers and cells is modified to eliminate
|
|
|
|
|
* some symbols.
|
|
|
|
|
*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
bool
|
K&R: cif/*.c bulk function implementation conversion
Beware of the MISMATCH with the prototype found in original
source, with the type declaration below.
External call sites checked to confirm argument order is
correct with the argument name order.
// nedges <> dir
bool
cifOrient(edges, nedges, dir)
CIFPath *edges[], /* Array of edges to be categorized. */
int dir[], /* Array to hold directions. */
int nedges) /* Size of arrays. */
// spacing <> border
int
CIFGetContactSize(type, edge, spacing, border)
TileType type,
int *edge,
int *border,
int *spacing)
K&R obsolete syntax removal for C23 compatibility series
2024-10-04 12:34:19 +02:00
|
|
|
CIFParseDelete(void)
|
2017-04-25 14:41:48 +02:00
|
|
|
{
|
|
|
|
|
int number;
|
|
|
|
|
|
|
|
|
|
/* Take the `D'. */
|
|
|
|
|
|
|
|
|
|
TAKE();
|
|
|
|
|
if (!CIFParseInteger(&number))
|
|
|
|
|
{
|
|
|
|
|
CIFReadError("definition delete, but no symbol number; ignored.\n");
|
|
|
|
|
CIFSkipToSemi();
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Unlink the hash entry from its target definition */
|
|
|
|
|
cifForgetCell(number);
|
|
|
|
|
|
|
|
|
|
CIFSkipToSemi();
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
/*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* cifParseName --
|
|
|
|
|
*
|
|
|
|
|
* Parse a name, which is a string of alphabetics, numerics,
|
|
|
|
|
* or underscores, possibly preceded by whitespace.
|
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* The return value is a pointer to the name read from the
|
|
|
|
|
* CIF file. This is a statically-allocated area, so the
|
|
|
|
|
* caller should copy out of this area before invoking this
|
|
|
|
|
* procedure again.
|
|
|
|
|
*
|
|
|
|
|
* Side effects:
|
|
|
|
|
* None.
|
|
|
|
|
*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
char *
|
K&R: cif/*.c bulk function implementation conversion
Beware of the MISMATCH with the prototype found in original
source, with the type declaration below.
External call sites checked to confirm argument order is
correct with the argument name order.
// nedges <> dir
bool
cifOrient(edges, nedges, dir)
CIFPath *edges[], /* Array of edges to be categorized. */
int dir[], /* Array to hold directions. */
int nedges) /* Size of arrays. */
// spacing <> border
int
CIFGetContactSize(type, edge, spacing, border)
TileType type,
int *edge,
int *border,
int *spacing)
K&R obsolete syntax removal for C23 compatibility series
2024-10-04 12:34:19 +02:00
|
|
|
cifParseName(void)
|
2017-04-25 14:41:48 +02:00
|
|
|
{
|
|
|
|
|
char ch;
|
|
|
|
|
char *bufferp;
|
|
|
|
|
static char buffer[128];
|
|
|
|
|
|
|
|
|
|
/* Skip white space. */
|
|
|
|
|
|
|
|
|
|
for (ch = PEEK() ; ch == ' ' || ch == '\t' ; ch = PEEK())
|
|
|
|
|
TAKE();
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
/* Read the string. */
|
|
|
|
|
|
|
|
|
|
bufferp = &buffer[0];
|
|
|
|
|
for (ch = PEEK() ; (! isspace(ch)) && ch != ';' ; ch = PEEK())
|
|
|
|
|
{
|
|
|
|
|
*bufferp++ = TAKE();
|
|
|
|
|
}
|
|
|
|
|
*bufferp = '\0';
|
|
|
|
|
return buffer;
|
|
|
|
|
}
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
/*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* cifParseUser9 --
|
|
|
|
|
*
|
|
|
|
|
* This procedure processes user extension 9: the name of the
|
|
|
|
|
* current symbol (cell) definition.
|
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* TRUE is returned if the parse completed successfully, and
|
|
|
|
|
* FALSE is returned otherwise.
|
|
|
|
|
*
|
|
|
|
|
* Side effects:
|
|
|
|
|
* The current CIF symbol is renamed from its default "cifxx" name
|
|
|
|
|
* to the given name.
|
|
|
|
|
*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
bool
|
K&R: cif/*.c bulk function implementation conversion
Beware of the MISMATCH with the prototype found in original
source, with the type declaration below.
External call sites checked to confirm argument order is
correct with the argument name order.
// nedges <> dir
bool
cifOrient(edges, nedges, dir)
CIFPath *edges[], /* Array of edges to be categorized. */
int dir[], /* Array to hold directions. */
int nedges) /* Size of arrays. */
// spacing <> border
int
CIFGetContactSize(type, edge, spacing, border)
TileType type,
int *edge,
int *border,
int *spacing)
K&R obsolete syntax removal for C23 compatibility series
2024-10-04 12:34:19 +02:00
|
|
|
cifParseUser9(void)
|
2017-04-25 14:41:48 +02:00
|
|
|
{
|
|
|
|
|
char *name;
|
|
|
|
|
|
|
|
|
|
name = cifParseName();
|
|
|
|
|
if (!DBCellRenameDef(cifReadCellDef, name))
|
|
|
|
|
{
|
|
|
|
|
CIFReadError("%s already exists, so cell from CIF is named %s.\n",
|
|
|
|
|
name, cifReadCellDef->cd_name);
|
|
|
|
|
}
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
/*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* CIFParseCall --
|
|
|
|
|
*
|
|
|
|
|
* This procedure processes subcell uses. The syntax of a call is
|
|
|
|
|
* call ::= C integer transform
|
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* TRUE is returned if the parse completed successfully, and
|
|
|
|
|
* FALSE is returned otherwise.
|
|
|
|
|
*
|
|
|
|
|
* Side effects:
|
|
|
|
|
* A subcell is added to the current Magic cell we're generating.
|
|
|
|
|
*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
bool
|
K&R: cif/*.c bulk function implementation conversion
Beware of the MISMATCH with the prototype found in original
source, with the type declaration below.
External call sites checked to confirm argument order is
correct with the argument name order.
// nedges <> dir
bool
cifOrient(edges, nedges, dir)
CIFPath *edges[], /* Array of edges to be categorized. */
int dir[], /* Array to hold directions. */
int nedges) /* Size of arrays. */
// spacing <> border
int
CIFGetContactSize(type, edge, spacing, border)
TileType type,
int *edge,
int *border,
int *spacing)
K&R obsolete syntax removal for C23 compatibility series
2024-10-04 12:34:19 +02:00
|
|
|
CIFParseCall(void)
|
2017-04-25 14:41:48 +02:00
|
|
|
{
|
|
|
|
|
int called;
|
|
|
|
|
Transform transform;
|
|
|
|
|
CellUse *use;
|
|
|
|
|
CellDef *def;
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
/* Take the `C'. */
|
|
|
|
|
|
|
|
|
|
TAKE();
|
|
|
|
|
if (!CIFParseInteger(&called))
|
|
|
|
|
{
|
|
|
|
|
CIFReadError("call, but no symbol number; ignored.\n");
|
|
|
|
|
CIFSkipToSemi();
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Get optional transformation. */
|
|
|
|
|
|
|
|
|
|
(void) CIFParseTransform(&transform);
|
|
|
|
|
|
|
|
|
|
def = cifFindCell(called);
|
|
|
|
|
|
|
|
|
|
/* avoid recursion
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
if (DBIsAncestor(def, cifReadCellDef))
|
|
|
|
|
{
|
|
|
|
|
CIFReadError("attempt to place cell use inside its own definition!\n");
|
|
|
|
|
CIFSkipToSemi();
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Find the use and add it to the current cell. Give it an
|
|
|
|
|
* id also.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
use = DBCellNewUse(def, cifSubcellId);
|
|
|
|
|
(void) DBLinkCell(use, cifReadCellDef);
|
|
|
|
|
DBSetTrans(use, &transform);
|
|
|
|
|
DBPlaceCell(use, cifReadCellDef);
|
|
|
|
|
|
|
|
|
|
(void) StrDup(&cifSubcellId, (char *) NULL);
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
/*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* cifParseUser91 --
|
|
|
|
|
*
|
|
|
|
|
* This procedure handles 91 user commands, which provide id's
|
|
|
|
|
* for following cell calls. The syntax is:
|
|
|
|
|
* 91 ::= 91 blanks name
|
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* TRUE is returned if the parse completed successfully, and
|
|
|
|
|
* FALSE is returned otherwise.
|
|
|
|
|
*
|
|
|
|
|
* Side effects:
|
|
|
|
|
* The identifier is saved until the call is read. Then it is
|
|
|
|
|
* used as the identifier for the cell.
|
|
|
|
|
*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
bool
|
K&R: cif/*.c bulk function implementation conversion
Beware of the MISMATCH with the prototype found in original
source, with the type declaration below.
External call sites checked to confirm argument order is
correct with the argument name order.
// nedges <> dir
bool
cifOrient(edges, nedges, dir)
CIFPath *edges[], /* Array of edges to be categorized. */
int dir[], /* Array to hold directions. */
int nedges) /* Size of arrays. */
// spacing <> border
int
CIFGetContactSize(type, edge, spacing, border)
TileType type,
int *edge,
int *border,
int *spacing)
K&R obsolete syntax removal for C23 compatibility series
2024-10-04 12:34:19 +02:00
|
|
|
cifParseUser91(void)
|
2017-04-25 14:41:48 +02:00
|
|
|
{
|
|
|
|
|
if (cifSubcellId != NULL)
|
|
|
|
|
{
|
|
|
|
|
CIFReadError("91 command with identifier %s pending; %s discarded.\n" ,
|
|
|
|
|
cifSubcellId , cifSubcellId);
|
|
|
|
|
}
|
|
|
|
|
(void) StrDup(&cifSubcellId, cifParseName());
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
/*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* cifParseUser94 --
|
|
|
|
|
*
|
|
|
|
|
* This procedure parses 94 user commands, which are labelled
|
|
|
|
|
* points. The syntax is:
|
|
|
|
|
* 94 ::= 94 blanks name point
|
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* TRUE is returned if the parse completed successfully, and
|
|
|
|
|
* FALSE is returned otherwise.
|
|
|
|
|
*
|
|
|
|
|
* Side effects:
|
|
|
|
|
* A label is added to the current cell.
|
|
|
|
|
*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
bool
|
K&R: cif/*.c bulk function implementation conversion
Beware of the MISMATCH with the prototype found in original
source, with the type declaration below.
External call sites checked to confirm argument order is
correct with the argument name order.
// nedges <> dir
bool
cifOrient(edges, nedges, dir)
CIFPath *edges[], /* Array of edges to be categorized. */
int dir[], /* Array to hold directions. */
int nedges) /* Size of arrays. */
// spacing <> border
int
CIFGetContactSize(type, edge, spacing, border)
TileType type,
int *edge,
int *border,
int *spacing)
K&R obsolete syntax removal for C23 compatibility series
2024-10-04 12:34:19 +02:00
|
|
|
cifParseUser94(void)
|
2017-04-25 14:41:48 +02:00
|
|
|
{
|
|
|
|
|
Rect rectangle;
|
|
|
|
|
char *name = NULL;
|
|
|
|
|
TileType type;
|
|
|
|
|
int layer, flags, i;
|
|
|
|
|
int savescale;
|
|
|
|
|
|
|
|
|
|
(void) StrDup(&name, cifParseName());
|
|
|
|
|
if (! CIFParsePoint(&rectangle.r_ll, 1))
|
|
|
|
|
{
|
|
|
|
|
CIFReadError("94 command, but no location; ignored.\n");
|
|
|
|
|
CIFSkipToSemi();
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Scale the coordinates, then make the location into a
|
|
|
|
|
* rectangle.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
rectangle.r_xbot = CIFScaleCoord(rectangle.r_xbot, COORD_ANY);
|
|
|
|
|
savescale = cifCurReadStyle->crs_scaleFactor;
|
|
|
|
|
rectangle.r_ybot = CIFScaleCoord(rectangle.r_ybot, COORD_ANY);
|
|
|
|
|
if (savescale != cifCurReadStyle->crs_scaleFactor)
|
|
|
|
|
rectangle.r_xbot *= (savescale / cifCurReadStyle->crs_scaleFactor);
|
|
|
|
|
|
|
|
|
|
rectangle.r_ur = rectangle.r_ll;
|
|
|
|
|
|
|
|
|
|
/* Get a layer, lookup the layer, then add the label to the
|
|
|
|
|
* current cell. Tricky business: in order for the default
|
|
|
|
|
* label location to be computed
|
|
|
|
|
*/
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
CIFSkipBlanks();
|
|
|
|
|
if (PEEK() != ';')
|
|
|
|
|
{
|
|
|
|
|
char *lname = cifParseName();
|
|
|
|
|
layer = CIFReadNameToType(lname, FALSE);
|
|
|
|
|
if (layer < 0)
|
|
|
|
|
{
|
|
|
|
|
CIFReadError("label attached to unknown layer %s.\n",
|
|
|
|
|
lname);
|
|
|
|
|
type = TT_SPACE;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
type = cifCurReadStyle->crs_labelLayer[layer];
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
type = cifCurLabelType;
|
|
|
|
|
|
|
|
|
|
/* Should do this better, by defining cifCurLabelFlags. . . */
|
|
|
|
|
layer = -1;
|
|
|
|
|
for (i = 0; i < cifCurReadStyle->crs_nLayers; i++)
|
|
|
|
|
if (cifCurReadStyle->crs_labelLayer[i] == type) {
|
|
|
|
|
layer = i;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (type >=0 )
|
|
|
|
|
{
|
2017-08-02 04:14:42 +02:00
|
|
|
if (layer >= 0 && cifCurReadStyle->crs_labelSticky[layer])
|
2017-04-25 14:41:48 +02:00
|
|
|
flags = LABEL_STICKY;
|
|
|
|
|
else
|
|
|
|
|
flags = 0;
|
2021-12-13 04:09:31 +01:00
|
|
|
(void) DBPutLabel(cifReadCellDef, &rectangle, -1, name, type, flags, 0);
|
2017-04-25 14:41:48 +02:00
|
|
|
}
|
|
|
|
|
freeMagic(name);
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
/*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* cifParseUser95 --
|
|
|
|
|
*
|
|
|
|
|
* This procedure parses 95 user commands, which are labelled
|
|
|
|
|
* points. The syntax is:
|
|
|
|
|
* 95 ::= 95 blanks name length width point
|
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* TRUE is returned if the parse completed successfully, and
|
|
|
|
|
* FALSE is returned otherwise.
|
|
|
|
|
*
|
|
|
|
|
* Side effects:
|
|
|
|
|
* An area label is added to the current cell.
|
|
|
|
|
*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
bool
|
K&R: cif/*.c bulk function implementation conversion
Beware of the MISMATCH with the prototype found in original
source, with the type declaration below.
External call sites checked to confirm argument order is
correct with the argument name order.
// nedges <> dir
bool
cifOrient(edges, nedges, dir)
CIFPath *edges[], /* Array of edges to be categorized. */
int dir[], /* Array to hold directions. */
int nedges) /* Size of arrays. */
// spacing <> border
int
CIFGetContactSize(type, edge, spacing, border)
TileType type,
int *edge,
int *border,
int *spacing)
K&R obsolete syntax removal for C23 compatibility series
2024-10-04 12:34:19 +02:00
|
|
|
cifParseUser95(void)
|
2017-04-25 14:41:48 +02:00
|
|
|
{
|
2018-08-21 04:13:16 +02:00
|
|
|
/* Modified by BIM 1/8/2018 */
|
2017-04-25 14:41:48 +02:00
|
|
|
Rect rectangle;
|
2018-08-21 04:13:16 +02:00
|
|
|
Point size, center, lowerleft, upperright;
|
2017-04-25 14:41:48 +02:00
|
|
|
char *name = NULL;
|
|
|
|
|
TileType type;
|
|
|
|
|
int layer, i;
|
|
|
|
|
int savescale;
|
|
|
|
|
|
|
|
|
|
(void) StrDup(&name, cifParseName());
|
2018-08-21 04:13:16 +02:00
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
if (! CIFParsePoint(&size, 1))
|
|
|
|
|
{
|
|
|
|
|
CIFReadError("95 command, but no size; ignored.\n");
|
|
|
|
|
CIFSkipToSemi();
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2018-08-21 04:13:16 +02:00
|
|
|
savescale = cifCurReadStyle->crs_scaleFactor;
|
|
|
|
|
|
|
|
|
|
/* The center coordinates returned are in CIF units *2 */
|
|
|
|
|
/* the values will be halved later before conversion to magic units */
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2018-08-21 04:13:16 +02:00
|
|
|
if (! CIFParsePoint(¢er, 2))
|
2017-04-25 14:41:48 +02:00
|
|
|
{
|
|
|
|
|
CIFReadError("95 command, but no location; ignored.\n");
|
|
|
|
|
CIFSkipToSemi();
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
2018-08-21 04:13:16 +02:00
|
|
|
/* If reading the center causes a CIF input scale to be redefined, */
|
|
|
|
|
/* then the length and width must also be changed. */
|
|
|
|
|
|
|
|
|
|
if (savescale != cifCurReadStyle->crs_scaleFactor)
|
|
|
|
|
{
|
|
|
|
|
size.p_x *= (cifCurReadStyle->crs_scaleFactor / savescale);
|
|
|
|
|
size.p_y *= (cifCurReadStyle->crs_scaleFactor / savescale);
|
|
|
|
|
}
|
|
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
/* Scale the coordinates and create the rectangular area. */
|
2018-08-21 04:13:16 +02:00
|
|
|
/* Explicitly calculate lowerleft and upperright using CIF units *2 */
|
2017-04-25 14:41:48 +02:00
|
|
|
/* so that half-lambda centers are resolved before remapping to */
|
|
|
|
|
/* magic coordinates. */
|
|
|
|
|
|
2018-08-21 04:13:16 +02:00
|
|
|
lowerleft.p_x = center.p_x - size.p_x;
|
|
|
|
|
lowerleft.p_y = center.p_y - size.p_y;
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2018-08-21 04:13:16 +02:00
|
|
|
upperright.p_x = center.p_x + size.p_x;
|
|
|
|
|
upperright.p_y = center.p_y + size.p_y;
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2018-08-21 04:13:16 +02:00
|
|
|
if ((lowerleft.p_x % 2 == 0) && (lowerleft.p_y % 2 == 0)) {
|
|
|
|
|
|
|
|
|
|
/* if possible convert values to CIF units by dividing by two */
|
|
|
|
|
|
|
|
|
|
lowerleft.p_x /= 2;
|
|
|
|
|
lowerleft.p_y /= 2;
|
|
|
|
|
|
|
|
|
|
upperright.p_x /= 2;
|
|
|
|
|
upperright.p_y /= 2;
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
|
|
/* if division by two would create inaccuracy then rescale to accommodate */
|
|
|
|
|
|
|
|
|
|
CIFInputRescale(2, 1);
|
|
|
|
|
|
|
|
|
|
}
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2018-08-21 04:13:16 +02:00
|
|
|
/* now scale each of the co-ordinates in turn */
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2018-08-21 04:13:16 +02:00
|
|
|
lowerleft.p_x = CIFScaleCoord(lowerleft.p_x, COORD_ANY);
|
2017-04-25 14:41:48 +02:00
|
|
|
savescale = cifCurReadStyle->crs_scaleFactor;
|
2018-08-21 04:13:16 +02:00
|
|
|
|
|
|
|
|
lowerleft.p_y = CIFScaleCoord(lowerleft.p_y, COORD_ANY);
|
2017-04-25 14:41:48 +02:00
|
|
|
if (savescale != cifCurReadStyle->crs_scaleFactor)
|
|
|
|
|
{
|
2018-08-21 04:13:16 +02:00
|
|
|
lowerleft.p_x *= (savescale / cifCurReadStyle->crs_scaleFactor);
|
2017-04-25 14:41:48 +02:00
|
|
|
savescale = cifCurReadStyle->crs_scaleFactor;
|
|
|
|
|
}
|
2018-08-21 04:13:16 +02:00
|
|
|
|
|
|
|
|
upperright.p_x = CIFScaleCoord(upperright.p_x, COORD_ANY);
|
2017-04-25 14:41:48 +02:00
|
|
|
if (savescale != cifCurReadStyle->crs_scaleFactor)
|
|
|
|
|
{
|
2018-08-21 04:13:16 +02:00
|
|
|
lowerleft.p_x *= (savescale / cifCurReadStyle->crs_scaleFactor);
|
|
|
|
|
lowerleft.p_y *= (savescale / cifCurReadStyle->crs_scaleFactor);
|
2017-04-25 14:41:48 +02:00
|
|
|
savescale = cifCurReadStyle->crs_scaleFactor;
|
|
|
|
|
}
|
2018-08-21 04:13:16 +02:00
|
|
|
|
|
|
|
|
upperright.p_y = CIFScaleCoord(upperright.p_y, COORD_ANY);
|
2017-04-25 14:41:48 +02:00
|
|
|
if (savescale != cifCurReadStyle->crs_scaleFactor)
|
|
|
|
|
{
|
2018-08-21 04:13:16 +02:00
|
|
|
lowerleft.p_x *= (savescale / cifCurReadStyle->crs_scaleFactor);
|
|
|
|
|
lowerleft.p_y *= (savescale / cifCurReadStyle->crs_scaleFactor);
|
|
|
|
|
upperright.p_x *= (savescale / cifCurReadStyle->crs_scaleFactor);
|
2017-04-25 14:41:48 +02:00
|
|
|
}
|
2018-08-21 04:13:16 +02:00
|
|
|
|
|
|
|
|
rectangle.r_xbot = lowerleft.p_x;
|
|
|
|
|
rectangle.r_ybot = lowerleft.p_y;
|
|
|
|
|
rectangle.r_xtop = upperright.p_x;
|
|
|
|
|
rectangle.r_ytop = upperright.p_y;
|
2017-04-25 14:41:48 +02:00
|
|
|
|
|
|
|
|
/* Get a layer, lookup the layer, then add the label to the
|
|
|
|
|
* current cell. Tricky business: in order for the default
|
|
|
|
|
* label location to be computed
|
|
|
|
|
*/
|
|
|
|
|
CIFSkipBlanks();
|
|
|
|
|
if (PEEK() != ';')
|
|
|
|
|
{
|
|
|
|
|
char *name = cifParseName();
|
|
|
|
|
layer = CIFReadNameToType(name, FALSE);
|
|
|
|
|
if (layer < 0)
|
|
|
|
|
{
|
|
|
|
|
CIFReadError("label attached to unknown layer %s.\n",
|
|
|
|
|
name);
|
|
|
|
|
type = TT_SPACE;
|
|
|
|
|
}
|
|
|
|
|
else type = cifCurReadStyle->crs_labelLayer[layer];
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
type = TT_SPACE;
|
|
|
|
|
layer = -1;
|
|
|
|
|
for (i = 0; i < cifCurReadStyle->crs_nLayers; i++)
|
|
|
|
|
if (cifCurReadStyle->crs_labelLayer[i] == type) {
|
|
|
|
|
layer = i;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (type >=0 )
|
|
|
|
|
{
|
|
|
|
|
int flags;
|
2017-08-02 04:14:42 +02:00
|
|
|
if (layer >= 0 && cifCurReadStyle->crs_labelSticky[layer])
|
2017-04-25 14:41:48 +02:00
|
|
|
flags = LABEL_STICKY;
|
|
|
|
|
else
|
|
|
|
|
flags = 0;
|
2021-12-13 04:09:31 +01:00
|
|
|
(void) DBPutLabel(cifReadCellDef, &rectangle, -1, name, type, flags, 0);
|
2017-04-25 14:41:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
freeMagic(name);
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
/*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* CIFParseUser --
|
|
|
|
|
*
|
|
|
|
|
* This procedure is called to process user-defined statements.
|
|
|
|
|
* The syntax is user ::= digit usertext.
|
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* TRUE is returned if the parse completed successfully, and
|
|
|
|
|
* FALSE is returned otherwise.
|
|
|
|
|
*
|
|
|
|
|
* Side effects:
|
|
|
|
|
* Depends on the user command.
|
|
|
|
|
*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
bool
|
K&R: cif/*.c bulk function implementation conversion
Beware of the MISMATCH with the prototype found in original
source, with the type declaration below.
External call sites checked to confirm argument order is
correct with the argument name order.
// nedges <> dir
bool
cifOrient(edges, nedges, dir)
CIFPath *edges[], /* Array of edges to be categorized. */
int dir[], /* Array to hold directions. */
int nedges) /* Size of arrays. */
// spacing <> border
int
CIFGetContactSize(type, edge, spacing, border)
TileType type,
int *edge,
int *border,
int *spacing)
K&R obsolete syntax removal for C23 compatibility series
2024-10-04 12:34:19 +02:00
|
|
|
CIFParseUser(void)
|
2017-04-25 14:41:48 +02:00
|
|
|
{
|
|
|
|
|
char ch;
|
|
|
|
|
|
|
|
|
|
ch = TAKE();
|
|
|
|
|
switch (ch)
|
|
|
|
|
{
|
|
|
|
|
case '9':
|
|
|
|
|
ch = PEEK();
|
|
|
|
|
switch (ch)
|
|
|
|
|
{
|
|
|
|
|
case '1':
|
|
|
|
|
(void) TAKE();
|
|
|
|
|
return cifParseUser91();
|
|
|
|
|
case '4':
|
|
|
|
|
(void) TAKE();
|
|
|
|
|
return cifParseUser94();
|
|
|
|
|
case '5':
|
|
|
|
|
(void) TAKE();
|
|
|
|
|
return cifParseUser95();
|
|
|
|
|
default:
|
|
|
|
|
if (isspace(ch)) return cifParseUser9();
|
|
|
|
|
}
|
|
|
|
|
default:
|
|
|
|
|
CIFReadError("unimplemented user extension; ignored.\n");
|
|
|
|
|
CIFSkipToSemi();
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
/*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* CIFReadCellCleanup --
|
|
|
|
|
*
|
|
|
|
|
* This procedure is called after processing the CIF file.
|
|
|
|
|
* It performs various cleanup functions on the cells that
|
|
|
|
|
* have been read in.
|
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* None.
|
|
|
|
|
*
|
|
|
|
|
* Side effects:
|
|
|
|
|
* The area of each cell is DRC'ed and redisplayed. Error
|
|
|
|
|
* messages are output for any cells whose contents weren't
|
|
|
|
|
* in the CIF file. An error message is also output if
|
|
|
|
|
* we're still in the middle of reading a subcell.
|
|
|
|
|
*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
void
|
2024-10-04 12:44:01 +02:00
|
|
|
CIFReadCellCleanup(
|
|
|
|
|
int filetype)
|
2017-04-25 14:41:48 +02:00
|
|
|
{
|
|
|
|
|
HashEntry *h;
|
|
|
|
|
HashSearch hs;
|
|
|
|
|
CellDef *def;
|
|
|
|
|
MagWindow *window;
|
|
|
|
|
int flags;
|
|
|
|
|
|
|
|
|
|
if (cifSubcellBeingRead)
|
|
|
|
|
{
|
2019-07-23 14:45:42 +02:00
|
|
|
if (filetype == FILE_CIF)
|
2017-04-25 14:41:48 +02:00
|
|
|
CIFReadError("CIF ended partway through a symbol definition.\n");
|
|
|
|
|
else
|
2019-07-23 14:45:42 +02:00
|
|
|
CalmaReadError("GDS ended partway through a symbol definition.\n");
|
2017-04-25 14:41:48 +02:00
|
|
|
(void) CIFParseFinish();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
HashStartSearch(&hs);
|
|
|
|
|
while (TRUE)
|
|
|
|
|
{
|
|
|
|
|
h = HashNext(&CifCellTable, &hs);
|
|
|
|
|
if (h == NULL) break;
|
|
|
|
|
|
|
|
|
|
def = (CellDef *) HashGetValue(h);
|
|
|
|
|
if (def == NULL)
|
|
|
|
|
{
|
2019-07-23 14:45:42 +02:00
|
|
|
if (filetype == FILE_CIF)
|
2017-04-25 14:41:48 +02:00
|
|
|
CIFReadError("cell table has NULL entry (Magic error).\n");
|
|
|
|
|
else
|
2019-07-23 14:45:42 +02:00
|
|
|
CalmaReadError("cell table has NULL entry (Magic error).\n");
|
2017-04-25 14:41:48 +02:00
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
flags = def->cd_flags;
|
|
|
|
|
if (!(flags & CDAVAILABLE))
|
|
|
|
|
{
|
2019-07-23 14:45:42 +02:00
|
|
|
if (filetype == FILE_CIF)
|
2017-04-25 14:41:48 +02:00
|
|
|
CIFReadError("cell %s was used but not defined.\n", def->cd_name);
|
|
|
|
|
else
|
2019-07-23 14:45:42 +02:00
|
|
|
CalmaReadError("cell %s was used but not defined.\n", def->cd_name);
|
2017-04-25 14:41:48 +02:00
|
|
|
}
|
|
|
|
|
def->cd_flags &= ~CDPROCESSEDGDS;
|
|
|
|
|
|
2019-07-23 14:45:42 +02:00
|
|
|
if ((filetype == FILE_CIF && CIFNoDRCCheck == FALSE) ||
|
2024-10-04 12:44:01 +02:00
|
|
|
(filetype == FILE_CALMA && CalmaNoDRCCheck == FALSE))
|
2017-04-25 14:41:48 +02:00
|
|
|
DRCCheckThis(def, TT_CHECKPAINT, &def->cd_bbox);
|
|
|
|
|
DBWAreaChanged(def, &def->cd_bbox, DBW_ALLWINDOWS, &DBAllButSpaceBits);
|
|
|
|
|
DBCellSetModified(def, TRUE);
|
2022-01-22 04:17:54 +01:00
|
|
|
|
|
|
|
|
/* Only mark cell as needing a timestamp update if the timestamp is zero */
|
|
|
|
|
if (def->cd_timestamp != 0)
|
|
|
|
|
def->cd_flags &= ~CDGETNEWSTAMP;
|
2017-04-25 14:41:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Do geometrical processing on the top-level cell. */
|
|
|
|
|
|
2019-07-23 14:45:42 +02:00
|
|
|
CIFPaintCurrent(FILE_CIF);
|
2017-04-25 14:41:48 +02:00
|
|
|
DBAdjustLabels(EditCellUse->cu_def, &TiPlaneRect);
|
|
|
|
|
DBReComputeBbox(EditCellUse->cu_def);
|
|
|
|
|
DBWAreaChanged(EditCellUse->cu_def, &EditCellUse->cu_def->cd_bbox,
|
|
|
|
|
DBW_ALLWINDOWS, &DBAllButSpaceBits);
|
|
|
|
|
DBCellSetModified(EditCellUse->cu_def, TRUE);
|
|
|
|
|
|
|
|
|
|
/* Clean up saved CIF/GDS planes in cd_client records of cells */
|
|
|
|
|
|
|
|
|
|
HashStartSearch(&hs);
|
|
|
|
|
while (TRUE)
|
|
|
|
|
{
|
|
|
|
|
h = HashNext(&CifCellTable, &hs);
|
|
|
|
|
if (h == NULL) break;
|
|
|
|
|
|
|
|
|
|
def = (CellDef *) HashGetValue(h);
|
|
|
|
|
if (def == NULL) continue;
|
|
|
|
|
|
|
|
|
|
if (def->cd_flags & CDFLATGDS)
|
|
|
|
|
{
|
|
|
|
|
/* These cells have been flattened and are no longer needed. */
|
2022-06-08 22:02:40 +02:00
|
|
|
/* Do not remove the actual CellDef, though, because it is */
|
|
|
|
|
/* still instanced, and that instance tells the GDS write */
|
|
|
|
|
/* routine that the subcell needs to be included in the */
|
|
|
|
|
/* output. But all clientdata and labels should be removed. */
|
2017-04-25 14:41:48 +02:00
|
|
|
|
|
|
|
|
int pNum;
|
|
|
|
|
Plane **cifplanes = (Plane **)def->cd_client;
|
|
|
|
|
|
|
|
|
|
UndoDisable();
|
|
|
|
|
|
2020-05-08 23:02:36 +02:00
|
|
|
/* cifplanes should be valid, but don't crash magic if not */
|
2020-11-21 01:56:41 +01:00
|
|
|
if (cifplanes != (Plane **)0)
|
2017-04-25 14:41:48 +02:00
|
|
|
{
|
2020-05-08 23:02:36 +02:00
|
|
|
for (pNum = 0; pNum < MAXCIFRLAYERS; pNum++)
|
2017-04-25 14:41:48 +02:00
|
|
|
{
|
2020-05-08 23:02:36 +02:00
|
|
|
if (cifplanes[pNum] != NULL)
|
|
|
|
|
{
|
|
|
|
|
DBFreePaintPlane(cifplanes[pNum]);
|
|
|
|
|
TiFreePlane(cifplanes[pNum]);
|
|
|
|
|
}
|
2017-04-25 14:41:48 +02:00
|
|
|
}
|
2020-05-08 23:02:36 +02:00
|
|
|
freeMagic((char *)def->cd_client);
|
2017-04-25 14:41:48 +02:00
|
|
|
}
|
2020-11-21 01:56:41 +01:00
|
|
|
def->cd_client = (ClientData)0;
|
2022-01-22 17:32:43 +01:00
|
|
|
def->cd_flags &= ~CDFLATGDS;
|
2017-04-25 14:41:48 +02:00
|
|
|
|
|
|
|
|
UndoEnable();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
HashKill(&CifCellTable);
|
|
|
|
|
}
|