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:
parent
9a79a1eee2
commit
46baae0ce6
|
|
@ -3359,6 +3359,7 @@ char *nodeSpiceName(hname, rnode)
|
||||||
EFNodeName *nn;
|
EFNodeName *nn;
|
||||||
HashEntry *he;
|
HashEntry *he;
|
||||||
EFNode *node;
|
EFNode *node;
|
||||||
|
char *p, *s;
|
||||||
|
|
||||||
if (rnode) *rnode = (EFNode *)NULL;
|
if (rnode) *rnode = (EFNode *)NULL;
|
||||||
he = EFHNLook(hname, (char *) NULL, "nodeName");
|
he = EFHNLook(hname, (char *) NULL, "nodeName");
|
||||||
|
|
@ -3384,8 +3385,21 @@ makeName:
|
||||||
if ( esFormat == HSPICE ) /* more processing */
|
if ( esFormat == HSPICE ) /* more processing */
|
||||||
nodeHspiceName(esTempName);
|
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:
|
retName:
|
||||||
return ((nodeClient *) (node->efnode_client))->spiceNodeName;
|
return ((nodeClient *) (node->efnode_client))->spiceNodeName;
|
||||||
|
|
@ -3399,7 +3413,8 @@ retName:
|
||||||
* Create a hierarchical node name.
|
* Create a hierarchical node name.
|
||||||
* The flags in EFTrimFlags control whether global (!) or local (#)
|
* The flags in EFTrimFlags control whether global (!) or local (#)
|
||||||
* suffixes are to be trimmed. Also substitutes \. with \@ if the
|
* 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:
|
* Results:
|
||||||
* None.
|
* None.
|
||||||
|
|
@ -3416,36 +3431,34 @@ EFHNSprintf(str, hierName)
|
||||||
HierName *hierName;
|
HierName *hierName;
|
||||||
{
|
{
|
||||||
bool trimGlob, trimLocal, convertComma, convertEqual, convertBrackets;
|
bool trimGlob, trimLocal, convertComma, convertEqual, convertBrackets;
|
||||||
char *s, *cp, c;
|
char *cp, c;
|
||||||
char *efHNSprintfPrefix(HierName *, char *);
|
char *efHNSprintfPrefix(HierName *, char *);
|
||||||
|
|
||||||
s = str;
|
|
||||||
if (hierName->hn_parent) str = efHNSprintfPrefix(hierName->hn_parent, 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;
|
switch (c)
|
||||||
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)
|
case '!': if (!trimGlob) *str++ = c; break;
|
||||||
{
|
case '.': *str++ = (esFormat == HSPICE)?'@':'.'; break;
|
||||||
case '!': if (!trimGlob) *str++ = c; break;
|
case '=': if (convertEqual) *str++ = ':'; break;
|
||||||
case '.': *str++ = (esFormat == HSPICE)?'@':'.'; break;
|
case ',': if (convertComma) *str++ = '|'; break;
|
||||||
case '=': if (convertEqual) *str++ = ':'; break;
|
case '[': *str++ = (convertBrackets) ? '_' : '['; break;
|
||||||
case ',': if (convertComma) *str++ = '|'; break;
|
case ']': *str++ = (convertBrackets) ? '_' : ']'; break;
|
||||||
case '[': *str++ = (convertBrackets) ? '_' : '['; break;
|
case '\\': if (*(cp + 1) == '/') str++; break;
|
||||||
case ']': *str++ = (convertBrackets) ? '_' : ']'; break;
|
case '#': if (trimLocal) break; // else fall through
|
||||||
case '#': if (trimLocal) break; // else fall through
|
default: *str++ = c; break;
|
||||||
default: *str++ = c; break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
*str++ = '\0';
|
|
||||||
}
|
}
|
||||||
else strcpy(str, hierName->hn_name);
|
*str++ = '\0';
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1142,6 +1142,98 @@ efBuildAddStr(table, pMax, size, str)
|
||||||
return max;
|
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)
|
&newuse->use_ylo, &newuse->use_yhi, &newuse->use_ysep)) == 6)
|
||||||
{
|
{
|
||||||
*cp = '\0';
|
*cp = '\0';
|
||||||
newuse->use_id = StrDup((char **) NULL, subUseId);
|
newuse->use_id = efMakeCleanName(subUseId, 0);
|
||||||
*cp = '[';
|
*cp = '[';
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
newuse->use_id = StrDup((char **) NULL, subUseId);
|
newuse->use_id = efMakeCleanName(subUseId, 0);
|
||||||
newuse->use_xlo = newuse->use_xhi = 0;
|
newuse->use_xlo = newuse->use_xhi = 0;
|
||||||
newuse->use_ylo = newuse->use_yhi = 0;
|
newuse->use_ylo = newuse->use_yhi = 0;
|
||||||
newuse->use_xsep = newuse->use_ysep = 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 ac; /* Number of strings in av */
|
||||||
{
|
{
|
||||||
int n;
|
int n;
|
||||||
|
char *locName1, *locName2;
|
||||||
Connection *conn;
|
Connection *conn;
|
||||||
unsigned size = sizeof (Connection)
|
unsigned size = sizeof (Connection)
|
||||||
+ (efNumResistClasses - 1) * sizeof (EFPerimArea);
|
+ (efNumResistClasses - 1) * sizeof (EFPerimArea);
|
||||||
|
|
||||||
conn = (Connection *) mallocMagic((unsigned)(size));
|
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_cap = (EFCapValue) deltaC;
|
||||||
conn->conn_next = def->def_conns;
|
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;
|
conn->conn_pa[n].pa_area = conn->conn_pa[n].pa_perim = 0;
|
||||||
def->def_conns = conn;
|
def->def_conns = conn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (locName1 != nodeName1) freeMagic(locName1);
|
||||||
|
if (locName2 != nodeName2) freeMagic(locName2);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
||||||
|
|
@ -225,7 +225,8 @@ EFStrToHN(prefix, suffixStr)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Convert the relative name into a HierName path, with one HierName
|
* 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;
|
cp = slashPtr = suffixStr;
|
||||||
for (;;)
|
for (;;)
|
||||||
|
|
@ -242,6 +243,7 @@ EFStrToHN(prefix, suffixStr)
|
||||||
slashPtr = cp;
|
slashPtr = cp;
|
||||||
prefix = hierName;
|
prefix = hierName;
|
||||||
}
|
}
|
||||||
|
else if ((*cp == '\\') && (*(cp + 1) == '/')) cp += 2;
|
||||||
else cp++;
|
else cp++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue