From 862df7fadb02499829286bed86bffd921df3364a Mon Sep 17 00:00:00 2001 From: h_vogt Date: Mon, 8 Aug 2016 21:08:55 +0200 Subject: [PATCH] subckt.c, xpressn.c, spicenum.c, add level information for .subckt entries nupa_scan is totally without level info. This preliminary fix at least lets us decide to issue a warning if subckt have equal names and are on the same level. Still nupa_scan only enters the first entry into its hash table, irrespective of its level. --- src/frontend/numparam/numpaif.h | 2 +- src/frontend/numparam/numparam.h | 6 +++-- src/frontend/numparam/spicenum.c | 10 ++++---- src/frontend/numparam/xpressn.c | 44 ++++++++++++++++++++++++++------ src/frontend/subckt.c | 2 +- 5 files changed, 47 insertions(+), 17 deletions(-) diff --git a/src/frontend/numparam/numpaif.h b/src/frontend/numparam/numpaif.h index 240a1ae77..94d2beaff 100644 --- a/src/frontend/numparam/numpaif.h +++ b/src/frontend/numparam/numpaif.h @@ -14,7 +14,7 @@ extern char *nupa_copy(char *s, int linenum); extern int nupa_eval(char *s, int linenum, int orig_linenum); extern int nupa_signal(int sig, char *info); -extern void nupa_scan(char * s, int linenum, int is_subckt); +extern void nupa_scan(char * s, int linenum, int is_subckt, unsigned short level[]); extern void nupa_list_params(FILE *cp_out); extern double nupa_get_param(char *param_name, int *found); extern void nupa_add_param(char *param_name, double value); diff --git a/src/frontend/numparam/numparam.h b/src/frontend/numparam/numparam.h index 4e4b90997..337c36801 100644 --- a/src/frontend/numparam/numparam.h +++ b/src/frontend/numparam/numparam.h @@ -6,6 +6,7 @@ #include "numpaif.h" #include "ngspice/hash.h" +#include "ngspice/inpdefs.h" /***** numparam internals ********/ @@ -27,6 +28,7 @@ typedef struct entry_s { int ivl; /* int value or string buffer index */ char *sbbase; /* string buffer base address if any */ struct entry_s *pointer; /* pointer chain */ + unsigned short levelinfo[NESTINGDEPTH]; } entry_t; @@ -53,7 +55,7 @@ typedef struct { /* the input scanner data structure */ void initdico(dico_t *); int donedico(dico_t *); void dico_free_entry(entry_t *); -bool defsubckt(dico_t *, char *s, int w, char categ); +bool defsubckt(dico_t *, char *s, int w, char categ, unsigned short level[]); int findsubckt(dico_t *, char *s, SPICE_DSTRINGPTR subname); bool nupa_substitute(dico_t *, char *s, char *r, bool err); bool nupa_assignment(dico_t *, char *s, char mode); @@ -61,5 +63,5 @@ bool nupa_subcktcall(dico_t *, char *s, char *x, bool err); void nupa_subcktexit(dico_t *); dico_t *nupa_fetchinstance(void); char getidtype(dico_t *, char *s); -entry_t *attrib(dico_t *, NGHASHPTR htable, char *t, char op); +entry_t *attrib(dico_t *, NGHASHPTR htable, char *t, char op, unsigned short level[]); void del_attrib(void *); diff --git a/src/frontend/numparam/spicenum.c b/src/frontend/numparam/spicenum.c index aa0a10b46..31292beb1 100644 --- a/src/frontend/numparam/spicenum.c +++ b/src/frontend/numparam/spicenum.c @@ -533,12 +533,12 @@ nupa_done(void) /* SJB - Scan the line for subcircuits */ void -nupa_scan(char *s, int linenum, int is_subckt) +nupa_scan(char *s, int linenum, int is_subckt, unsigned short level[]) { if (is_subckt) - defsubckt(dicoS, s, linenum, 'U'); + defsubckt(dicoS, s, linenum, 'U', level); else - defsubckt(dicoS, s, linenum, 'O'); + defsubckt(dicoS, s, linenum, 'O', level); } @@ -661,7 +661,7 @@ nupa_add_param(char *param_name, double value) htable_p = dico->symbols[dico->stack_depth]; - entry = attrib(dico, htable_p, up_name, 'N'); + entry = attrib(dico, htable_p, up_name, 'N', NULL); if (entry) { entry->vl = value; entry->tp = 'R'; @@ -688,7 +688,7 @@ nupa_add_inst_param(char *param_name, double value) if (!(dico->inst_symbols)) dico->inst_symbols = nghash_init(NGHASH_MIN_SIZE); - entry = attrib(dico, dico->inst_symbols, up_name, 'N'); + entry = attrib(dico, dico->inst_symbols, up_name, 'N', NULL); if (entry) { entry->vl = value; entry->tp = 'R'; diff --git a/src/frontend/numparam/xpressn.c b/src/frontend/numparam/xpressn.c index 37bdf5aa8..d20955006 100644 --- a/src/frontend/numparam/xpressn.c +++ b/src/frontend/numparam/xpressn.c @@ -421,7 +421,7 @@ fetchnumentry(dico_t *dico, char *s, bool *perr) /******* writing dictionary entries *********/ entry_t * -attrib(dico_t *dico, NGHASHPTR htable_p, char *t, char op) +attrib(dico_t *dico, NGHASHPTR htable_p, char *t, char op, unsigned short levelinfo[]) { /* seek or attribute dico entry number for string t. Option op='N' : force a new entry, if tos>level and old is valid. @@ -436,10 +436,14 @@ attrib(dico_t *dico, NGHASHPTR htable_p, char *t, char op) } if (!entry) { + int i; entry = TMALLOC(entry_t, 1); entry->symbol = strdup(t); entry->tp = '?'; /* signal Unknown */ entry->level = dico->stack_depth; + if (levelinfo) + for (i = 0; i < NESTINGDEPTH; i++) + entry->levelinfo[i] = levelinfo[i]; nghash_insert(htable_p, t, entry); } @@ -470,7 +474,8 @@ nupa_define(dico_t *dico, char tpe, /* type marker */ double z, /* float value if any */ int w, /* integer value if any */ - char *base) /* string pointer if any */ + char *base, /* string pointer if any */ + unsigned short level[]) /* level info */ { /*define t as real or integer, opcode= 'N' impose a new item under local conditions. @@ -491,7 +496,7 @@ nupa_define(dico_t *dico, htable_p = dico->symbols[dico->stack_depth]; - entry = attrib(dico, htable_p, t, op); + entry = attrib(dico, htable_p, t, op, level); err = 0; if (!entry) { @@ -523,8 +528,31 @@ nupa_define(dico_t *dico, warn = message(dico, "%s:%d overwritten.\n", t, entry->level); } else { - /* error message for redefinition of symbols */ - fprintf(stderr, "Warning: %s is already used,\n cannot be redefined\n", t); + /* FIXME: better do this recursively in a new function */ + /* No new entry defined, but previous entry with same name returned + from function attrib(), compare levels, if not equal, o.k. (for now) */ + unsigned short newlevel[NESTINGDEPTH]; + unsigned short oldlevel[NESTINGDEPTH]; + int i; + for (i = 0; i < NESTINGDEPTH; i++) { + newlevel[i] = level[i]; + oldlevel[i] = entry->levelinfo[i]; + } + /* top level */ + if ((newlevel[0] > 0) && (oldlevel[0] > 0) + && (newlevel[1] == 0) && (oldlevel[1] == 0)) + fprintf(stderr, "Warning: %s is already used,\n cannot be redefined\n", t); + /* second level */ + else if ((newlevel[0] > 0) && (oldlevel[0] == newlevel[0]) + && (newlevel[1] > 0) && (oldlevel[1] > 1) + && (newlevel[2] == 0) && (oldlevel[2] == 0)) + fprintf(stderr, "Warning: %s is already used,\n cannot be redefined\n", t); + /* third level */ + else if ((newlevel[0] > 0) && (oldlevel[0] == newlevel[0]) + && (newlevel[1] > 0) && (oldlevel[1] == newlevel[1]) + && (newlevel[2] > 0) && (oldlevel[2] > 1) + && (newlevel[3] == 0) && (oldlevel[3] == 0)) + fprintf(stderr, "Warning: %s is already used,\n cannot be redefined\n", t); } } @@ -533,7 +561,7 @@ nupa_define(dico_t *dico, bool -defsubckt(dico_t *dico, char *s, int w, char categ) +defsubckt(dico_t *dico, char *s, int w, char categ, unsigned short level[]) /* called on 1st pass of spice source code, to enter subcircuit (categ=U) and model (categ=O) names */ @@ -562,7 +590,7 @@ defsubckt(dico_t *dico, char *s, int w, char categ) SPICE_DSTRING ustr; /* temp user string */ spice_dstring_init(&ustr); pscopy_up(&ustr, s, i, j - i); - err = nupa_define(dico, spice_dstring_value(&ustr), ' ', categ, 0.0, w, NULL); + err = nupa_define(dico, spice_dstring_value(&ustr), ' ', categ, 0.0, w, NULL, level); spice_dstring_free(&ustr); } else { err = message(dico, "Subcircuit or Model without name.\n"); @@ -1533,7 +1561,7 @@ nupa_assignment(dico_t *dico, char *s, char mode) } err = nupa_define(dico, spice_dstring_value(&tstr), mode /* was ' ' */ , - dtype, rval, wval, NULL); + dtype, rval, wval, NULL, NULL); error = error || err; } diff --git a/src/frontend/subckt.c b/src/frontend/subckt.c index 166353e6c..2b24556c4 100644 --- a/src/frontend/subckt.c +++ b/src/frontend/subckt.c @@ -236,7 +236,7 @@ inp_subcktexpand(struct line *deck) { /* get the subckt names from the deck */ for (c = deck; c; c = c->li_next) /* first Numparam pass */ if (ciprefix(".subckt", c->li_line)) - nupa_scan(c->li_line, c->li_linenum, TRUE); + nupa_scan(c->li_line, c->li_linenum, TRUE, c->level); /* now copy instances */ for (c = deck; c; c = c->li_next) /* first Numparam pass */ c->li_line = nupa_copy(c->li_line, c->li_linenum);