Search path for .lib and .include has been enhanced to read complete
or partial paths from environmental variables. The env variable names have to start with '$' as the first character after the .inc or .lib token. Two consecutive env variables are possible. They are read each until directory separator '/' or '\\', or if none is found, until the end of the line. In this case the filename has to be included in the env variable. A .lib line may look like .lib "$ENVS1\$ENVS2/libraries\sky130_fd_pr\latest\models\sky130.lib.spice" tt If an env variable is read successfully, a ngspice variable with the same name (without leading '$') and contents is defined for use in a .control section.
This commit is contained in:
parent
94522f5c14
commit
92f32fb8e1
|
|
@ -122,7 +122,7 @@ static bool has_if = FALSE; /* if we have an .if ... .endif pair */
|
|||
static char *readline(FILE *fd);
|
||||
int get_number_terminals(char *c);
|
||||
static void inp_stripcomments_deck(struct card *deck, bool cs);
|
||||
static void inp_stripcomments_line(char *s, bool cs);
|
||||
static void inp_stripcomments_line(char *s, bool cs, bool inc);
|
||||
static void inp_fix_for_numparam(
|
||||
struct names *subckt_w_params, struct card *deck);
|
||||
static void inp_remove_excess_ws(struct card *deck);
|
||||
|
|
@ -1417,7 +1417,7 @@ static struct inp_read_t inp_read(FILE* fp, int call_depth, const char* dir_name
|
|||
|
||||
struct card* newcard;
|
||||
|
||||
inp_stripcomments_line(buffer, FALSE);
|
||||
inp_stripcomments_line(buffer, FALSE, TRUE);
|
||||
|
||||
s = skip_non_ws(buffer); /* advance past non-space chars */
|
||||
|
||||
|
|
@ -1942,9 +1942,99 @@ char *inp_pathresolve(const char *name)
|
|||
} /* end of function inp_pathresolve */
|
||||
|
||||
|
||||
|
||||
/* Figure out if name starts with: environmental variables (replace them),
|
||||
~/ (expand the tilde), absolute path name, all others and return the
|
||||
path, if file exists. */
|
||||
static char *inp_pathresolve_at(const char *name, const char *dir)
|
||||
{
|
||||
/* the string might contain one or two environmental variables at its front:
|
||||
.lib $ENV1/filename
|
||||
.lib $ENV1\$ENV2\filename
|
||||
.lib $ENV1
|
||||
.lib $ENV1/$ENV2
|
||||
*/
|
||||
if (name[0] == '$') {
|
||||
char* s, * s1 = NULL, * tmpnam, * tmpcurr, * tmpcurr2 = NULL;
|
||||
char* envvar, * envvar2 = NULL;
|
||||
bool secenv = FALSE;
|
||||
tmpcurr = tmpnam = copy(name);
|
||||
while (*tmpcurr != '\0') {
|
||||
if (*tmpcurr == '\\')
|
||||
*tmpcurr = '/';
|
||||
tmpcurr++;
|
||||
}
|
||||
tmpcurr = tmpnam;
|
||||
/* extract env variable, add rest of token to its contents */
|
||||
/* MS Windows directory separators */
|
||||
envvar = gettok_char(&tmpcurr, '/', FALSE, FALSE);
|
||||
if (envvar && ciprefix("/$", tmpcurr)) {
|
||||
tmpcurr2 = tmpcurr + 1;
|
||||
envvar2 = gettok_char(&tmpcurr2, '/', FALSE, FALSE);
|
||||
secenv = TRUE;
|
||||
}
|
||||
if (envvar && !secenv) {
|
||||
s = getenv(envvar + 1);
|
||||
if (s) {
|
||||
cp_vset(s, CP_STRING, envvar + 1);
|
||||
char* newname = tprintf("%s%s", s, tmpcurr);
|
||||
char* const r = inp_pathresolve(newname);
|
||||
tfree(newname);
|
||||
tfree(envvar);
|
||||
return r;
|
||||
}
|
||||
fprintf(stderr, "Error: Cannot read environmental variable %s\n", envvar + 1);
|
||||
controlled_exit(EXIT_BAD);
|
||||
}
|
||||
else if (envvar && envvar2) {
|
||||
s = getenv(envvar + 1);
|
||||
s1 = getenv(envvar2 + 1);
|
||||
if (s && s1) {
|
||||
char* newname = tprintf("%s/%s%s", s, s1, tmpcurr2);
|
||||
char* const r = inp_pathresolve(newname);
|
||||
tfree(newname);
|
||||
tfree(envvar);
|
||||
tfree(envvar2);
|
||||
return r;
|
||||
}
|
||||
if (!s)
|
||||
fprintf(stderr, "Error: Cannot read environmental variable %s\n", envvar + 1);
|
||||
if (!s1)
|
||||
fprintf(stderr, "Error: Cannot read environmental variable %s\n", envvar2 + 1);
|
||||
controlled_exit(EXIT_BAD);
|
||||
}
|
||||
else if (envvar && !envvar2 && secenv) {
|
||||
s = getenv(envvar + 1);/* skip "$" */
|
||||
envvar2 = copy(tmpcurr);
|
||||
s1 = getenv(envvar2 + 2);/* skip "$/" */
|
||||
if (s && s1) {
|
||||
char* newname = tprintf("%s/%s", s, s1);
|
||||
char* const r = inp_pathresolve(newname);
|
||||
tfree(newname);
|
||||
tfree(envvar);
|
||||
tfree(envvar2);
|
||||
return r;
|
||||
}
|
||||
if (!s)
|
||||
fprintf(stderr, "Error: Cannot read environmental variable %s\n", envvar + 1);
|
||||
if (!s1)
|
||||
fprintf(stderr, "Error: Cannot read environmental variable %s\n", envvar2 + 1);
|
||||
controlled_exit(EXIT_BAD);
|
||||
}
|
||||
|
||||
/* no directory separator found, just use the env entry (must include file name) */
|
||||
envvar = tmpnam;
|
||||
s = getenv(envvar + 1);/* skip '$' */
|
||||
if (s) {
|
||||
cp_vset(s, CP_STRING, envvar + 1);
|
||||
char* const r = inp_pathresolve(s);
|
||||
tfree(envvar);
|
||||
return r;
|
||||
}
|
||||
fprintf(stderr, "Error: Cannot read environmental variable %s\n", envvar + 1);
|
||||
tfree(envvar);
|
||||
controlled_exit(EXIT_BAD);
|
||||
}
|
||||
|
||||
/* if name is an absolute path name,
|
||||
* or if we haven't anything to prepend anyway
|
||||
*/
|
||||
|
|
@ -1952,6 +2042,7 @@ static char *inp_pathresolve_at(const char *name, const char *dir)
|
|||
return inp_pathresolve(name);
|
||||
}
|
||||
|
||||
/* expand "~/" */
|
||||
if (name[0] == '~' && name[1] == '/') {
|
||||
char * const y = cp_tildexpand(name);
|
||||
if (y) {
|
||||
|
|
@ -3239,7 +3330,7 @@ static void inp_stripcomments_deck(struct card *c, bool cf)
|
|||
found_control = TRUE;
|
||||
if (ciprefix(".endc", c->line))
|
||||
found_control = FALSE;
|
||||
inp_stripcomments_line(c->line, found_control | cf);
|
||||
inp_stripcomments_line(c->line, found_control | cf, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -3267,7 +3358,7 @@ static void inp_stripcomments_deck(struct card *c, bool cf)
|
|||
character, not as end-of-line comment delimiter, except for that it is
|
||||
located at the beginning of a line. If inside of a control section,
|
||||
still '$ ' is read a an end-of-line comment delimiter.*/
|
||||
static void inp_stripcomments_line(char *s, bool cs)
|
||||
static void inp_stripcomments_line(char *s, bool cs, bool inc)
|
||||
{
|
||||
char c = ' '; /* anything other than a comment character */
|
||||
char *d = s;
|
||||
|
|
@ -3280,6 +3371,12 @@ static void inp_stripcomments_line(char *s, bool cs)
|
|||
return;
|
||||
}
|
||||
|
||||
if (inc) {
|
||||
d = nexttok(d);
|
||||
if (*d == '$')
|
||||
d = nexttok(d);
|
||||
}
|
||||
|
||||
/* Look for comments in body of line. */
|
||||
while ((c = *d) != '\0') {
|
||||
d++;
|
||||
|
|
|
|||
Loading…
Reference in New Issue