/* Set a variable. */ void cp_vset(char *varname, enum cp_types type, void *value) { struct variable *v, *u, *w; int i; //bool alreadythere = FALSE, v_free = FALSE; int alreadythere = FALSE, v_free = FALSE; char *copyvarname; /* varname = cp_unquote(varname); DG: Memory leak old varname is lost*/ copyvarname = cp_unquote(varname); w = NULL; for (v = variables; v; v = v->va_next) { if (eq(copyvarname, v->va_name)) { alreadythere = TRUE; break; } w = v; } if (alreadythere) { if (v->va_type == CP_LIST) free_struct_variable(v->va_vlist); if (v->va_type == CP_STRING) tfree(v->va_string); } if (!v) { v = alloc(struct variable); v->va_name = copy(copyvarname); v->va_next = NULL; v_free = TRUE; }
/* free the struct variable. The type of the union is given by va_type */ void free_struct_variable(struct variable *v) { while (v) { struct variable *next_v = v->va_next; if (v->va_name) tfree(v->va_name); if (v->va_type == CP_LIST) free_struct_variable(v->va_vlist); if (v->va_type == CP_STRING) tfree(v->va_string); tfree(v); v = next_v; } }
/* The option command. Syntax is option [opt ...] [opt = val ...]. * Val may be a string, an int, a float, or a list of the * form (elt1 elt2 ...). */ void com_option(wordlist *wl) { struct variable *vars; CKTcircuit *circuit = NULL; if (!ft_curckt) { fprintf(cp_err, "Error: no circuit loaded\n"); return; } circuit = (ft_curckt->ci_ckt); if (wl == NULL) { printf("******************************\n"); printf("* Current simulation options *\n"); printf("******************************\n\n"); printf("Temperatures:\n"); printf("temp = %f\n", circuit->CKTtemp); printf("tnom = %f\n", circuit->CKTnomTemp); printf("\nIntegration method summary:\n"); switch (circuit->CKTintegrateMethod) { case TRAPEZOIDAL: printf("Integration Method = TRAPEZOIDAL\n"); break; case GEAR: printf("Integration Method = GEAR\n"); break; default: printf("Unknown integration method\n"); } printf("MaxOrder = %d\n", circuit->CKTmaxOrder); printf("\nTolerances (absolute):\n"); printf("abstol (current) = %g\n", circuit->CKTabstol); printf("chgtol (charge) = %g\n", circuit->CKTchgtol); printf("vntol (voltage) = %g\n", circuit->CKTvoltTol); printf("pivtol (pivot) = %g\n", circuit->CKTpivotAbsTol); printf("\nTolerances (relative):\n"); printf("reltol (current) = %g\n", circuit->CKTreltol); printf("pivrel (pivot) = %g\n", circuit->CKTpivotRelTol); printf("\nIteration limits:\n"); printf("ITL1 = %d\n", circuit->CKTdcMaxIter); printf("ITL2 = %d\n", circuit->CKTdcTrcvMaxIter); printf("ITL4 = %d\n", circuit->CKTtranMaxIter); printf("\nTruncation error correction:\n"); printf("trtol = %f\n", circuit->CKTtrtol); #ifdef NEWTRUNC printf("ltereltol = %g\n", circuit->CKTlteReltol); printf("lteabstol = %g\n", circuit->CKTlteAbstol); #endif /* NEWTRUNC */ printf("\nConductances:\n"); printf("gmin (devices) = %g\n", circuit->CKTgmin); printf("diaggmin (stepping) = %g\n", circuit->CKTdiagGmin); printf("gshunt = %g\n", circuit->CKTgshunt); printf("delmin = %g\n", circuit->CKTdelmin); printf("\nDefault parameters for MOS devices\n"); printf("Default M: %f\n", circuit->CKTdefaultMosM); printf("Default L: %f\n", circuit->CKTdefaultMosL); printf("Default W: %f\n", circuit->CKTdefaultMosW); printf("Default AD: %f\n", circuit->CKTdefaultMosAD); printf("Default AS: %f\n", circuit->CKTdefaultMosAS); return; } vars = cp_setparse(wl); /* This is sort of a hassle... */ while (vars) { void *s; switch (vars->va_type) { case CP_BOOL: s = &vars->va_bool; break; case CP_NUM: s = &vars->va_num; break; case CP_REAL: s = &vars->va_real; break; case CP_STRING: s = vars->va_string; break; case CP_LIST: s = vars->va_vlist; break; default: s = NULL; } /* qui deve settare le opzioni di simulazione */ cp_vset(vars->va_name, vars->va_type, s); vars = vars->va_next; } free_struct_variable(vars); }
/* Print the values of currently defined variables. */ void cp_vprint(void) { struct variable *v; struct variable *uv1; wordlist *wl; int i, j; char *s; struct xxx *vars; uv1 = cp_usrvars(); for (v = variables, i = 0; v; v = v->va_next) i++; for (v = uv1; v; v = v->va_next) i++; if (plot_cur) for (v = plot_cur->pl_env; v; v = v->va_next) i++; if (ft_curckt) for (v = ft_curckt->ci_vars; v; v = v->va_next) i++; vars = TMALLOC(struct xxx, i); out_init(); for (v = variables, i = 0; v; v = v->va_next, i++) { vars[i].x_v = v; vars[i].x_char = ' '; } for (v = uv1; v; v = v->va_next, i++) { vars[i].x_v = v; vars[i].x_char = '*'; } if (plot_cur) for (v = plot_cur->pl_env; v; v = v->va_next, i++) { vars[i].x_v = v; vars[i].x_char = '*'; } if (ft_curckt) for (v = ft_curckt->ci_vars; v; v = v->va_next, i++) { vars[i].x_v = v; vars[i].x_char = '+'; } qsort(vars, (size_t) i, sizeof(*vars), vcmp); for (j = 0; j < i; j++) { if (j && eq(vars[j].x_v->va_name, vars[j-1].x_v->va_name)) continue; v = vars[j].x_v; if (v->va_type == CP_BOOL) { out_printf("%c %s\n", vars[j].x_char, v->va_name); } else { out_printf("%c %s\t", vars[j].x_char, v->va_name); wl = vareval(v->va_name); s = wl_flatten(wl); if (v->va_type == CP_LIST) out_printf("( %s )\n", s); else out_printf("%s\n", s); } } free_struct_variable(uv1); tfree(vars); }
/* Set a variable. */ void cp_vset(char *varname, enum cp_types type, void *value) { struct variable *v, *u, *w; int i; bool alreadythere = FALSE, v_free = FALSE; char *copyvarname; /* varname = cp_unquote(varname); DG: Memory leak old varname is lost*/ copyvarname = cp_unquote(varname); w = NULL; for (v = variables; v; v = v->va_next) { if (eq(copyvarname, v->va_name)) { alreadythere = TRUE; break; } w = v; } if (alreadythere) { if (v->va_type == CP_LIST) free_struct_variable(v->va_vlist); if (v->va_type == CP_STRING) tfree(v->va_string); } if (!v) { v = var_alloc(copy(copyvarname), NULL); v_free = TRUE; } switch (type) { case CP_BOOL: if (* ((bool *) value) == FALSE) { cp_remvar(copyvarname); if (v_free) { tfree(v->va_name); tfree(v); } tfree(copyvarname); return; } else { var_set_bool(v, TRUE); } break; case CP_NUM: var_set_num(v, * (int *) value); break; case CP_REAL: var_set_real(v, * (double *) value); break; case CP_STRING: var_set_string(v, copy((char*) value)); break; case CP_LIST: var_set_vlist(v, (struct variable *) value); break; default: fprintf(cp_err, "cp_vset: Internal Error: bad variable type %d.\n", type); tfree(copyvarname); return; } /* Now, see if there is anything interesting going on. We * recognise these special variables: noglob, nonomatch, history, * echo, noclobber, prompt, and verbose. cp_remvar looks for these * variables too. The host program will get any others. */ if (eq(copyvarname, "noglob")) cp_noglob = TRUE; else if (eq(copyvarname, "nonomatch")) cp_nonomatch = TRUE; else if (eq(copyvarname, "history") && (type == CP_NUM)) cp_maxhistlength = v->va_num; else if (eq(copyvarname, "history") && (type == CP_REAL)) cp_maxhistlength = (int)floor(v->va_real + 0.5); else if (eq(copyvarname, "noclobber")) cp_noclobber = TRUE; else if (eq(varname, "echo")) /*CDHW*/ cp_echo = TRUE; /*CDHW*/ else if (eq(copyvarname, "prompt") && (type == CP_STRING)) cp_promptstring = v->va_string; else if (eq(copyvarname, "ignoreeof")) cp_ignoreeof = TRUE; else if (eq(copyvarname, "cpdebug")) { cp_debug = TRUE; #ifndef CPDEBUG fprintf(cp_err, "Warning: program not compiled with cshpar debug messages\n"); #endif } switch (i = cp_usrset(v, TRUE)) { case US_OK: /* Normal case. */ if (!alreadythere) { v->va_next = variables; variables = v; } else if (v_free) free_struct_variable(v); break; case US_DONTRECORD: /* 'curplot' 'curplotname' 'curplottitle' 'curplotdate' */ /* Do nothing... */ if (alreadythere) { fprintf(cp_err, "cp_vset: Internal Error: " "%s already there, but 'dont record'\n", v->va_name); } if (v_free) free_struct_variable(v); break; case US_READONLY: /* 'plots' and any var in plot_cur->pl_env */ fprintf(cp_err, "Error: %s is a read-only variable.\n", v->va_name); if (alreadythere) fprintf(cp_err, "cp_vset: Internal Error: " "it was already there too!!\n"); break; case US_SIMVAR: /* variables processed by if_option(ft_curckt->ci_ckt, ...) */ if (alreadythere) { /* somehow it got into the front-end list of variables */ if (w) { w->va_next = v->va_next; } else { variables = v->va_next; } } alreadythere = FALSE; if (ft_curckt) { for (u = ft_curckt->ci_vars; u; u = u->va_next) if (eq(copyvarname, u->va_name)) { alreadythere = TRUE; break; } if (!alreadythere) { v->va_next = ft_curckt->ci_vars; ft_curckt->ci_vars = v; } else { if (u->va_type == CP_STRING) tfree(u->va_string); else if (u->va_type == CP_LIST) tfree(u->va_vlist); u->va_V = v->va_V; u->va_type = v->va_type; /* va_name is the same string */ tfree(u->va_name); u->va_name = v->va_name; /* va_next left unchanged */ tfree(v); } } break; case US_NOSIMVAR: /* variables processed by if_option(NULL, ...) */ /* What do you do? */ free_struct_variable(v); break; default: fprintf(cp_err, "cp_vset: Internal Error: bad US val %d\n", i); break; } tfree(copyvarname); }
/* Determine the value of a variable. Fail if the variable is unset, * and if the type doesn't match, try and make it work... */ bool cp_getvar(char *name, enum cp_types type, void *retval) { struct variable *v; struct variable *uv1; uv1 = cp_usrvars(); #ifdef TRACE /* SDB debug statement */ fprintf(stderr, "in cp_getvar, trying to get value of variable %s.\n", name); #endif for (v = variables; v; v = v->va_next) if (eq(name, v->va_name)) break; if (!v) for (v = uv1; v; v = v->va_next) if (eq(name, v->va_name)) break; if (!v && plot_cur) for (v = plot_cur->pl_env; v; v = v->va_next) if (eq(name, v->va_name)) break; if (!v && ft_curckt) for (v = ft_curckt->ci_vars; v; v = v->va_next) if (eq(name, v->va_name)) break; if (!v) { if (type == CP_BOOL && retval) *(bool *) retval = FALSE; free_struct_variable(uv1); return (FALSE); } if (v->va_type == type) { if (retval) switch (type) { case CP_BOOL: *(bool *) retval = TRUE; break; case CP_NUM: *(int *) retval = v->va_num; break; case CP_REAL: *(double *) retval = v->va_real; break; case CP_STRING: { /* Gotta be careful to have room. */ char *s = cp_unquote(v->va_string); cp_wstrip(s); strcpy((char*) retval, s); tfree(s); break; } case CP_LIST: /* Funny case... */ *(struct variable **) retval = v->va_vlist; break; default: fprintf(cp_err, "cp_getvar: Internal Error: bad var type %d.\n", type); break; } free_struct_variable(uv1); return (TRUE); } /* Try to coerce it.. */ if ((type == CP_NUM) && (v->va_type == CP_REAL)) { *(int *) retval = (int) v->va_real; } else if ((type == CP_REAL) && (v->va_type == CP_NUM)) { *(double *) retval = (double) v->va_num; } else if ((type == CP_STRING) && (v->va_type == CP_NUM)) { sprintf((char*) retval, "%d", v->va_num); } else if ((type == CP_STRING) && (v->va_type == CP_REAL)) { sprintf((char*) retval, "%f", v->va_real); } else { free_struct_variable(uv1); return (FALSE); } free_struct_variable(uv1); return (TRUE); }
void cp_remvar(char *varname) { struct variable *v, **p; struct variable *uv1; int i; uv1 = cp_usrvars(); for (p = &variables; *p; p = &(*p)->va_next) if (eq((*p)->va_name, varname)) break; if (*p == NULL) for (p = &uv1; *p; p = &(*p)->va_next) if (eq((*p)->va_name, varname)) break; if (*p == NULL && plot_cur) for (p = &plot_cur->pl_env; *p; p = &(*p)->va_next) if (eq((*p)->va_name, varname)) break; if (*p == NULL && ft_curckt) for (p = &ft_curckt->ci_vars; *p; p = &(*p)->va_next) if (eq((*p)->va_name, varname)) break; v = *p; /* make up an auxiliary struct variable for cp_usrset() */ if (!v) v = var_alloc_num(copy(varname), 0, NULL); /* Note that 'unset history' doesn't do anything here... Causes * trouble... */ if (eq(varname, "noglob")) cp_noglob = FALSE; else if (eq(varname, "nonomatch")) cp_nonomatch = FALSE; else if (eq(varname, "noclobber")) cp_noclobber = FALSE; else if (eq(varname, "echo")) /*CDHW*/ cp_echo = FALSE; /*CDHW*/ else if (eq(varname, "prompt")) cp_promptstring = NULL; else if (eq(varname, "cpdebug")) cp_debug = FALSE; else if (eq(varname, "ignoreeof")) cp_ignoreeof = FALSE; else if (eq(varname, "program")) cp_program = ""; switch (i = cp_usrset(v, FALSE)) { case US_OK: /* Normal case. */ if (*p) { *p = v->va_next; } break; case US_DONTRECORD: /* 'curplot' 'curplotname' 'curplottitle' 'curplotdate' */ /* Do nothing... */ if (*p) fprintf(cp_err, "cp_remvar: Internal Error: var %d\n", *varname); break; case US_READONLY: /* 'plots' and any var in plot_cur->pl_env */ /* Badness... */ fprintf(cp_err, "Error: %s is read-only.\n", v->va_name); if (*p) fprintf(cp_err, "cp_remvar: Internal Error: var %d\n", *varname); break; case US_SIMVAR: /* variables processed by if_option(ft_curckt->ci_ckt, ...) */ fprintf(stderr, "it's a US_SIMVAR!\n"); if (ft_curckt) { for (p = &ft_curckt->ci_vars; *p; p = &(*p)->va_next) if (eq(varname, (*p)->va_name)) break; if (*p) { struct variable *u = *p; *p = u->va_next; tfree(u); } } break; case US_NOSIMVAR: default: /* variables processed by if_option(NULL, ...) */ fprintf(cp_err, "cp_remvar: Internal Error: US val %d\n", i); break; } v->va_next = NULL; free_struct_variable(v); free_struct_variable(uv1); }