Modified the .ext file reading and the .spice file writing so that

array delimiters and hierarchy separators (characters '/', '[', and ']')
that are part of instances or labels passed to magic, are preserved
from input to output, but internally marked (with a backslash escape)
so that they are not misinterpreted my magic when running ext2spice.
This commit is contained in:
Tim Edwards 2021-02-23 13:46:12 -05:00
parent 9a79a1eee2
commit 46baae0ce6
3 changed files with 147 additions and 30 deletions

View File

@ -3359,6 +3359,7 @@ char *nodeSpiceName(hname, rnode)
EFNodeName *nn;
HashEntry *he;
EFNode *node;
char *p, *s;
if (rnode) *rnode = (EFNode *)NULL;
he = EFHNLook(hname, (char *) NULL, "nodeName");
@ -3384,8 +3385,21 @@ makeName:
if ( esFormat == HSPICE ) /* more processing */
nodeHspiceName(esTempName);
}
((nodeClient *) (node->efnode_client))->spiceNodeName =
StrDup(NULL, esTempName);
/* Strip any escaped-slash hiearchy dividers or array delimiters */
/* out of the name, as they have been put there to prevent magic */
/* from interpeting them as hierarchy divers or array delimiters. */
for (s = p = esTempName; *s; p++, s++)
{
if ((*s == '\\') && ((*(s + 1) == '/') || (*(s + 1) == '[')
|| (*(s + 1) == ']')))
s++;
if (p != s) *p = *s;
}
if (p != s) *p = *s; /* Copy trailing NULL */
((nodeClient *)(node->efnode_client))->spiceNodeName = StrDup(NULL, esTempName);
retName:
return ((nodeClient *) (node->efnode_client))->spiceNodeName;
@ -3399,7 +3413,8 @@ retName:
* Create a hierarchical node name.
* The flags in EFTrimFlags control whether global (!) or local (#)
* suffixes are to be trimmed. Also substitutes \. with \@ if the
* format is hspice.
* format is hspice. Backslash-escaped slashes are converted back
* to the original character.
*
* Results:
* None.
@ -3416,36 +3431,34 @@ EFHNSprintf(str, hierName)
HierName *hierName;
{
bool trimGlob, trimLocal, convertComma, convertEqual, convertBrackets;
char *s, *cp, c;
char *cp, c;
char *efHNSprintfPrefix(HierName *, char *);
s = str;
if (hierName->hn_parent) str = efHNSprintfPrefix(hierName->hn_parent, str);
if (EFTrimFlags)
cp = hierName->hn_name;
trimGlob = (EFTrimFlags & EF_TRIMGLOB);
trimLocal = (EFTrimFlags & EF_TRIMLOCAL);
convertComma = (EFTrimFlags & EF_CONVERTCOMMA);
convertEqual = (EFTrimFlags & EF_CONVERTEQUAL);
convertBrackets = (EFTrimFlags & EF_CONVERTBRACKETS);
while (c = *cp++)
{
cp = hierName->hn_name;
trimGlob = (EFTrimFlags & EF_TRIMGLOB);
trimLocal = (EFTrimFlags & EF_TRIMLOCAL);
convertComma = (EFTrimFlags & EF_CONVERTCOMMA);
convertEqual = (EFTrimFlags & EF_CONVERTEQUAL);
convertBrackets = (EFTrimFlags & EF_CONVERTBRACKETS);
while (c = *cp++)
switch (c)
{
switch (c)
{
case '!': if (!trimGlob) *str++ = c; break;
case '.': *str++ = (esFormat == HSPICE)?'@':'.'; break;
case '=': if (convertEqual) *str++ = ':'; break;
case ',': if (convertComma) *str++ = '|'; break;
case '[': *str++ = (convertBrackets) ? '_' : '['; break;
case ']': *str++ = (convertBrackets) ? '_' : ']'; break;
case '#': if (trimLocal) break; // else fall through
default: *str++ = c; break;
}
case '!': if (!trimGlob) *str++ = c; break;
case '.': *str++ = (esFormat == HSPICE)?'@':'.'; break;
case '=': if (convertEqual) *str++ = ':'; break;
case ',': if (convertComma) *str++ = '|'; break;
case '[': *str++ = (convertBrackets) ? '_' : '['; break;
case ']': *str++ = (convertBrackets) ? '_' : ']'; break;
case '\\': if (*(cp + 1) == '/') str++; break;
case '#': if (trimLocal) break; // else fall through
default: *str++ = c; break;
}
*str++ = '\0';
}
else strcpy(str, hierName->hn_name);
*str++ = '\0';
return 0;
}

View File

@ -1142,6 +1142,98 @@ efBuildAddStr(table, pMax, size, str)
return max;
}
/*
* ----------------------------------------------------------------------------
*
* efNeedsCleanName --
*
* Determine if a name needs to be cleaned by efMakeCleanName, to avoid
* excessive and unnecessary string allocation and copying .
*
* "level" is 0 or 1, defined as it is for efMakeCleanName() (see below).
*
* ----------------------------------------------------------------------------
*/
bool
efNeedsCleanName(str, level)
char *str;
int level;
{
char *s;
bool seenOne = FALSE;
bool needsCleaning = FALSE;
for (s = str; *s; s++)
if (*s == '/')
if ((s == str) || (*(s - 1) != '\\'))
{
if ((level == 0) || seenOne)
{
needsCleaning = TRUE;
break;
}
seenOne = TRUE;
}
return needsCleaning;
}
/*
* ----------------------------------------------------------------------------
*
* efMakeCleanName --
*
* Generate a copy of a name like StrDup(), but cleanse the name of slash
* characters by backslash-escaping them. This lets ext2spice differentiate
* between slashes that are part of an instance name and the hierarchical
* name for a node, which is built up internally with slash characters.
*
* "level" is the number of slashes at the end which are part of the
* hierarchy and not part of the name. "use" lines in the .ext file should
* have a level of 0, while "merge" lines have a level of 1. No other values
* of "level" are supported.
*
* ----------------------------------------------------------------------------
*/
char *
efMakeCleanName(str, level)
char *str;
int level;
{
char *rstr;
char *s, *p, *ssave;
int escapes;
/* Count unescaped slashes in the string */
escapes = 0;
ssave = NULL;
for (s = str; *s; s++)
if (*s == '/')
if ((s == str) || (*(s - 1) != '\\'))
{
ssave = s;
escapes++;
}
if (escapes > 0)
escapes -= level;
rstr = (char *)mallocMagic(strlen(str) + 1 + escapes);
for (s = str, p = rstr; *s; s++, p++)
{
if (*s == '/')
if ((s == str) || (*(s - 1) != '\\'))
if ((level == 0) || (s != ssave))
*p++ = '\\';
*p = *s;
}
*p = *s; /* Copy final NULL */
return rstr;
}
/*
* ----------------------------------------------------------------------------
*
@ -1213,12 +1305,12 @@ efBuildUse(def, subDefName, subUseId, ta, tb, tc, td, te, tf)
&newuse->use_ylo, &newuse->use_yhi, &newuse->use_ysep)) == 6)
{
*cp = '\0';
newuse->use_id = StrDup((char **) NULL, subUseId);
newuse->use_id = efMakeCleanName(subUseId, 0);
*cp = '[';
}
else
{
newuse->use_id = StrDup((char **) NULL, subUseId);
newuse->use_id = efMakeCleanName(subUseId, 0);
newuse->use_xlo = newuse->use_xhi = 0;
newuse->use_ylo = newuse->use_yhi = 0;
newuse->use_xsep = newuse->use_ysep = 0;
@ -1260,13 +1352,20 @@ efBuildConnect(def, nodeName1, nodeName2, deltaC, av, ac)
int ac; /* Number of strings in av */
{
int n;
char *locName1, *locName2;
Connection *conn;
unsigned size = sizeof (Connection)
+ (efNumResistClasses - 1) * sizeof (EFPerimArea);
conn = (Connection *) mallocMagic((unsigned)(size));
if (efConnInitSubs(conn, nodeName1, nodeName2))
locName1 = nodeName1;
if (efNeedsCleanName(nodeName1)) locName1 = efMakeCleanName(nodeName1, 1);
locName2 = nodeName2;
if (efNeedsCleanName(nodeName2)) locName2 = efMakeCleanName(nodeName2, 1);
if (efConnInitSubs(conn, locName1, locName2))
{
conn->conn_cap = (EFCapValue) deltaC;
conn->conn_next = def->def_conns;
@ -1280,6 +1379,9 @@ efBuildConnect(def, nodeName1, nodeName2, deltaC, av, ac)
conn->conn_pa[n].pa_area = conn->conn_pa[n].pa_perim = 0;
def->def_conns = conn;
}
if (locName1 != nodeName1) freeMagic(locName1);
if (locName2 != nodeName2) freeMagic(locName2);
}
/*

View File

@ -225,7 +225,8 @@ EFStrToHN(prefix, suffixStr)
/*
* Convert the relative name into a HierName path, with one HierName
* created for each slash-separated segment of suffixStr.
* created for each slash-separated segment of suffixStr. Backslash-
* escaped slashes are not part of a path and are ignored.
*/
cp = slashPtr = suffixStr;
for (;;)
@ -242,6 +243,7 @@ EFStrToHN(prefix, suffixStr)
slashPtr = cp;
prefix = hierName;
}
else if ((*cp == '\\') && (*(cp + 1) == '/')) cp += 2;
else cp++;
}