Implemented native gzip compression/decompression using zlib routines.

Compression levels of the output can be controlled with the "gds
compress [<value>]" command, where <value> 0 (default) is uncompressed
output, 6 is "normal" gzip compression, and 9 is maximum compression.
This commit is contained in:
Tim Edwards 2022-05-10 09:19:39 -04:00
parent 6e0768ebd4
commit 371018ae4b
16 changed files with 3102 additions and 172 deletions

View File

@ -1 +1 @@
8.3.300 8.3.301

View File

@ -91,19 +91,19 @@ typedef struct {
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
*/ */
off_t OFFTYPE
calmaSetPosition(sname) calmaSetPosition(sname)
char *sname; char *sname;
{ {
off_t originalPos = 0, currentPos = 0; OFFTYPE originalPos = 0, currentPos = 0;
int nbytes, rtype; int nbytes, rtype;
char *strname = NULL; char *strname = NULL;
int strRecSize = 0; int strRecSize = 0;
bool found = FALSE; bool found = FALSE;
originalPos = ftello(calmaInputFile); originalPos = FTELL(calmaInputFile);
while (feof(calmaInputFile) == 0) while (FEOF(calmaInputFile) == 0)
{ {
do do
{ {
@ -113,7 +113,7 @@ calmaSetPosition(sname)
/* Skip no of bytes in record header until /* Skip no of bytes in record header until
* we reach to next structure record. * we reach to next structure record.
*/ */
fseek(calmaInputFile, nbytes - CALMAHEADERLENGTH, SEEK_CUR); FSEEK(calmaInputFile, nbytes - CALMAHEADERLENGTH, SEEK_CUR);
} while (rtype != CALMA_BGNSTR); } while (rtype != CALMA_BGNSTR);
if (nbytes <= 0) break; if (nbytes <= 0) break;
@ -126,7 +126,7 @@ calmaSetPosition(sname)
*/ */
strRecSize = strlen(strname); strRecSize = strlen(strname);
if (strRecSize & 01) strRecSize++; if (strRecSize & 01) strRecSize++;
fseek(calmaInputFile, -(nbytes + strRecSize + CALMAHEADERLENGTH), FSEEK(calmaInputFile, -(nbytes + strRecSize + CALMAHEADERLENGTH),
SEEK_CUR); SEEK_CUR);
freeMagic(strname); freeMagic(strname);
return originalPos; return originalPos;
@ -188,7 +188,7 @@ calmaNextCell()
{ {
int nbytes, rtype; int nbytes, rtype;
if (feof(calmaInputFile) == 0) if (FEOF(calmaInputFile) == 0)
{ {
do do
{ {
@ -199,17 +199,17 @@ calmaNextCell()
* try to set the file pointer somewhere sane, but * try to set the file pointer somewhere sane, but
* it will likely dump an error later on. * it will likely dump an error later on.
*/ */
fseek(calmaInputFile, -(CALMAHEADERLENGTH), SEEK_END); FSEEK(calmaInputFile, -(CALMAHEADERLENGTH), SEEK_END);
return; return;
} }
/* Skip no. of bytes in record header to reach the next /* Skip no. of bytes in record header to reach the next
* structure record. * structure record.
*/ */
fseek(calmaInputFile, nbytes - CALMAHEADERLENGTH, SEEK_CUR); FSEEK(calmaInputFile, nbytes - CALMAHEADERLENGTH, SEEK_CUR);
} while((rtype != CALMA_BGNSTR) && (rtype != CALMA_ENDLIB)); } while((rtype != CALMA_BGNSTR) && (rtype != CALMA_ENDLIB));
fseek(calmaInputFile, -nbytes, SEEK_CUR); FSEEK(calmaInputFile, -nbytes, SEEK_CUR);
} }
} }
@ -307,7 +307,7 @@ calmaParseStructure(filename, origname)
int timestampval = 0; int timestampval = 0;
int suffix; int suffix;
int mfactor; int mfactor;
off_t filepos; OFFTYPE filepos;
bool was_called; bool was_called;
bool was_initialized; bool was_initialized;
bool predefined; bool predefined;
@ -327,7 +327,7 @@ calmaParseStructure(filename, origname)
TxPrintf("Reading \"%s\".\n", strname); TxPrintf("Reading \"%s\".\n", strname);
/* Used for read-only and annotated LEF views */ /* Used for read-only and annotated LEF views */
filepos = ftello(calmaInputFile); filepos = FTELL(calmaInputFile);
/* Set up the cell definition */ /* Set up the cell definition */
he = HashFind(&calmaDefInitHash, strname); he = HashFind(&calmaDefInitHash, strname);
@ -455,7 +455,7 @@ calmaParseStructure(filename, origname)
DBPropPut(cifReadCellDef, "GDS_START", (ClientData)fpcopy); DBPropPut(cifReadCellDef, "GDS_START", (ClientData)fpcopy);
fpcopy = (char *)mallocMagic(20); fpcopy = (char *)mallocMagic(20);
filepos = ftello(calmaInputFile); filepos = FTELL(calmaInputFile);
sprintf(fpcopy, "%"DLONG_PREFIX"d", (dlong) filepos); sprintf(fpcopy, "%"DLONG_PREFIX"d", (dlong) filepos);
DBPropPut(cifReadCellDef, "GDS_END", (ClientData)fpcopy); DBPropPut(cifReadCellDef, "GDS_END", (ClientData)fpcopy);
@ -743,8 +743,8 @@ calmaElementSref(filename)
* Added by Nishit 8/16/2004 * Added by Nishit 8/16/2004
*/ */
off_t originalFilePos = calmaSetPosition(sname); OFFTYPE originalFilePos = calmaSetPosition(sname);
if (!feof(calmaInputFile)) if (!FEOF(calmaInputFile))
{ {
HashTable OrigCalmaLayerHash; HashTable OrigCalmaLayerHash;
int crsMultiplier = cifCurReadStyle->crs_multiplier; int crsMultiplier = cifCurReadStyle->crs_multiplier;
@ -758,7 +758,7 @@ calmaElementSref(filename)
calmaParseStructure(filename); calmaParseStructure(filename);
/* Put things back to the way they were. */ /* Put things back to the way they were. */
fseek(calmaInputFile, originalFilePos, SEEK_SET); FSEEK(calmaInputFile, originalFilePos, SEEK_SET);
cifReadCellDef = calmaLookCell(currentSname); cifReadCellDef = calmaLookCell(currentSname);
def = calmaLookCell(sname); def = calmaLookCell(sname);
cifCurReadPlanes = savePlanes; cifCurReadPlanes = savePlanes;
@ -783,7 +783,7 @@ calmaElementSref(filename)
{ {
/* This is redundant messaging */ /* This is redundant messaging */
// TxPrintf("Cell definition %s does not exist!\n", sname); // TxPrintf("Cell definition %s does not exist!\n", sname);
fseek(calmaInputFile, originalFilePos, SEEK_SET); FSEEK(calmaInputFile, originalFilePos, SEEK_SET);
def = calmaFindCell(sname, NULL, NULL); def = calmaFindCell(sname, NULL, NULL);
/* Cell flags set to "dereferenced" in case there is no */ /* Cell flags set to "dereferenced" in case there is no */
/* definition in the GDS file. If there is a definition */ /* definition in the GDS file. If there is a definition */
@ -821,7 +821,7 @@ calmaElementSref(filename)
READI2(rows); READI2(rows);
xlo = 0; xhi = cols - 1; xlo = 0; xhi = cols - 1;
ylo = 0; yhi = rows - 1; ylo = 0; yhi = rows - 1;
if (feof(calmaInputFile)) return -1; if (FEOF(calmaInputFile)) return -1;
(void) calmaSkipBytes(nbytes - CALMAHEADERLENGTH - 4); (void) calmaSkipBytes(nbytes - CALMAHEADERLENGTH - 4);
} }
else else
@ -897,7 +897,7 @@ calmaElementSref(filename)
refarray[n].p_x *= (savescale / cifCurReadStyle->crs_scaleFactor); refarray[n].p_x *= (savescale / cifCurReadStyle->crs_scaleFactor);
} }
if (feof(calmaInputFile)) if (FEOF(calmaInputFile))
return -1; return -1;
} }

View File

@ -219,7 +219,7 @@ calmaReadI2Record(type, pvalue)
/* Read the value */ /* Read the value */
READI2(n); READI2(n);
if (feof(calmaInputFile)) goto eof; if (FEOF(calmaInputFile)) goto eof;
*pvalue = n; *pvalue = n;
return (TRUE); return (TRUE);
@ -264,7 +264,7 @@ calmaReadI4Record(type, pvalue)
/* Read the value */ /* Read the value */
READI4(n); READI4(n);
if (feof(calmaInputFile)) goto eof; if (FEOF(calmaInputFile)) goto eof;
*pvalue = n; *pvalue = n;
return (TRUE); return (TRUE);
@ -386,7 +386,7 @@ calmaReadStringRecord(type, str)
nbytes -= CALMAHEADERLENGTH; nbytes -= CALMAHEADERLENGTH;
*str = (char *) mallocMagic(nbytes + 1); *str = (char *) mallocMagic(nbytes + 1);
if (fread(*str, sizeof (char), nbytes, calmaInputFile) != nbytes) if (FREAD(*str, sizeof (char), nbytes, calmaInputFile) != nbytes)
goto eof; goto eof;
*(*str + nbytes) = '\0'; *(*str + nbytes) = '\0';
@ -425,7 +425,7 @@ calmaReadR8(pd)
double mantissa, d; double mantissa, d;
bool isneg; bool isneg;
if (fread((char *) dchars, sizeof (char), sizeof dchars, if (FREAD((char *) dchars, sizeof (char), sizeof dchars,
calmaInputFile) != sizeof dchars) calmaInputFile) != sizeof dchars)
return (FALSE); return (FALSE);
@ -616,7 +616,7 @@ calmaSkipBytes(nbytes)
int nbytes; /* Skip this many bytes */ int nbytes; /* Skip this many bytes */
{ {
while (nbytes-- > 0) while (nbytes-- > 0)
if (getc(calmaInputFile) < 0) if (FGETC(calmaInputFile) < 0)
return (FALSE); return (FALSE);
return (TRUE); return (TRUE);

View File

@ -1075,7 +1075,7 @@ calmaReadPath(pathheadpp, iscale)
CalmaReadError("Warning: Very large point in path: (%d, %d)\n", CalmaReadError("Warning: Very large point in path: (%d, %d)\n",
path.cifp_x, path.cifp_y); path.cifp_x, path.cifp_y);
} }
if (feof(calmaInputFile)) if (FEOF(calmaInputFile))
{ {
CIFFreePath(*pathheadpp); CIFFreePath(*pathheadpp);
return (FALSE); return (FALSE);

View File

@ -50,7 +50,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
#include "utils/undo.h" #include "utils/undo.h"
/* Globals for Calma reading */ /* Globals for Calma reading */
FILE *calmaInputFile = NULL; /* Read from this stream */ FILETYPE calmaInputFile = NULL; /* Read from this stream */
FILE *calmaErrorFile = NULL; /* Write error output here */ FILE *calmaErrorFile = NULL; /* Write error output here */
bool CalmaSubcellPolygons = FALSE; /* Put non-Manhattan polygons bool CalmaSubcellPolygons = FALSE; /* Put non-Manhattan polygons
* in their own subcells. * in their own subcells.
@ -153,7 +153,7 @@ int calmaElementIgnore[] = { CALMA_ELFLAGS, CALMA_PLEX, -1 };
void void
CalmaReadFile(file, filename, origname) CalmaReadFile(file, filename, origname)
FILE *file; /* File from which to read Calma */ FILETYPE file; /* File from which to read Calma */
char *filename; /* The real name of the file read */ char *filename; /* The real name of the file read */
char *origname; /* Original name of file read (used for char *origname; /* Original name of file read (used for
* compressed files) * compressed files)
@ -269,7 +269,7 @@ done:
HashKill(&calmaDefInitHash); HashKill(&calmaDefInitHash);
UndoEnable(); UndoEnable();
if (calmaErrorFile != NULL) fclose(calmaErrorFile); if (calmaErrorFile != NULL) FCLOSE(calmaErrorFile);
} }
/* /*
@ -386,14 +386,14 @@ CalmaReadError(format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10)
char *format; char *format;
char *a1, *a2, *a3, *a4, *a5, *a6, *a7, *a8, *a9, *a10; char *a1, *a2, *a3, *a4, *a5, *a6, *a7, *a8, *a9, *a10;
{ {
off_t filepos; OFFTYPE filepos;
calmaTotalErrors++; calmaTotalErrors++;
if (CIFWarningLevel == CIF_WARN_NONE) return; if (CIFWarningLevel == CIF_WARN_NONE) return;
if ((calmaTotalErrors < 100) || (CIFWarningLevel != CIF_WARN_LIMIT)) if ((calmaTotalErrors < 100) || (CIFWarningLevel != CIF_WARN_LIMIT))
{ {
filepos = ftello(calmaInputFile); filepos = FTELL(calmaInputFile);
if (CIFWarningLevel == CIF_WARN_REDIRECT) if (CIFWarningLevel == CIF_WARN_REDIRECT)
{ {

View File

@ -66,6 +66,10 @@ bool CalmaAllowUndefined = FALSE; /* If TRUE, allow calls to undefined cells */
bool CalmaContactArrays = FALSE; /* If TRUE, output contacts as subcell arrays */ bool CalmaContactArrays = FALSE; /* If TRUE, output contacts as subcell arrays */
bool CalmaMergeTiles = FALSE; /* If TRUE, merge tiles into polygons in output. */ bool CalmaMergeTiles = FALSE; /* If TRUE, merge tiles into polygons in output. */
#ifdef HAVE_ZLIB
int CalmaCompression = 0; /* Output file compression level (0 = uncompressed) */
#endif
/* Forward declarations */ /* Forward declarations */
extern int calmaWriteInitFunc(); extern int calmaWriteInitFunc();
extern int calmaWriteMarkFunc(); extern int calmaWriteMarkFunc();
@ -286,7 +290,7 @@ CalmaWrite(rootDef, f)
CellDef *rootDef; /* Pointer to CellDef to be written */ CellDef *rootDef; /* Pointer to CellDef to be written */
FILE *f; /* Open output file */ FILE *f; /* Open output file */
{ {
int oldCount = DBWFeedbackCount, problems; int oldCount = DBWFeedbackCount, problems, nerr;
bool good; bool good;
CellUse dummy; CellUse dummy;
HashEntry *he; HashEntry *he;

2714
calma/CalmaWriteZ.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -4,7 +4,7 @@
MODULE = calma MODULE = calma
MAGICDIR = .. MAGICDIR = ..
SRCS = CalmaRead.c CalmaRdcl.c CalmaRdio.c CalmaRdpt.c CalmaWrite.c SRCS = CalmaRead.c CalmaRdcl.c CalmaRdio.c CalmaRdpt.c CalmaWrite.c CalmaWriteZ.c
include ${MAGICDIR}/defs.mak include ${MAGICDIR}/defs.mak
include ${MAGICDIR}/rules.mak include ${MAGICDIR}/rules.mak

View File

@ -42,6 +42,9 @@ extern bool CalmaFlattenUses;
extern char **CalmaFlattenUsesByName; extern char **CalmaFlattenUsesByName;
extern bool CalmaReadOnly; extern bool CalmaReadOnly;
extern bool CalmaContactArrays; extern bool CalmaContactArrays;
#ifdef HAVE_ZLIB
extern bool CalmaCompression;
#endif
extern bool CalmaPostOrder; extern bool CalmaPostOrder;
extern bool CalmaAllowUndefined; extern bool CalmaAllowUndefined;

View File

@ -25,6 +25,10 @@
#include "utils/magic.h" #include "utils/magic.h"
#include "database/database.h" #include "database/database.h"
#ifdef HAVE_ZLIB
#include <zlib.h>
#endif
/* Record data types */ /* Record data types */
#define CALMA_NODATA 0 /* No data present */ #define CALMA_NODATA 0 /* No data present */
#define CALMA_BITARRAY 1 /* Bit array */ #define CALMA_BITARRAY 1 /* Bit array */
@ -136,8 +140,30 @@ typedef enum { LABEL_TYPE_NONE, LABEL_TYPE_TEXT, LABEL_TYPE_PORT, LABEL_TYPE_CEL
/* ------------------------- Input macros ----------------------------- */ /* ------------------------- Input macros ----------------------------- */
#ifdef HAVE_ZLIB
#define FOPEN gzopen
#define FCLOSE gzclose
#define FGETC gzgetc
#define FREAD(a,b,c,d) gzread(d,a,b*c)
#define FEOF gzeof
#define FSEEK gzseek
#define FTELL gztell
#define FILETYPE gzFile
#define OFFTYPE z_off_t
#else
#define FOPEN fopen
#define FCLOSE fclose
#define FGETC getc
#define FREAD fread
#define FEOF feof
#define FSEEK fseek
#define FTELL ftello
#define FILETYPE FILE *
#define OFFTYPE off_t
#endif
/* Globals for Calma reading */ /* Globals for Calma reading */
extern FILE *calmaInputFile; extern FILETYPE calmaInputFile;
extern char *calmaFilename; extern char *calmaFilename;
extern int calmaReadScale1; extern int calmaReadScale1;
extern int calmaReadScale2; extern int calmaReadScale2;
@ -168,8 +194,8 @@ typedef union { char uc[4]; unsigned int ul; } FourByteInt;
#define READI2(z) \ #define READI2(z) \
{ \ { \
TwoByteInt u; \ TwoByteInt u; \
u.uc[0] = getc(calmaInputFile); \ u.uc[0] = FGETC(calmaInputFile); \
u.uc[1] = getc(calmaInputFile); \ u.uc[1] = FGETC(calmaInputFile); \
(z) = (int) ntohs(u.us); \ (z) = (int) ntohs(u.us); \
} }
@ -177,10 +203,10 @@ typedef union { char uc[4]; unsigned int ul; } FourByteInt;
#define READI4(z) \ #define READI4(z) \
{ \ { \
FourByteInt u; \ FourByteInt u; \
u.uc[0] = getc(calmaInputFile); \ u.uc[0] = FGETC(calmaInputFile); \
u.uc[1] = getc(calmaInputFile); \ u.uc[1] = FGETC(calmaInputFile); \
u.uc[2] = getc(calmaInputFile); \ u.uc[2] = FGETC(calmaInputFile); \
u.uc[3] = getc(calmaInputFile); \ u.uc[3] = FGETC(calmaInputFile); \
(z) = (int) ntohl(u.ul); \ (z) = (int) ntohl(u.ul); \
} }
@ -193,10 +219,10 @@ typedef union { char uc[4]; unsigned int ul; } FourByteInt;
calmaLApresent = FALSE; \ calmaLApresent = FALSE; \
} else { \ } else { \
READI2(nb); \ READI2(nb); \
if (feof(calmaInputFile)) nb = -1; \ if (FEOF(calmaInputFile)) nb = -1; \
else { \ else { \
(rt) = getc(calmaInputFile); \ (rt) = FGETC(calmaInputFile); \
(void) getc(calmaInputFile); \ (void) FGETC(calmaInputFile); \
} \ } \
} \ } \
} }

View File

@ -49,6 +49,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
#include "utils/malloc.h" #include "utils/malloc.h"
#include "cif/CIFint.h" #include "cif/CIFint.h"
#include "cif/CIFread.h" #include "cif/CIFread.h"
#include "calma/calmaInt.h"
/* The following structure is used by CmdCorner to keep track of /* The following structure is used by CmdCorner to keep track of
* areas to be filled. * areas to be filled.
@ -91,28 +92,29 @@ bool cmdDumpParseArgs();
#define CALMA_HELP 0 #define CALMA_HELP 0
#define CALMA_ADDENDUM 1 #define CALMA_ADDENDUM 1
#define CALMA_ARRAYS 2 #define CALMA_ARRAYS 2
#define CALMA_CONTACTS 3 #define CALMA_COMPRESS 3
#define CALMA_DATESTAMP 4 #define CALMA_CONTACTS 4
#define CALMA_DRCCHECK 5 #define CALMA_DATESTAMP 5
#define CALMA_FLATTEN 6 #define CALMA_DRCCHECK 6
#define CALMA_FLATGLOB 7 #define CALMA_FLATTEN 7
#define CALMA_ORDERING 8 #define CALMA_FLATGLOB 8
#define CALMA_LABELS 9 #define CALMA_ORDERING 9
#define CALMA_LIBRARY 10 #define CALMA_LABELS 10
#define CALMA_LOWER 11 #define CALMA_LIBRARY 11
#define CALMA_MASKHINTS 12 #define CALMA_LOWER 12
#define CALMA_MERGE 13 #define CALMA_MASKHINTS 13
#define CALMA_NO_STAMP 14 #define CALMA_MERGE 14
#define CALMA_NO_DUP 15 #define CALMA_NO_STAMP 15
#define CALMA_READ 16 #define CALMA_NO_DUP 16
#define CALMA_READONLY 17 #define CALMA_READ 17
#define CALMA_RESCALE 18 #define CALMA_READONLY 18
#define CALMA_WARNING 19 #define CALMA_RESCALE 19
#define CALMA_WRITE 20 #define CALMA_WARNING 20
#define CALMA_POLYS 21 #define CALMA_WRITE 21
#define CALMA_PATHS 22 #define CALMA_POLYS 22
#define CALMA_UNDEFINED 23 #define CALMA_PATHS 23
#define CALMA_UNIQUE 24 #define CALMA_UNDEFINED 24
#define CALMA_UNIQUE 25
#define CALMA_WARN_HELP CIF_WARN_END /* undefined by CIF module */ #define CALMA_WARN_HELP CIF_WARN_END /* undefined by CIF module */
@ -121,17 +123,18 @@ CmdCalma(w, cmd)
MagWindow *w; MagWindow *w;
TxCommand *cmd; TxCommand *cmd;
{ {
int option, ext; int option, ext, value;
char **msg, *namep, *dotptr; char **msg, *namep, *dotptr;
char writeMode[3];
CellDef *rootDef; CellDef *rootDef;
FILE *f; FILE *f;
int namelen; #ifdef HAVE_ZLIB
bool gzipd; gzFile fz;
char *realName, *saveName, *modName; #endif
extern int CalmaFlattenLimit; extern int CalmaFlattenLimit;
static char *gdsExts[] = {".gds", ".gds2", ".strm", "", NULL}; static char *gdsExts[] = {".gds", ".gds.gz", ".gds2", ".strm", "", NULL};
static char *cmdCalmaYesNo[] = { static char *cmdCalmaYesNo[] = {
"no", "false", "off", "0", "yes", "true", "on", "1", 0 }; "no", "false", "off", "0", "yes", "true", "on", "1", 0 };
static char *cmdCalmaAllowDisallow[] = {"disallow", "0", "allow", "1", 0}; static char *cmdCalmaAllowDisallow[] = {"disallow", "0", "allow", "1", 0};
@ -142,6 +145,7 @@ CmdCalma(w, cmd)
"help print this help information", "help print this help information",
"addendum [yes|no] output only cells that are not type \"readonly\"", "addendum [yes|no] output only cells that are not type \"readonly\"",
"arrays [yes|no] output arrays as individual subuses (like in CIF)", "arrays [yes|no] output arrays as individual subuses (like in CIF)",
"compress [value] compress output with zlib compression 0 to 6",
"contacts [yes|no] optimize output by arraying contacts as subcells", "contacts [yes|no] optimize output by arraying contacts as subcells",
"datestamp [yes|value] use current time or value as the creation date stamp", "datestamp [yes|value] use current time or value as the creation date stamp",
"drccheck [yes|no] mark all cells as needing DRC checking", "drccheck [yes|no] mark all cells as needing DRC checking",
@ -312,6 +316,41 @@ CmdCalma(w, cmd)
CalmaAllowUndefined = (option < 2) ? FALSE : TRUE; CalmaAllowUndefined = (option < 2) ? FALSE : TRUE;
return; return;
case CALMA_COMPRESS:
if (cmd->tx_argc == 2)
{
#ifdef HAVE_ZLIB
#ifdef MAGIC_WRAPPER
Tcl_SetObjResult(magicinterp, Tcl_NewIntObj(CalmaCompression));
#else
if (CalmaCompression == 0)
TxPrintf("Calma files are not compressed.\n");
else
TxPrintf("Calma files are compressed with zlib compression level %d.\n", CalmaCompression);
#endif
#else /* !HAVE_ZLIB */
#ifdef MAGIC_WRAPPER
Tcl_SetObjResult(magicinterp, Tcl_NewIntObj(0));
#else
TxPrintf("No file compression has been enabled.\n");
#endif
#endif /* !HAVE_ZLIB */
return;
}
#ifdef HAVE_ZLIB
else if (cmd->tx_argc != 3)
goto wrongNumArgs;
value = atoi(cmd->tx_argv[2]);
if ((value < 0) || (value > 9))
TxError("Bad compression value %d. Value must be in the range 0 to 9.\n", value);
else
CalmaCompression = value;
#else
goto wrongNumArgs;
#endif
return;
case CALMA_CONTACTS: case CALMA_CONTACTS:
if (cmd->tx_argc == 2) if (cmd->tx_argc == 2)
{ {
@ -873,58 +912,15 @@ CmdCalma(w, cmd)
case CALMA_READ: case CALMA_READ:
if (cmd->tx_argc != 3) goto wrongNumArgs; if (cmd->tx_argc != 3) goto wrongNumArgs;
/* Check for compressed files, and uncompress them. */
/* Always uncompress into the current working directory */
/* because the original compressed file might be in an */
/* unwriteable directory. */
modName = cmd->tx_argv[2];
namelen = strlen(modName);
if ((namelen > 4) && !strcmp(modName + namelen - 3, ".gz"))
{
char *sysCmd, *sptr;
/* First try to open the uncompressed file name. If */
/* the file exists, then don't try to uncompress on top */
/* of it, but just fail. */
sptr = strrchr(modName, '/');
if (sptr == NULL)
sptr = modName;
else
sptr++;
modName = StrDup((char **)NULL, sptr);
*(modName + strlen(modName) - 3) = '\0';
if ((f = PaOpen(modName, "r", NULL, Path,
(char *)NULL, NULL)) != (FILE *)NULL)
{
fclose(f);
TxError("Uncompressed file \"%s\" already exists!\n", modName);
freeMagic(modName);
return;
}
sysCmd = mallocMagic(18 + namelen + strlen(modName));
/* Note: "-k" keeps the original compressed file */
TxPrintf("Uncompressing file \"%s\".\n", cmd->tx_argv[2]);
sprintf(sysCmd, "gunzip -c %s > %s", cmd->tx_argv[2], modName);
if (system(sysCmd) != 0)
{
freeMagic(modName);
modName = NULL;
}
freeMagic(sysCmd);
}
/* Check for various common file extensions, including */ /* Check for various common file extensions, including */
/* no extension (as-is), ".gds", ".gds2", and ".strm". */ /* no extension (as-is), ".gds", ".gds2", and ".strm". */
for (ext = 0; gdsExts[ext] != NULL; ext++) for (ext = 0; gdsExts[ext] != NULL; ext++)
if ((f = PaOpen(modName, "r", gdsExts[ext], Path, if ((f = PaZOpen(cmd->tx_argv[2], "r", gdsExts[ext], Path,
(char *) NULL, &namep)) != (FILE *)NULL) (char *) NULL, &namep)) != (FILETYPE)NULL)
break; break;
if (f == (FILE *) NULL) if (f == (FILETYPE) NULL)
{ {
TxError("Cannot open %s.gds, %s.strm or %s to read " TxError("Cannot open %s.gds, %s.strm or %s to read "
"GDS-II stream input.\n", "GDS-II stream input.\n",
@ -932,19 +928,7 @@ CmdCalma(w, cmd)
return; return;
} }
CalmaReadFile(f, namep, cmd->tx_argv[2]); CalmaReadFile(f, namep, cmd->tx_argv[2]);
(void) fclose(f); (void) FCLOSE(f);
if (modName != cmd->tx_argv[2])
{
/* A gzipped file was read and now the uncompressed */
/* file that was generated should be removed. */
if (unlink(namep) != 0)
{
TxError("Error attempting to delete uncompressed file \"%s\"\n",
namep);
}
freeMagic(modName);
}
return; return;
} }
@ -956,54 +940,49 @@ CmdCalma(w, cmd)
outputCalma: outputCalma:
dotptr = strrchr(namep, '.'); dotptr = strrchr(namep, '.');
/* Check for additional ".gz" extension */ #ifdef HAVE_ZLIB
if (dotptr && !strcmp(dotptr, ".gz")) /* Handle compression based on value of CalmaCompression */
if (CalmaCompression > 0)
{ {
gzipd = TRUE; sprintf(writeMode, "w%d", CalmaCompression);
*dotptr = '\0'; fz = PaZOpen(namep, writeMode, (dotptr == NULL) ? ".gds.gz" : "", ".", (char *) NULL, (char **)NULL);
dotptr = strrchr(namep, '.'); if (fz == (gzFile)NULL)
{
TxError("Cannot open %s%s to write compressed GDS-II stream output\n", namep,
(dotptr == NULL) ? ".gds.gz" : "");
return;
}
if (!CalmaWriteZ(rootDef, fz))
{
TxError("I/O error in writing compressed file %s.\n", namep);
TxError("File may be incompletely written.\n");
}
(void) gzclose(fz);
} }
else else
gzipd = FALSE;
f = PaOpen(namep, "w", (dotptr == NULL) ? ".gds" : "", ".",
(char *) NULL, (char **)&realName);
if (gzipd)
saveName = StrDup((char **)NULL, realName);
if (f == (FILE *) NULL)
{ {
TxError("Cannot open %s%s to write GDS-II stream output\n", namep,
(dotptr == NULL) ? ".gds" : "");
return;
}
if (!CalmaWrite(rootDef, f))
{
TxError("I/O error in writing file %s.\n", namep);
TxError("File may be incompletely written.\n");
}
(void) fclose(f);
if (gzipd)
{
char *sysCmd;
sysCmd = mallocMagic(16 + strlen(saveName));
TxPrintf("Compressing file \"%s\"\n", saveName);
sprintf(sysCmd, "gzip -n --best %s", saveName);
/* Note that without additional arguments, "gzip" will wholly */
/* replace the uncompressed file with the compressed one. */
if (system(sysCmd) != 0)
{
TxError("Failed to compress file \"%s\"\n", saveName);
}
freeMagic(sysCmd);
freeMagic(saveName);
}
}
#endif #endif
f = PaOpen(namep, "w", (dotptr == NULL) ? ".gds" : "", ".", (char *) NULL, (char **)NULL);
if (f == (FILE *)NULL)
{
TxError("Cannot open %s%s to write GDS-II stream output\n", namep,
(dotptr == NULL) ? ".gds" : "");
return;
}
if (!CalmaWrite(rootDef, f))
{
TxError("I/O error in writing file %s.\n", namep);
TxError("File may be incompletely written.\n");
}
(void) fclose(f);
#ifdef HAVE_ZLIB
}
#endif
}
#endif /* CALMA_MODULE */
/* /*
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
@ -5095,3 +5074,4 @@ cmdDumpFunc(rect, name, label, point)
*point = rect->r_ll; *point = rect->r_ll;
return 1; return 1;
} }

View File

@ -194,6 +194,16 @@ Read GDSII input or generate GDSII output.
<DT> <B>arrays</B> [<B>yes</B>|<B>no</B>] <DT> <B>arrays</B> [<B>yes</B>|<B>no</B>]
<DD> Output arrays as individual subuses (like in CIF). Default <DD> Output arrays as individual subuses (like in CIF). Default
is "no". Normally there is no reason to do this. is "no". Normally there is no reason to do this.
<DT> <B>compress</B> [<I>value</I>]
<DD> For non-zero <I>value</I>, apply gzip-style compression to the
output stream. Per the gzip compression algorithm, <I>value</I>
represents a level of compression effort, and ranges from 1 to
9. When <I>value</I> is zero, no compression is applied and the
output is standard GDS format, and the output file extension is
".gds". When <I>value</I> is non-zero, compression is applied,
and the output file extension is ".gds.gz". With no argument,
return the current compression setting. The default compression
setting is zero (no compression applied; output is plain GDS).
<DT> <B>contacts</B> [<B>yes</B>|<B>no</B>] <DT> <B>contacts</B> [<B>yes</B>|<B>no</B>]
<DD> Causes contacts to be written to the GDS file as subcell <DD> Causes contacts to be written to the GDS file as subcell
arrays (experimental, introduced in version 7.3.55). This arrays (experimental, introduced in version 7.3.55). This
@ -270,6 +280,10 @@ Read GDSII input or generate GDSII output.
If no option is given, a CALMA GDS-II stream file is produced for the If no option is given, a CALMA GDS-II stream file is produced for the
root cell, with the default name of the root cell definition and the root cell, with the default name of the root cell definition and the
filename extension ".gds". <P> filename extension ".gds". <P>
<B>gds read</B> will read both (gzip-)compressed and uncompressed GDS
files. <B>gds write</B> will only write compressed files as indicated
by the <B>gds compress</B> setting. <P>
</BLOCKQUOTE> </BLOCKQUOTE>
<H3>Implementation Notes:</H3> <H3>Implementation Notes:</H3>
@ -307,6 +321,6 @@ Read GDSII input or generate GDSII output.
<TD> <A HREF=commands.html>Return to command index</A> <TD> <A HREF=commands.html>Return to command index</A>
</TR> </TR>
</TABLE> </TABLE>
<P><I>Last updated:</I> April 27, 2021 at 1:06pm <P> <P><I>Last updated:</I> May 10, 2022 at 9:14am <P>
</BODY> </BODY>
</HTML> </HTML>

43
scripts/configure vendored
View File

@ -5035,6 +5035,49 @@ $as_echo "#define HAVE___VA_COPY 1" >>confdefs.h
fi fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for gzopen in -lz" >&5
$as_echo_n "checking for gzopen in -lz... " >&6; }
if ${ac_cv_lib_z_gzopen+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
LIBS="-lz $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
char gzopen ();
int
main ()
{
return gzopen ();
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
ac_cv_lib_z_gzopen=yes
else
ac_cv_lib_z_gzopen=no
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_z_gzopen" >&5
$as_echo "$ac_cv_lib_z_gzopen" >&6; }
if test "x$ac_cv_lib_z_gzopen" = xyes; then :
$as_echo "#define HAVE_ZLIB 1" >>confdefs.h
fi

View File

@ -178,6 +178,9 @@ then
AC_DEFINE(HAVE___VA_COPY, 1, [Define if we have __va_copy]) AC_DEFINE(HAVE___VA_COPY, 1, [Define if we have __va_copy])
fi fi
dnl Check for zlib
AC_CHECK_LIB([z],[gzopen],[AC_DEFINE([HAVE_ZLIB],[1],["zlib compression"])])
dnl Check for some C99 functions dnl Check for some C99 functions
dnl Built-in round/roundf require CFLAGS -std=c99, but this also dnl Built-in round/roundf require CFLAGS -std=c99, but this also

View File

@ -28,6 +28,10 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
#include <ctype.h> #include <ctype.h>
#include <sys/param.h> #include <sys/param.h>
#ifdef HAVE_ZLIB
#include <zlib.h>
#endif
#include "tcltk/tclmagic.h" #include "tcltk/tclmagic.h"
#include "utils/magic.h" #include "utils/magic.h"
#include "utils/hash.h" #include "utils/hash.h"
@ -531,6 +535,137 @@ PaLockOpen(file, mode, ext, path, library, pRealName, is_locked)
return NULL; return NULL;
} }
#ifdef HAVE_ZLIB
/*-------------------------------------------------------------------
* PaZOpen --
* This routine does a file lookup using the current path and
* supplying a default extension. The return type is a Zlib-
* type compressed stream.
*
* Results:
* A gzFile type, or NULL if the file couldn't be found.
*
* Side Effects:
* See notes for PaLockOpen() for handling of extensions.
*
* Path Format:
* A path is a string containing directory names separated by
* colons or white space. Tilde notation may be used within paths.
*-------------------------------------------------------------------
*/
gzFile
PaZOpen(file, mode, ext, path, library, pRealName)
char *file; /* Name of the file to be opened. */
char *mode; /* The file mode, as given to gzopen. */
char *ext; /* The extension to be added to the file name,
* or NULL. Note: this string must include
* the dot (or whatever separator you use).
*/
char *path; /* A search path: a list of directory names
* separated by colons or blanks. To use
* only the working directory, use "." for
* the path.
*/
char *library; /* A 2nd path containing library names. Can be
* NULL to indicate no library.
*/
char **pRealName; /* Pointer to a location that will be filled
* in with the address of the real name of
* the file that was successfully opened.
* If NULL, then nothing is stored.
*/
{
char extendedName[MAXSIZE], *p1, *p2;
static char realName[MAXSIZE];
int length, extLength, i;
gzFile f;
if (file == NULL) return (gzFile) NULL;
if (file[0] == '\0') return (gzFile) NULL;
if (pRealName != NULL) (*pRealName) = realName;
/* See if we must supply an extension. */
length = strlen(file);
if (length >= MAXSIZE) length = MAXSIZE - 1;
if (ext != NULL)
{
(void) strncpy(extendedName, file, length + 1);
i = MAXSIZE - 1 - length;
extLength = strlen(ext);
if (extLength > i) extLength = i;
(void) strncpy(&(extendedName[length]), ext, extLength + 1);
extendedName[MAXSIZE-1] = '\0';
file = extendedName;
}
/* If the first character of the file name is a tilde or dollar sign,
* do tilde or environment variable expansion but don't touch a search
* path.
*/
if (file[0] == '~' || file[0] == '$')
{
p1 = realName;
p2 = file;
if (PaExpand(&p2, &p1, MAXSIZE) < 0) return NULL;
return gzopen(realName, mode);
}
/* If we were already given a full rooted file name,
* or a relative pathname, just use it.
*/
if (file[0] == '/'
|| (file[0] == '.' && (strcmp(file, ".") == 0
|| strncmp(file, "./", 2) == 0
|| strcmp(file, "..") == 0
|| strncmp(file, "../", 3) == 0)))
{
(void) strncpy(realName, file, MAXSIZE-1);
realName[MAXSIZE-1] = '\0';
return gzopen(realName, mode);
}
/* Now try going through the path, one entry at a time. */
while (nextName(&path, file, realName, MAXSIZE) != NULL)
{
if (*realName == 0) continue;
f = gzopen(realName, mode);
if (f != NULL) return f;
// If any error other than "file not found" occurred,
// then halt immediately.
if (errno != ENOENT) return NULL;
}
/* We've tried the path and that didn't work. Now go through
* the library area, one entry at a time.
*/
if (library == NULL) return NULL;
while (nextName(&library, file, realName, MAXSIZE) != NULL)
{
f = gzopen(realName, mode);
if (f != NULL) return f;
// If any error other than "file not found" occurred,
// then halt immediately.
if (errno != ENOENT) return NULL;
}
return NULL;
}
#endif /* HAVE_ZLIB */
/* /*
*------------------------------------------------------------------- *-------------------------------------------------------------------
* PaOpen -- * PaOpen --

View File

@ -21,6 +21,10 @@
#ifndef _UTILS_H #ifndef _UTILS_H
#define _UTILS_H 1 #define _UTILS_H 1
#ifdef HAVE_ZLIB
#include <zlib.h>
#endif
#include "utils/magic.h" #include "utils/magic.h"
/* /*
@ -52,6 +56,10 @@ extern bool StrIsWhite(char *, bool);
extern bool StrIsInt(char *); extern bool StrIsInt(char *);
extern bool StrIsNumeric(char *); extern bool StrIsNumeric(char *);
#ifdef HAVE_ZLIB
extern gzFile PaZOpen(char *, char *, char *, char *, char *, char **);
#endif
extern int SetNoisyBool(bool *, char *, FILE *); extern int SetNoisyBool(bool *, char *, FILE *);
#ifdef FILE_LOCKS #ifdef FILE_LOCKS