From 94e9f07b90dbb2daef43da78b5f7ae7482afd4c1 Mon Sep 17 00:00:00 2001 From: h_vogt Date: Wed, 21 Dec 2011 21:33:47 +0000 Subject: [PATCH] Gxxx n1 n2 TABLE {expression} = (x0, y0) (x1, y1) (x2, y2) --- ChangeLog | 7 + src/frontend/inpcom.c | 262 ++++++++++++++++++++++++++----- src/include/ngspice/stringutil.h | 1 + src/misc/string.c | 34 ++++ 4 files changed, 261 insertions(+), 43 deletions(-) diff --git a/ChangeLog b/ChangeLog index 950f1f0b6..45cd63604 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2011-12-21 Holger Vogt + * src/misc/string.c , + src/frontend/inpcom.c , + src/include/ngspice/stringutil.h: + allow syntax Gxxx n1 n2 TABLE {expression} = (x0, y0) (x1, y1) (x2, y2) + or Exxx n1 n2 TABLE {expression} = (x0, y0) (x1, y1) (x2, y2) + 2011-12-17 Robert Larice * src/xspice/cmpp/ifs_lex.l , * src/xspice/cmpp/ifs_yacc.y , diff --git a/src/frontend/inpcom.c b/src/frontend/inpcom.c index 3d497f2ba..6cdc6716d 100644 --- a/src/frontend/inpcom.c +++ b/src/frontend/inpcom.c @@ -3780,52 +3780,11 @@ inp_split_multi_param_lines( struct line *deck, int line_num ) return line_num; } - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - /* ps compatibility: - ECOMP 3 0 TABLE {V(1,2)} = (-1MV 0V) (1MV, 10V) + ECOMP 3 0 TABLE {V(1,2)} = (-1 0V) (1, 10V) --> ECOMP 3 0 int3 int0 1 - BECOMP int3 int0 V = pwl(V(1,2), -1MV, 0 , 1MV, 10V) + BECOMP int3 int0 V = pwl(V(1,2), -2, 0, -1, 0 , 1, 10V, 2, 10V) GD16 16 1 TABLE {V(16,1)} ((-100V,-1pV)(0,0)(1m,1u)(2m,1m)) --> @@ -3925,7 +3884,114 @@ static void inp_compat(struct line *deck) *(str_ptr + 3) = 'o'; *(str_ptr + 4) = 'l'; } + /* Exxx n1 n2 TABLE {expression} = (x0, y0) (x1, y1) (x2, y2) + --> + Exxx n1 n2 int1 0 1 + BExxx int1 0 V = pwl (expression, x0-(x2-x0)/2, y0, x0, y0, x1, y1, x2, y2, x2+(x2-x0)/2, y2) + */ + if ((str_ptr = strstr( curr_line, "table" )) != NULL) { + char *expression, *firstno, *ffirstno, *secondno, *midline, *lastno, *lastlastno; + double fnumber, lnumber, delta; + int nerror; + cut_line = curr_line; + /* title and nodes */ + title_tok = gettok(&cut_line); + node1 = gettok(&cut_line); + node2 = gettok(&cut_line); + // Exxx n1 n2 int1 0 1 + xlen = 2*strlen(title_tok) + strlen(node1) + strlen(node2) + + 20 - 4*2 + 1; + ckt_array[0] = TMALLOC(char, xlen); + sprintf(ckt_array[0], "%s %s %s %s_int1 0 1", + title_tok, node1, node2, title_tok); + // get the expression + str_ptr = gettok(&cut_line); /* ignore 'table' */ + tfree(str_ptr); + expression = gettok_char(&cut_line, '}', TRUE); /* expression */ + if (!expression) { + fprintf(stderr, "Error: bad sytax in line %d\n %s\n", + card->li_linenum_orig, card->li_line); + controlled_exit(EXIT_BAD); + } + /* remove '{' and '}' from expression */ + if ((str_ptr = strstr( expression, "{" )) != NULL) + *str_ptr = ' '; + if ((str_ptr = strstr( expression, "}" )) != NULL) + *str_ptr = ' '; + /* cut_line may now have a '=', if yes, it will have '{' and '}' + (braces around token after '=') */ + if ((str_ptr = strstr( cut_line, "=" )) != NULL) + *str_ptr = ' '; + if ((str_ptr = strstr( cut_line, "{" )) != NULL) + *str_ptr = ' '; + if ((str_ptr = strstr( cut_line, "}" )) != NULL) + *str_ptr = ' '; + /* get first two numbers to establish extrapolation */ + str_ptr = cut_line; + ffirstno = gettok_node(&cut_line); + firstno = copy(ffirstno); + fnumber = INPevaluate(&ffirstno, &nerror, TRUE); + secondno = gettok_node(&cut_line); + midline = cut_line; + cut_line = strrchr(str_ptr, '('); + /* replace '(' with ',' and ')' with ' ' */ + while(*str_ptr) { + if (*str_ptr == '(') + *str_ptr = ','; + else if (*str_ptr == ')') + *str_ptr = ' '; + *str_ptr++; + } + /* scan for last two numbers */ + lastno = gettok_node(&cut_line); + lnumber = INPevaluate(&lastno, &nerror, FALSE); + /* check for max-min and take half the difference for delta */ + delta = (lnumber-fnumber)/2.; + lastlastno = gettok_node(&cut_line); + if (!secondno || (*midline == 0) || (delta <= 0.) || !lastlastno) { + fprintf(stderr, "Error: bad sytax in line %d\n %s\n", + card->li_linenum_orig, card->li_line); + controlled_exit(EXIT_BAD); + } + xlen = 2*strlen(title_tok) + strlen(expression) + 14 + strlen(firstno) + + 2*strlen(secondno) + strlen(midline) + 14 + + strlen(lastlastno) + 50; + ckt_array[1] = TMALLOC(char, xlen); + sprintf(ckt_array[1], "b%s %s_int1 0 v = pwl(%s, %e, %s, %s, %s, %s, %e, %s)", + title_tok, title_tok, expression, fnumber-delta, secondno, firstno, secondno, + midline, lnumber + delta, lastlastno); + // insert new B source line immediately after current line + tmp_ptr = card->li_next; + for ( i = 0; i < 2; i++ ) { + if ( param_end ) { + param_end->li_next = alloc(struct line); + param_end = param_end->li_next; + } else { + param_end = param_beg = alloc(struct line); + } + param_end->li_next = NULL; + param_end->li_error = NULL; + param_end->li_actual = NULL; + param_end->li_line = ckt_array[i]; + param_end->li_linenum = 0; + } + // comment out current variable e line + *(card->li_line) = '*'; + // insert new param lines immediately after current line + tmp_ptr = card->li_next; + card->li_next = param_beg; + param_end->li_next = tmp_ptr; + // point 'card' pointer to last in scalar list + card = param_end; + + param_beg = param_end = NULL; + tfree(firstno); + tfree(lastlastno); + tfree(title_tok); + tfree(node1); + tfree(node2); + } /* Exxx n1 n2 VOL = {equation} --> Exxx n1 n2 int1 0 1 @@ -4003,6 +4069,116 @@ static void inp_compat(struct line *deck) *(str_ptr + 3) = 'u'; *(str_ptr + 4) = 'r'; } + + /* Gxxx n1 n2 TABLE {expression} = (x0, y0) (x1, y1) (x2, y2) + --> + Gxxx n1 n2 int1 0 1 + BGxxx int1 0 V = pwl (expression, x0-(x2-x0)/2, y0, x0, y0, x1, y1, x2, y2, x2+(x2-x0)/2, y2) + */ + if ((str_ptr = strstr( curr_line, "table" )) != NULL) { + char *expression, *firstno, *ffirstno, *secondno, *midline, *lastno, *lastlastno; + double fnumber, lnumber, delta; + int nerror; + cut_line = curr_line; + /* title and nodes */ + title_tok = gettok(&cut_line); + node1 = gettok(&cut_line); + node2 = gettok(&cut_line); + // Gxxx n1 n2 int1 0 1 + xlen = 2*strlen(title_tok) + strlen(node1) + strlen(node2) + + 20 - 4*2 + 1; + ckt_array[0] = TMALLOC(char, xlen); + sprintf(ckt_array[0], "%s %s %s %s_int1 0 1", + title_tok, node1, node2, title_tok); + // get the expression + str_ptr = gettok(&cut_line); /* ignore 'table' */ + tfree(str_ptr); + expression = gettok_char(&cut_line, '}', TRUE); /* expression */ + if (!expression) { + fprintf(stderr, "Error: bad sytax in line %d\n %s\n", + card->li_linenum_orig, card->li_line); + controlled_exit(EXIT_BAD); + } + /* remove '{' and '}' from expression */ + if ((str_ptr = strstr( expression, "{" )) != NULL) + *str_ptr = ' '; + if ((str_ptr = strstr( expression, "}" )) != NULL) + *str_ptr = ' '; + /* cut_line may now have a '=', if yes, it will have '{' and '}' + (braces around token after '=') */ + if ((str_ptr = strstr( cut_line, "=" )) != NULL) + *str_ptr = ' '; + if ((str_ptr = strstr( cut_line, "{" )) != NULL) + *str_ptr = ' '; + if ((str_ptr = strstr( cut_line, "}" )) != NULL) + *str_ptr = ' '; + /* get first two numbers to establish extrapolation */ + str_ptr = cut_line; + ffirstno = gettok_node(&cut_line); + firstno = copy(ffirstno); + fnumber = INPevaluate(&ffirstno, &nerror, TRUE); + secondno = gettok_node(&cut_line); + midline = cut_line; + cut_line = strrchr(str_ptr, '('); + /* replace '(' with ',' and ')' with ' ' */ + while(*str_ptr) { + if (*str_ptr == '(') + *str_ptr = ','; + else if (*str_ptr == ')') + *str_ptr = ' '; + *str_ptr++; + } + /* scan for last two numbers */ + lastno = gettok_node(&cut_line); + lnumber = INPevaluate(&lastno, &nerror, FALSE); + /* check for max-min and take half the difference for delta */ + delta = (lnumber-fnumber)/2.; + lastlastno = gettok_node(&cut_line); + if (!secondno || (*midline == 0) || (delta <= 0.) || !lastlastno) { + fprintf(stderr, "Error: bad sytax in line %d\n %s\n", + card->li_linenum_orig, card->li_line); + controlled_exit(EXIT_BAD); + } + /* BGxxx int1 0 V = pwl (expression, x0-(x2-x0)/2, y0, x0, y0, x1, y1, x2, y2, x2+(x2-x0)/2, y2) */ + xlen = 2*strlen(title_tok) + strlen(expression) + 14 + strlen(firstno) + + 2*strlen(secondno) + strlen(midline) + 14 + + strlen(lastlastno) + 50; + ckt_array[1] = TMALLOC(char, xlen); + sprintf(ckt_array[1], "b%s %s_int1 0 v = pwl(%s, %e, %s, %s, %s, %s, %e, %s)", + title_tok, title_tok, expression, fnumber-delta, secondno, firstno, secondno, + midline, lnumber + delta, lastlastno); + + // insert new B source line immediately after current line + tmp_ptr = card->li_next; + for ( i = 0; i < 2; i++ ) { + if ( param_end ) { + param_end->li_next = alloc(struct line); + param_end = param_end->li_next; + } else { + param_end = param_beg = alloc(struct line); + } + param_end->li_next = NULL; + param_end->li_error = NULL; + param_end->li_actual = NULL; + param_end->li_line = ckt_array[i]; + param_end->li_linenum = 0; + } + // comment out current variable e line + *(card->li_line) = '*'; + // insert new param lines immediately after current line + tmp_ptr = card->li_next; + card->li_next = param_beg; + param_end->li_next = tmp_ptr; + // point 'card' pointer to last in scalar list + card = param_end; + + param_beg = param_end = NULL; + tfree(firstno); + tfree(lastlastno); + tfree(title_tok); + tfree(node1); + tfree(node2); + } /* Gxxx n1 n2 CUR = {equation} --> diff --git a/src/include/ngspice/stringutil.h b/src/include/ngspice/stringutil.h index 3d09afbe1..0e10f9367 100644 --- a/src/include/ngspice/stringutil.h +++ b/src/include/ngspice/stringutil.h @@ -22,6 +22,7 @@ void strtoupper(char *str); char * stripWhiteSpacesInsideParens(char *str); char * gettok(char **s); char * gettok_instance(char **); +char * gettok_char(char **s, char p, bool inc_p); #ifdef CIDER diff --git a/src/misc/string.c b/src/misc/string.c index 74e374b62..634ef409c 100644 --- a/src/misc/string.c +++ b/src/misc/string.c @@ -360,6 +360,40 @@ gettok_instance(char **s) return ( token ) ; } +/* get the next token starting at next non white spice, stopping + at p, if inc_p is true, then including p, else excluding p +*/ +char * +gettok_char(char **s, char p, bool inc_p) +{ + char c; + char *token ; /* return token */ + SPICE_DSTRING buf ; /* allow any length string */ + + while ( isspace(**s) ) + (*s)++; /* iterate over whitespace */ + + if (!**s) + return (NULL); /* return NULL if we come to end of line */ + + spice_dstring_init(&buf) ; + while ((c = **s) != '\0' && + ( **s != p ) + ) { + spice_dstring_append_char( &buf, *(*s)++ ) ; + } + if (inc_p) + spice_dstring_append_char( &buf, *(*s)++ ) ; + + /* Now iterate up to next non-whitespace char */ + while ( isspace(**s) ) + (*s)++; + + token = copy( spice_dstring_value(&buf) ) ; + spice_dstring_free(&buf) ; + return ( token ) ; +} + /*-------------------------------------------------------------------------* * gettok_node was added by SDB on 12.3.2003 * It acts like gettok, except that it treats parens and commas like