more flexible my_strtok_r (handle quoting and escapes), allow quoted expressions in graphs for doing math on vectors

This commit is contained in:
Stefan Frederik 2022-02-07 03:52:42 +01:00
parent 432db0799e
commit e37d5a28b8
6 changed files with 65 additions and 19 deletions

View File

@ -635,7 +635,7 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int
char *saven, *nptr, *ntok, *node = NULL;;
my_strdup2(1426, &node, get_tok_value(r->prop_ptr,"node",0));
nptr = node;
while( (ntok = my_strtok_r(nptr, "\n\t ", &saven)) ) {
while( (ntok = my_strtok_r(nptr, "\n\t ", "", &saven)) ) {
nptr = NULL;
j = get_raw_index(ntok);
if(j >= 0) {

View File

@ -1659,8 +1659,8 @@ static SPICE_DATA **get_bus_idx_array(const char *ntok, int *n_bits)
p = 0;
my_strdup2(1402, &ntok_copy, ntok);
ntok_ptr = ntok_copy;
my_strtok_r(ntok_ptr, ",", &ntok_savep); /*strip off bus name (1st field) */
while( (bit_name = my_strtok_r(NULL, ",", &ntok_savep)) ) {
my_strtok_r(ntok_ptr, ",", "", &ntok_savep); /*strip off bus name (1st field) */
while( (bit_name = my_strtok_r(NULL, ",", "", &ntok_savep)) ) {
int idx;
if( (idx = get_raw_index(bit_name)) != -1) {
idx_arr[p] = xctx->graph_values[idx];
@ -2279,9 +2279,9 @@ int edit_wave_attributes(int what, int i, Graph_ctx *gr)
sptr = sweep;
n_nodes = count_items(node, " \t\n");
/* process each node given in "node" attribute, get also associated color/sweep var if any */
while( (ntok = my_strtok_r(nptr, "\n\t ", &saven)) ) {
ctok = my_strtok_r(cptr, " ", &savec);
stok = my_strtok_r(sptr, " ", &saves);
while( (ntok = my_strtok_r(nptr, "\n\t ", "\"", &saven)) ) {
ctok = my_strtok_r(cptr, " ", "", &savec);
stok = my_strtok_r(sptr, " ", "", &saves);
nptr = cptr = sptr = NULL;
dbg(1, "ntok=%s ctok=%s\n", ntok, ctok? ctok: "NULL");
if(stok && stok[0]) {
@ -2347,7 +2347,7 @@ int edit_wave_attributes(int what, int i, Graph_ctx *gr)
}
}
wcnt++;
} /* while( (ntok = my_strtok_r(nptr, "\n\t ", &saven)) ) */
} /* while( (ntok = my_strtok_r(nptr, "\n\t ", "", &saven)) ) */
my_free(1494, &node);
my_free(1495, &color);
my_free(1496, &sweep);
@ -2399,14 +2399,14 @@ void draw_graph(int i, const int flags, Graph_ctx *gr)
sptr = sweep;
n_nodes = count_items(node, " \t\n");
/* process each node given in "node" attribute, get also associated color/sweep var if any*/
while( (ntok = my_strtok_r(nptr, "\n\t ", &saven)) ) {
while( (ntok = my_strtok_r(nptr, "\n\t ", "\"", &saven)) ) {
if(strstr(ntok, ",")) {
my_strdup2(1452, &bus_msb, find_nth(ntok, ',', 2));
}
ctok = my_strtok_r(cptr, " ", &savec);
stok = my_strtok_r(sptr, " ", &saves);
ctok = my_strtok_r(cptr, " ", "", &savec);
stok = my_strtok_r(sptr, " ", "", &saves);
nptr = cptr = sptr = NULL;
dbg(1, "ntok=%s ctok=%s\n", ntok, ctok? ctok: "NULL");
dbg(0, "ntok=%s ctok=%s\n", ntok, ctok? ctok: "NULL");
if(ctok && ctok[0]) wave_color = atoi(ctok);
if(wave_color < 0) wave_color = 4;
if(wave_color >= cadlayers) wave_color = cadlayers - 1;
@ -2526,7 +2526,7 @@ void draw_graph(int i, const int flags, Graph_ctx *gr)
} /* if( (idx = get_raw_index(bus_msb ? bus_msb : ntok)) != -1 ) */
wcnt++;
if(bus_msb) my_free(1453, &bus_msb);
} /* while( (ntok = my_strtok_r(nptr, "\n\t ", &saven)) ) */
} /* while( (ntok = my_strtok_r(nptr, "\n\t ", "", &saven)) ) */
my_free(1391, &node);
my_free(1392, &color);
my_free(1408, &sweep);

View File

@ -47,7 +47,49 @@ int my_strncasecmp(const char *s1, const char *s2, size_t n)
return tolower(*s1) - tolower(*s2);
}
char *my_strtok_r(char *str, const char *delim, char **saveptr)
/* split a string into tokens like standard strtok_r,
* if quote string is not empty any character matching quote is considered a quoting
* character, removed from input and all characters before next quote are considered
* as part of the token. backslash can be used to enter literal quoting characters and
* literal backslashes.
* if quote is empty no backslash is removed from input and behavior is identical
* to strtok_r
*/
char *my_strtok_r(char *str, const char *delim, const char *quote, char **saveptr)
{
char *tok;
int q = 0; /* quote */
int e = 0; /* escape */
int ne = 0; /* number of escapes / quoting chars to remove */
if(str) { /* 1st call */
*saveptr = str;
}
while(**saveptr && strchr(delim, **saveptr) ) { /* skip separators */
++(*saveptr);
}
tok = *saveptr; /* start of token */
while(**saveptr && (e || q || !strchr(delim, **saveptr)) ) { /* look for sep. marking end of current token */
if(ne) *(*saveptr - ne) = **saveptr; /* shift back eating escapes / quotes */
if(!e && strchr(quote, **saveptr)) {
q = !q;
ne++;
}
if(quote[0] && !e && **saveptr == '\\') { /* if quote is empty string do not skip backslashes either */
e = 1;
ne++;
} else e = 0;
++(*saveptr);
}
if(**saveptr) {
**saveptr = '\0'; /* mark end of token */
if(ne) *(*saveptr - ne) = **saveptr; /* shift back eating escapes / quotes */
++(*saveptr); /* if not at end of string advance one char for next iteration */
} else if(ne) *(*saveptr - ne ) = **saveptr; /* shift back eating escapes / quotes */
if(tok[0]) return tok; /* return token */
else return NULL; /* no more tokens */
}
char *xmy_strtok_r(char *str, const char *delim, char **saveptr)
{
char *tok;
if(str) { /* 1st call */

View File

@ -1943,8 +1943,8 @@ void print_tedax_element(FILE *fd, int inst)
/* fprintf(errfp, "extra_pinnumber: |%s|\n", extra_pinnumber); */
/* fprintf(errfp, "extra: |%s|\n", extra); */
for(extra_ptr = extra, extra_pinnumber_ptr = extra_pinnumber; ; extra_ptr=NULL, extra_pinnumber_ptr=NULL) {
extra_pinnumber_token=my_strtok_r(extra_pinnumber_ptr, " ", &saveptr1);
extra_token=my_strtok_r(extra_ptr, " ", &saveptr2);
extra_pinnumber_token=my_strtok_r(extra_pinnumber_ptr, " ", "", &saveptr1);
extra_token=my_strtok_r(extra_ptr, " ", "", &saveptr2);
if(!extra_token) break;
/* fprintf(errfp, "extra_pinnumber_token: |%s|\n", extra_pinnumber_token); */
/* fprintf(errfp, "extra_token: |%s|\n", extra_token); */

View File

@ -1310,7 +1310,7 @@ extern int my_snprintf(char *str, int size, const char *fmt, ...);
extern size_t my_strdup(int id, char **dest, const char *src);
extern void my_strndup(int id, char **dest, const char *src, int n);
extern size_t my_strdup2(int id, char **dest, const char *src);
extern char *my_strtok_r(char *str, const char *delim, char **saveptr);
extern char *my_strtok_r(char *str, const char *delim, const char *quote, char **saveptr);
extern int my_strncpy(char *d, const char *s, int n);
extern int my_strcasecmp(const char *s1, const char *s2);
extern int my_strncasecmp(const char *s1, const char *s2, size_t n);

View File

@ -659,7 +659,11 @@ proc sim_is_xyce {} {
proc tolist {s} {
set s [string trim $s]
regsub -all {[\t\n ]+} $s { } s
return [split $s]
if { [string is list $s] } {
return $s
} else {
return [split $s]
}
}
proc set_sim_defaults {{reset {}}} {
@ -1501,7 +1505,7 @@ proc graph_update_nodelist {} {
# tagging nodes in text widget:
set col [xschem getprop rect 2 $graph_selected color]
set col [string trim $col " \n"]
set tt [.graphdialog.center.right.text1 search -all -nolinestop -regexp -count cc {[^ \n]+} 1.0]
set tt [.graphdialog.center.right.text1 search -all -nolinestop -regexp -count cc {"[^"]+"|[^ \n]+} 1.0] ;#"4vim
set n 0
if { [info exists cc] && ($tt ne {}) } {
foreach t $tt c $cc {
@ -1538,7 +1542,7 @@ proc fill_graph_listbox {} {
proc update_graph_node {node} {
global graph_selected
graph_update_nodelist
regsub -all {(["\\])} $node {\\\1} node_quoted ;#" editor is confused by the previous quote
regsub -all {(["\\])} $node {\\\1} node_quoted ;#"4vim
xschem setprop rect 2 $graph_selected node $node_quoted fast
xschem draw_graph $graph_selected
}