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

View File

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

View File

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

View File

@ -50,7 +50,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
#include "utils/undo.h"
/* 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 */
bool CalmaSubcellPolygons = FALSE; /* Put non-Manhattan polygons
* in their own subcells.
@ -153,7 +153,7 @@ int calmaElementIgnore[] = { CALMA_ELFLAGS, CALMA_PLEX, -1 };
void
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 *origname; /* Original name of file read (used for
* compressed files)
@ -269,7 +269,7 @@ done:
HashKill(&calmaDefInitHash);
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 *a1, *a2, *a3, *a4, *a5, *a6, *a7, *a8, *a9, *a10;
{
off_t filepos;
OFFTYPE filepos;
calmaTotalErrors++;
if (CIFWarningLevel == CIF_WARN_NONE) return;
if ((calmaTotalErrors < 100) || (CIFWarningLevel != CIF_WARN_LIMIT))
{
filepos = ftello(calmaInputFile);
filepos = FTELL(calmaInputFile);
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 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 */
extern int calmaWriteInitFunc();
extern int calmaWriteMarkFunc();
@ -286,7 +290,7 @@ CalmaWrite(rootDef, f)
CellDef *rootDef; /* Pointer to CellDef to be written */
FILE *f; /* Open output file */
{
int oldCount = DBWFeedbackCount, problems;
int oldCount = DBWFeedbackCount, problems, nerr;
bool good;
CellUse dummy;
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
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}/rules.mak

View File

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

View File

