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;
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -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++;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue