1 /***************************************************************************
2 JSPICE3 adaptation of Spice3e2 - Copyright (c) Stephen R. Whiteley 1992
3 Copyright 1990 Regents of the University of California. All rights reserved.
4 Authors: 1985 Wayne A. Christopher
5 1992 Stephen R. Whiteley
6 ****************************************************************************/
7
8 /*
9 * The user-supplied routine to deal with variables. Most variables we
10 * don't use often, so just call cp_getvar when they are needed. Spice
11 * variables, though, and a few commonly used ones are dealt with here.
12 */
13
14 #include "spice.h"
15 #include "ftedefs.h"
16 #include "fteinp.h"
17
18 /* used by Josephson junction model,
19 * default max phase change is 2*PI/10
20 */
21 double JJdphi = 2.07e-16;
22
23 bool ft_nopage = false;
24 bool ft_parsedb = false;
25 bool ft_vecdb = false;
26 bool ft_simdb = false;
27 bool ft_evdb = false;
28 bool ft_grdb = false;
29 bool ft_gidb = false;
30 bool ft_controldb = false;
31 bool ft_asyncdb = false;
32
33 #ifdef __STDC__
34 static struct variable *vec2var(struct dvec*,int,int);
35 static struct variable *getlist(struct dvec*,int,char**);
36 #else
37 static struct variable *vec2var();
38 static struct variable *getlist();
39 #endif
40
41 /* The following routines take care of managing internal variables.
42 * Some of the functionality was previously found in variable.c. Here,
43 * all variables are included in a single table below, many of which
44 * have dispatch functions. This code should be much faster.
45 */
46
47 /* These are the dispatch functions... */
48
49 #define def_fn(name) \
50 static int name(v,flag) \
51 struct variable *v; \
52 bool flag;
53
54 /* "shell" variables */
55
def_fn(_iv_cpdebug)56 def_fn(_iv_cpdebug)
57 {
58 cp_debug = flag;
59 #ifndef CPDEBUG
60 if(flag)
61 fprintf(cp_err,
62 "Warning: program not compiled with cshpar debug messages\n");
63 #endif
64 return (US_OK);
65 }
66
def_fn(_iv_history)67 def_fn(_iv_history)
68 {
69 if (!flag) return (US_OK);
70 if (v->va_type == VT_NUM)
71 cp_maxhistlength = v->va_num;
72 else if (v->va_type == VT_REAL)
73 cp_maxhistlength = v->va_real;
74 return (US_OK);
75 }
76
def_fn(_iv_ignoreeof)77 def_fn(_iv_ignoreeof) {cp_ignoreeof=flag; return (US_OK);}
def_fn(_iv_noclobber)78 def_fn(_iv_noclobber) {cp_noclobber=flag; return (US_OK);}
def_fn(_iv_noglob)79 def_fn(_iv_noglob) {cp_noglob=flag; return (US_OK);}
def_fn(_iv_nonomatch)80 def_fn(_iv_nonomatch) {cp_nonomatch=flag; return (US_OK);}
81
def_fn(_iv_prompt)82 def_fn(_iv_prompt)
83 {
84 if (!flag)
85 cp_promptstring = "";
86 else if (v->va_type == VT_STRING)
87 cp_promptstring = copy(v->va_string);
88 return (US_OK);
89 }
90
91
92 /* spice and nutmeg variables */
93
94 static char *huhmsg = "Excuse me??\n";
95 static char *pltmsg = "Error: can't set plot";
96
def_fn(_iv_acct)97 def_fn(_iv_acct) {ft_acctprint=flag; return (US_OK);}
98
def_fn(_iv_curplot)99 def_fn(_iv_curplot)
100 {
101 if (v->va_type == VT_STRING)
102 plot_setcur(v->va_string);
103 else if (flag)
104 fprintf(cp_err, "Error: plot name not a string\n");
105 return (US_DONTRECORD);
106 }
107
def_fn(_iv_curplotdate)108 def_fn(_iv_curplotdate)
109 {
110 if (plot_cur && (v->va_type == VT_STRING))
111 plot_cur->pl_date = copy(v->va_string);
112 else if (flag)
113 fprintf(cp_err,"%s %s\n",pltmsg,"date");
114 return (US_DONTRECORD);
115 }
116
def_fn(_iv_curplotname)117 def_fn(_iv_curplotname)
118 {
119 if (plot_cur && (v->va_type == VT_STRING))
120 plot_cur->pl_name = copy(v->va_string);
121 else if (flag)
122 fprintf(cp_err,"%s %s\n",pltmsg,"name");
123 return (US_DONTRECORD);
124 }
125
def_fn(_iv_curplottitle)126 def_fn(_iv_curplottitle)
127 {
128 if (plot_cur && (v->va_type == VT_STRING))
129 plot_cur->pl_title = copy(v->va_string);
130 else
131 fprintf(cp_err,"%s %s\n",pltmsg,"title");
132 return (US_DONTRECORD);
133 }
134
135 static void
setdb(word)136 setdb(word)
137
138 char *word;
139 {
140 if (eq(word,"async"))
141 ft_asyncdb = true;
142 else if (eq(word,"control"))
143 ft_controldb = true;
144 else if (eq(word,"cshpar"))
145 cp_debug = true;
146 else if (eq(word,"eval"))
147 ft_evdb = true;
148 else if (eq(word,"ginterface"))
149 ft_gidb = true;
150 else if (eq(word,"graf"))
151 ft_grdb = true;
152 else if (eq(word,"parser"))
153 ft_parsedb = true;
154 else if (eq(word,"siminterface"))
155 ft_simdb = true;
156 else if (eq(word,"vecdb"))
157 ft_vecdb = true;
158 }
159
def_fn(_iv_debug)160 def_fn(_iv_debug)
161 {
162 struct variable *tv;
163 char *dbgmsg = "Error: bad type for debug var\n";
164
165 if (v->va_type == VT_BOOL) {
166 cp_debug = ft_simdb = ft_parsedb = ft_evdb = ft_vecdb =
167 ft_grdb = ft_gidb = ft_controldb = flag;
168 }
169 else if (v->va_type == VT_LIST) {
170 for (tv = v->va_vlist; tv; tv = tv->va_next) {
171 if (v->va_type != VT_STRING)
172 fprintf(cp_err,dbgmsg);
173 else
174 setdb(tv->va_string);
175 }
176 }
177 else if (v->va_type == VT_STRING) {
178 setdb(v->va_string);
179 }
180 else if (flag)
181 fprintf(cp_err,dbgmsg);
182 #ifndef FTEDEBUG
183 if (flag)
184 fprintf(cp_err, "Warning: %s compiled without debug messages\n",
185 cp_program);
186 #endif
187 return (US_OK);
188 }
189
def_fn(_iv_display)190 def_fn(_iv_display) { return (US_READONLY);}
191
def_fn(_iv_height)192 def_fn(_iv_height)
193 {
194 if ((v->va_type == VT_BOOL) && (flag == false))
195 out_height = 0;
196 else if (v->va_type == VT_REAL)
197 out_height = v->va_real;
198 else if (v->va_type == VT_NUM)
199 out_height = v->va_num;
200 else
201 fprintf(cp_err, "Bad 'height' \"%s\"\n", v->va_name);
202 return (US_OK);
203 }
204
def_fn(_iv_jjdphimax)205 def_fn(_iv_jjdphimax)
206 {
207 if (flag == false)
208 JJdphi = 2.07e-16;
209 else if (v->va_type == VT_REAL) {
210 if (v->va_real < M_PI/50 || v->va_real > M_PI/2)
211 goto errm;
212 JJdphi = v->va_real*3.3e-16; /* phi0 /2*pi */
213 }
214 else if (v->va_type == VT_NUM) {
215 if (v->va_num < M_PI/50 || v->va_num > M_PI/2)
216 goto errm;
217 JJdphi = v->va_num*3.3e-16; /* phi0 /2*pi */
218 }
219 else
220 fprintf(cp_err,huhmsg);
221 return (US_OK);
222 errm:
223 fprintf(cp_err, "Error: must be between pi/50 and pi/2\n");
224 return (US_OK);
225 }
226
def_fn(_iv_list)227 def_fn(_iv_list) {ft_listprint=flag; return (US_OK);}
def_fn(_iv_nocc)228 def_fn(_iv_nocc) {cp_nocc=flag; return (US_OK);}
def_fn(_iv_node)229 def_fn(_iv_node) {ft_nodesprint=flag; return (US_OK);}
def_fn(_iv_noiter)230 def_fn(_iv_noiter) {return (US_OK);}
def_fn(_iv_nomoremode)231 def_fn(_iv_nomoremode) {out_moremode=!flag; return (US_OK);}
def_fn(_iv_nopage)232 def_fn(_iv_nopage) {ft_nopage=flag; return (US_OK);}
233
def_fn(_iv_numdgt)234 def_fn(_iv_numdgt)
235 {
236 if ((v->va_type == VT_BOOL) && (flag == false))
237 cp_numdgt = -1;
238 else if (v->va_type == VT_REAL)
239 cp_numdgt = v->va_real;
240 else if (v->va_type == VT_NUM)
241 cp_numdgt = v->va_num;
242 else
243 fprintf(cp_err,huhmsg);
244 return (US_OK);
245 }
246
def_fn(_iv_opts)247 def_fn(_iv_opts) {ft_optsprint=flag; return (US_OK);}
def_fn(_iv_plots)248 def_fn(_iv_plots) {return (US_READONLY);}
249
def_fn(_iv_program)250 def_fn(_iv_program)
251 {
252 if (!flag)
253 cp_program = "";
254 else if (v->va_type == VT_STRING)
255 cp_program = copy(v->va_string);
256 return (US_OK);
257 }
258
def_fn(_iv_rawfile)259 def_fn(_iv_rawfile)
260 {
261 if (!flag)
262 ft_rawfile = "";
263 else if (v->va_type == VT_STRING)
264 ft_rawfile = copy(v->va_string);
265 return (US_OK);
266 }
267
def_fn(_iv_rawfileprec)268 def_fn(_iv_rawfileprec)
269 {
270 if ((v->va_type == VT_BOOL) && (flag == false))
271 raw_prec = -1;
272 else if (v->va_type == VT_REAL)
273 raw_prec = v->va_real;
274 else if (v->va_type == VT_NUM)
275 raw_prec = v->va_num;
276 else
277 fprintf(cp_err, "Bad 'rawfileprec' \"%s\"\n", v->va_name);
278 return (US_OK);
279 }
280
def_fn(_iv_strictnumparse)281 def_fn(_iv_strictnumparse) {ft_strictnumparse=flag; return (US_OK);}
282
def_fn(_iv_units)283 def_fn(_iv_units)
284 {
285 if (false && ((*v->va_string == 'd') ||
286 (*v->va_string == 'D')))
287 cx_degrees = true;
288 else
289 cx_degrees = false;
290 return (US_OK);
291 }
292
def_fn(_iv_unixcom)293 def_fn(_iv_unixcom)
294 {
295 char *s;
296
297 cp_dounixcom = flag;
298 if (flag) {
299 s = getenv("PATH");
300 if (s)
301 cp_rehash(s, !cp_nocc);
302 else
303 fprintf(cp_err,
304 "Warning: no PATH in environment.\n");
305 }
306 else {
307 struct comm *c;
308 cp_ccrestart(false);
309 for (c = cp_coms; c->co_func; c++)
310 cp_addcomm(c->co_comname, c->co_cctypes[0],
311 c->co_cctypes[1], c->co_cctypes[2],
312 c->co_cctypes[3]);
313 }
314 return (US_OK);
315 }
316
def_fn(_iv_width)317 def_fn(_iv_width)
318 {
319 if ((v->va_type == VT_BOOL) && (flag == false))
320 out_width = 0;
321 else if (v->va_type == VT_REAL)
322 out_width = v->va_real;
323 else if (v->va_type == VT_NUM)
324 out_width = v->va_num;
325 else
326 fprintf(cp_err, "Bad 'width' \"%s\"\n", v->va_name);
327 return (US_OK);
328 }
329
330
331
332 /* The table below includes all variables with significance to the
333 * program.
334 */
335 char *kw_abstol = "abstol";
336 char *kw_acct = "acct";
337 char *kw_appendwrite = "appendwrite";
338 char *kw_checkiterate = "checkiterate";
339 char *kw_chgtol = "chgtol";
340 char *kw_color = "color";
341 char *kw_cpdebug = "cpdebug";
342 char *kw_curplot = "curplot";
343 char *kw_curplotname = "curplotname";
344 char *kw_curplottitle = "curplottitle";
345 char *kw_curplotdate = "curplotdate";
346 char *kw_debug = "debug";
347 char *kw_defad = "defad";
348 char *kw_defas = "defas";
349 char *kw_defl = "defl";
350 char *kw_defw = "defw";
351 char *kw_device = "device";
352 char *kw_display = "display";
353 char *kw_dontplot = "dontplot";
354 char *kw_editor = "editor";
355 char *kw_filetype = "filetype";
356 char *kw_fourgridsize = "fourgridsize";
357 char *kw_gmin = "gmin";
358 char *kw_gridsize = "gridsize";
359 char *kw_gridstyle = "gridstyle";
360 char *kw_hcopydev = "hcopydev";
361 char *kw_hcopydevtype = "hcopydevtype";
362 char *kw_height = "height";
363 char *kw_history = "history";
364 char *kw_hitusertp = "hitusertp";
365 char *kw_ignoreeof = "ignoreeof";
366 char *kw_itl1 = "itl1";
367 char *kw_itl2 = "itl2";
368 char *kw_itl3 = "itl3";
369 char *kw_itl4 = "itl4";
370 char *kw_itl5 = "itl5";
371 char *kw_jjdphimax = "jjdphimax";
372 char *kw_level = "level";
373 char *kw_list = "list";
374 char *kw_maxwins = "maxwins";
375 char *kw_modelcard = "modelcard";
376 char *kw_mplot_cur = "mplot_cur";
377 char *kw_nfreqs = "nfreqs";
378 char *kw_noasciiplotvalue = "noasciiplotvalue";
379 char *kw_noaskquit = "noaskquit";
380 char *kw_nobjthack = "nobjthack";
381 char *kw_nobreak = "nobreak";
382 char *kw_nocc = "nocc";
383 char *kw_noclobber = "noclobber";
384 char *kw_node = "node";
385 char *kw_noglob = "noglob";
386 char *kw_nogrid = "nogrid";
387 char *kw_noiter = "noiter";
388 char *kw_nojjtp = "nojjtp";
389 char *kw_nomoremode = "nomoremode";
390 char *kw_nonomatch = "nonomatch";
391 char *kw_nopage = "nopage";
392 char *kw_noparse = "noparse";
393 char *kw_noprintscale = "noprintscale";
394 char *kw_nosort = "nosort";
395 char *kw_nosubckt = "nosubckt";
396 char *kw_nousertp = "nousertp";
397 char *kw_numdgt = "numdgt";
398 char *kw_opts = "opts";
399 char *kw_pivrel = "pivrel";
400 char *kw_pivtol = "pivtol";
401 char *kw_plots = "plots";
402 char *kw_plotstyle = "plotstyle";
403 char *kw_pointchars = "pointchars";
404 char *kw_polydegree = "polydegree";
405 char *kw_polysteps = "polysteps";
406 char *kw_printinfo = "printinfo";
407 char *kw_program = "program";
408 char *kw_prompt = "prompt";
409 char *kw_rawfile = "rawfile";
410 char *kw_rawfileprec = "rawfileprec";
411 char *kw_reltol = "reltol";
412 char *kw_renumber = "renumber";
413 char *kw_rhost = "rhost";
414 char *kw_rprogram = "rprogram";
415 char *kw_scedfont = "scedfont";
416 char *kw_slowplot = "slowplot";
417 char *kw_sourcepath = "sourcepath";
418 char *kw_spicepath = "spicepath";
419 char *kw_strictnumparse = "strictnumparse";
420 char *kw_subend = "subend";
421 char *kw_subinvoke = "subinvoke";
422 char *kw_substart = "substart";
423 char *kw_term = "term";
424 char *kw_ticmarks = "ticmarks";
425 char *kw_tnom = "tnom";
426 char *kw_trtol = "trtol";
427 char *kw_units = "units";
428 char *kw_unixcom = "unixcom";
429 char *kw_vntol = "vntol";
430 char *kw_width = "width";
431 char *kw_wpboxh = "wpboxh";
432 char *kw_wpboxw = "wpboxw";
433 char *kw_xglinewidth = "xglinewidth";
434 char *kw_xgmarkers = "xgmarkers";
435 char *kw_xfont = "xfont";
436
437
438 struct intvar {
439 char **name;
440 char *descr;
441 #ifdef __STDC__
442 int (*func)(struct variable*,bool);
443 #else
444 int (*func)();
445 #endif
446 };
447 static struct intvar int_vars[] = {
448 {&kw_abstol, "real Absolute error tolerance, default 1e-12.", NULL},
449 {&kw_acct, "bool Print accounting summary.", _iv_acct},
450 {&kw_appendwrite, "bool Append to file with write command, no overwrite.", NULL},
451 {&kw_checkiterate,"int Binary search iterations in range analysis.", NULL},
452 {&kw_chgtol,"real Charge tolerance, default 1e-14.", NULL},
453 {&kw_color, "list X window colors, see help.", NULL},
454 {&kw_cpdebug, "bool Enable command processor debugging.", _iv_cpdebug},
455 {&kw_curplot, "str Current plot.", _iv_curplot},
456 {&kw_curplotname, "str Current plot name, read only.", _iv_curplotname},
457 {&kw_curplottitle, "str Current plot title, read only.", _iv_curplottitle},
458 {&kw_curplotdate, "str Current plot date, read only", _iv_curplotdate},
459 {&kw_debug, "list Enable debugging, see help for keywords.", _iv_debug},
460 {&kw_defad, "real MOS drain diffusion area, default 0.", NULL},
461 {&kw_defas, "real MOS source diffusion area, defalut 0", NULL},
462 {&kw_defl, "real MOS channel length, default 100 microns.", NULL},
463 {&kw_defw, "real MOS channel width, default 100 microns.", NULL},
464 {&kw_device, "str UNIX /dev/tty?? device for output.", NULL},
465 {&kw_display, "str X uses this display, read only.", _iv_display},
466 {&kw_dontplot, "bool Don't send graphics code to output device.", NULL},
467 {&kw_editor, "str Editor invocation string.", NULL},
468 {&kw_filetype, "str Rawfile type: ascii or binary.", NULL},
469 {&kw_fourgridsize, "int Number of interpolation points in fourier analysis.", NULL},
470 {&kw_gmin, "real Minimum conductance allowed, default 1e-12.", NULL},
471 {&kw_gridsize, "real Number of y-axis grid lines.", NULL},
472 {&kw_gridstyle, "str Plot default grid type (lingrid, loglog, nogrid, \n\t\t xlog, ylog, polar, smith).", NULL},
473 {&kw_hcopydev, "str UNIX: send hardcopy using LPR -P??. DOS: prn,lpt?.", NULL},
474 {&kw_hcopydevtype, "str Hardcopy device type: postscript, etc.", NULL},
475 {&kw_height, "real Screen height in characters.", _iv_height},
476 {&kw_history, "int Number of remembered commands, default 1000.", _iv_history},
477 {&kw_hitusertp, "bool Force transient analysis at user time points.", NULL},
478 {&kw_ignoreeof,"bool Ignore end of file (^D) in UNIX.", _iv_ignoreeof},
479 {&kw_itl1, "int DC iteration limit, default 100.", NULL},
480 {&kw_itl2, "int DC transfer curve iteration limit, default 50", NULL},
481 {&kw_itl3, "int Lower transient iteration limit, default 4.", NULL},
482 {&kw_itl4, "int Upper transient iteration limit, default 10.", NULL},
483 {&kw_itl5, "int Unused.", NULL},
484 {&kw_jjdphimax, "real Max Josephson phase delta per step, default pi/10.", _iv_jjdphimax},
485 {&kw_level, "str Level for newhelp, (b, i, or a).", NULL},
486 {&kw_list, "bool Causes the input to be listed.", _iv_list},
487 {&kw_maxwins, "int Maximum number of windows in X.", NULL},
488 {&kw_modelcard, "str Name of model card, default .model.", NULL},
489 {&kw_mplot_cur, "str Name of current output file for check command", NULL},
490 {&kw_nfreqs, "int Number of frequencies in fourier command, default 10.", NULL},
491 {&kw_noasciiplotvalue, "bool Don't print scale value in asciiplot.", NULL},
492 {&kw_noaskquit, "bool Don't verify before termination.", NULL},
493 {&kw_nobjthack, "bool Assume BJT's have 4 nodes.", NULL},
494 {&kw_nobreak, "bool No break between pages in asciiplot.", NULL},
495 {&kw_nocc, "bool No command completion.", _iv_nocc},
496 {&kw_noclobber, "bool Don't overwrite files when redirecting output.", _iv_noclobber},
497 {&kw_node, "bool Print node table.", _iv_node},
498 {&kw_noglob, "bool Don't expand wildcard characters.", _iv_noglob},
499 {&kw_nogrid, "bool Don't plot a grid.", NULL},
500 {&kw_noiter, "bool No transient iterations past predictor.", _iv_noiter},
501 {&kw_nojjtp, "bool No Josephson phase change timestep, use trunc error.", NULL},
502 {&kw_nomoremode, "bool Turn off more mode.", _iv_nomoremode},
503 {&kw_nonomatch, "bool Use wildcard characters literally if no match.", _iv_nonomatch},
504 {&kw_nopage, "bool Supress page ejects.", _iv_nopage},
505 {&kw_noparse, "bool Don't parse circuit.", NULL},
506 {&kw_noprintscale, "bool Don't print scale in print command.", NULL},
507 {&kw_nosort, "bool Supress sorting of variable names.", NULL},
508 {&kw_nosubckt, "bool No subcircuit expansion.", NULL},
509 {&kw_nousertp, "bool Save raw time point values in transient analysis.", NULL},
510 {&kw_numdgt, "int Number of significant digits to print, default 4.", _iv_numdgt},
511 {&kw_opts, "bool Print options.", _iv_opts},
512 {&kw_pivrel, "real Relative pivot value, default 1e-3.", NULL},
513 {&kw_pivtol, "real Minimum pivot value, default 1e-13.", NULL},
514 {&kw_plots, "list Read only, list of plots.", _iv_plots},
515 {&kw_plotstyle, "str Default plot type (linplot, combplot, pointplot).", NULL},
516 {&kw_pointchars, "str Point characters for plotting.", NULL},
517 {&kw_polydegree, "int Degree of interpolating polynomial.", NULL},
518 {&kw_polysteps, "int Number of interpolating points, default 10.", NULL},
519 {&kw_printinfo, "bool Print debugging info when plot starts.", NULL},
520 {&kw_program, "str Program name.", _iv_program},
521 {&kw_prompt, "str Prompt string.", _iv_prompt},
522 {&kw_rawfile, "str Rawfile path.", _iv_rawfile},
523 {&kw_rawfileprec, "int Significant digits in rawfile.", _iv_rawfileprec},
524 {&kw_reltol, "real Relative error tolerance, default 1e-3.", NULL},
525 {&kw_renumber, "bool Renumber source lines after subcircuit expansion.", NULL},
526 {&kw_rhost, "str Remote host name, for UNIX remote simulations.", NULL},
527 {&kw_rprogram, "str Remote simulation program name, for UNIX.", NULL},
528 {&kw_scedfont, "str Name of X font used in SCED.", NULL},
529 {&kw_slowplot, "bool Wait for input between plots.", NULL},
530 {&kw_sourcepath, "str Path to search for source command.", NULL},
531 {&kw_spicepath, "str Path to use in aspice command.", NULL},
532 {&kw_strictnumparse, "bool Don't allow trailing characters after number.", _iv_strictnumparse},
533 {&kw_subend, "str End subcircuits, default .ends.", NULL},
534 {&kw_subinvoke, "str Prefix to invoke subcircuits, default x.", NULL},
535 {&kw_substart, "str Start subcircuit definition, default .subckt.", NULL},
536 {&kw_term, "str Name of current terminal, for MFB.", NULL},
537 {&kw_ticmarks, "bool Plot tic marks, if int, set tic mark separation.", NULL},
538 {&kw_tnom, "real Nominal temperature, default 27C.", NULL},
539 {&kw_trtol, "real Truncation error tolerance, default 7.", NULL},
540 {&kw_units, "str If \"degrees\", trig functions don't use radians.", _iv_units},
541 {&kw_unixcom, "bool Execute operating system commands.", _iv_unixcom},
542 {&kw_vntol, "real Voltage error tolerance, default 1e-6.", NULL},
543 {&kw_width, "int Width of screen in characters.", _iv_width},
544 {&kw_wpboxh, "real Graphics box height for WordPerfect plot, (4\").", NULL},
545 {&kw_wpboxw, "real Graphics box width for WordPerfect plot (4\").", NULL},
546 {&kw_xglinewidth, "int Pixel linewidth used in xgraph, default 1.", NULL},
547 {&kw_xgmarkers, "bool Use markers in xgraph pointplot, else big pixels.", NULL},
548 {&kw_xfont, "str Name of X font for graphics, default \"fixed\".", NULL}
549 } ;
550
551
552 static void *internalvars; /* hash table for dispatch functions */
553
554 void
cp_internal_init()555 cp_internal_init()
556
557 /* This has to be called before anything, it sets up the hash table */
558 {
559 int i;
560
561 if (internalvars == NULL)
562 internalvars = htab_init();
563 for (i = 0; i < sizeof(int_vars)/sizeof(struct intvar); i++) {
564 if (int_vars[i].func) {
565 htab_add(*(int_vars[i].name),(void*)&int_vars[i],internalvars);
566 cp_addkword(CT_VARIABLES, *(int_vars[i].name));
567 }
568 }
569 }
570
571
572 void
com_usrset(wl)573 com_usrset(wl)
574
575 /* print a listing of option keywords and descriptions */
576 wordlist *wl;
577 {
578 int i;
579
580 out_init();
581 if (wl == NULL) {
582 for (i = 0; i < sizeof(int_vars)/sizeof(struct intvar); i++) {
583 out_printf("%-18s %s\n",*(int_vars[i].name),int_vars[i].descr);
584 }
585 return;
586 }
587 while (wl) {
588 for (i = 0; i < sizeof(int_vars)/sizeof(struct intvar); i++) {
589 if (eq(wl->wl_word,*(int_vars[i].name))) {
590 out_printf("%-18s %s\n",*(int_vars[i].name),int_vars[i].descr);
591 break;
592 }
593 }
594 if (i == sizeof(int_vars)/sizeof(struct intvar))
595 out_printf("%-18s %s\n",wl->wl_word,"not an internal variable");
596 wl = wl->wl_next;
597 }
598 }
599
600
601 int
cp_internalset(v,flag)602 cp_internalset(v,flag)
603
604 /* The one variable that we consider read-only so far is plots. The ones
605 * that are 'dontrecord' are curplottitle, curplotname, and curplotdate.
606 * Also things already in the plot env are 'dontrecord'.
607 */
608 struct variable *v;
609 bool flag;
610 {
611 struct intvar *x;
612 struct variable *tv;
613 int i;
614 char val[BSIZE_SP];
615 char *vv;
616 bool bv;
617 double dv;
618 int iv;
619
620 x = (struct intvar *)htab_get(v->va_name,internalvars);
621 if (x)
622 i = (*x->func)(v,flag);
623 else
624 return (US_OK);
625
626 if (i != US_OK)
627 return (i);
628
629 if (plot_cur)
630 for (tv = plot_cur->pl_env; tv; tv = tv->va_next)
631 if (eq(tv->va_name, v->va_name))
632 return (US_READONLY);
633
634 if (!flag || ft_nutmeg)
635 return (US_OK);
636
637 /* Now call the interface option routine. */
638 switch (v->va_type) {
639 case VT_BOOL:
640 if (v->va_bool) {
641 val[0] = '\0';
642 bv = true;
643 vv = (char *) &bv;
644 break;
645 }
646 else {
647 bv = false;
648 vv = (char *) &bv;
649 }
650 case VT_STRING:
651 (void) strcpy(val, v->va_string);
652 vv = val;
653 break;
654 case VT_NUM:
655 (void) sprintf(val, "%d", v->va_num);
656 iv = v->va_num;
657 vv = (char *) &iv;
658 break;
659 case VT_REAL:
660 (void) strcpy(val, printnum(v->va_real));
661 dv = v->va_real;
662 vv = (char *) &dv;
663 break;
664 case VT_LIST:
665 /* if_option can't handle lists anyway. */
666 break;
667 default:
668 fprintf(cp_err,
669 "cp_usrset: Internal Error: Bad var type %d\n",
670 v->va_type);
671 }
672
673 if (ft_curckt)
674 if_option(ft_curckt->ci_ckt, v->va_name, v->va_type, vv);
675
676 return (US_OK);
677 }
678
679
680 /* The user-supplied routine to query the values of variables. This
681 * recognises the $&varname notation, and also searches the values of
682 * plot and circuit environment variables.
683 * This function now accepts a range extension for $& variables.
684 * It will also evaluate vector expressions encased in ( ).
685 */
686
687 struct variable *
cp_enqvar(word)688 cp_enqvar(word)
689
690 char *word;
691 {
692 struct dvec *d;
693 struct variable *vv = NULL, *tv;
694 struct plot *pl;
695 int i;
696 char **x;
697 char *range, *r;
698 char *tt = NULL;
699 int low, up;
700
701 if (*word == '&') {
702 word++;
703
704 low = 0;
705 up = -1;
706
707 if (*word == '(') {
708 /* an expression */
709 tt = strrchr(word,')');
710 if (tt == NULL) {
711 fprintf(cp_err,"Error: closing ')' not found.\n");
712 return (NULL);
713 }
714 r = range = strchr(tt,'[');
715 }
716 else
717 r = range = strchr(word,'[');
718
719 if (r) {
720 *r = '\0';
721 r++;
722 if (!isdigit(*r) && *r != '-')
723 fprintf(cp_err,
724 "Warning: nonparseable range specified, %s[%s\n",
725 word,r);
726 for (low = 0; isdigit(*r); r++)
727 low = low * 10 + *r - '0';
728 if ((*r == '-') && isdigit(r[1]))
729 for (up = 0, r++; isdigit(*r); r++)
730 up = up * 10 + *r - '0';
731 else if (*r != '-')
732 up = low;
733 }
734 if (tt) {
735 /* evaluate the expression */
736 wordlist wl;
737 struct pnode *pn;
738
739 wl.wl_word = word;
740 wl.wl_next = wl.wl_prev = NULL;
741 pn = ft_getpnames(&wl,true);
742 if (pn == NULL) {
743 fprintf(cp_err,"Error: parse failed.\n");
744 return (NULL);
745 }
746 d = ft_evaluate(pn);
747 inp_pnfree(pn);
748 }
749 else
750 d = vec_get(word);
751
752 if (d) {
753 if (d->v_link2) {
754 fprintf(cp_err,
755 "Warning: only one vector may be accessed with the $& notation.\n");
756 d = d->v_link2->dl_dvec;
757 }
758 if (d->v_numdims <= 1) {
759 d->v_numdims = 1;
760 d->v_dims[0] = d->v_length;
761 }
762 if (up == -1)
763 up = d->v_dims[0] - 1;
764 vv = vec2var(d,low,up);
765 }
766 if (range)
767 *range = '[';
768 return (vv);
769 }
770 if (eq(word, kw_display)) {
771 vv = alloc(struct variable);
772 vv->va_name = copy(word);
773 vv->va_type = VT_STRING;
774 vv->va_string = copy(cp_display);
775 return (vv);
776 }
777 if (plot_cur) {
778 for (vv = plot_cur->pl_env; vv; vv = vv->va_next)
779 if (eq(vv->va_name, word))
780 break;
781 if (vv)
782 vv = var_copy(vv);
783 else if (eq(word, kw_curplotname)) {
784 vv = alloc(struct variable);
785 vv->va_name = copy(word);
786 vv->va_type = VT_STRING;
787 vv->va_string = copy(plot_cur->pl_name);
788 }
789 else if (eq(word, kw_curplottitle)) {
790 vv = alloc(struct variable);
791 vv->va_name = copy(word);
792 vv->va_type = VT_STRING;
793 vv->va_string = copy(plot_cur->pl_title);
794 }
795 else if (eq(word, kw_curplotdate)) {
796 vv = alloc(struct variable);
797 vv->va_name = copy(word);
798 vv->va_type = VT_STRING;
799 vv->va_string = copy(plot_cur->pl_date);
800 }
801 else if (eq(word, kw_curplot)) {
802 vv = alloc(struct variable);
803 vv->va_name = copy(word);
804 vv->va_type = VT_STRING;
805 vv->va_string = copy(plot_cur->pl_typename);
806 }
807 else if (eq(word, kw_plots)) {
808 vv = alloc(struct variable);
809 vv->va_name = copy(word);
810 vv->va_type = VT_LIST;
811 for (pl = plot_list; pl; pl = pl->pl_next) {
812 tv = alloc(struct variable);
813 tv->va_type = VT_STRING;
814 tv->va_string = copy(pl->pl_typename);
815 tv->va_next = vv->va_vlist;
816 vv->va_vlist = tv;
817 }
818 }
819 if (vv)
820 return (vv);
821 }
822 if (ft_curckt) {
823 for (vv = ft_curckt->ci_vars; vv; vv = vv->va_next)
824 if (eq(vv->va_name, word))
825 break;
826 if (vv)
827 return var_copy(vv);
828 }
829 return (NULL);
830 }
831
832
833 static struct variable *
vec2var(d,lo,hi)834 vec2var(d,lo,hi)
835
836 struct dvec *d;
837 int lo, hi;
838 {
839 int i, sz, sn;
840 struct variable *vv, *tv = NULL;
841 char *x;
842
843 sn = ((hi < lo) ? -1 : 1);
844 sz = d->v_length/d->v_dims[0];
845
846 for (i = lo; ((sn == 1) ? (i <= hi) : (i >= hi)); i += sn) {
847 if (i >= d->v_dims[0])
848 continue;
849 if (!tv)
850 tv = vv = alloc(struct variable);
851 else {
852 vv->va_next = alloc(struct variable);
853 vv = vv->va_next;
854 }
855 if (d->v_numdims == 1) {
856 if (isreal(d))
857 vv->va_real = d->v_realdata[i];
858 else
859 vv->va_real = realpart(&d->v_compdata[i]);
860 vv->va_type = VT_REAL;
861 }
862 else {
863 if (isreal(d))
864 x = (char*)&d->v_realdata[i*sz];
865 else
866 x = (char*)&d->v_compdata[i*sz];
867 vv->va_type = VT_LIST;
868 vv->va_vlist = getlist(d,1,&x);
869 }
870 }
871 if (tv) {
872 if (lo == hi)
873 return (tv);
874 vv = alloc(struct variable);
875 vv->va_type = VT_LIST;
876 vv->va_vlist = tv;
877 return (vv);
878 }
879 return (NULL);
880 }
881
882
883 static struct variable *
getlist(d,dim,x)884 getlist(d,dim,x)
885
886 struct dvec *d;
887 int dim;
888 char **x;
889 {
890 struct variable *vv, *tv = NULL;
891 int i;
892
893 for (i = d->v_dims[dim] - 1; i >= 0; i--) {
894 if (!tv)
895 tv = vv = alloc(struct variable);
896 else {
897 vv->va_next = alloc(struct variable);
898 vv = vv->va_next;
899 }
900 if (dim == d->v_numdims-1) {
901 if (isreal(d)) {
902 vv->va_real = *(*(double**)x);
903 *x += sizeof(double);
904 }
905 else {
906 vv->va_real = (*(complex**)x)->cx_real;
907 *x += sizeof(complex);
908 }
909 vv->va_type = VT_REAL;
910 }
911 else {
912 vv->va_vlist = getlist(d,dim+1,x);
913 vv->va_type = VT_LIST;
914 }
915 }
916 return (tv);
917 }
918
919
920 /* Return the plot and ckt env vars, $plots, and $curplot{name,title,date,} */
921
922 void
cp_usrvars(v1,v2)923 cp_usrvars(v1, v2)
924
925 struct variable **v1, **v2;
926 {
927 struct variable *v, *tv;
928
929 if (plot_cur)
930 v = var_copy(plot_cur->pl_env);
931 else
932 v = NULL;
933 if (tv = cp_enqvar(kw_plots)) {
934 tv->va_next = v;
935 v = tv;
936 }
937 if (tv = cp_enqvar(kw_curplot)) {
938 tv->va_next = v;
939 v = tv;
940 }
941 if (tv = cp_enqvar(kw_curplottitle)) {
942 tv->va_next = v;
943 v = tv;
944 }
945 if (tv = cp_enqvar(kw_curplotname)) {
946 tv->va_next = v;
947 v = tv;
948 }
949 if (tv = cp_enqvar(kw_curplotdate)) {
950 tv->va_next = v;
951 v = tv;
952 }
953 if (tv = cp_enqvar(kw_display)) {
954 tv->va_next = v;
955 v = tv;
956 }
957 *v1 = v;
958 if (ft_curckt)
959 *v2 = var_copy(ft_curckt->ci_vars);
960 else
961 *v2 = NULL;
962 return;
963 }
964
965
966 /* Extract the .option cards from the deck... */
967
968 struct line *
inp_getopts(deck)969 inp_getopts(deck)
970
971 struct line *deck;
972 {
973 struct line *last, *opts = NULL, *dd, *next;
974
975 last = deck;
976 for (dd = deck->li_next; dd; dd = next) {
977 next = dd->li_next;
978
979 if (ciprefix(".opt", dd->li_line)) {
980 inp_casefix(dd->li_line);
981 last->li_next = next;
982 dd->li_next = opts;
983 opts = dd;
984 continue;
985 }
986 last = dd;
987 }
988
989 return (opts);
990 }
991