home *** CD-ROM | disk | FTP | other *** search
Text File | 1988-01-27 | 24.0 KB | 1,321 lines |
-
-
-
-
-
-
-
-
-
- CHAPTER 1
-
-
- Front End
-
-
-
-
- Note: there is a lot in this section that is out of
-
- date, but the code is in such a condition that it will
-
- have to be cleaned up a great deal before I can update the
-
- documentation...
-
-
- The SPICE3 front end (FTE) is designed to be easily
-
- adaptable to different programs. There are several impor-
-
- tant parts: the "C-shell parser", which handles aliases,
-
- history, and the other csh-type functions, which is com-
-
- pletely modular and may easily be used with other pro-
-
- grams; the routines for the various commands; the parser
-
- for algebraic expressions; the expression evaluation rou-
-
- tines; the complex math routines; and the plotting rou-
-
- tines.
-
-
- The global front-end routines and variables are all
-
- prefixed with these characters (there are some exceptions
-
- in "std.c"):
-
-
-
-
-
-
-
-
-
-
-
-
- 1
-
-
-
-
-
-
-
-
-
- 2
-
-
- com_ Front-end command routines
- cp_ C-shell parser routines and variables
- cx_ Complex math routines
- dg_ Diagnostic stuff like stack backtrace routines
- ft_ General front-end routines and variables
- gr_ Graphics routines
- if_ SPICE3 interface routines
- inp_ Input routines
- sp_ SPICE3 variables
- wl_ Routines to do wordlist manipulation
- wl_ Wordlist manipulation routines
- wrd_ Routines in the writedata package
-
-
-
- 1.1. Csh Parser
-
-
- The C-shell parser (cshpar) does aliasing, history,
-
- quoting, backquote evaluation, globbing (expansion of *,
-
- ?, ~, {}, and []), filename, command, and keyword comple-
-
- tion, and IO redirection. It is supposed to function the
-
- same way that the C-shell does, so unless otherwise noted
-
- the C Shell User's Manual should be consulted for the
-
- details of how these operate.
-
-
- To use cshpar, the file "FTEcshpar.h" should be
-
- included. The host program then must call
-
-
- cp_parse(string);
-
-
- If string is non-NULL then the string will be used for
-
- input instead of the current input file. This will return
-
- a doubly-linked list of words in the following format:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 3
-
-
- typedef struct wordlist {
- char *wl_word; /* The word. */
- struct wordlist *wl_next; /* Forward link. */
- struct wordlist *wl_prev; /* Backward link. */
- } wordlist;
-
-
- The list will be what the user typed, after alias substi-
-
- tutions, etc. The user must supply two routines:
-
-
- cp_userset(var, isset)
- struct variable *var;
- bool isset;
-
-
- which cshpar calls if a variable that it doesn't know
-
- about gets set (it knows about such variables as prompt,
-
- noglob, history, and verbose). The isset argument is true
-
- (bool is typedef'd as char, with true = (char) 1 and false
-
- = (char) 0) if the variable has been set, and false if the
-
- variable has been unset. If the host program doesn't care
-
- about any variables, the function can just be a dummy rou-
-
- tine. Also required is
-
-
- struct variable
- cp_enqvar(word)
- char *word;
-
-
- which gets called when cshpar doesn't know about a vari-
-
- able mentioned - if the host program doesn't know about
-
- the variable either it should return NULL.
-
-
- The definition for the variable structure is
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 4
-
-
- struct variable {
- char va_type; /* The type (see below). */
- char *va_name; /* The variable name. */
- union { /* The value of the variable. */
- bool vV_bool;
- long vV_num;
- double vV_real;
- char *vV_string;
- struct variable *vV_list;
- } va_V;
- struct variable *va_next; /* Forward link. */
- struct variable *va_prev; /* Backward link. */
- } ;
-
- #define va_bool va_V.vV_bool
- #define va_num va_V.vV_num
- #define va_real va_V.vV_real
- #define va_string va_V.vV_string
- #define va_list va_V.vV_list
-
- #define VT_BOOL 1
- #define VT_NUM 2
- #define VT_REAL 3
- #define VT_STRING 4
- #define VT_LIST 5
-
-
-
- In addition to these entry points, the behavior of
-
- cshpar can be changed with the routine
-
-
- cp_modify(c, what)
- char c;
-
-
- where what is one of:
-
-
- #define CPM_REGC 1 /* Character made non-special to the parser. */
- #define CPM_DEF 2 /* Character restored to default meaning. */
- #define CPM_BRR 3 /* Break to right of character. */
- #define CPM_BRL 4 /* Break to left of character. */
- #define CPM_ALONE 5 /* Make character a single word. */
- #define CPM_NOBRK 6 /* Don't break at character. */
- #define CPM_NOAL 7 /* No aliasing. */
- #define CPM_AL 8 /* Aliasing. */
- #define CPM_INTER 9 /* Interactive mode. */
- #define CPM_NOINTER 10 /* Noninteractive mode (sources, etc). */
-
-
-
-
-
-
-
-
-
-
-
-
-
- 5
-
-
- and c is a character, if one is required. (Otherwise it is
-
- ignored.) Making a character non-special usually prevents
-
- some action from being carried out -- for instance, making
-
- the character * non-special prevents it from being
-
- expanded into filenames. This is done with SPICE3, as it
-
- is used for multiplication. Setting non-interactive mode
-
- prevents a prompt from being displayed and command and
-
- keyword completion from being done. To do a source, one
-
- would set non-interactive mode with
-
-
- cp_modify((char) 0, CPM_NOINTER);
-
-
- and the change the FILE pointer cp_curinput to the desired
-
- input stream. When cp_parse returns NULL, then the end of
-
- file has been reached and cp_curinput should be reset to
-
- whatever it was before.
-
-
- The characters that are used for the various func-
-
- tions generally may be changed: the variables (all char's)
-
- containing them are as follows:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 6
-
-
- Function Variable Default
-
- history cp_bang !
- substitute cp_hat ^ (this is , in the front end)
- variables cp_dol $
- wildcard cp_star *
- wildcard cp_huh ?
- wildcard cp_obrac [
- wildcard cp_cbrac ]
- home directory cp_til ~
- expansion cp_ocurl {
- expansion cp_ccurl }
- expansion cp_comma ,
- input redirect cp_lt <
- output redirect cp_gt >
- error redirect cp_amp &
- comment cp_hash # (this is * in the front end)
-
-
- If the variable noglob is set, this inhibits expansion of
-
- the wildcard characters *, ?, [, and ].
-
-
- If the host program wants to take advantage of the IO
-
- redirection features of the front-end, it should use the
-
- FILE pointers cp_in, cp_out, and cp_err instead of stdin,
-
- stdout, and stderr. These are reset every time cp_parse is
-
- called. Whenever the user uses '>' or '<', the appropri-
-
- ate file is opened and the cp_ FILE pointers are set to
-
- that file.
-
-
- A few routines are available for setting and unset-
-
- ting aliases, setting and unsetting variables, and print-
-
- ing history, aliases, and variables:
-
-
- cp_setalias(word, substitute)
- char *word;
- wordlist *substitute;
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 7
-
-
- The substitute list may contain history substitution
-
- characters, which operate on the current argument list.
-
-
- cp_unalias(word)
- char *word;
-
-
- If word has an alias then it is removed.
-
-
- cp_vset(varname, type, value)
- char *varname;
- char *value;
-
-
- The variable called varname with the type type (see the
-
- VT_ defines above) is set to the value pointed to by value
-
- (of whatever type is specified by the type argument.)
-
-
- cp_getvar(name, type, value)
- char *name;
- char *value;
-
-
- The value of the variable with the given name and type is
-
- stored in the object pointed to by value. Value should be
-
- an array of char's is type is VT_STRING, an int * if it is
-
- VT_NUM, and so forth. If the variable is defined with a
-
- different type, it is converted to the desired type if
-
- possible.
-
-
- cp_remvar(varname)
- char *varname;
-
-
- If there is a variable called varname then it is deleted.
-
-
- cp_vprint()
-
-
-
-
-
-
-
-
-
-
-
-
-
- 8
-
-
- Print the values of all the variables currently defined.
-
-
- cp_paliases(name)
- char *name;
-
-
- Print the alias associated with name, or all aliases if
-
- the name is NULL.
-
-
- cp_hprint(eventhi, eventlo)
-
-
- Print the history from event number eventhi to event
-
- number eventlo.
-
-
- cp_addcomm(word, keywords, filec)
- char *word;
- wordlist *keywords;
- bool filec;
-
-
- Add the command word to the list used for command comple-
-
- tion. If keywords is non-NULL then these keywords are
-
- used for keyword completion for this command, in addition
-
- to the global keyword list, which is cp_keywords (also a
-
- wordlist, which the host program may alter at any time).
-
- If the filec argument is true, then instead of keyword
-
- completion, filename and user name completion is done for
-
- this command. There is no way to specifiy certain argu-
-
- ments as being filenames and certain ones as keywords,
-
- etc. The keyword lists and file completion flags will
-
- also work when a command is aliased, but not through his-
-
- tory substitutions (yet).
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 9
-
-
- When EOF (control-D) is typed, then cshpar prints out
-
- the alternatives that the user may type at this point, and
-
- when escape is typed then cshpar attempts to complete as
-
- much of the command, keyword, or filename already typed as
-
- it can.
-
-
- cp_remcomm(word)
- char *word;
-
-
- Remove word from the list of commands that may be com-
-
- pleted, if it is there.
-
-
- cp_addkword(word)
- char *word;
-
-
- Add a keyword to the default list of keywords for keyword
-
- completion. These are in addition to keywords specific to
-
- particular commands.
-
-
- cp_addkword(word)
- char *word;
-
-
- Remove the keyword from the default list, if it is there.
-
-
- There are several commands that the host program
-
- should recognise and call the proper routines for -- they
-
- all take wordlists as arguments (the cdr of the wordlist
-
- returned by cp_parse) and are as follows:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 10
-
-
- Name Function
-
- set cp_cset
- unset cp_cunset
- alias cp_calias
- unalias cp_cualias
- history cp_chistory
- echo cp_cecho
-
-
-
- One note about using cshpar -- if you type a word as
-
- "word", it will be returned by cp_parse with the quotes
-
- on, so you should always use cp_unquote() with it. (This
-
- doesn't happen with single-quoted arguments -- the reason
-
- it is useful with double quotes is to be able to distin-
-
- guish between strings and numbers if they are written the
-
- same.) The way that cshpar quotes characters with single
-
- quotes and backslashes is by turning on the eighth bit,
-
- which is unfortunately slightly non-portable but is pretty
-
- easy to deal with...
-
-
- 1.2. The Basic Command Interpreter
-
-
- The front end maintains a list of the commands avail-
-
- able to it -- there is a array called Coms in the file
-
- "front.c" of the following structures:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 11
-
-
- struct comm {
- char *co_comname; /* The name of the command. */
- int (*co_func) (); /* The function that handles the command. */
- bool co_stringargs; /* Collapse the arguments into a string. */
- bool co_spiceonly; /* These can't be used from nutmeg. */
- bool co_filec; /* Do filename completion. */
- int co_minargs; /* Minimum number of args. */
- int co_maxargs; /* Maximum number of args. */
- char *co_help; /* A short help string. */
- } ;
-
-
- If the co_stringargs field is true, then the function will
-
- be passed its arguments in a string, otherwise it will be
-
- passed a wordlist. If co_spiceonly is true and the program
-
- that is being run is nutmeg, then the command will not be
-
- executed, as it is SPICE3-specific. The help function
-
- prints the help string with
-
-
- printf(helpstring, ft_program);
-
-
- where ft_program is a global string containing the name of
-
- the current program (argv[0]), so the help string may con-
-
- tain a "%s" in the place of the program name.
-
-
- Any routines that are added to the front end may be
-
- made usable simply by adding an entry to the ft_coms
-
- array. (Also, if there are any special keywords for this
-
- command, see the stuff in the function cpinit in
-
- "front.c". This isn't well done, because it is there just
-
- to show off keyword completion.)
-
-
- If any options are added to SPICE3 (which go on the
-
- .options card), its name, type, and code number (as in
-
-
-
-
-
-
-
-
-
-
-
-
- 12
-
-
- PARMdefs.h) should be added to the opts array in
-
- spiceonly.c.
-
-
- SPICE3 data is stored in the front end in two ways.
-
- First, there is the spicedata format, which is more like
-
- the way the data is saved in files (the data arrays are by
-
- points instead of vectors, as this is the way SPICE3 out-
-
- puts them), and is used only in the file "format.c" and
-
- routines like write and load.
-
-
- The more usual format is defined in "FTEdata.h":
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 13
-
-
- struct dvec {
- char *v_name; /* The name of the vector. */
- int v_type; /* The vector type (see FTEspicedata.h) */
- short v_flags; /* Flags: */
-
- #define VF_REAL 000001 /* The data is complex. */
- #define VF_COMPLEX 000002 /* The data is real. */
- #define VF_UPLIM 000004 /* An upper limit is in effect (see below). */
- #define VF_LOWLIM 000010 /* A lower limit is in effect. */
- #define VF_ACCUM 000020 /* writedata() should accumulate this vector. */
- #define VF_PLOT 000040 /* writedata() should incrementally plot it. */
- #define VF_PRINT 000100 /* writedata() should print this vector. */
-
- union {
- double *vU_realdata;
- complex *vU_compdata;
- } v_U; /* The actual data. */
-
- #define v_realdata v_U.vU_realdata
- #define v_compdata v_U.vU_compdata
-
- #define isreal(v) ((v)->v_flags & VF_REAL)
- #define iscomplex(v) ((v)->v_flags & VF_COMPLEX)
-
- int v_length; /* Length of the vector. */
- int v_rlength; /* How much space we really have. */
- double v_yhi; /* The upper and lower y limits, if this */
- double v_ylo; /* is a dvec to be plotted. */
- int v_outindex; /* Index if writedata is building the vector. */
- int v_linestyle; /* What line style we are using. */
- int v_color; /* What color we are using. */
- bool v_permanent; /* Don't garbage collect this dvec. */
-
- struct plot *v_plot; /* The plot structure (if it has one). */
- struct dvec *v_next; /* Forward link. */
- struct dvec *v_link2; /* Extra link for use with some commands. */
- } ;
-
-
- All the dvecs that are available are linked together under
-
- ft_plots, which correspond to seperate SPICE3 runs. The
-
- current plot is where vectors are searched for first by
-
- name, and is pointed to by the variable ft_curplot. The
-
- plot structure is as follows:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 14
-
-
- struct plot {
- char *pl_title; /* The title card. */
- char *pl_date; /* Date. */
- char *pl_name; /* The plot name. */
- struct dvec *pl_dvecs; /* The data vectors in this plot. */
- struct dvec *pl_scale; /* The "scale" for the rest of the vectors. */
- struct plot *pl_next; /* List of plots. */
- wordlist *pl_commands; /* Commands to execute when this plot is set. */
- } ;
-
-
- In order to get a dvec, given a name, the function
-
- ft_vecbyname(name), where name is the name of the desired
-
- vector, is used. This tries to find the named vector, and
-
- if it can't it then tried "V(name)" and "I(name)". It lim-
-
- its the search to the current plot.
-
-
- 1.3. Functions
-
-
- There is a table of data on the available functions
-
- in the file psubr.c, of the form:
-
-
- struct func {
- char *fu_name; /* The print name of the function. */
- complex *(*fu_func)(); /* The function. */
- } ;
-
-
- When an expression like sin (foo) is parsed, the routines
-
- in psubr.c try to find a function in the funcs table
-
- called sin. If there is one, then a function node is added
-
- to the parse tree (see FTEparse.h), but if there is none,
-
- then a vector named sin(foo) is checked for. Also if a
-
- name of the form type(name) is given, where type can be V
-
- or I, a vector with name name will match. When a parse
-
- tree is evaluated with the function evaluate(parsenode),
-
-
-
-
-
-
-
-
-
-
-
-
- 15
-
-
- and a function node is encountered, then the routine
-
- apply_func applies the appropriate complex math routine to
-
- each point of the data vector to obtain the new vector.
-
-
- To add a new function, it is necessary to add a func
-
- structure to the above array, and add the function refer-
-
- enced by fu_func to "cmath.c".
-
-
- Complex math functions are called in the following
-
- manner:
-
-
- char *
- cx_function (data, type, length, newlength, newtype)
- char *data;
- short type;
- int length;
- int *newlength;
- short *newtype;
-
-
- The function should cast data to either double * or com-
-
- plex *, depending on whether type is VF_REAL or
-
- VF_COMPLEX. It should set *newtype likewise, depending on
-
- what the result of its application will be, and also it
-
- should set *newlength to the length of the result. There
-
- are three types of functions defined so far - the sort
-
- that operate pointwise, where *newlength = length, the
-
- sort that take a scalar and return a vector, like
-
- cx_vector, where *newlength = something independent of
-
- length, and the sort that take a vector and return a
-
- scalar, like cx_mean, where *newlength = 1.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 16
-
-
- 1.4. Operations
-
-
- Operations are done in much the same way as complex
-
- functions are done. The routine doop(func_name, function,
-
- arg1, arg2), where function is a pointer to a function
-
- returning a char * and arg1 and arg2 are dvecs, is used.
-
- Complex functions are called as follows:
-
-
- char *
- cx_operation (data1, data2, type1, type2, length)
- char *data1, data2;
- short type1, type2;
-
-
- Vectors that are operated on are made the same length. The
-
- result is assumed to be of the same length as the operands
-
- and its type is complex if either of the operands is com-
-
- plex. (The exception to this is the comma operator.)
-
- Adding new operations requires changing the ops table in
-
- "psubr.c", adding the relevant information to the parser
-
- (the files "parse.c" and "getpname.c), adding a routine
-
- like the ones in "evaluate.c", and perhaps adding a com-
-
- plex function to "cmath.c". The format of the ops table
-
- is:
-
-
- struct op {
- int op_num; /* From parser #defines. */
- char *op_name; /* Printing name. */
- char op_arity; /* One or two. */
- struct dvec *(*op_func)(); /* The function to do the work. */
- }
-
-
- These functions are actually dummy functions that call
-
-
-
-
-
-
-
-
-
-
-
-
-
- 17
-
-
- doop() directly.
-
-
- The parser is a simple operator-precedence parser.
-
-
- 1.5. Plotting Routines
-
-
- The plotting routines use MFB, the Model Frame Buffer
-
- graphics package. The main stuff is in the file "graf.c".
-
-
- 1.6. Using The Front End With Other Programs
-
-
- The front end may be adapted to use with other
-
- circuit-simulation programs besides SPICE3 without much
-
- difficulty. See the manual page for writedata for details
-
- on how to use this set of routines seperately from the
-
- rest of the front-end.
-
-
- All SPICE3-specific code is in the file "spiceif.c".
-
- The following routines are defined, and should be re-
-
- written for another simulator. In general, pointers to
-
- circuits are kept as char *'s, and are only cast to the
-
- appropriate thing (CKTcircuit *'s for SPICE3) in the
-
- interface routines.
-
-
- if_run(ckt, what)
- char *ckt;
- char *what;
-
-
-
- This runs a simulation of the circuit. The type of
-
- simulation is determined by the string what - in SPICE3
-
-
-
-
-
-
-
-
-
-
-
-
-
- 18
-
-
- the possibilities are "tran", "ac", "dc", "op", "run", and
-
- "continue" (continue the run that is already in progress).
-
- XXXXXXXXXXXX
-
-
- if_dump(ckt, fp)
- char *ckt;
- FILE *fp;
-
-
-
- Do a "dump" of the current circuit - with SPICE3 now
-
- this is just a listing of what SPICE3 thinks the circuit
-
- looks like.
-
-
- if_inpline(ckt, line)
- char *ckt;
- char *line;
-
-
-
- Parse the given line and add it to the circuit. Since
-
- the INP parser is incremental this it is possible with
-
- SPICE3 to add lines to the circuit at any point.
-
-
- char *
- if_inpdeck(deck)
- struct card *deck;
-
-
-
- The card structure, as defined in "FTEinput.h" is as
-
- follows:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 19
-
-
- struct card {
- int ca_linenum;
- char *ca_line;
- char *ca_error;
- struct card *ca_next;
- struct card *ca_actual;
- } ;
-
-
- The complete deck is passed to this routine, which has it
-
- parsed and returns a pointer to the circuit structure. See
-
- the chapter in the INP parser for the details of how the
-
- card structure works.
-
-
- if_option(ckt, name, type, value)
- char *ckt;
- char *name;
- int type;
- char *value;
-
-
-
- Add an option to the circuit. The name, type, and
-
- value arguments are the same as the corresponding fields
-
- in the variable structure. If the routine can't use the
-
- option it should just return.
-
-
- if_cktfree(ckt)
- char *ckt;
-
-
-
- Free the data occupied by the circuit. This may be a
-
- no-op, of course.
-
-
- char *
- if_errstring(code)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 20
-
-
- If code is a number that denotes a particular SPICE3
-
- error, this routine should return a string describing the
-
- error.
-
-
- Additionally, there is some code in "subckt.c" and
-
- "fourier.c" that refers to SPICE3 routines, but subcircuit
-
- expansion can be easily disabled and the file "CKTfour.c"
-
- taken from SPICE3 for use with the front-end.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-