@ -25,6 +25,10 @@
#include "utils/magic.h"
#include "database/database.h"
#ifdef HAVE_ZLIB
#include <zlib.h>
#endif
/* Record data types */
#define CALMA_NODATA 0 /* No data present */
#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 ----------------------------- */
#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 */
extern FILE *calmaInputFile;
extern FILETYPE calmaInputFile;
extern char *calmaFilename;
extern int calmaReadScale1;
extern int calmaReadScale2;
@ -168,8 +194,8 @@ typedef union { char uc[4]; unsigned int ul; } FourByteInt;
#define READI2(z) \
{ \
TwoByteInt u; \
u.uc[0] = getc(calmaInputFile); \
u.uc[1] = getc(calmaInputFile); \
u.uc[0] = FGETC(calmaInputFile); \
u.uc[1] = FGETC(calmaInputFile); \
(z) = (int) ntohs(u.us); \
}
@ -177,10 +203,10 @@ typedef union { char uc[4]; unsigned int ul; } FourByteInt;
#define READI4(z) \
{ \
FourByteInt u; \
u.uc[0] = getc(calmaInputFile); \
u.uc[1] = getc(calmaInputFile); \
u.uc[2] = getc(calmaInputFile); \
u.uc[3] = getc(calmaInputFile); \
u.uc[0] = FGETC(calmaInputFile); \
u.uc[1] = FGETC(calmaInputFile); \
u.uc[2] = FGETC(calmaInputFile); \
u.uc[3] = FGETC(calmaInputFile); \
(z) = (int) ntohl(u.ul); \
}
@ -193,10 +219,10 @@ typedef union { char uc[4]; unsigned int ul; } FourByteInt;
calmaLApresent = FALSE; \
} else { \
READI2(nb); \
if (feof(calmaInputFile)) nb = -1; \
if (FEOF(calmaInputFile)) nb = -1; \
else { \
(rt) = getc(calmaInputFile); \
(void) getc(calmaInputFile); \
(rt) = FGETC(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 "cif/CIFint.h"
#include "cif/CIFread.h"
#include "calma/calmaInt.h"
/* The following structure is used by CmdCorner to keep track of
* areas to be filled.
@ -91,28 +92,29 @@ bool cmdDumpParseArgs();
#define CALMA_HELP 0
#define CALMA_ADDENDUM 1
#define CALMA_ARRAYS 2
#define CALMA_CONTACTS 3
#define CALMA_DATESTAMP 4
#define CALMA_DRCCHECK 5
#define CALMA_FLATTEN 6
#define CALMA_FLATGLOB 7
#define CALMA_ORDERING 8
#define CALMA_LABELS 9
#define CALMA_LIBRARY 10
#define CALMA_LOWER 11
#define CALMA_MASKHINTS 12
#define CALMA_MERGE 13
#define CALMA_NO_STAMP 14
#define CALMA_NO_DUP 15
#define CALMA_READ 16
#define CALMA_READONLY 17
#define CALMA_RESCALE 18
#define CALMA_WARNING 19
#define CALMA_WRITE 20
#define CALMA_POLYS 21
#define CALMA_PATHS 22
#define CALMA_UNDEFINED 23
#define CALMA_UNIQUE 24
#define CALMA_COMPRESS 3
#define CALMA_CONTACTS 4
#define CALMA_DATESTAMP 5
#define CALMA_DRCCHECK 6
#define CALMA_FLATTEN 7
#define CALMA_FLATGLOB 8
#define CALMA_ORDERING 9
#define CALMA_LABELS 10
#define CALMA_LIBRARY 11
#define CALMA_LOWER 12
#define CALMA_MASKHINTS 13
#define CALMA_MERGE 14
#define CALMA_NO_STAMP 15
#define CALMA_NO_DUP 16
#define CALMA_READ 17
#define CALMA_READONLY 18
#define CALMA_RESCALE 19
#define CALMA_WARNING 20
#define CALMA_WRITE 21
#define CALMA_POLYS 22
#define CALMA_PATHS 23
#define CALMA_UNDEFINED 24
#define CALMA_UNIQUE 25
#define CALMA_WARN_HELP CIF_WARN_END /* undefined by CIF module */
@ -121,17 +123,18 @@ CmdCalma(w, cmd)
MagWindow *w;
TxCommand *cmd;
{
int option, ext;
int option, ext, value;
char **msg, *namep, *dotptr;
char writeMode[3];
CellDef *rootDef;
FILE *f;
int namelen;
bool gzipd;
char *realName, *saveName, *modName;
#ifdef HAVE_ZLIB
gzFile fz;
#endif
extern int CalmaFlattenLimit;
static char *gdsExts[] = {".gds", ".gds2", ".strm", "", NULL};
static char *gdsExts[] = {".gds", ".gds.gz", ".gds2", ".strm", "", NULL};
static char *cmdCalmaYesNo[] = {
"no", "false", "off", "0", "yes", "true", "on", "1", 0 };
static char *cmdCalmaAllowDisallow[] = {"disallow", "0", "allow", "1", 0};
@ -142,6 +145,7 @@ CmdCalma(w, cmd)
"help print this help information",
"addendum [yes|no] output only cells that are not type \"readonly\"",
"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",
"datestamp [yes|value] use current time or value as the creation date stamp",
"drccheck [yes|no] mark all cells as needing DRC checking",
@ -312,6 +316,41 @@ CmdCalma(w, cmd)
CalmaAllowUndefined = (option < 2) ? FALSE : TRUE;
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:
if (cmd->tx_argc == 2)
{
@ -873,58 +912,15 @@ CmdCalma(w, cmd)
case CALMA_READ:
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 */
/* no extension (as-is), ".gds", ".gds2", and ".strm". */
for (ext = 0; gdsExts[ext] != NULL; ext++)
if ((f = PaOpen(modName, "r", gdsExts[ext], Path,
(char *) NULL, &namep)) != (FILE *)NULL)
if ((f = PaZOpen(cmd->tx_argv[2], "r", gdsExts[ext], Path,
(char *) NULL, &namep)) != (FILETYPE)NULL)
break;
if (f == (FILE *) NULL)
if (f == (FILETYPE) NULL)
{
TxError("Cannot open %s.gds, %s.strm or %s to read "
"GDS-II stream input.\n",
@ -932,19 +928,7 @@ CmdCalma(w, cmd)
return;
}
CalmaReadFile(f, namep, cmd->tx_argv[2]);
(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);
}
(void) FCLOSE(f);
return;
}
@ -956,54 +940,49 @@ CmdCalma(w, cmd)
outputCalma:
dotptr = strrchr(namep, '.');
/* Check for additional ".gz" extension */
if (dotptr && !strcmp(dotptr, ".gz"))
#ifdef HAVE_ZLIB
/* Handle compression based on value of CalmaCompression */
if (CalmaCompression > 0)
{
gzipd = TRUE;
*dotptr = '\0';
dotptr = strrchr(namep, '.');
sprintf(writeMode, "w%d", CalmaCompression);
fz = PaZOpen(namep, writeMode, (dotptr == NULL) ? ".gds.gz" : "", ".", (char *) NULL, (char **)NULL);
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
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
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;
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>]
<DD> Output arrays as individual subuses (like in CIF). Default
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>]
<DD> Causes contacts to be written to the GDS file as subcell
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
root cell, with the default name of the root cell definition and the
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>
<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>
</TR>
</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>
</HTML>

43
scripts/configure vendored
View File

@ -5035,6 +5035,49 @@ $as_echo "#define HAVE___VA_COPY 1" >>confdefs.h
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])
fi
dnl Check for zlib
AC_CHECK_LIB([z],[gzopen],[AC_DEFINE([HAVE_ZLIB],[1],["zlib compression"])])
dnl Check for some C99 functions
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 <sys/param.h>
#ifdef HAVE_ZLIB
#include <zlib.h>
#endif
#include "tcltk/tclmagic.h"
#include "utils/magic.h"
#include "utils/hash.h"
@ -531,6 +535,137 @@ PaLockOpen(file, mode, ext, path, library, pRealName, is_locked)
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 --

View File

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