home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1993 #3 / NN_1993_3.iso / spool / alt / sources / 3113 < prev    next >
Encoding:
Text File  |  1993-01-28  |  49.4 KB  |  1,629 lines

  1. Path: sparky!uunet!das.wang.com!ulowell!m2c!nic.umass.edu!caen!spool.mu.edu!darwin.sura.net!ukma!cs.widener.edu!dsinc!ub!galileo.cc.rochester.edu!ee.rochester.edu!rbc!al
  2. From: al@rbc.uucp (Al Davis)
  3. Newsgroups: alt.sources
  4. Subject: ACS  circuit simulator  part 15/20
  5. Message-ID: <1993Jan27.040920.11780@rbc.uucp>
  6. Date: 27 Jan 93 04:09:20 GMT
  7. Sender: al@rbc.uucp (Al Davis)
  8. Organization: Huh?
  9. Lines: 1618
  10.  
  11. #! /bin/sh
  12. # This is a shell archive, meaning:
  13. # 1. Remove everything above the #! /bin/sh line.
  14. # 2. Save the resulting text in a file.
  15. # 3. Execute the file with /bin/sh (not csh) to create the files:
  16. #    src/error.c
  17. #    src/fft.c
  18. #    src/file.c
  19. #    src/findbr.c
  20. #    src/findfile.c
  21. #    src/fourier.c
  22. #    src/ftos.c
  23. #    src/generat.c
  24. #    src/getckt.c
  25. #    src/getlines.c
  26. #    src/globals.c
  27. # This archive created: Tue Jan 26 22:51:05 1993
  28. export PATH; PATH=/bin:$PATH
  29. if test -f 'src/error.c'
  30. then
  31.     echo shar: will not over-write existing file "'src/error.c'"
  32. else
  33. cat << \SHAR_EOF > 'src/error.c'
  34. /* error.c  12/30/92
  35.  * Copyright 1983-1992   Albert Davis
  36.  * Error handler.
  37.  * Collection of functions to handle all types of errors
  38.  * including user interrupts, system errors, overflow, etc.
  39.  * Also, some user patience functions like "pause" and "comment".
  40.  * (that don't really belong here)
  41.  */
  42. #include "ecah.h"
  43. #include "error.h"
  44. #include "io.h"
  45. #include "options.h"
  46. #include <signal.h>
  47. #include "declare.h"
  48. /*--------------------------------------------------------------------------*/
  49.     void    stubmess(void);
  50.     void    syntax(const char*,int*,int);
  51.     void    error();
  52.     void    sig_int(int);
  53.     void    sig_fpe(int);
  54.     void    ccck(void);
  55.     void    cmd_pause(const char*,int*);
  56.     void    cmd_comment(const char*,int*);
  57.     int    matherr(struct exception*);
  58. /*--------------------------------------------------------------------------*/
  59. extern const struct ioctrl io;
  60. extern const struct options opt;
  61. extern int errorcount;
  62. extern int cmdcount;
  63. extern jmp_buf envp;
  64. static int count;
  65. /*--------------------------------------------------------------------------*/
  66. /* stubmess: generic function that doesn't work
  67.  */
  68. void stubmess()
  69. {
  70.  error(bDISASTER, "stub mess\n");
  71. }
  72. /*--------------------------------------------------------------------------*/
  73. /* syntax: handle syntax errors
  74.  * called on parsing an input string when nothing else matches.
  75.  * if the rest of the line is nothing, just return
  76.  * if comment, increment *cnt, so what is left is a valid comment string
  77.  * otherwise, it is an error (the arrow pointing at the offending word)
  78.  */
  79. void syntax(cmd,cnt,badness)
  80. const char *cmd;
  81. int *cnt;
  82. int badness;
  83. {
  84.  char cc;
  85.  
  86.  skipbl(cmd,cnt);
  87.  cc = cmd[*cnt];
  88.  switch (cc) {
  89.     case '\'':
  90.        (*cnt)++;
  91.     case '\0':
  92.        break;
  93.     default:
  94.        if (badness >= opt.picky){
  95.           if (*cnt < 20){
  96.              mprintf(io.mstderr, "%.40s\n", cmd);
  97.              mtab(*cnt, io.mstderr);
  98.              error(badness,"^ ?\n");
  99.           }else{
  100.              mprintf(io.mstderr, "... %.36s\n", &cmd[(*cnt)-16]);
  101.              mtab(20, io.mstderr);
  102.              error(badness,"^ ?\n");
  103.           }
  104.        }
  105.  }
  106. }
  107. /*--------------------------------------------------------------------------*/
  108. /* error: error message printer
  109.  * print it, if severe enough
  110.  * terminate command, if really bad
  111.  */
  112. /*VARARGS2*/
  113. void error(badness,fmt,va_alist)
  114. int badness;
  115. const char *fmt;
  116. va_dcl /* ; */
  117. {
  118.  char buffer[BIGBUFLEN];
  119.  va_list arg_ptr;
  120.  
  121.  if (badness >= opt.picky){
  122.     errorcount++;
  123.     va_start(arg_ptr);
  124.     vsprintf(buffer,fmt,arg_ptr);
  125.     va_end(arg_ptr);
  126.     mputs(buffer,io.mstderr);
  127.  }
  128.  if (badness >= bDISASTER)
  129.     abort();
  130.  if (badness >= bEXIT)
  131.     exit(badness);
  132.  if (badness >= bERROR)
  133.     longjmp(envp,1);
  134. }
  135. /*--------------------------------------------------------------------------*/
  136. #ifdef ANSI                /* ANSI C varargs (stdarg.h)        */
  137. void error(badness,fmt)
  138. int badness;
  139. char *fmt;
  140. {
  141.  char buffer[BIGBUFLEN];
  142.  va_list arg_ptr;
  143.  
  144.  if (badness >= picky) {
  145.     va_start(arg_ptr,fmt);
  146.     vsprintf(buffer,fmt,arg_ptr);
  147.     va_end(arg_ptr);
  148.     mputs(buffer,io.mstderr);
  149.  }
  150.  if (badness >= bEXIT)
  151.     exit(badness);
  152.  if (badness >= bERROR)
  153.     longjmp(envp,1);
  154. }
  155. #endif
  156. /*--------------------------------------------------------------------------*/
  157. /* sig_int: what to do on receipt of interrupt signal (SIGINT)
  158.  * cancel batch files, then back to command mode.
  159.  * (actually, control-c trap)
  160.  */
  161. /*ARGSUSED*/
  162. void sig_int(sig)
  163. int sig;
  164. {
  165.  (void)signal(SIGINT,sig_int);
  166.  error(bERROR, "\n");
  167. }
  168. /*--------------------------------------------------------------------------*/
  169. /*ARGSUSED*/
  170. void sig_fpe(sig)
  171. int sig;
  172. {
  173.  error(bERROR, "floating point error\n");
  174.  reset_fpe();
  175. }
  176. /*--------------------------------------------------------------------------*/
  177. /* ccck: control-c check.
  178.  * process user interrupts: ^c, ^s, escape
  179.  * this is necessary because the solution could lock out the user
  180.  * when there is no i/o.
  181.  * called periodically when it is likely to have a long time with no i/o
  182.  */
  183. void ccck()
  184. {
  185.  switch (csts()) {
  186.     case 'S'-'@':
  187.        (void)ci();
  188.        (void)ci();
  189.        break;
  190.     case 'C'-'@':
  191.        (void)ci();
  192.        error(bERROR, "\r");
  193.        break;
  194.     case '['-'@':
  195.        (void)ci();
  196.        error(bERROR, "\r");
  197.        break;
  198.     default:
  199.        break;
  200.  }
  201. }
  202. /*--------------------------------------------------------------------------*/
  203. /* cmd_pause: user command
  204.  */
  205. /*ARGSUSED*/
  206. void cmd_pause(cmd,cnt)
  207. const char *cmd;
  208. int  *cnt;
  209. {
  210.  register int ch;
  211.  
  212.  count = cmdcount;
  213.  mprintf( io.mstderr, "Continue? " );
  214.  ch = ci();
  215.  mprintf( io.mstderr, "%c\n", ch );
  216.  if ( ch=='n' || ch=='N' || ch=='C'-'@' || ch=='['-'@' ) {
  217.     error(bERROR, "\r");
  218.  }
  219. }
  220. /*--------------------------------------------------------------------------*/
  221. /* cmd_comment: user command
  222.  * if there are two consecutive comments, exit graphics mode
  223.  * (this is a kluge)
  224.  * the syntax check exists because this is called whenever nothing else is,
  225.  * by the command interpreter.  another kluge.
  226.  */
  227. void cmd_comment(cmd,cnt)        /* switch back to text mode        */
  228. const char *cmd;            /* on second consecutive comment    */
  229. int  *cnt;
  230. {                    /* also, check syntax.            */
  231.  if (cmdcount == count+1)
  232.     plclear();
  233.  count = cmdcount;
  234.  syntax(cmd,cnt,bWARNING);
  235. }
  236. /*--------------------------------------------------------------------------*/
  237. /* matherr: handle math function errors.
  238.  * replacement for the standard library function.
  239.  */
  240. int matherr(x)
  241. struct exception *x;
  242. {
  243.  if (x->type==DOMAIN) {
  244.     if (strcmp(x->name,"atan2")==0) {    /* both args are 0.            */
  245.        x->retval = 0.;
  246.        return 1;
  247.     }
  248.  } else if (x->type==SING) {
  249.     if (strncmp(x->name,"log",3)==0) {    /* arg is 0.                */
  250.        x->retval = -HUGE;        /* return -HUGE (it is, usually        */
  251.        return 1;            /*    but some return 0.)        */
  252.     }
  253.  } else if (x->type==UNDERFLOW) {
  254.     if (strcmp(x->name,"exp")==0) {    /* arg is big negative            */
  255.        x->retval = 0.;
  256.        return 1;
  257.     }
  258.  }
  259.  mprintf(io.mstderr,"internal error: %s %u %g %g %g\n",
  260.     x->name, x->type, x->arg1, x->arg2, x->retval);
  261.  return 0;
  262. }
  263. /*--------------------------------------------------------------------------*/
  264. /*--------------------------------------------------------------------------*/
  265. SHAR_EOF
  266. fi # end of overwriting check
  267. if test -f 'src/fft.c'
  268. then
  269.     echo shar: will not over-write existing file "'src/fft.c'"
  270. else
  271. cat << \SHAR_EOF > 'src/fft.c'
  272. /* fft    03/23/92
  273.  * Copyright 1983-1992   Albert Davis
  274.  * fast fourier transform
  275.  */
  276. #include "ecah.h"
  277. #include "declare.h"
  278. /*--------------------------------------------------------------------------*/
  279.     void    fft(complex_t*,int,int);
  280. /*--------------------------------------------------------------------------*/
  281. /*--------------------------------------------------------------------------*/
  282. void fft(x, n, inv)
  283. complex_t *x;
  284. int n, inv;
  285. {
  286.  complex_t w, t;
  287.  int s, nxp, nxp2, m;
  288.  double wpwr, arg;
  289.  
  290.  s = (inv) ? 1 : -1;
  291.  for (nxp=n  ;    nxp2=nxp/2  ;  nxp=nxp2){
  292.     wpwr = PI2 / nxp;
  293.     for (m=0 ;     m<nxp2 ;  m++){
  294.        register int j1, j2;
  295.        arg = m * wpwr;
  296.        w.x =    cos(arg);
  297.        w.y = s*sin(arg);
  298.        for (j1=m  ;  j1+nxp-m<=n  ;  j1+=nxp){
  299.       j2 = j1 + nxp2;
  300.       t.x = x[j1].x - x[j2].x;
  301.       t.y = x[j1].y - x[j2].y;
  302.       x[j1].x += x[j2].x;
  303.       x[j1].y += x[j2].y;
  304.       x[j2].x = t.x * w.x - t.y * w.y;
  305.       x[j2].y = t.y * w.x + t.x * w.y;
  306.        }
  307.     }
  308.  }
  309.  /* unscramble */
  310.  {
  311.     register int j, k;
  312.     int i;
  313.     for (i=j=0 ;  i<n-1 ;  i++, j+=k){
  314.        if (i<j){
  315.       t     = x[j];
  316.       x[j] = x[i];
  317.       x[i] = t;
  318.        }
  319.        for (k=n/2 ;  k<=j ;  k/=2)
  320.       j -= k;
  321.     }
  322.  }
  323.  /* fix level */
  324.  {
  325.     if (!inv){
  326.        register int i;
  327.        register int nn;
  328.        nn = n;
  329.        for ( i=0 ;  i<nn ;  i++ ){
  330.       x[i].x /= nn;
  331.       x[i].y /= nn;
  332.        }
  333.     }
  334.  }
  335. }
  336. /*--------------------------------------------------------------------------*/
  337. /*--------------------------------------------------------------------------*/
  338. SHAR_EOF
  339. fi # end of overwriting check
  340. if test -f 'src/file.c'
  341. then
  342.     echo shar: will not over-write existing file "'src/file.c'"
  343. else
  344. cat << \SHAR_EOF > 'src/file.c'
  345. /* file     01/05/93
  346.  * Copyright 1983-1992   Albert Davis
  347.  * route output to & from files, get command
  348.  */
  349. #include "ecah.h"
  350. #include "error.h"
  351. #include "io.h"
  352. #include "declare.h"
  353. /*--------------------------------------------------------------------------*/
  354.     void    cmd_log(const char*,int*);
  355.     void    cmd_file(const char*,int*);
  356.     char*    getcmd(const char*,char*,int);
  357. /*--------------------------------------------------------------------------*/
  358. extern struct ioctrl io;
  359. extern char e_int[];
  360.  
  361. static FILE *fin = stdin;    /* file to use for stdin    */
  362. static int   mout;        /* > file bitmap        */
  363. static int   mlog;        /* log file bitmap        */
  364. /*--------------------------------------------------------------------------*/
  365. /* cmd_log: "log" command processing
  366.  * open a file for logging (history)
  367.  * arg is name of file (.eca is appended)
  368.  * no arg closes the one most recently opened
  369.  * the file will contain a list of commands executed, for use by "<"
  370.  * multiple files can be open, they are nested, output to all.
  371.  */
  372. void cmd_log(cmd,cnt)
  373. const char *cmd;
  374. int  *cnt;
  375. {
  376.  char *access;
  377.  static FILE *files[RECURSE];
  378.  static int nest = 0;
  379.  
  380.  if (cmd[*cnt]){
  381.     if (nest >= RECURSE){
  382.        error(bWARNING, "too many files open\n");
  383.     }else{
  384.        access = "w";
  385.        while (cmd[*cnt] == '>'){
  386.           access = "a";
  387.           ++*cnt;
  388.           skipbl(cmd,cnt);
  389.        }
  390.        files[nest] = xopen(cmd,cnt,"eca",access);
  391.        if (files[nest]){
  392.           mlog |= 1<<fileno(files[nest]);
  393.           nest++;
  394.        }
  395.     }
  396.  }else{                    /* empty command                */
  397.     if (nest == 0){            /* close it.                */
  398.        error(bWARNING, "no files open\n");
  399.     }else{
  400.        nest--;
  401.        mlog &= ~(1<<fileno(files[nest]));
  402.        (void)fclose(files[nest]);
  403.        files[nest] = (FILE*)NULL;
  404.     }
  405.  }
  406. }
  407. /*--------------------------------------------------------------------------*/
  408. /* cmd_file: ">" command processing
  409.  * open a file for all output
  410.  * the file will contain a copy of all screen output.
  411.  * arg is name of file (.eca is appended)
  412.  * no arg closes it
  413.  * the file will contain all that would go to stdout
  414.  */
  415. void cmd_file(cmd,cnt)
  416. const char *cmd;
  417. int  *cnt;
  418. {
  419.  char *access;
  420.  static FILE *files[RECURSE];
  421.  static int nest = 0;
  422.  
  423.  if (cmd[*cnt]){                   /* if there is more to the command,     */
  424.     if (nest >= RECURSE){          /* open a new file.                     */
  425.        error(bWARNING, "too many files open\n");
  426.     }else{
  427.        access = "w";
  428.        while (cmd[*cnt] == '>'){
  429.           access = "a";
  430.           ++*cnt;
  431.           skipbl(cmd,cnt);
  432.        }
  433.        files[nest] = xopen(cmd,cnt,"   ",access);
  434.        if (files[nest]){
  435.           mout       |= 1<<fileno(files[nest]);
  436.           io.mstdout |= 1<<fileno(files[nest]);
  437.           nest++;
  438.        }
  439.     }
  440.  }else{                            /* empty command                        */
  441.     if (nest == 0){                /* close it.                            */
  442.        error(bWARNING, "no files open\n");
  443.     }else{
  444.        nest--;
  445.        mout       &= ~(1<<fileno(files[nest]));
  446.        io.mstdout &= ~(1<<fileno(files[nest]));
  447.        (void)fclose(files[nest]);
  448.        files[nest] = (FILE*)NULL;
  449.     }
  450.  }
  451. }
  452. /*--------------------------------------------------------------------------*/
  453. /* getcmd: get a command.
  454.  * if "fin" is stdin, display a prompt first.
  455.  * Also, actually do logging, echo, etc.
  456.  */
  457. char *getcmd(prompt,buffer,buflen)
  458. const char *prompt;
  459. char *buffer;
  460. int buflen;
  461. {
  462.  pllocate();
  463.  if (!fin) /* 1st time thru */
  464.     error(bWARNING, e_int, "stdin != stdin");
  465.  if (fin == stdin){
  466.     mputs( prompt, io.mstdout );
  467.     mputs( " \b",  io.mstdout );
  468.  }
  469.  
  470.  if (!fgets(buffer, buflen, fin)){
  471.     if (fin == stdin)
  472.        error(bEXIT, "\n");
  473.     buffer[0] = '\0';
  474.  }
  475.  
  476.  (void)trim(buffer);
  477.  mprintf(mlog, "%s\n", buffer);
  478.  if (fin == stdin){
  479.     mputc('\r', io.mstdout&~mout);     /* reset col counter */
  480.     mprintf(mout, "%s\n", buffer);
  481.  }else{                             /* echo disk reads, if reading a file   */
  482.     volatile int n = 0;
  483.     skipbl(buffer,&n);              /* normally, print the prompt first     */
  484.     switch (buffer[n]){             /* (default) but if the line is a blank */
  485.        case '\0':            /* or comment, do not print the prompt  */
  486.           mputc('\n', io.mstdout);
  487.           break;
  488.        case '\'':
  489.           mprintf(io.mstdout, "%s\n", &buffer[n+1]);
  490.           break;
  491.        default:
  492.           mprintf(io.mstdout, "%s%s\n", prompt, buffer);
  493.           break;
  494.     }
  495.  }
  496.  return buffer;
  497. }
  498. /*--------------------------------------------------------------------------*/
  499. /*--------------------------------------------------------------------------*/
  500. SHAR_EOF
  501. fi # end of overwriting check
  502. if test -f 'src/findbr.c'
  503. then
  504.     echo shar: will not over-write existing file "'src/findbr.c'"
  505. else
  506. cat << \SHAR_EOF > 'src/findbr.c'
  507. /* findbr  01/01/93
  508.  * Copyright 1983-1992   Albert Davis
  509.  * find a branch with matching label
  510.  * returns the branch pointer
  511.  */
  512. #include "ecah.h"
  513. #include "branch.h"
  514. #include "error.h"
  515. #include "declare.h"
  516. /*--------------------------------------------------------------------------*/
  517.     branch_t *findbranch(const char*,int*,const branch_t*,const branch_t*);
  518.     int     wmatch(const char*,const char*);
  519. /*--------------------------------------------------------------------------*/
  520. extern const char e_int[];
  521. /*--------------------------------------------------------------------------*/
  522. /* findbranch: find a matching label, by (ugh) linear search
  523.  *     start searching at "start", stop at "stop"
  524.  *    label to look for is in command line: &cmd[*cnt]
  525.  * return pointer to match if exists (and eat input)
  526.  *      pointer to a non-existent branch if no match (don't eat input)
  527.  * caution: caller must check return value before using
  528.  */
  529. branch_t *findbranch(cmd,cnt,start,stop)
  530. const char *cmd;
  531. int  *cnt;
  532. const branch_t *start, *stop;
  533. {
  534.  int save;
  535.  const branch_t *brh;
  536.  char labelwanted[LABELEN+1];
  537.  char thislabel[LABELEN+1];
  538.  char *dot;
  539.  char *wanted;
  540.  
  541.  save = *cnt;                /* copy the name to local space        */
  542.  (void)ctostr(cmd, cnt, labelwanted, LABELEN);
  543.  
  544.  if (!labelwanted[1]  ||  !isalpha(labelwanted[0])){
  545.     *cnt = save;            /* don't match single letter or dot */
  546.     return (branch_t*)NULL;        /* probably a command            */
  547.  }
  548.  
  549.  labelwanted[LABELEN] = thislabel[LABELEN] = '\0';
  550.  
  551.  dot = strrchr(labelwanted,'.');    /* trim off front stuff for subckt  */
  552.  if (dot){
  553.     *dot = '\0';
  554.     wanted = dot + 1;
  555.  }else{
  556.     wanted = labelwanted;
  557.  }
  558.  
  559.  brh = start;
  560.  do {
  561.     volatile int dummy = 0;
  562.     (void)ctostr( brh->label, &dummy, thislabel, LABELEN );
  563.     if (wmatch(wanted,thislabel)){
  564.        if (!dot){                /* found it */
  565.           return (branch_t*)brh;
  566.        }else{
  567.           branch_t *subbrh;
  568.       int dummy = 0;
  569.           subbrh=findbranch(labelwanted,&dummy,brh->subckt,brh->subckt->prev);
  570.       if (exists(subbrh)){
  571.          return subbrh;
  572.       }else if (brh == stop){        /* found subckt but */
  573.          *cnt = save;            /* no match within it */
  574.          return (branch_t*)NULL;
  575.       }
  576.        }
  577.     }else if (brh == stop){
  578.        *cnt = save;
  579.        return (branch_t*)NULL;            /* didn't find it */
  580.     }
  581.  } while (brh = nextbranch_all(brh),  brh != start);
  582.  
  583.  error(bWARNING, e_int, "findbranch: no stop");
  584.  *cnt = save;                    /* trap endless loop */
  585.  return (branch_t*)NULL;
  586. }
  587. /*--------------------------------------------------------------------------*/
  588. /* wmatch: string match with wild cards
  589.  * s1 may have wild cards: ? any character matches; * any repeated 0 or more
  590.  * returns YES or NO
  591.  * normally not case sensitive,
  592.  *    but \ before any letter in s1 forces exact match
  593.  * recursive
  594.  * in the wrong file, but it started here as a static.....
  595.  */
  596. int wmatch(s1, s2)
  597. const char *s1, *s2;
  598. {
  599.  for (   ;  (*s1 && *s2) || (*s1=='*');  s1++, s2++){
  600.     if (*s1 == '?'){            /* '?' matches anything            */
  601.        ;
  602.     }else if (*s1 == '*'){        /* '*' matches 0 or more of anything    */
  603.        if (wmatch(s1+1,s2)){        /* try '*' matches nothing            */
  604.       return YES;
  605.        }else{                /* '*' matches at least one character   */
  606.       s1--;                /* match it, try for more            */
  607.       if (*s2 == '\0')        /* there is more in s1.  If this were   */
  608.          return NO;            /* all, the recursive call above would  */
  609.        }                /* have matched.                */
  610.     }else if (*s1 == '\\'){        /* '\' requires an exact match        */
  611.        s1++;                /* including case                */
  612.        if (*s1 != *s2)
  613.       return NO;
  614.     }else if (to_lower(*s1) != to_lower(*s2)){
  615.     return NO;            /* try to match, ignoring case        */
  616.     }
  617.  }
  618. return *s1 == *s2;            /* one of the strings ended            */
  619. }                    /* if match, both will be '\0'        */
  620.                     /*        and return YES, otherwise NO    */
  621. /*--------------------------------------------------------------------------*/
  622. /*--------------------------------------------------------------------------*/
  623. SHAR_EOF
  624. fi # end of overwriting check
  625. if test -f 'src/findfile.c'
  626. then
  627.     echo shar: will not over-write existing file "'src/findfile.c'"
  628. else
  629. cat << \SHAR_EOF > 'src/findfile.c'
  630. /* findfile  04/02/92
  631.  * Modified by AD.  Sent to me by C-WARE
  632.  * This file contains the routine to locate a file,
  633.  *    using a path string for the directories to search.
  634.  * Interface:
  635.  *    findfile(filename, paths, mode)
  636.  *        filename is the name of the file to be searched for,
  637.  *        paths is the path to follow to find it.
  638.  *        mode is how you want to open the file
  639.  *    returns full path name, if successful, else NULL.
  640. */
  641. #include "ecah.h"
  642. #include "declare.h"
  643. /*--------------------------------------------------------------------------*/
  644.     char*    findfile(const char*,const char*,int);
  645. /*--------------------------------------------------------------------------*/
  646. /*--------------------------------------------------------------------------*/
  647. char *findfile(filename, paths, mode)
  648. const char *filename, *paths;
  649. int mode;
  650. {
  651.  const char *p_ptr;
  652.  static char target_buf[BUFSIZ];
  653.  
  654. #if CHECK_LOCAL_FIRST
  655.     strcpy(target_buf, filename);        /* check in the local directory */
  656.     if (access(target_buf, mode) == GOOD)
  657.        return target_buf;
  658. #endif
  659.  
  660.  if (!paths)
  661.     paths = "";
  662.  
  663.  for (p_ptr=paths;  *p_ptr != '\0';   ) {   /* for each item in the path ...*/
  664.     char *t_ptr;
  665.     t_ptr = target_buf;                /* copy the directory name        */
  666.     while (*p_ptr != PATHSEP  &&  *p_ptr != '\0')
  667.        *t_ptr++ = *p_ptr++;
  668.     if (t_ptr != target_buf  &&  t_ptr[-1] != '/'  &&  t_ptr[-1] != '\\')
  669.        *t_ptr++ = '/';                /* append '/' if needed        */
  670.     *t_ptr = '\0';
  671.     
  672.     strcat(target_buf, filename);
  673.     if (access(target_buf, mode) == GOOD)
  674.        return target_buf;
  675.     if (*p_ptr)                        /* beyond the SEP            */
  676.        p_ptr++;
  677.  }
  678.  return (char*)NULL;                /* can't find one            */
  679. }
  680. /*--------------------------------------------------------------------------*/
  681. /*--------------------------------------------------------------------------*/
  682. SHAR_EOF
  683. fi # end of overwriting check
  684. if test -f 'src/fourier.c'
  685. then
  686.     echo shar: will not over-write existing file "'src/fourier.c'"
  687. else
  688. cat << \SHAR_EOF > 'src/fourier.c'
  689. /* fourier  01/03/93
  690.  * Copyright 1983-1992   Albert Davis
  691.  * all functions needed in addition to the transient analysis
  692.  * to perform the fourier command.
  693.  */
  694. #include "ecah.h"
  695. #include "error.h"
  696. #include "io.h"
  697. #include "mode.h"
  698. #include "probh.h"
  699. #include "declare.h"
  700. /*--------------------------------------------------------------------------*/
  701.     void    foinit(long);
  702.     void    fonext(void);
  703.     void    fosave(double);
  704.     void    foout(double,double,double);
  705. static  void    head(void);
  706. static  double    topolar(complex_t*);
  707. static  void    tagmax(double*,double*,double*,int,complex_t*);
  708. static  int    stepno(double,double,double);
  709. /*--------------------------------------------------------------------------*/
  710. extern const struct ioctrl io;
  711.  
  712. extern complex_t *fodata;
  713. extern probe_t *probelist[];
  714. extern char e_om[], e_int[];
  715. static long datapts, timesteps;
  716. static long indx;
  717. static int  timestepno, probes;
  718. /*--------------------------------------------------------------------------*/
  719. void foinit(points)             /* initialize fourier analysis.             */
  720. long points;                    /* allocate memory, set up arrays, etc.     */
  721. {
  722. long statsize;
  723.  
  724. qfree((void**)&fodata);
  725. timesteps = points+1;
  726. probes = probcount(sTRAN);
  727. datapts = probes * timesteps;
  728. statsize = datapts * sizeof(complex_t);
  729. if ( statsize>SEGSIZ )
  730.     error(bERROR, "too many data points\n");
  731. fodata = (complex_t*)calloc( (unsigned int)statsize, 1 );
  732. if ( !fodata )
  733.     error(bERROR,  e_om, "fourier");
  734. timestepno = 0;
  735. indx = -timesteps;        /* skip the first probe.  It is the time.   */
  736. }
  737. /*--------------------------------------------------------------------------*/
  738. void fonext()                             /* next time step            */
  739. {                                         /* set to next column in 2d array.*/
  740. indx = ++timestepno - timesteps;      /* stored by row            */
  741. }                                         /* ignore the first (time)        */
  742. /*--------------------------------------------------------------------------*/
  743. void fosave(realvalue)          /* save single point of trans. analysis     */
  744. double realvalue;               /* no need to save imag value. always 0.    */
  745. {                               /* all points at a probe are a vector       */
  746. if (fodata)
  747.     {
  748.     if (indx >= datapts)
  749.     error(bERROR, e_int, "fourier");
  750.     if (indx >= 0L)                  /* don't save time */
  751.     fodata[indx].x = realvalue;
  752.     indx += timesteps;
  753.     }
  754. }
  755. /*--------------------------------------------------------------------------*/
  756. void foout(sstart,sstop,sstep)  /* print out the results of the transform   */
  757. double sstart, sstop, sstep;
  758. {
  759. register int fstep, prob;
  760. double mag, phz, db, relmag, relphz, reldb, freq;
  761. double maxmag[20], maxphz[20], maxdb[20];
  762. int startstep, stopstep;
  763.  
  764. plclose();
  765. plclear();
  766. if (probes >= 20)
  767.     error(bERROR, e_int, "fourier: too many probes");
  768. startstep = stepno( 0., sstep, sstart );
  769. stopstep  = stepno( 0., sstep, sstop  );
  770. head();
  771. for ( prob=0 ; prob < probes ; prob++ )                     /* each probe   */
  772.     {
  773.     fft( &fodata[prob*timesteps], (int)timesteps-1, 0 );
  774.     maxmag[prob]=0.;
  775.     for ( fstep=startstep ; fstep<=stopstep ; fstep++ )     /* each step    */
  776.     {
  777.     int ind;                    /* find the largest */
  778.     ind = (int)(prob*timesteps) + fstep;
  779.     mag = topolar(&fodata[ind]);
  780.     if (fstep > 0)
  781.         fodata[ind].x *= 2;
  782.     tagmax(maxmag,maxphz,maxdb,prob,&fodata[ind]);
  783.     }
  784.     if (maxmag[prob]==0.)                   /* if all zero, don't normalize */
  785.     {
  786.     maxmag[prob] = 1.;
  787.     maxphz[prob] = 0.;
  788.     maxdb[prob]  = 0.;
  789.     }
  790.     }
  791. for ( fstep=startstep ; fstep<=stopstep ; ++fstep )         /* each step    */
  792.     {
  793.     freq = sstep * fstep;
  794.     for ( prob=0 ; prob < probes ; prob++ )                 /* each probe   */
  795.     {
  796.     int ind;
  797.     ind = (int)(prob*timesteps) + fstep;
  798.     mag = fodata[ind].x;
  799.     phz = fodata[ind].y;
  800.     db  = 20. * log10(mag);             /* BUG:it is not always 20 */
  801.     relmag = mag / maxmag[prob];
  802.     relphz = phz - maxphz[prob];
  803.     reldb  = db  - maxdb[prob];
  804.     if (relphz > 180.)
  805.         relphz -= 360.;
  806.     if (relphz < -180.)
  807.         relphz += 360.;
  808.     if (db < -999.99)
  809.         db = -999.99;
  810.     if (reldb < -999.99)
  811.         reldb = -999.99;
  812.     mprintf(io.where, "%-12s", ftos(freq,"            ",6,io.formaat) );
  813.     mprintf(io.where, "%-11s", probename(probelist[sFOURIER][prob]));
  814.     mprintf(io.where, "%s%7.2f %8.3f %s%7.2f %8.3f\n",
  815.         ftos(mag,   "           ",5,io.formaat),
  816.         db,
  817.         phz,
  818.         ftos(relmag,    "           ",5,io.formaat),
  819.         reldb,
  820.         relphz ) ;
  821.     }
  822.     }
  823. }
  824. /*--------------------------------------------------------------------------*/
  825. static void head()
  826. {
  827. register int w;
  828. w = io.where&(io.mstdout|io.mprint);
  829. mprintf(w,"                        ");
  830. mprintf(w,"--------- actual ---------  -------- relative --------\n");
  831. mprintf(w," freq       probe       ");
  832. mprintf(w,"value        dB      phase  value        dB      phase\n");
  833. }
  834. /*--------------------------------------------------------------------------*/
  835. static double topolar(arg)      /* convert rectangular to polar             */
  836. complex_t *arg;                /* rotates 90 degrees!                      */
  837. {                               /* (ref to sine instead of cosine)          */
  838. double mag, phz;
  839. mag = hypot( arg->x, arg->y);
  840. phz = phase(-arg->y, arg->x);
  841. arg->x = mag;
  842. arg->y = phz;
  843. return mag;
  844. }
  845. /*--------------------------------------------------------------------------*/
  846. static void tagmax(maxmag,maxphz,maxdb,prob,arg)
  847. double *maxmag, *maxphz, *maxdb;
  848. register int prob;
  849. complex_t *arg;
  850. {
  851. if (arg->x > maxmag[prob])                              /* find max         */
  852.     {
  853.     maxmag[prob] = arg->x;
  854.     maxphz[prob] = arg->y;
  855.     maxdb[prob]  = 20. * log10(arg->x);          /* BUG:it is not always 20 */
  856.     }
  857. }
  858. /*--------------------------------------------------------------------------*/
  859. static int stepno(start, step, this)
  860. double start, step, this;
  861. {
  862. double num;
  863. num = (this-start)/step + .5;
  864. return (int)num;
  865. }
  866. /*--------------------------------------------------------------------------*/
  867. /*--------------------------------------------------------------------------*/
  868. SHAR_EOF
  869. fi # end of overwriting check
  870. if test -f 'src/ftos.c'
  871. then
  872.     echo shar: will not over-write existing file "'src/ftos.c'"
  873. else
  874. cat << \SHAR_EOF > 'src/ftos.c'
  875. /* ftos  12/08/91
  876.  * Copyright 1983-1992   Albert Davis
  877.  * float to string
  878.  * builds string representing floating number
  879.  * num = number to convert.
  880.  * str = string to put it in.  Must be big enough, or else!!
  881.  *        Must have length at least len+6.
  882.  *        sig digits + dec.pt.(1) + sign(1) + exp(4)
  883.  * len = max number of displayed digits. (left + right of dp)
  884.  *        (includes d.p. if 'e' notation and 2 digit exp)
  885.  * fmt = format : 0      = alpha for exp notation
  886.  *          FMTEXP  = exponential notation
  887.  *          FMTSIGN = always inlcude sign
  888.  *          FMTFILL = fill in zeros
  889.  * BUG:
  890.  * returns a pointer to static space where the string is.
  891.  * there is a finite pool, so repeated calls work, to a point.
  892.  * after that, the space is overwritten, every POOLSIZE calls
  893.  */
  894. #include "ecah.h"
  895. #include "formats.h"
  896. #include "options.h"
  897. #include "declare.h"
  898. /*--------------------------------------------------------------------------*/
  899.     char *ftos(double,const char*,int,int);
  900. /*--------------------------------------------------------------------------*/
  901. #define POOLSIZE 10
  902. #define MAXLENGTH 40
  903. extern const struct options opt;
  904. /*--------------------------------------------------------------------------*/
  905. /*VARARGS4*/
  906. char *ftos(num, dummy, len, fmt)
  907. double num;    /* number to convert            */
  908. const char *dummy;/* place holder, was where to put it    */
  909. int len;    /* max length of new string        */
  910. int fmt;    /* how to format it            */
  911. {
  912.  char sign;    /* sign storage ( +,-,bl )        */
  913.  int expo;    /* exponent                */
  914.  int flg;    /* flag used to supress leading zeros    */
  915.  int dig;    /* the next digit to print        */
  916.  int iii;    /* loop counter                */
  917.  int nnn;    /* char counter -- pos in string    */
  918.  double rnd;    /* rounding adder            */
  919.  static char strpool[POOLSIZE][MAXLENGTH];    /* destination string pool */
  920.  static int poolindex = 0;
  921.  char *str;
  922.  
  923.  poolindex++;
  924.  if (poolindex >= POOLSIZE)
  925.     poolindex = 0;
  926.  str = strpool[poolindex];
  927.  for (iii=0;  iii<strlen(dummy);  ++iii)
  928.     str[iii] = ' ';
  929.  for (     ;  iii<MAXLENGTH;      ++iii)
  930.     str[iii] = '\0';
  931.  
  932.  nnn = 0;
  933.  if (len <= 3)
  934.     return str;                /*  error   */
  935.  
  936.  if (fabs(num) < 1e-99   ||   fabs(num) < opt.floor)
  937.     num = 0.;
  938.  
  939.  for ( iii=len+5; iii>=0; --iii )
  940.     str[iii] = ' ';            /* fill with blanks            */
  941.  
  942.  if (num == 0.){
  943.     strcpy( str, " 0." );
  944.     nnn = strlen( str );        /* num==0 .. build string 0.000...  */
  945.     while ( --len )
  946.     str[nnn++] = '0';
  947.     expo = 0;
  948.     sign = ' ';
  949.  }else{                    /* num != 0 */
  950.     if (num < 0.){
  951.        sign = '-';            /* sign */
  952.        num = -num;
  953.     }else if (fmt & FMTSIGN){
  954.        sign = '+';
  955.     }else{
  956.        sign = ' ';
  957.     }
  958.  
  959.     expo = -3;
  960.     while (num < .001){            /* scale to .001 - 1.0 */
  961.        num *= 1000.;
  962.        expo -= 3;
  963.     }
  964.     while (num >= 1.){
  965.        num *= .001;
  966.        expo += 3;
  967.     }
  968.     if ((fmt&FMTEXP&&expo<-9) || expo>10 || expo<-13)
  969.        --len;                /* one less digit if 'e' notation   */
  970.     if (len <= 3){            /*        and exp is 2 digits        */
  971.        return str;
  972.     }
  973.     
  974.     rnd = .5 / x10(len);        /* find amt to add to round        */
  975.     if (num < .01)
  976.        rnd /= 100.;
  977.     else if (num < .1)
  978.        rnd /= 10.;
  979.     num += rnd;                /* add it                */
  980.     if (num >= 1.){
  981.        num *= .001;            /* created an extra digit: rescale  */
  982.        expo += 3;
  983.     }
  984.     
  985.     flg = 0;
  986.     nnn = 1;
  987.     if (expo == -3){            /* exp is -3.                */
  988.        expo = 0;            /* print in fixed point, no exponent*/
  989.        str[nnn++] = '0';
  990.        str[nnn++] = '.';
  991.        while (len > 0){
  992.       num *= 10.;
  993.       dig = (int)floor(num);
  994.       num -= (double)dig;
  995.       str[nnn++] = (char)(dig + '0');
  996.       if (flg += dig)
  997.          --len;
  998.        }
  999.     }else{
  1000.        for (iii=2; len>0; --iii){    /* mantissa                */
  1001.       num *= 10.;            /* get next digit            */
  1002.       dig = (int)floor(num);
  1003.       num -= (double)dig;        /* subtract off last digit        */
  1004.       if (flg += dig){        /* if int part !=0            */
  1005.          str[nnn++]=(char)dig+'0';    /*  (not all zeros so far)        */
  1006.          --len;            /* stuff the digit into the string */
  1007.       }
  1008.       if (!iii && len>0){        /* if we found the dec.pt. and        */
  1009.          str[nnn++] = '.';        /*   haven't used up all the space  */
  1010.       }                /* put a dec.pt. in the string        */
  1011.        }
  1012.     }
  1013.  }
  1014.  
  1015.  for (iii=1; str[iii]==' '; ++iii)    /* insert sign at beginning        */
  1016.     ;
  1017.  str[iii-1] = sign;
  1018.  
  1019.  if (!(fmt&FMTFILL))            /* supress trailing zeros        */
  1020.     while ( str[nnn-1]=='0' )
  1021.        str[--nnn] = (char)((nnn<strlen(dummy)) ? ' ' : '\0');  
  1022.  
  1023.  if (expo == 0)
  1024.      return str;
  1025.  
  1026.  if (fmt&FMTEXP || expo>10 || expo<-13){    /* if exponential format        */
  1027.     str[nnn++] = 'E';                /* put the letter 'E' and        */
  1028.     if (expo < 100)                 /* convert the exponent        */
  1029.        (void)itos( expo, &str[nnn], -2, FMTSIGN );
  1030.     else
  1031.        (void)utos( (unsigned)expo, &str[nnn], -3 );
  1032.  }else{                       /* if letter-scale format        */
  1033.     str[nnn++] = "fpnum KMGT"[(expo+15)/3];/* put the appropriate letter    */
  1034.  }                 /* note that letter-scale is not valid        */
  1035.                  /* for exp==-3 or exp not in -15..+12        */
  1036.                  /* this is trapped but letter-scale is also*/
  1037.                  /* not valid if exp not divisible by 3.    */
  1038.                  /* This is not trapped, since it supposedly*/
  1039.                  /* cant happen.                */
  1040.  if (str[nnn-1] == 'M'){
  1041.     str[nnn++] = 'e';
  1042.     str[nnn++] = 'g';
  1043.  }
  1044.  if (strlen(dummy)==0)        /* BUG: this cleans up stray trailing    */
  1045.     trim(str);            /* blanks.  I don't know why they exist    */
  1046.  
  1047.  return str;
  1048. }
  1049. /*--------------------------------------------------------------------------*/
  1050. /*--------------------------------------------------------------------------*/
  1051. SHAR_EOF
  1052. fi # end of overwriting check
  1053. if test -f 'src/generat.c'
  1054. then
  1055.     echo shar: will not over-write existing file "'src/generat.c'"
  1056. else
  1057. cat << \SHAR_EOF > 'src/generat.c'
  1058. /* generator  02/23/92
  1059.  * Copyright 1983-1992   Albert Davis
  1060.  * set up generator for transient analysis
  1061.  */
  1062. #include "ecah.h"
  1063. #include "error.h"
  1064. #include "io.h"
  1065. #include "declare.h"
  1066. /*--------------------------------------------------------------------------*/
  1067.     void    cmd_generator(const char*,int*);
  1068.     double    gen(void);
  1069. /*--------------------------------------------------------------------------*/
  1070. #define ARGS 12
  1071. #define freq    argv[0]
  1072. #define ampl    argv[1]
  1073. #define phaz    argv[2]
  1074.  
  1075. #define maxv    argv[3]
  1076. #define minv    argv[4]
  1077. #define offset  argv[5]
  1078.  
  1079. #define init    argv[6]
  1080. #define rise    argv[7]
  1081. #define fall    argv[8]
  1082.  
  1083. #define delay   argv[9]
  1084. #define width   argv[10]
  1085. #define period  argv[11]
  1086.  
  1087. extern const struct ioctrl io;
  1088. extern double trtime;
  1089. static double argv[ARGS] =
  1090.     { 0.   , 1.   , 0.    , 1.    , 0.    , 0.     ,
  1091.       0.   , 1e-12, 1e-12 , 0.    , 0.    , 0.     };
  1092. static char *argnam[ARGS] =
  1093.     {"Freq","Ampl","Phase","MAx"  ,"MIn"  ,"Offset",
  1094.      "Init","Rise","Fall" ,"Delay","Width","PEriod"};
  1095. static int positive[ARGS] =
  1096.     { YES  , NO   , NO    , NO    , NO    , NO     ,
  1097.       NO   , YES  , YES   , YES   , YES   , YES    };
  1098. /*--------------------------------------------------------------------------*/
  1099. void cmd_generator(cmd,cnt)
  1100. const char *cmd;
  1101. int  *cnt;
  1102. {
  1103.  int ii;                   /* iteration counter                    */
  1104.  int where;
  1105.  
  1106.  where = (cmd[*cnt])  ?  0  :  io.mstdout;
  1107.  
  1108.  for (ii=0;  ii<ARGS;  ++ii){       /* try to match each name in the list   */
  1109.     if (pmatch(cmd,cnt,argnam[ii])){            /* match the control name   */
  1110.        if (isfloat(cmd[*cnt]))                  /* if match, assign a value */
  1111.       argv[ii] = (positive[ii])
  1112.         ? fabs(ctof(cmd,cnt))
  1113.         :      ctof(cmd,cnt);
  1114.        ii = -1;                                /* start over               */
  1115.     }
  1116.  }
  1117.  
  1118.  syntax(cmd,cnt,bWARNING);
  1119.  
  1120.  for (ii=0;  ii<ARGS;  ++ii){
  1121.     mprintf( where, " %s=%s ", 
  1122.         argnam[ii],
  1123.         ftos(argv[ii], "", 6, 0));
  1124.  }
  1125.  mprintf( where, "\n" );
  1126. }
  1127. /*--------------------------------------------------------------------------*/
  1128. double gen()
  1129. {
  1130.  double loctime;
  1131.  double level;
  1132.  
  1133.  if (trtime <= delay)
  1134.     return init;
  1135.  loctime = trtime - delay;
  1136.  if (period > 0.){
  1137.     if    (loctime > period * 1048576)
  1138.        error(bERROR, "step size much too large\n");
  1139.     while (loctime > period * 65536)
  1140.        loctime -= period * 65536;
  1141.     while (loctime > period * 4096)        /* to improve code, */
  1142.        loctime -= period * 4096;        /* use fmod.        */
  1143.     while (loctime > period * 256)
  1144.        loctime -= period * 256;
  1145.     while (loctime > period * 16)
  1146.        loctime -= period * 16;
  1147.     while (loctime > period)
  1148.        loctime -= period;
  1149.  }
  1150.  if (trtime <= delay + rise)                         /* initial rise */
  1151.     level = (maxv - 0) * (loctime/rise) + 0;
  1152.  else if (loctime <= rise)                           /* rising       */
  1153.     level = (maxv - minv) * (loctime/rise) + minv;
  1154.  else if (width==0.  ||  (loctime-=rise) <= width)   /* pulse on     */
  1155.     level = maxv;
  1156.  else if ((loctime-=width) <= fall)                  /* falling      */
  1157.     level = (minv - maxv) * (loctime/fall) + maxv;
  1158.  else                                                /* pulse off    */
  1159.     level = minv;
  1160.  level *= (freq == 0.) 
  1161.     ? ampl
  1162.     : ampl * sin(PI2*freq*(trtime-delay) + phaz*DTOR);
  1163.  return (trtime <= delay + rise)
  1164.     ? level + (offset - init) * (loctime/rise) + init
  1165.     : level + offset;
  1166. }
  1167. /*--------------------------------------------------------------------------*/
  1168. /*--------------------------------------------------------------------------*/
  1169. SHAR_EOF
  1170. fi # end of overwriting check
  1171. if test -f 'src/getckt.c'
  1172. then
  1173.     echo shar: will not over-write existing file "'src/getckt.c'"
  1174. else
  1175. cat << \SHAR_EOF > 'src/getckt.c'
  1176. /* getckt  02/15/92
  1177.  * Copyright 1983-1992   Albert Davis
  1178.  * build, get, merge, "<" commands
  1179.  * process circuit files, and keyboard entry
  1180.  */
  1181. #include "ecah.h"
  1182. #include "argparse.h"
  1183. #include "branch.h"
  1184. #include "dev.h"
  1185. #include "error.h"
  1186. #include "io.h"
  1187. #include "mode.h"
  1188. #include "options.h"
  1189. #include "status.h"
  1190. #include "types.h"
  1191. #include "declare.h"
  1192. /*--------------------------------------------------------------------------*/
  1193.     void    cmd_build(const char*, int*);
  1194.     void    cmd_get(const char*,int*);
  1195.     void    cmd_merge(const char*,int*);
  1196.     void    cmd_run(const char*,int*);
  1197. static  void    getmerge(const char*,int*,int);
  1198. static    branch_t *parsebranch(char*,int);
  1199. static    branch_t *cparse(const char*);
  1200. /*--------------------------------------------------------------------------*/
  1201. extern const struct ioctrl io;
  1202. extern const struct options opt;
  1203. extern       struct status stats;
  1204.  
  1205. extern char head[];                 /* place to store title line            */
  1206. extern char e_int[];
  1207. extern int  run_mode;
  1208. extern branch_t *insertbefore;
  1209. /*--------------------------------------------------------------------------*/
  1210. /* cmd_build: build command
  1211.  * get circuit description direct from keyboard (or stdin if redirected)
  1212.  * Command syntax: build <before>
  1213.  * Bare command: add to end of list
  1214.  * If there is an arg: add before that element
  1215.  * null line exits this mode
  1216.  * preset, but do not execute "dot cards"
  1217.  */
  1218. void cmd_build(cmd,cnt)
  1219. const char *cmd;
  1220. int *cnt;
  1221. {
  1222.  branch_t *brh;
  1223.  
  1224.  time_zstart(&(stats.get));
  1225.  stats.iter[iTOTAL] = 1;
  1226.  run_mode = rPRESET;
  1227.  dealloc(YES);
  1228.  insertbefore = findbranch(cmd,cnt, firstbranch_all(), lastbranch_all());
  1229.  if (!(exists(insertbefore))){
  1230.     insertbefore = lastbranch_all()->next;
  1231.     if (!insertbefore)
  1232.        error(bWARNING, e_int, "build: insertbefore");
  1233.  }
  1234.  do {
  1235.     char buffer[BIGBUFLEN];
  1236.     (void)getcmd(">",buffer,BIGBUFLEN);
  1237.     brh = parsebranch(buffer,YES);
  1238.  } while (exists(brh));
  1239.  time_stop(&(stats.get));
  1240. }
  1241. /*--------------------------------------------------------------------------*/
  1242. /* cmd_get: get command
  1243.  * get circuit from a file, after clearing the old one
  1244.  * preset, but do not execute "dot cards"
  1245.  */
  1246. void cmd_get(cmd,cnt)
  1247. const char *cmd;
  1248. int  *cnt;
  1249. {
  1250.  time_zstart(&(stats.get));
  1251.  run_mode = rPRESET;
  1252.  getmerge(cmd,cnt,YES);
  1253.  time_stop(&(stats.get));
  1254. }
  1255. /*--------------------------------------------------------------------------*/
  1256. /* cmd_merge: merge command
  1257.  * as get, but do not clear first
  1258.  */
  1259. void cmd_merge(cmd,cnt)
  1260. const char *cmd;
  1261. int  *cnt;
  1262. {
  1263.  time_zstart(&(stats.get));
  1264.  run_mode = rPRESET;
  1265.  getmerge(cmd,cnt,NO);
  1266.  time_stop(&(stats.get));
  1267. }
  1268. /*--------------------------------------------------------------------------*/
  1269. /* cmd_run: "<" and "<<" commands
  1270.  * run in batch mode
  1271.  * "<<" clears old circuit first, "<" does not
  1272.  * get circuit from file, execute dot cards in sequence
  1273.  */
  1274. void cmd_run(cmd,cnt)
  1275. const char *cmd;
  1276. int  *cnt;
  1277. {
  1278.  int deleteold = NO;
  1279.  time_zstart(&(stats.get));
  1280.  while (cmd[*cnt] == '<'){
  1281.     deleteold = YES;
  1282.     ++*cnt;
  1283.     skipbl(cmd,cnt);
  1284.  }
  1285.  run_mode = rEXECUTE;
  1286.  getmerge(cmd,cnt,deleteold);
  1287.  time_stop(&(stats.get));
  1288. }
  1289. /*--------------------------------------------------------------------------*/
  1290. /* getmerge: actually do the work for "get", "merge", etc.
  1291.  */
  1292. static void getmerge(cmd,cnt,deleteold)
  1293. const char *cmd;
  1294. int  *cnt;
  1295. int deleteold;
  1296. {
  1297.  char buffer[BIGBUFLEN];
  1298.  int  echoon;        /* echo on/off flag (echo as read from file)        */
  1299.  int  liston;        /* list on/off flag (list actual values)            */
  1300.  int  quiet;        /* don't echo title                                 */
  1301.  static FILE *filen;    /* file number (static for safety)                  */
  1302.  
  1303.  stats.iter[iTOTAL] = 1;
  1304.  dealloc(YES);
  1305.  xclose(&filen);
  1306.  filen = xopen(cmd,cnt,"ckt","r");
  1307.  if (!filen)
  1308.     error(bERROR, "");
  1309.  
  1310.  echoon = liston = quiet = NO;
  1311.  for (;;){
  1312.     if (argparse(cmd,cnt,REPEAT,
  1313.         "Echo",         aENUM,      &echoon,    YES,
  1314.         "List",         aENUM,      &liston,    YES,
  1315.         "Quiet",        aENUM,      &quiet,     YES,
  1316.         "")){
  1317.        ;
  1318.     }else if (cmd[*cnt]){
  1319.        xclose(&filen);
  1320.        syntax(cmd, cnt, bERROR);
  1321.     }else{
  1322.        break;
  1323.     }
  1324.  }
  1325.  
  1326.  if (deleteold)
  1327.     cmd_clear();
  1328.  
  1329.  if (!getlines(buffer, BIGBUFLEN, filen))    /* title */
  1330.     error(bWARNING, "empty circuit file\n");
  1331.  (void)trim(buffer);
  1332.  if (!quiet)
  1333.     mprintf(io.mstdout, "%s\n", buffer);
  1334.  if (*buffer)
  1335.     strcpy(head, buffer);
  1336.  
  1337.  insertbefore = lastbranch_all()->next;
  1338.  if (!insertbefore)
  1339.     error(bWARNING, e_int, "getmerge: insertbefore");
  1340.  while (getlines(buffer, BIGBUFLEN, filen)){
  1341.     branch_t *brh;
  1342.     if (echoon)
  1343.        mprintf(io.mstdout, "%s\n", buffer);
  1344.     brh = parsebranch(buffer,NO);
  1345.     if (liston  &&  exists(brh)){
  1346.        print_branch(brh, io.mstdout, NO);
  1347.     }
  1348.  }
  1349.  xclose(&filen);
  1350. }
  1351. /*--------------------------------------------------------------------------*/
  1352. /* parsebranch: parse an input line, and process it
  1353.  */
  1354. static branch_t *parsebranch(buffer,alwaysdupcheck)
  1355. char *buffer;
  1356. int alwaysdupcheck;
  1357. {
  1358.  branch_t *brh;            /* place for cparse to return data        */
  1359.  branch_t *old;            /* possible replace this one            */
  1360.  branch_t *before;        /* actually insert here                */
  1361.  
  1362.  before = insertbefore;        /* save insert place in case something like */
  1363.                  /* a subckt changes it                */
  1364.  
  1365.  brh = cparse(buffer);                /* parse it                     */
  1366.  if (exists(brh)){
  1367.     if (opt.dupcheck ||  alwaysdupcheck){
  1368.        volatile int dummy;    /* string index for parse package        */
  1369.        dummy = 0;
  1370.        old = findbranch(brh->label, &dummy, insertbefore, insertbefore->prev);
  1371.        if (exists(old)){            /* already exists, replace it   */
  1372.           error(bWARNING, "replacing: %s\n", brh->label);
  1373.           brh->next = old->next;        /* set link so new is in same   */
  1374.           (void)deletebranch(old);        /* place, then delete.        */
  1375.        }else{
  1376.           brh->next = before;
  1377.        }
  1378.     }else{
  1379.        brh->next = before;
  1380.     }
  1381.     brh = insertbranch(brh);
  1382.  }
  1383.  if (isdevice(brh)){
  1384.     dealloc(YES);
  1385.  }
  1386.  return brh;
  1387. }
  1388. /*--------------------------------------------------------------------------*/
  1389. /* cparse: circuit parse: parse one line of a netlist
  1390.  * mostly, dispatches to the proper function.
  1391.  */
  1392. static branch_t *cparse(cmd)
  1393. const char *cmd;    /* string to parse */
  1394. {
  1395.  functions_t *dev;
  1396.  branch_t *brh;
  1397.  volatile int i = 0;
  1398.  volatile int *cnt = &i;
  1399.  
  1400.  skipbl(cmd,cnt);
  1401.  if (isdigit(cmd[*cnt]))
  1402.     (void)ctoi(cmd,cnt);    /* ignore line numbers                */
  1403.  
  1404.  dev = (functions_t*)NULL;
  1405.  switch (to_upper(cmd[*cnt])){
  1406.     case '\0':    /* nothing */            break;
  1407.     case '.':    dev = &dev_dotcard;        break;
  1408.     case '\'':
  1409.     case '"':
  1410.     case '*':    dev = &dev_comment;        break;
  1411.     case 'A':    syntax(cmd,cnt,bWARNING);    break;
  1412.     case 'B':    syntax(cmd,cnt,bWARNING);    break;
  1413.     case 'C':    dev = &dev_cap;            break;
  1414.     case 'D':    dev = &dev_diode;        break;
  1415.     case 'E':    dev = &dev_vcvs;        break;
  1416.     case 'F':    syntax(cmd,cnt,bWARNING);    break;
  1417.     case 'G':    dev = &dev_vccs;        break;
  1418.     case 'H':    syntax(cmd,cnt,bWARNING);    break;
  1419.     case 'I':    dev = &dev_cs;            break;
  1420.     case 'J':    syntax(cmd,cnt,bWARNING);    break;
  1421.     case 'K':    syntax(cmd,cnt,bWARNING);    break;
  1422.     case 'L':    dev = &dev_coil;        break;
  1423.     case 'M':    dev = &dev_mos;            break;
  1424.     case 'N':    syntax(cmd,cnt,bWARNING);    break;
  1425.     case 'O':    syntax(cmd,cnt,bWARNING);    break;
  1426.     case 'P':    syntax(cmd,cnt,bWARNING);    break;
  1427.     case 'Q':    dev = &dev_bjt;            break;
  1428.     case 'R':    dev = &dev_resistor;        break;
  1429.     case 'S':    syntax(cmd,cnt,bWARNING);    break;
  1430.     case 'T':    dev = &dev_trnlin;        break;
  1431.     case 'U':    dev = &dev_logic;        break;
  1432.     case 'V':    dev = &dev_vs;            break;
  1433.     case 'W':    syntax(cmd,cnt,bWARNING);    break;
  1434.     case 'X':    dev = &dev_subckt;        break;
  1435.     case 'Y':    dev = &dev_admittance;        break;
  1436.     case 'Z':    syntax(cmd,cnt,bWARNING);    break;
  1437.     default:    syntax(cmd,cnt,bWARNING);    break;
  1438.  }
  1439.  if (dev){    /* new device created */
  1440.     brh = (*(dev->create))((branch_t*)NULL);
  1441.  }else{        /* either syntax error or empty line */
  1442.     brh = (branch_t*)NULL;
  1443.  }
  1444.  
  1445.  if (exists(brh)){
  1446.     parse_branch(brh,cmd,cnt);
  1447.  }else if (brh){
  1448.     error(bWARNING, "internal error: branch has no type <%s>\n", cmd);
  1449.     free((void*)brh);
  1450.     brh = (branch_t*)NULL;
  1451.  }
  1452.  
  1453.  return brh;
  1454. }
  1455. /*--------------------------------------------------------------------------*/
  1456. /*--------------------------------------------------------------------------*/
  1457. SHAR_EOF
  1458. fi # end of overwriting check
  1459. if test -f 'src/getlines.c'
  1460. then
  1461.     echo shar: will not over-write existing file "'src/getlines.c'"
  1462. else
  1463. cat << \SHAR_EOF > 'src/getlines.c'
  1464. /* getlines.c  04/02/92
  1465.  * Copyright 1983-1992   Albert Davis
  1466.  * get a bunch of lines, from a file
  1467.  * interface is just line fgets.
  1468.  * hooks together extension lines
  1469.  * not recommended for getting from stdin.  use for files only.
  1470.  * is always a line ahead
  1471.  * start with + is extension line, spice compatibility.
  1472.  */
  1473. #include "ecah.h"
  1474. #include "error.h"
  1475. #include "declare.h"
  1476. /*--------------------------------------------------------------------------*/
  1477.     char     *getlines(char*,int,FILE*);
  1478. /*--------------------------------------------------------------------------*/
  1479. extern const char e_int[];
  1480. /*--------------------------------------------------------------------------*/
  1481. char *getlines(s, n, stream)
  1482. char *s;
  1483. int n;
  1484. FILE *stream;
  1485. {
  1486.  int count = 0;
  1487.  int c;
  1488.  char *got;
  1489.  
  1490.  do {
  1491.     got = fgets(&s[count], n-count, stream);
  1492.     if (!got){
  1493.        if (count == 0)
  1494.       return (char*)NULL;
  1495.        else
  1496.       error(bWARNING, e_int, "getlines");
  1497.     }
  1498.     (void)trim(s);
  1499.     count = strlen(s);
  1500.     c = fgetc(stream);
  1501.     if (count >= n-1)
  1502.        break;
  1503.     s[count++] = ' ';
  1504.  } while (c == '+');
  1505.  
  1506.  (void)ungetc(c,stream);
  1507.  return s;
  1508. }
  1509. /*--------------------------------------------------------------------------*/
  1510. /*--------------------------------------------------------------------------*/
  1511. SHAR_EOF
  1512. fi # end of overwriting check
  1513. if test -f 'src/globals.c'
  1514. then
  1515.     echo shar: will not over-write existing file "'src/globals.c'"
  1516. else
  1517. cat << \SHAR_EOF > 'src/globals.c'
  1518. /* globals  01/06/93
  1519.  * Copyright 1983-1992   Albert Davis
  1520.  */
  1521. #include "ecah.h"
  1522. #include "ac.h"
  1523. #include "branch.h"
  1524. #include "defaults.h"
  1525. #include "error.h"
  1526. #include "io.h"
  1527. #include "mode.h"
  1528. #include "nodestat.h"
  1529. #include "options.h"
  1530. #include "probh.h"
  1531. #include "status.h"
  1532. /*--------------------------------------------------------------------------*/
  1533. /* sparse matrix */
  1534. /* far heap, temporary */
  1535. double *reals, *imags;        /* big array allocation bases        */
  1536.  
  1537. /* near heap, hold between commands */
  1538. int *basnode;            /* lowest node connected to this node    */
  1539. int *nm;            /* node map (correspondence) table    */
  1540. double *volts;            /* node voltages            */
  1541.  
  1542. /* near heap, temporary */
  1543. double **rerow, **imrow;    /* array of row pointers        */
  1544. double **recol, **imcol;    /* array of column pointers        */
  1545. double **redia, **imdia;    /* array of diagonal pointers        */
  1546. double *recon,*imcon;        /* right side vector            */
  1547. double *oldcon,*fwcon;        /* old versions of right side vector    */
  1548. complex_t *fodata;        /* Fourier analysis data collection    */
  1549. struct nodestat *nstat;        /* node status flags            */
  1550.  
  1551. /* other sparse matrix stuff */
  1552. unsigned aspace;        /* count of non-zero array elements    */
  1553. int decomp;            /* how far the matrix has been decomposed */
  1554. double zero;            /* a constant, could change if bugs    */
  1555. /*--------------------------------------------------------------------------*/
  1556. /* other (the ultimate in disorder) */
  1557. ac_t ac;            /* stuff for ac analysis        */
  1558. struct status stats;        /* timing data for status command    */
  1559. branch_t *insertbefore;        /* place to add new elements (subckt?)    */
  1560. int inc_mode;            /* flag: make incremental changes    */
  1561. int currents_bad;        /* flag: stored currents are bad    */
  1562. int stiff;            /* flag: use "stiff" integration method    */
  1563. double last_time;        /* time at which "volts" is valid    */
  1564. double trtime;            /* transient analysis time        */
  1565. double genout;            /* tr dc input to circuit (generator)    */
  1566. probe_t *plotlist[sCOUNT];    /* list of plot points            */
  1567. probe_t *probelist[sCOUNT];    /* list of print points            */
  1568. double temp;            /* local temperature            */
  1569. char head[BUFLEN+3];
  1570. /*--------------------------------------------------------------------------*/
  1571. /* command interpreter, control stuff */
  1572. jmp_buf envp;            /* environment for setjmp, longjmp    */
  1573. int errorcount;            /* count of errors since last reset    */
  1574. int cmdcount;            /* command counter, for history        */
  1575. int crtplot = NO;        /* flag: is plotting on the crt        */
  1576.  
  1577. /* sweep command */
  1578. int swp_count[RECURSE];        /* sweep counter            */
  1579. int swp_steps[RECURSE];        /* sweep number of steps        */
  1580. int swp_type[RECURSE];        /* type of sweep (log or linear)    */
  1581. int swp_nest;            /* sweep nesting (recursion) level    */
  1582.  
  1583. /* flags: what is it doing */
  1584. int worstcase;            /* bits flag: worst case, etc. mode    */
  1585. int run_mode;            /* variations on handling of dot cmds    */
  1586. int sim_mode;            /* simulation type (AC, DC, ...)    */
  1587. int sim_phase;            /* phase of simulation (iter, init-dc, )*/
  1588.  
  1589. /* initial conditions fudge (yuck) */
  1590. int in_curr;            /* flag: initial current exists        */
  1591. int in_volt;            /* flag: initial voltage exists        */
  1592. int in_cond;            /* flag: generic initial cond exists    */
  1593. double init_curr;        /* initial current            */
  1594. double init_volt;        /* initial voltage            */
  1595. double init_cond;        /* generic initial condition        */
  1596.  
  1597. /* options : set command */
  1598. struct options opt = {oDEFAULT_acct, oDEFAULT_list, oDEFAULT_nomod,
  1599.    oDEFAULT_page, oDEFAULT_node, oDEFAULT_opts, oDEFAULT_gmin,
  1600.    oDEFAULT_reltol, oDEFAULT_abstol, oDEFAULT_vntol, oDEFAULT_trtol,
  1601.    oDEFAULT_chgtol, oDEFAULT_pivtol, oDEFAULT_pivrel, oDEFAULT_numdgt,
  1602.    oDEFAULT_tnom, oDEFAULT_cptime, oDEFAULT_limtim, oDEFAULT_limpts,
  1603.    oDEFAULT_lvlcod, oDEFAULT_lvltim, oDEFAULT_method, oDEFAULT_maxord,
  1604.    oDEFAULT_seed, oDEFAULT_wczero, oDEFAULT_damp, oDEFAULT_floor,
  1605.    oDEFAULT_tempamb, oDEFAULT_short, oDEFAULT_picky, oDEFAULT_inwidth,
  1606.    oDEFAULT_outwidth, oDEFAULT_xdivisions, oDEFAULT_ydivisions,
  1607.    oDEFAULT_order, oDEFAULT_mode, oDEFAULT_transits,
  1608.    oDEFAULT_dupcheck, oDEFAULT_bypass, oDEFAULT_incmode, oDEFAULT_limit,
  1609.    oDEFAULT_mrt,
  1610.    oDEFAULT_foooo, oDEFAULT_lowlim, oDEFAULT_uplim,
  1611.    {oDEFAULT_itl0, oDEFAULT_itl1, oDEFAULT_itl2, oDEFAULT_itl3,
  1612.    oDEFAULT_itl4, oDEFAULT_itl5, oDEFAULT_itl6, oDEFAULT_itl7, oDEFAULT_itl8}};
  1613.  
  1614. /* io control */
  1615. struct ioctrl io = {ioDEFmstdin, ioDEFmstdout, ioDEFmstderr, ioDEFmpr,
  1616.    ioDEFwhere, ioDEFformaat, ioDEFwhence, ioDEFsuppresserrors, ioDEFechoflag,
  1617.    ioDEFprintflag, ioDEFincipher, ioDEFoutcipher, ioDEFpack, ioDEFploton,
  1618.    ioDEFplotset};
  1619.  
  1620. /* commonly used error messages */
  1621. char e_int[]    = "internal error: %s\n";
  1622. char e_om[]    = "out of memory: %s\n";
  1623. /*--------------------------------------------------------------------------*/
  1624. /*--------------------------------------------------------------------------*/
  1625. SHAR_EOF
  1626. fi # end of overwriting check
  1627. #    End of shell archive
  1628. exit 0
  1629.