ftp.nice.ch/pub/next/science/physics/gck.2.01.s.tar.gz#/gckc.2.0.1/gck_lib.c

This is gck_lib.c in view mode; [Download] [Up]

/* ******************************************************************** */
/* *                           GCK                                    * */
/* *               A Circuit Simulation Program                       * */
/* *                    by Tanju Cataltepe                            * */
/* *                    (c) Copyright 1989                            * */
/* ******************************************************************** */
/* (c) Copyright 1989, Tanju Cataltepe */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>			
#include <ctype.h>
#include <time.h>

#ifdef Macintosh
#include <console.h> 
#include <Files.h>
#else
#include <sys/types.h>
#include <sys/stat.h>
#endif

#include <math.h>
#include <float.h>
#include "gck.h"
#include "gck_vars.h"
#include "gck_protos.h"
#include "gck_errors.h"


void *c_malloc(n)
long n;
{
void *ptr;

if (n == 0)
  errorReport(ERROR_C_MALLOC_SIZE_ZERO,0,ERR_VOID,0);

ptr = calloc(n,1);

if (ptr == NULL)
  errorReport(ERROR_C_MALLOC_VOID,0,ERR_VOID,0);
   
return (ptr);
}

int P_eof(f)
FILE *f;
{
    register int ch;

    if (feof(f))
        return 1;
    if (f == stdin)
        return 0; 
    ch = getc(f);
    if (ch == EOF)
        return 1;
    ungetc(ch, f);
    return 0;
}

int P_eoln(f)
FILE *f;
{
    register int ch;

    ch = getc(f);
    if (ch == EOF)
        return 1;
    ungetc(ch, f);
    return (ch == '\n');
}



double gck_random()
{
return((double)((double)rand() / (double)(RAND_MAX >> 1)) - 1.0);
}


void initializeGlobals()
{
  long i;

  rfile.depth = 0;
  for (i = 0; i < MAX_FILE_DEPTH; i++)
    rfile.filePtr[i] = NULL;
  strcpy(rfile.filename,"\0");

  for (i = 0; i < MAX_SUBCKT_DEPTH; i++)
    strcpy(sd[i],"\0");

  ID_nindex_size = DYNAMIC_INITIAL_SIZE;
  ID_nindex = (long *)c_malloc(sizeof(long) * (ID_nindex_size + 1)); 

  nodeNames.max_nodes = DYNAMIC_INITIAL_SIZE;
  nodeNames.node_size = 1;

  nodeNames.node = (nodeNameStruct *)
  	c_malloc(sizeof(nodeNameStruct) * DYNAMIC_INITIAL_SIZE);

  strcpy(nodeNames.node[0].name,"0");
  for (i = 1; i < DYNAMIC_INITIAL_SIZE; i++)
    nodeNames.node[i].name[0] = NULL_CHAR;

  symbolNames.max_symbols = DYNAMIC_INITIAL_SIZE;
  symbolNames.symbol_size = 0;

  commandNames.max_symbols = DYNAMIC_INITIAL_SIZE;
  commandNames.symbol_size = 0;

  symbolNames.symbol = (symbolNameStruct *)
  	c_malloc(sizeof(symbolNameStruct) * DYNAMIC_INITIAL_SIZE);

  commandNames.symbol = (symbolNameStruct *)
        c_malloc(sizeof(symbolNameStruct) * DYNAMIC_INITIAL_SIZE);

  for (i = 0; i < DYNAMIC_INITIAL_SIZE; i++) {
    symbolNames.symbol[i].name[0] = NULL_CHAR;
    commandNames.symbol[i].name[0] = NULL_CHAR;
    }

  up_to_date = TRUE;
  cmdline_symbols = FALSE;
  sample_card_found = FALSE;
#ifdef Macintosh
  object_stamp = (long) 0;
#else
  object_stamp = (time_t) 0;
#endif

    
  flag_dialog = DIALOG_NORMAL;
  flag_compiler = COMPILER_FORCE_COMPILATION;

  deltaT = 1.0;
  periodT = 0.0;
  samplesOn = 1;
  The_Time = 0.0;
  lastTime = 0.0;
  GND = (double *)c_malloc(sizeof(double));
  *GND = 0.0;
  sampleTicks = (clockRec *)c_malloc(sizeof(clockRec));
  NoOfTicks = 1;
  TicksRegistered = FALSE;
  presentTick = 1;
  NoOfVars = 0;
  baseOfBranch = NULL;
  baseOfClock = NULL;
  baseOfNode = NULL;
  baseOfNonlin = NULL;
  baseOfDigital = NULL;
  baseOfLogic = NULL;
  baseOfTable = NULL;
  baseOfModel = NULL;
  baseOfSource = NULL;
  baseOfPrint = NULL;
  baseOfFFT = NULL;
  baseOfMFFT = NULL;
  baseOfStatus = NULL;
  baseOfSubckt = NULL;
  twoTerminal = (1L << ((long)resistor)) | (1L << ((long)capacitor)) |
                (1L << ((long)inductor)) | (1L << ((long)switch_)) |
                (1L << ((long)vs)) | (1L << ((long)cs));
  fourTerminal = (1L << ((long)coupledInductor)) | (1L << ((long)opamp)) |
                 (1L << ((long)quantizer)) | (1L << ((long)comparator));
  fourTerminal |= (1L << ((long)vcvs)) | (1L << ((long)vccs)) |
                  (1L << ((long)adder));
  nonlinears = (1L << ((long)opamp)) | (1L << ((long)quantizer)) |
               (1L << ((long)comparator));
  globalControl = (1L << ((long)switch_)) | (1L << ((long)opamp)) |
                  (1L << ((long)quantizer)) | (1L << ((long)subckt)) |
                  (1L << ((long)delay)) | (1L << ((long)vs)) |
                  (1L << ((long)cs)) | (1L << ((long)l_general));
  digitals = (1L << ((long)delay)) | (1L << ((long)adder)) |
             (1L << ((long)multiplier));
  logicals = 1L << ((long)l_general);
  print_to_file = FALSE;
  strcpy(prn_filename,"\0");
  fft_to_file = FALSE;
  strcpy(fft_filename,"\0");
  fft_window = WINDOW_RECTANGULAR;
  fft_must_reorder = TRUE;		/* FFT vs. DFT */
  shortPrint = TRUE;
  timePrint = TRUE;
  runDiag = FALSE;
  binaryArray[0] = 1;
  for (i = 1; i <= BINARY_LEN; i++)
    binaryArray[i] = binaryArray[i - 1] * 2;
  terminate_on_eof = FALSE;
  terminate = FALSE;
}


void MakeValueList(base, n)
flex *base;
long n;
{
  MakeSymbolList(base, n);
  
  base->dim = n;
  base->UU.c = c_malloc(sizeof(double) * n);
}


void MakeIDList(base, n)
flex *base;
long n;
{
  MakeSymbolList(base, n);

  base->dim = n;
  base->UU.c = c_malloc(sizeof(long) * n);
}


 long GetID(np, n)
flex np;
long n;
{
  return (np.UU.n[n - 1]);
}


 double GetValue(vp, n)
flex vp;
long n;
{
  return (vp.UU.x[n - 1]);
}


/* this function is never called.... */
void PutToID(p, n, d)
flex *p;
long n, d;
{
  p->UU.n[n - 1] = d;
}


void PutToValue(p, n, x)
flex *p;
long n;
double x;
{
  p->UU.x[n - 1] = x;
}





 long CloneID(src, res)
flex src, *res;
{
  long i;
  
  res->dim = src.dim;
  res->UU.c = c_malloc(sizeof(long) * src.dim);
  for (i = 0; i < src.dim; i++)
    res->UU.n[i] = src.UU.n[i];
  return (res->dim);
}


void GetBranchByID(there, n_ID)
branchRec **there;
long n_ID;
{
  /*Finds the branch with ID number n_ID in the linked list*/
  *there = baseOfBranch;
  while (*there != NULL && (*there)->ID.UU.n[0] != n_ID)
    *there = (*there)->next;
}


void GetBranchByName(there, bname)
branchRec **there;
char *bname;
{
  /*Finds the branch with name bname in the linked list*/
  boolean found;

  *there = baseOfBranch;
  found = FALSE;
  while (*there != NULL && !found) {
    if (strcmp((*there)->name, bname) == 0)
      found = TRUE;
    else
      *there = (*there)->next;
  }
  if (!found)
    errorReport(ERROR_UNRESOLVED_BRANCH, bname, ERR_VOID, 0);
}


void newBranch(b, no_ID, no_val)
branchRec **b;
long no_ID, no_val;
{
  *b = (branchRec *)c_malloc(sizeof(branchRec));
  (*b)->next = NULL;
  MakeIDList(&(*b)->ID, no_ID);
  MakeValueList(&(*b)->value, no_val);
}


void GetModelByName(there, mname)
modelRec **there;
char *mname;
{
  /*Finds the model with name mname in the linked list*/
  boolean found;

  *there = baseOfModel;
  found = FALSE;
  while (*there != NULL && !found) {
    if (strcmp((*there)->name, mname) == 0)
      found = TRUE;
    else
      *there = (*there)->next;
  }
  if (!found)
    errorReport(ERROR_UNRESOLVED_MODEL, mname, ERR_VOID, 0);
}


void GetClockByName(there, pname)
clockRec **there;
char *pname;
{
  /*Finds the clock waveform named pname in the linked list*/
  boolean found;

  *there = baseOfClock;
  found = FALSE;
  while (*there != NULL && !found) {
    if (strcmp((*there)->name, pname) == 0)
      found = TRUE;
    else
      *there = (*there)->next;
  }
  if (!found)
    errorReport(ERROR_UNRESOLVED_CLOCK, pname, ERR_VOID, 0);
}


void GetSubcktByName(there, sname)
subcktRec **there;
char *sname;
{
  /*Finds the subcircuit names sname in the linked list*/
  boolean found;

  *there = baseOfSubckt;
  found = FALSE;
  while (*there != NULL && !found) {
    if (strcmp((*there)->name, sname) == 0)
      found = TRUE;
    else
      *there = (*there)->next;
  }
  if (!found)
    errorReport(ERROR_UNRESOLVED_SUBCKT, sname, ERR_VOID, 0);
}


void GetFromSystem(there, n)
systemRec **there;
long n;
{
  /*Finds the system record for the nth clock tick*/
  long i;

  *there = baseOfSystem;
  for (i = 2; i <= n; i++)
    *there = (*there)->next;
}


void InitializeSystem()
{
  systemRec *tmp;
  long matrix_loop;
  long i, FORLIM;

  baseOfSystem = NULL;

  FORLIM = NoOfTicks;
  for (i = 1; i <= FORLIM; i++) {
    tmp = (systemRec *)c_malloc(sizeof(systemRec));
    tmp->next = baseOfSystem;

	/* No longer dependent upon VAR limitation ... 1 Mar 92 RdH */

	/* Initialize new tmpSystem records */
	tmp->N = (double **) c_malloc(NoOfVars * sizeof (double *));
    tmp->B = (double **) c_malloc(NoOfVars * sizeof (double *));
  
    for (matrix_loop = 0; matrix_loop < NoOfVars; matrix_loop++) {
  	  tmp->N[matrix_loop] = (double *) c_malloc(NoOfVars * sizeof (double));
      tmp->B[matrix_loop] = (double *) c_malloc(NoOfVars * sizeof (double));
    }
    
    baseOfSystem = tmp;
  }
}




/* branchID returns a new branch number for every time it's called. */
 long branchID()
{
  NoOfVars++;
  /* error checking eliminated ... no such limit exists */
  return NoOfVars;
}


/************ Reading Utilities *************************/
void readCard(f, l)
FILE **f;
char *l;
{

  char ch;
  char dead_char;	/* RdH */
  long i, j;
  
  boolean null_encountered;
  int wordnum;
  int aa;
  int found;		/* used to ignore blanks preceeding 1st char */
  
  i = 1;
  
  found = FALSE;
  
  while (!P_eoln(*f)) {
    ch = getc(*f);
    if (ch == '\n')
      ch = SPACE_CHAR;
    if (ch == TAB_CHAR)
      ch = SPACE_CHAR;
	if (found == TRUE) {
      l[i - 1] = ch;
	  i++;
	  }
    else if ((ch != SPACE_CHAR) && (ch != TAB_CHAR)) {
      found = TRUE;
      l[i-1] = ch;
      i++;
      }
  }
  fscanf(*f, "%*[^\n]");
  dead_char = getc(*f);
  l[i-1] = '\0';


  /* The following junk performs "getwords" on the entire card...
    the function getword may now perform a single lookup... */

  rcard.FIRSTCHAR = toupper(l[0]);
  for (j = 0; j < 80; j++)
    rcard.Card[j] = NULL_CHAR;
  strcpy(rcard.Card,l);
  /* get ALL words! */
  for (wordnum = 0; wordnum < MAX_WORDS; wordnum++)
    for (aa = 0; aa < MAX_WORD_LENGTH; aa++) {
      rcard.Word[wordnum][aa] = NULL_CHAR;
      rcard.WORD[wordnum][aa] = NULL_CHAR;
      }
  for (j = 0; j < 80; j++)
    rcard.CARD[j] = l[j] = toupper(rcard.Card[j]);
  if (&(rcard.Card[0]) != NULL_CHAR) {
    wordnum = 0;
    i = 0;
    aa = 0;
    null_encountered = FALSE;
    do {
      while ((rcard.Card[i] != NULL_CHAR)
        && (rcard.Card[i] != '=')
        && (rcard.Card[i] != SPACE_CHAR)
		&& (rcard.Card[i] != TAB_CHAR)
        && (i < 80)
        && (wordnum < MAX_WORDS)) {
        if (rcard.Card[i] == NULL_CHAR)
          null_encountered = TRUE;
        rcard.Word[wordnum][aa] = rcard.Card[i];
        rcard.WORD[wordnum][aa] = rcard.CARD[i];
		aa++;
        i++;
        }
      rcard.Word[wordnum][aa] = NULL_CHAR;
      rcard.WORD[wordnum][aa] = NULL_CHAR;
      wordnum++;
      i++;
      aa = 0;
      while ((rcard.Card[i] != NULL_CHAR)
        && ((rcard.Card[i] == '=') 
               || (rcard.Card[i] == SPACE_CHAR) 
               || (rcard.Card[i] == TAB_CHAR))
        && (i < 80)
        && (wordnum < MAX_WORDS)) {
        if (rcard.Card[i] == NULL_CHAR)
          null_encountered = TRUE;
        rcard.Word[wordnum][i] = rcard.Card[i];
        rcard.WORD[wordnum][i] = rcard.CARD[i];
        i++;
        }
      } while ((i < 80) && (wordnum < MAX_WORDS) && (null_encountered == FALSE));
    }

	for (i = 0; i < MAX_WORDS; i++)
	  if ((rcard.Word[i][0] == NULL_CHAR) ||
	      (rcard.Word[i][0] == ';') ||
	      (rcard.Word[i][0] == '#'))
	    break;
	  
    rcard.word_count = i;

}


char *GetWord(Result,n)
char *Result;
long n;
{
  return strcpy(Result,rcard.Word[n-1]);
}


char *GetWORD(Result,n)
char *Result;
long n;
{
  return strcpy(Result,rcard.WORD[n-1]);
}


void readNNode(b, l, n)
branchRec **b;
char *l;
long n;
{
  aWord tmp;
  long i;

  GetWORD(tmp,1L);
  for (i = 0; i < NAME_LEN; i++)
    (*b)->name[i] = tmp[i];
  (*b)->ID.UU.n[0] = branchID();
  for (i = 2; i <= n + 1; i++) {
    GetWORD(tmp,i);
    /* assigns a position for the given node RdH */
    (*b)->ID.UU.n[i - 1] = nodeID(tmp);
  }
}


/* Reads 2 more nodes from card */
void read2Node(b, l)
branchRec **b;
char *l;
{
  readNNode(b, l, 2L);
}


void read4Node(b, l)
branchRec **b;
char *l;
{
  readNNode(b, l, 4L);
}


void read2NodeName(b, l)
branchRec **b;
char *l;
{
  /*NAME1  N+  N-  NAME2*/
  aWord tmp;
  long i;

  read2Node(b, l);
  GetWORD(tmp,4L);
  strcpy((*b)->cname,tmp);
  (*b)->next = baseOfBranch;
  baseOfBranch = *b;
}


void read4NodeName(b, l)
branchRec **b;
char *l;
{
  /*NAME1  N+  N-  NC+  NC-  NAME2*/
  aWord tmp;
  long i;

  read4Node(b, l);
  GetWORD(tmp,6L);
  for (i = 0; i < NAME_LEN; i++)
    (*b)->cname[i] = tmp[i];
  (*b)->next = baseOfBranch;
  baseOfBranch = *b;
}


void read2NodeValue(b, l)
branchRec **b;
char *l;
{
  /*NAME  N+  N-  VALUE*/
  aWord tmp;

  read2Node(b, l);
  GetWORD(tmp,4L);

  if (isalpha(tmp[0]))
    (*b)->value.UU.x[0] = parseSymbol(b,0,4L);
  else
    (*b)->value.UU.x[0] = gck_atod(tmp);
  (*b)->next = baseOfBranch;
  baseOfBranch = *b;
}


void read4NodeValue(b, l)
branchRec **b;
char *l;
{
  /*NAME  N+  N-  NC+  NC-  VALUE*/
  aWord tmp;

  read4Node(b, l);
  GetWORD(tmp,6L);

  if (isalpha(tmp[0]))
    (*b)->value.UU.x[0] = parseSymbol(b,0,6L);
  else
    (*b)->value.UU.x[0] = gck_atod(tmp);
  (*b)->next = baseOfBranch;
  baseOfBranch = *b;
}


/************ Specific Components ***********************/
/********** Clock Specifications ************/
void readLibrary()
{
aWord tmp;

  GetWord(tmp,2L);
  
  if (rfile.depth == (MAX_FILE_DEPTH - 1)) 
    errorReport(ERROR_LIBRARY_DEPTH,0,ERR_VOID,0);
 
  if ((rfile.filePtr[++rfile.depth] = fopen(tmp,"r")) == NULL)
    errorReport(ERROR_LIBRARY_NOT_FOUND,tmp,ERR_VOID,0);

  if (object_stamp < FileAge(tmp))
    up_to_date = FALSE;

}


void readClock(l)
char *l;
{
  /*.CLOCK  NAME  11100001*/
  clockRec *b;
  aWord tmp;
  long i, j, FORLIM;

  b = (clockRec *)c_malloc(sizeof(clockRec));
  GetWORD(tmp,2L);
  strcpy(b->name,tmp);
  GetWORD(tmp,3L);
  i = 0;
  do {
    i++;
  } while (tmp[i - 1] != NULL_CHAR); /* was SPACE */
  i--;
  if ((TicksRegistered == TRUE) && (NoOfTicks != i)) 
    errorReport(ERROR_INCONSISTENT_CLOCKS,0,ERR_VOID,0);

  if (TicksRegistered == FALSE) {
    TicksRegistered = TRUE;
    NoOfTicks = i;
    }
  MakeValueList(&b->value, NoOfTicks);
  FORLIM = NoOfTicks;
  for (j = 0; j < FORLIM; j++) {
    if (tmp[j] == '1')
      b->value.UU.x[j] = 1.0;
    else
      b->value.UU.x[j] = 0.0;
  }
  b->next = baseOfClock;
  baseOfClock = b;
}


/*********** Node Specifications ******************/
void readNode(l)
char *l;
{
  /*.NODE  <NODE_NUMBER>  LOW = <VSAT_LOW>  HIGH = <VSAT_HIGH> SR = <SLEW_RATE>*/
  nodeRec *b;
  aWord tmp;
  long i;
  aWord TEMP;

  b = (nodeRec *)c_malloc(sizeof(nodeRec));
  GetWORD(tmp,2L);
  b->ID = nodeID(tmp);
  b->flo = FALSE;
  b->fhi = FALSE;
  b->fsr = FALSE;
  i = 3;
  GetWORD(tmp,i);
  while (tmp[0] != NULL_CHAR) {		/* was SPACE_CHAR RdH */
    if (strncmp(tmp,"LOW",3) == 0) {
      i++;
      b->lo = gck_atod(GetWORD(TEMP,i));
      b->flo = TRUE;
    } else if (strncmp(tmp,"HIGH",4) == 0) {
      i++;
      b->hi = gck_atod(GetWORD(TEMP,i));
      b->fhi = TRUE;
    } else if (strncmp(tmp,"SR",2) == 0) {
      i++;
      b->sr = gck_atod(GetWORD(TEMP,i));
      b->fsr = TRUE;
    }
    i++;
    GetWORD(tmp,i);
  }
  b->next = baseOfNode;
  baseOfNode = b;
}


void SetUpNodes()
{
  nodeRec *tmpNode;

  tmpNode = baseOfNode;
  while (tmpNode != NULL) {
    tmpNode->me = &vv_x[tmpNode->ID];
    /* tmpNode->me = var_vector_x[tmpNode->ID]; */
    tmpNode = tmpNode->next;
  }
}


void RunNodes()
{
  nodeRec *tmpN;
  double d;

  tmpN = baseOfNode;
  while (tmpN != NULL) {
    if (tmpN->flo) {
      if (*tmpN->me < tmpN->lo)
        *tmpN->me = tmpN->lo;
    }
    if (tmpN->fhi) {
      if (*tmpN->me > tmpN->hi)
        *tmpN->me = tmpN->hi;
    }
    if (tmpN->fsr) {
      d = *tmpN->me - tmpN->oldme;
      if (fabs(d) > tmpN->sr) {
        if (d > 0)
          *tmpN->me = tmpN->oldme + tmpN->sr;
        else
          *tmpN->me = tmpN->oldme - tmpN->sr;
      }
      tmpN->oldme = *tmpN->me;
    }
    tmpN = tmpN->next;
  }
}


/********** Simulation Time ***************/
void readTimeStep(l)
char *l;
{
  /*.STEP  <VALUE>*/
  aWord symbol;
  aWord value;

  GetWORD(symbol,2L);
  if (isalpha(symbol[0])) {
    GetWORD(value,3L);
    createSymbol(symbol,value);
    deltaT_sv.is_symbol = TRUE;
    strcpy(deltaT_sv.sName,symbol);
    if (strlen(value) == 0)
      deltaT = 0.0;
    else
      deltaT = gck_atod(value);    
    }
  else {
    deltaT_sv.is_symbol = FALSE;
    deltaT_sv.sName[0] = NULL_CHAR;
    deltaT = gck_atod(GetWORD(symbol,2L));
    }
}


void readClockPeriod(l)
char *l;
{
  /*.PERIOD  <VALUE>*/
  aWord symbol;
  aWord value;

  GetWORD(symbol,2L);
  if (isalpha(symbol[0])) {
    GetWORD(value,3L);
    createSymbol(symbol,value);
    periodT_sv.is_symbol = TRUE;
    strcpy(periodT_sv.sName,symbol);
    if (strlen(value) == 0)
      periodT = 0.0;
    else
      periodT = gck_atod(value);    
    }
  else {
    periodT_sv.is_symbol = FALSE;
    periodT_sv.sName[0] = NULL_CHAR;
    periodT = gck_atod(GetWORD(symbol,2L));
    }
}


void readTime(l)
char *l;
{
  /*.TIME <SIMULATION_TIME>*/
  aWord symbol;
  aWord value;

  GetWORD(symbol,2L);
  if (isalpha(symbol[0])) {
    GetWORD(value,3L);
    createSymbol(symbol,value);
    lastTime_sv.is_symbol = TRUE;
    strcpy(lastTime_sv.sName,symbol);
    if (strlen(value) == 0)
      lastTime = 0.0;
    else
      lastTime = gck_atod(value);    
    }
  else {
    lastTime_sv.is_symbol = FALSE;
    lastTime_sv.sName[0] = NULL_CHAR;
    lastTime = gck_atod(GetWORD(symbol,2L));
    }
}


void readSample(l)
char *l;
{
  /*.SAMPLE 00100*/
  aWord tmp;
  long i, j, FORLIM;

  sample_card_found = TRUE;
  GetWORD(tmp,2L);
  i = 0;
  do {
    i++;
  } while (tmp[i - 1] != NULL_CHAR); /* was SPACE_CHAR */
  i--;
  if ((TicksRegistered == TRUE) && (NoOfTicks != i)) 
    errorReport(ERROR_INCONSISTENT_CLOCKS,0,ERR_VOID,0);

  if (TicksRegistered == FALSE) {
    TicksRegistered = TRUE;
    NoOfTicks = i;
    }
  MakeValueList(&sampleTicks->value, NoOfTicks);
  FORLIM = NoOfTicks;
  samplesOn = 0;
  for (j = 0; j < FORLIM; j++) {
    if (tmp[j] == '1') {
      sampleTicks->value.UU.x[j] = 1.0;
      samplesOn++;
      }
    else
      sampleTicks->value.UU.x[j] = 0.0;
  }
}

void SetUpStubSample()
{
  long j;

  if (!sample_card_found) {
    MakeValueList(&sampleTicks->value, NoOfTicks);
    for (j = 0; j < NoOfTicks; j++) {
      sampleTicks->value.UU.x[j] = 1.0;
      }
  }
}

void readPrint(l)
char *l;
{
  /*.PRINT V(n1, n2) I(name) ...*/
  printRec *tmpP, *lastP;
  aWord tmpW;
  nameString tmpN;
  long i, j, k;
  long counter;

  i = 2;
  GetWORD(tmpW,i);

  while (tmpW[0] != NULL_CHAR) {
    switch (tmpW[0]) {

    case '>':	/* new option */
      print_to_file = TRUE;
      if (tmpW[1] == NULL_CHAR) {
        i++;
        GetWord(prn_filename,i);
        }
      else {
        GetWord(tmpW,i);
        strcpy(prn_filename,&tmpW[1]);
        }
      break;
    case 'V':
      tmpP = (printRec *)c_malloc(sizeof(printRec));
      tmpP->outType = branchVoltage;
      strcpy(tmpN,"\0");
      j = 3;
      while ((tmpW[j - 1] != ',') && (tmpW[j - 1] != ')')) {
        tmpN[j - 3] = tmpW[j - 1];
        j++;
      }
      tmpN[j - 3] = NULL_CHAR;

	  tmpP->n1 = nodeRecordFromList(tmpN,REQUEST_NODE);
	  
	  if (tmpW[j - 1] == ')') /* Remembering Ayse! */
	    tmpP->n2 = nodeRecordFromList("0",REQUEST_NODE);
      else {
        strcpy(tmpN,"\0");
        k = j + 1;
        while (tmpW[k - 1] != ')') {
          tmpN[k - j - 1] = tmpW[k - 1];
          k++;
          }
        tmpN[k - j - 1] = NULL_CHAR;
      
        tmpP->n2 = nodeRecordFromList(tmpN,REQUEST_NODE);
        }
      if (baseOfPrint == NULL) {
        baseOfPrint = tmpP;
        lastP = tmpP;
      } else {
        lastP->next = tmpP;
        lastP = tmpP;
      }
      break;

    case 'I':
      tmpP = (printRec *)c_malloc(sizeof(printRec));
      tmpP->outType = branchCurrent;
      strcpy(tmpN,"\0");
      j = 3;
      while (tmpW[j - 1] != ')') {
        tmpN[j - 3] = tmpW[j - 1];
        j++;
      }
      strcpy(tmpP->name,tmpN);
      if (baseOfPrint == NULL) {
        baseOfPrint = tmpP;
        lastP = tmpP;
      } else {
        lastP->next = tmpP;
        lastP = tmpP;
      }
      break;

    default:
      errorReport(ERROR_BAD_PRINTSPEC, progName, ERR_VOID, 0);
      break;
    }
    i++;
    GetWORD(tmpW,i);

  }
}



void SetUpPrint()
{
  printRec *tmp;
  branchRec *b;

  tmp = baseOfPrint;
  while (tmp != NULL) {
    switch (tmp->outType) {

    case branchVoltage:
      if (tmp->n1 == 0)
        tmp->vo1 = GND;
      else
        tmp->vo1 = &vv_x[ID_nindex[tmp->n1]];
      if (tmp->n2 == 0)
        tmp->vo2 = GND;
      else
        tmp->vo2 = &vv_x[ID_nindex[tmp->n2]];
      break;

    case branchCurrent:
      GetBranchByName(&b, tmp->name);
      tmp->vo1 = &vv_x[b->ID.UU.n[0]];
      tmp->vo2 = GND;
      break;
    }
    tmp = tmp->next;
  }
  
  if (print_to_file) {
    print_file = fopen(prn_filename,"w");
    if (print_file == NULL)
      errorReport(ERROR_FILE_PRINT_CANNOT_OPEN,prn_filename,ERR_VOID,0);
    }
  else {
    print_file = stdout;
    }
}

void RunPrint()
{
  printRec *tmp;
  float shTmp;

  if (baseOfPrint == NULL)
    return;
  tmp = baseOfPrint;
  if (shortPrint) {
    if (timePrint) {
      shTmp = The_Time;
      fprintf(print_file,"% .5E%c", shTmp, TAB_CHAR);
    }
  } else {
    if (timePrint)
      fprintf(print_file,"% .5E%c", The_Time, TAB_CHAR);
  }
  while (tmp != NULL) {
    if (shortPrint) {
      shTmp = *tmp->vo1 - *tmp->vo2;
      fprintf(print_file,"% .5E", shTmp);
    } else
      fprintf(print_file,"% .5E", *tmp->vo1 - *tmp->vo2);
    if (tmp->next != NULL)
      fprintf(print_file,"%c",TAB_CHAR);
    else
      fprintf(print_file,"\n");
    tmp = tmp->next;
  }
}


/*********** Model Specifications ********************/
void readModelSection(f, firstLine)
FILE **f;
char *firstLine;
{
  /*.MODEL  MODEL_NAME
    VAL1  VAL2 ...
    ..
   .END*/
  card l;
  aWord tmp;
  nameString tmpName;
  modelRec *tmpModel;
  flex tmpV;
  long i;
  
  long symbol_count, position, op_amp_stub; /* RdH */
  long model_size;

  model_size = 10;

  strcpy(l,firstLine);
  GetWORD(tmp,2L);
  strcpy(tmpName,tmp);
  tmpModel = baseOfModel;
  while (tmpModel != NULL) {
    if (strcmp(tmpModel->name, tmpName) == 0)
      errorReport(ERROR_DUPLICATE_MODEL, tmpName, ERR_VOID, 0);
    else
      tmpModel = tmpModel->next;
  }
  if (tmpModel != NULL)
    return;
  tmpModel = (modelRec *)c_malloc(sizeof(modelRec));
  tmpModel->next = baseOfModel;
  MakeSymbolList(&tmpV,2);	/* symbols only work for op amps */
  baseOfModel = tmpModel;
  strcpy(baseOfModel->name,tmpName);
  /*start reading the data section*/
  readCard(f, l);
  GetWORD(tmp,1L);
  /* this next line limits ADC size ... Grrr */
  tmpV.UU.c = c_malloc(sizeof(double) * model_size);
  tmpV.dim = 0;
  op_amp_stub = 0;
  while (strncmp(tmp,".END",4) != 0) {
    position = 1;
    symbol_count = 0;
    while (tmp[0] != NULL_CHAR) {
        tmpV.dim++;
        if (tmpV.dim == model_size) {
          model_size += 10L;
          tmpV.UU.c = realloc(tmpV.UU.c,sizeof(double) * model_size);
          if (tmpV.UU.c == NULL)
            errorReport(ERROR_REALLOC_MODEL,0,ERR_VOID,0);

          }
        GetWORD(tmp,position);
        if ((isalpha(tmp[0])) && (op_amp_stub < 2)) {
          symbol_count++;
          tmpV.UU.x[tmpV.dim - 1] = parseSymbolModel(&tmpModel,tmpV.dim - 1,position++);
          }
        else
          tmpV.UU.x[tmpV.dim - 1] = gck_atod(tmp);
        position++;
        op_amp_stub++;
        GetWORD(tmp,position); /* stub, but necessary */
        }
    readCard(f, l);
    GetWORD(tmp,1L);
  }
  baseOfModel->value.dim = tmpV.dim;
  baseOfModel->value.UU.c = c_malloc(sizeof(double) * tmpV.dim);
  
  for (i = 0; i < tmpV.dim; i++)
    baseOfModel->value.UU.x[i] = tmpV.UU.x[i];

  if (tmpV.UU.c != NULL)
    free(tmpV.UU.c);
}


/********** Subcircuit *********/
void readXCard(l)
char *l;
{
  /*XYYYYYYY  N1 N2 ... SUBCKT_NAME*/
  branchRec *b;
  aWord tmp;
  long i, nc;
  aWord TEMP;

  b = (branchRec *)c_malloc(sizeof(branchRec));
  GetWORD(tmp,1L);

  strcpy(b->name,tmp);
  b->element = subckt;
  nc = rcard.word_count - 2;	/* number of nodes to pass to subckt */
  MakeIDList(&b->ID, nc);
  for (i = 1; i <= nc; i++)
    b->ID.UU.n[i - 1] = nodeID(GetWORD(TEMP,i + 1));
  GetWORD(tmp,nc + 2);
  strcpy(b->cname,tmp);
  b->next = baseOfBranch;
  baseOfBranch = b;
}



void substituteSubckt(b)
branchRec **b;
{
  long i, k, bn, newn;
  branchRec *tmp, *tmpC;
  subcktRec *s;

  long depth;
  char the_name[32];
  
  depth = (*b)->depth + 1;
  strcpy(the_name,(*b)->name);

  GetSubcktByName(&s, (*b)->cname);
  if (s == NULL)
    errorReport(ERROR_UNRESOLVED_SUBCKT, (*b)->cname, ERR_VOID, 0);
  tmp = s->base;   /*branch(es) to be copied*/
  while (tmp != NULL) {
    if (tmp->element == subckt) {
      if (strcmp(tmp->cname,s->name) == 0)
        errorReport(ERROR_RECURSIVE_SUBCKT, s->name, ERR_VOID, 0);
    }
    tmpC = (branchRec *)c_malloc(sizeof(branchRec));
    tmpC->element = tmp->element;
    /*obtain unique names by concanating to the 1st
      8 characters of the subckt branch name the 1st
      8 characters of the calling branch name (i.e. XYYY)*/
    for (i = 0; i < NAME_HAF; i++)
      tmpC->name[i] = tmp->name[i];
    for (i = NAME_HAF + 1; i <= NAME_LEN; i++)
      tmpC->name[i - 1] = (*b)->name[i - 5];
    if (((1L << ((long)tmpC->element)) & globalControl) != 0) {
      for (i = 0; i < NAME_LEN; i++)
        tmpC->cname[i] = tmp->cname[i];
    } else {
      for (i = 0; i < NAME_HAF; i++)
        tmpC->cname[i] = tmp->cname[i];
      for (i = NAME_HAF + 1; i <= NAME_LEN; i++)
        tmpC->cname[i - 1] = (*b)->name[i - 5];
    }
    /*no need to replicate the value list*/
    tmpC->value = tmp->value;
    /*adjust the IDs*/
    k = CloneID(tmp->ID, &tmpC->ID);
    for (i = 0; i < k; i++) {
      bn = GetID(tmpC->ID, i + 1);
      if (bn != 0) {
        if (bn <= s->NConn)   /*external nodes*/
          tmpC->ID.UU.n[i] = (*b)->ID.UU.n[bn - 1];
        else {
          newn = NoOfVars + bn - s->NConn;
          tmpC->ID.UU.n[i] = newn;
        }
      }
    }
    /* RdH March 24, 1992 */
    tmpC->depth = depth;
    strcpy(tmpC->cktname,the_name);
    
    tmpC->next = (*b)->next;
    (*b)->next = tmpC;
    tmp = tmp->next;
  }
  NoOfVars += s->NVar - s->NConn;
}


/************** Capacitor **************/
void MakeCapacitor(b)
branchRec **b;
{
  newBranch(b, 3L, 1L);
  (*b)->element = capacitor;
}


void readCapacitor(l)
char *l;
{
  /*CXXXX  N+  N-  VALUE*/
  branchRec *b;

  MakeCapacitor(&b);
  read2NodeValue(&b, l);
}


/************** Inductor **************/
void MakeInductor(b)
branchRec **b;
{
  newBranch(b, 3L, 1L);
  (*b)->element = inductor;
}


void readInductor(l)
char *l;
{
  /*LXXXX  N+  N-  VALUE*/
  branchRec *b;

  MakeInductor(&b);
  read2NodeValue(&b, l);
}


/************** Resistor **************/
void MakeResistor(b)
branchRec **b;
{
  newBranch(b, 3L, 1L);
  (*b)->element = resistor;
}


void readResistor(l)
char *l;
{
  /*RXXXX  N+  N-  VALUE*/
  branchRec *b;

  MakeResistor(&b);
  read2NodeValue(&b, l);
}


/************** Sources **************/
void readSource(l)
char *l;
{
  /* vars help FILE implementation */
  char tmpfn[64];
  int  nn;

  /* RdH December 18 1991 v0.2.0 changes reflected here */
  /*VXXXX  N+  N-
            SIN <amp> <freq> 
          | DC <amp>
          | STDIN
          | FILE <filename>
          | RND <lim>
          | PULSE <unpulsed_amp> <pulsed_amp> <period> <delay> <rise_time> <duration> <fall_time>
          | IMPULSE  <amplitude>
          | COMB <amp> <start_freq> <delta_freq> <no_of_freq>
          */

  /*IXXXX  N+  N-  <source_specification> */
  branchRec *b;
  aWord tmp, tmpd;
  long i;
  aWord TEMP;
  aWord T2;
  long position;
  long loop;
  long symbol_count;

  newBranch(&b, 3L, 1L);	/* was 0L on 3rd parameter...3 Mar 92 RdH */
  read2Node(&b, l);
  GetWORD(tmp,4L);

  if (strncmp(tmp,"SIN",3) == 0) {
    MakeValueList(&b->value, 3L);

    position = 5;
    symbol_count = 0;
    for (loop = 0; loop < 3; loop++) {
      GetWORD(T2,position);
      if ((loop == 2) && (T2[0] == NULL_CHAR))
        b->value.UU.x[2] = 0.0;
      else if (isalpha(T2[0])) {
        symbol_count++;
        b->value.UU.x[loop] = parseSymbol(&b,loop,position++);
        }
      else
        b->value.UU.x[loop] = gck_atod(T2);
      position++;
      if ((loop == 2) && (T2[0] != NULL_CHAR))
        symbol_count++; /* not really, just error checking! */
      }      
    strcpy(b->cname,"SIN");
    if (rcard.word_count < (6 + symbol_count)) 
      errorReport(ERROR_SIN_CARD_BROKEN,0,ERR_VOID,0);
 
  } else if (strncmp(tmp,"COMB",4) == 0) {
    MakeValueList(&b->value, 4L);
    
    position = 5;
    symbol_count = 0;
    for (loop = 0; loop < 4; loop++) {
      GetWORD(T2,position);
      if (isalpha(T2[0])) {
        symbol_count++;
        b->value.UU.x[loop] = parseSymbol(&b,loop,position++);
        }
      else
        b->value.UU.x[loop] = gck_atod(T2);
      position++;
      }
    strcpy(b->cname,"COMB");
    if (rcard.word_count < (8 + symbol_count)) 
      errorReport(ERROR_COMB_CARD_BROKEN,0,ERR_VOID,0);
      


  } else if (strncmp(tmp,"DC",2) == 0) {
    MakeValueList(&b->value, 1L);
    
    GetWORD(T2,5L);
    if (isalpha(T2[0]))
      b->value.UU.x[0] = parseSymbol(&b,0,5L);
    else
      b->value.UU.x[0] = gck_atod(T2);
    strcpy(b->cname,"DC");



  } else if (strncmp(tmp,"IMPULSE",7) == 0) {
    MakeValueList(&b->value, 1L);

    GetWORD(T2,5L);
    if (isalpha(T2[0]))
      b->value.UU.x[0] = parseSymbol(&b,0,5L);
    else
      b->value.UU.x[0] = gck_atod(T2);
    strcpy(b->cname,"IMPULSE");



  } else if (strncmp(tmp,"RND",3) == 0) {
    MakeValueList(&b->value, 1L);

    GetWORD(T2,5L);
    if (isalpha(T2[0]))
      b->value.UU.x[0] = parseSymbol(&b,0,5L);
    else
      b->value.UU.x[0] = gck_atod(T2);
    strcpy(b->cname,"RND");



  } else if (strncmp(tmp,"STDIN",5) == 0)
    strcpy(b->cname,"STDIN");

  else if (strncmp(tmp,"FILE",4) == 0) {
    MakeValueList(&b->value, 32L);
    strcpy(tmpfn,GetWord(TEMP,5L));
    strcpy(&(b->value.UU.w[0]),tmpfn);
    strcpy(b->cname,"FILE");   
      
  } else if (strncmp(tmp, "PULSE",5) == 0) {
    MakeValueList(&b->value, 7L);
    
    position = 5;
    symbol_count = 0;
    for (loop = 0; loop < 7; loop++) {
      GetWORD(T2,position);
      if (isalpha(T2[0])) {
        symbol_count++;
        b->value.UU.x[loop] = parseSymbol(&b,loop,position++);
        }
      else
        b->value.UU.x[loop] = gck_atod(T2);
      position++;
      }
    strcpy(b->cname,"PULSE");
    if (rcard.word_count < (11 + symbol_count))
      errorReport(ERROR_PULSE_CARD_BROKEN,0,ERR_VOID,0);
    
  } else
    errorReport(ERROR_UNRESOLVED_SOURCE, progName, ERR_VOID, 0);
  GetWORD(tmp,1L);
  if (tmp[0] == 'v' || tmp[0] == 'V')
    b->element = vs;
  else if (tmp[0] == 'i' || tmp[0] == 'I')
    b->element = cs;
  b->next = baseOfBranch;
  baseOfBranch = b;
}

void CreateSourceList()
{
/* This function is completely new, in hopes that it will assist
in shattering the MaX_VARS requirement ... 1 Mar 92  RdH */

/* Now that the number of Vars is known, create an array for them */
  long i, FORLIM;

  FORLIM = NoOfVars;
  vv_s = (double *) c_malloc((NoOfVars + 1) * sizeof(double));
  /* limits should include "NoOfVars + 1"-th element */
  for (i = 0; i <= FORLIM; i++) { /* Init not really necessary */
    vv_s[i] = 0.0;
    }

}



void SetUpSources()
{
  branchRec *b;
  sourceRec *tmpS;
  long i, dummy;
  sourceRec *WITH;

  b = baseOfBranch;
  while (b != NULL) {
    if (((1L << ((long)b->element)) &
         ((1L << ((long)vs)) | (1L << ((long)cs)))) != 0) {
      tmpS = (sourceRec *)c_malloc(sizeof(sourceRec));
      tmpS->next = baseOfSource;
      baseOfSource = tmpS;
      if (!strncmp(b->cname, "SIN", sizeof(nameString))) {
        baseOfSource->signal = sinusoid;
        
	if (b->value.sv[0].is_symbol)
          baseOfSource->VV.U0.amp = getSymbolValueByName(b->value.sv[0].sName);
	else
          baseOfSource->VV.U0.amp = b->value.UU.x[0];

        if (b->value.sv[1].is_symbol)
	  baseOfSource->VV.U0.freq = TWOPI * getSymbolValueByName(b->value.sv[1].sName);
        else
          baseOfSource->VV.U0.freq = TWOPI * b->value.UU.x[1];
          
        if (b->value.sv[2].is_symbol)
	  baseOfSource->VV.U0.dly = getSymbolValueByName(b->value.sv[2].sName);
	else
	  baseOfSource->VV.U0.dly = b->value.UU.x[2];
	  


      } else if (!strncmp(b->cname, "COMB", sizeof(nameString))) {
        baseOfSource->signal = comb;
        
        if (b->value.sv[0].is_symbol)
          baseOfSource->VV.U5.amp0 = getSymbolValueByName(b->value.sv[0].sName);
        else
          baseOfSource->VV.U5.amp0 = b->value.UU.x[0];
          
        if (b->value.sv[1].is_symbol)
          baseOfSource->VV.U5.freq0 = TWOPI * getSymbolValueByName(b->value.sv[1].sName);
        else
          baseOfSource->VV.U5.freq0 = TWOPI * b->value.UU.x[1];

        if (b->value.sv[2].is_symbol)
          baseOfSource->VV.U5.deltaF = TWOPI * getSymbolValueByName(b->value.sv[2].sName);
        else
          baseOfSource->VV.U5.deltaF = TWOPI * b->value.UU.x[2];
          
        if (b->value.sv[3].is_symbol)
          baseOfSource->VV.U5.noFreq = (long) floor(getSymbolValueByName(b->value.sv[3].sName) + 0.5);
        else
          baseOfSource->VV.U5.noFreq = (long) floor(b->value.UU.x[3] + 0.5);
    
      } else if (!strncmp(b->cname, "DC", sizeof(nameString))) {
        baseOfSource->signal = dc;
		if (b->value.sv[0].is_symbol)
		  baseOfSource->VV.A = getSymbolValueByName(b->value.sv[0].sName);
		else
          baseOfSource->VV.A = b->value.UU.x[0];

      } else if (!strncmp(b->cname, "IMPULSE", sizeof(nameString))) {
        baseOfSource->signal = impulse;
        if (b->value.sv[0].is_symbol)
          baseOfSource->VV.A = getSymbolValueByName(b->value.sv[0].sName);
        else
          baseOfSource->VV.A = b->value.UU.x[0];
        
      } else if (!strncmp(b->cname, "STDIN", sizeof(nameString))) {
        baseOfSource->signal = fromStdin;
        terminate_on_eof = TRUE;
        }
      else if (!strncmp(b->cname, "FILE", sizeof(nameString))) {
        baseOfSource->signal = fromFile;
        terminate_on_eof = TRUE;
        baseOfSource->VV.U7.FilePtr = fopen(&(b->value.UU.w[0]),"r");
        if (baseOfSource->VV.U7.FilePtr == 0)
          errorReport(ERROR_INPUT_FILE_NOT_FOUND,&(b->value.UU.w[0]),ERR_VOID,0);

      } else if (!strncmp(b->cname, "RND", sizeof(nameString))) {
        baseOfSource->signal = rndm;
        if (b->value.sv[0].is_symbol)
          baseOfSource->VV.L = getSymbolValueByName(b->value.sv[0].sName);
        else
          baseOfSource->VV.L = b->value.UU.x[0];



      } else if (!strncmp(b->cname, "PULSE", sizeof(nameString))) {
        baseOfSource->signal = pulse;
        
          
        if (b->value.sv[0].is_symbol)
          baseOfSource->VV.U3.unpls = getSymbolValueByName(b->value.sv[0].sName);
        else
          baseOfSource->VV.U3.unpls = b->value.UU.x[0];
    
        if (b->value.sv[1].is_symbol)
          baseOfSource->VV.U3.pls = getSymbolValueByName(b->value.sv[1].sName);
        else
          baseOfSource->VV.U3.pls = b->value.UU.x[1];
          
        if (b->value.sv[2].is_symbol)
          baseOfSource->VV.U3.T = getSymbolValueByName(b->value.sv[2].sName);
        else
          baseOfSource->VV.U3.T = b->value.UU.x[2];
          
        if (b->value.sv[3].is_symbol)
          baseOfSource->VV.U3.td = getSymbolValueByName(b->value.sv[3].sName);
        else
          baseOfSource->VV.U3.td = b->value.UU.x[3];
          
        if (b->value.sv[4].is_symbol)
          baseOfSource->VV.U3.tr = getSymbolValueByName(b->value.sv[4].sName);
        else
          baseOfSource->VV.U3.tr = b->value.UU.x[4];
          
        if (b->value.sv[5].is_symbol)
          baseOfSource->VV.U3.tp = getSymbolValueByName(b->value.sv[5].sName);
        else
          baseOfSource->VV.U3.tp = b->value.UU.x[5];
          
        if (b->value.sv[6].is_symbol)
          baseOfSource->VV.U3.tf = getSymbolValueByName(b->value.sv[6].sName);
        else
          baseOfSource->VV.U3.tf = b->value.UU.x[6];

        WITH = baseOfSource;
        if (WITH->VV.U3.tr != 0)
          WITH->VV.U3.mr = (WITH->VV.U3.pls - WITH->VV.U3.unpls) / WITH->VV.U3.tr;
        if (WITH->VV.U3.tf != 0)
          /* was mf ... since Pascal ... RdH */
          WITH->VV.U3.mf = (WITH->VV.U3.unpls - WITH->VV.U3.pls) / WITH->VV.U3.tf;
      } else
        errorReport(ERROR_UNRESOLVED_SOURCE, progName, ERR_VOID, 0);
      baseOfSource->branch = b;
      i = b->ID.UU.n[0];
      baseOfSource->value = &vv_s[i];
    }
    b = b->next;
  }
  /* RdH Modified the following:
      the line:
  dummy := seed(wallclock);

      was changed to

  dummy := 0;

      the current compiler / system does not recognize neither the
      seed function, or the "wallclock" variable.....
      I must look into this more.
   */
  dummy = 0;
}



void RunSources()
{
  char dead_char;		/* RdH */
  sourceRec *tmpS;
  double tmp;
  long i, FORLIM;
  
  double t;			

  tmpS = baseOfSource;
  while (tmpS != NULL) {
    switch (tmpS->signal) {

    case sinusoid:
      *tmpS->value = tmpS->VV.U0.amp *
                     sin(tmpS->VV.U0.freq * (The_Time - tmpS->VV.U0.dly));
      break;

    case comb:
      tmp = sin(tmpS->VV.U5.freq0 * The_Time);
      FORLIM = tmpS->VV.U5.noFreq;
      for (i = 2; i <= FORLIM; i++)
        tmp += sin((tmpS->VV.U5.freq0 + i * tmpS->VV.U5.deltaF) * The_Time);
      *tmpS->value = tmpS->VV.U5.amp0 * tmp;
      break;

    case dc:
      *tmpS->value = tmpS->VV.A;
      break;

    case impulse:
      if (The_Time == 0)
        *tmpS->value = tmpS->VV.A;
      else
        *tmpS->value = 0.0;
      break;

    case fromStdin:
      if (!P_eof(stdin)) {
        scanf("%lg%*[^\n]", tmpS->value);
        dead_char = getchar();
        }
      if (P_eof(stdin))
        terminate = TRUE;
      break;

    case fromFile:
      if (!feof(tmpS->VV.U7.FilePtr)) {
        fscanf(tmpS->VV.U7.FilePtr,"%lg%*[^\n]", tmpS->value);
        }
      if (feof(tmpS->VV.U7.FilePtr))
        terminate = TRUE;
      break;

    case pulse:
      t = The_Time - floor(The_Time / tmpS->VV.U3.T) * tmpS->VV.U3.T;
      if (t < tmpS->VV.U3.td)
        *tmpS->value = tmpS->VV.U3.unpls;
      else if (t >= tmpS->VV.U3.td + tmpS->VV.U3.tr + tmpS->VV.U3.tp + tmpS->VV.U3.tf)
        *tmpS->value = tmpS->VV.U3.unpls;
      else if (t >= tmpS->VV.U3.td + tmpS->VV.U3.tr &&
               t < tmpS->VV.U3.td + tmpS->VV.U3.tr + tmpS->VV.U3.tp)
        *tmpS->value = tmpS->VV.U3.pls;
      else if (t >= tmpS->VV.U3.td &&
               t < tmpS->VV.U3.td + tmpS->VV.U3.tr)
        *tmpS->value = (t - tmpS->VV.U3.td) * tmpS->VV.U3.mr +
                       tmpS->VV.U3.unpls;
      else if (t >= tmpS->VV.U3.td + tmpS->VV.U3.tr + tmpS->VV.U3.tp &&
               t <
               tmpS->VV.U3.td + tmpS->VV.U3.tr + tmpS->VV.U3.tp + tmpS->VV.U3.tf)
        *tmpS->value = (t - tmpS->VV.U3.td - tmpS->VV.U3.tr - tmpS->VV.U3.tp)
             * tmpS->VV.U3.mf + tmpS->VV.U3.pls;
      break;

    case rndm:
      *tmpS->value = gck_random() * tmpS->VV.L;
      break;
    }

    tmpS = tmpS->next;
  }
}


/************** VCVS **************/
void MakeVCVS(b)
branchRec **b;
{
  newBranch(b, 5L, 1L);
  (*b)->element = vcvs;
}


void readVCVS(l)
char *l;
{
  /*EXXXX  N+  N-  NC+  NC-  VALUE*/
  branchRec *b;

  MakeVCVS(&b);
  read4NodeValue(&b, l);
}


/************** VCCS **************/
void MakeVCCS(b)
branchRec **b;
{
  newBranch(b, 5L, 1L);
  (*b)->element = vccs;
}


void readVCCS(l)
char *l;
{
  /*GXXXX  N+  N-  NC+  NC-  VALUE*/
  branchRec *b;

  MakeVCCS(&b);
  read4NodeValue(&b, l);
}


/************** CCVS **************/
void MakeCCVS(b)
branchRec **b;
{
  newBranch(b, 4L, 1L);
  (*b)->element = ccvs;		/* OH CRAP ? A BUG ? RdH Was "vccs" */
}


void readCCVS(l)
char *l;
{
  /*HYYY  N+  N-  CONTROL_NAME  VALUE*/
  aWord tmp;
  branchRec *b;

  MakeCCVS(&b);
  read2NodeName(&b, l);
  GetWORD(tmp,5L);
  if (isalpha(tmp[0]))
    b->value.UU.x[0] = parseSymbol(&b,0,5L);
  else
    b->value.UU.x[0] = gck_atod(tmp);

  
  
}


/************** CCCS **************/
void MakeCCCS(b)
branchRec **b;
{
  newBranch(b, 4L, 1L);
  (*b)->element = cccs;
}


void readCCCS(l)
char *l;
{
  /*FYYY  N+  N-  CONTROL_NAME  VALUE*/
  aWord tmp;
  branchRec *b;

  MakeCCCS(&b);
  read2NodeName(&b, l);
  GetWORD(tmp,5L);
  
  if (isalpha(tmp[0]))
    b->value.UU.x[0] = parseSymbol(&b,0,5L);
  else
    b->value.UU.x[0] = gck_atod(tmp);

}


/************** Switch **************/
void MakeSwitch(b)
branchRec **b;
{	/* value points to a clock sequence */
  newBranch(b, 3L, 1L);   /* was 0L on 3rd parameter...3 Mar 92 RdH */
  (*b)->element = switch_;
}


void readSwitch(l)
char *l;
{
  /*SXXXX  N+  N-  CLOCK_NAME*/
  branchRec *b;

  MakeSwitch(&b);
  read2NodeName(&b, l);
}


void SetUpClock(b)
branchRec **b;
{
  clockRec *clk;
  
  GetClockByName(&clk, (*b)->cname);
  (*b)->value = clk->value;
}


void SetUpModel(b)
branchRec **b;
{
  modelRec *mdl;

  GetModelByName(&mdl, (*b)->cname);
  (*b)->value = mdl->value;
}


/************** Opamp **************/
void MakeOpamp(b)
branchRec **b;
{
  newBranch(b, 5L, 1L);	/* was 0L on 3rd parameter...3 Mar 92 RdH */
  /*	
  	value_1 = gain,
  	value_2 = slew rate		a special case of vcvs
  */
  (*b)->element = opamp;
}


void readOpamp(l)
char *l;
{
  /*OXXXX  N+  N-  NC+  NC-  MODEL_NAME*/
  branchRec *b;

  MakeOpamp(&b);
  read4NodeName(&b, l);
}


void RunOpamp(op)
nonlinRec **op;
{
  double tmp1, tmp2, sr;

  sr = (*op)->branch->value.UU.x[1] * deltaT;
  tmp1 = *(*op)->out1 - *GND - (*op)->xdata1;
  tmp2 = *(*op)->out2 - *GND - (*op)->xdata2;
  *(*op)->src = 0.0;
  if (fabs(tmp1) > sr) {
    if (tmp1 > 0)
      *(*op)->out1 = (*op)->xdata1 + sr;
    else
      *(*op)->out1 = (*op)->xdata1 - sr;
  }
  if (fabs(tmp2) > sr) {
    if (tmp2 > 0)
      *(*op)->out2 = (*op)->xdata2 + sr;
    else
      *(*op)->out2 = (*op)->xdata2 - sr;
  }
  (*op)->xdata1 = *(*op)->out1;
  (*op)->xdata2 = *(*op)->out2;
}


/************** Quantizer **************/
void MakeQuantizer(b)
branchRec **b;
{	/* upper threshold and output level */
  newBranch(b, 5L, 1L);	/* was 0L on 3rd parameter...3 Mar 92 RdH */
  (*b)->element = quantizer;
}


void readQuantizer(l)
char *l;
{
  /*QXXXX  N+  N-  NC+  NC-  MODEL_NAME*/
  branchRec *b;

  MakeQuantizer(&b);
  read4NodeName(&b, l);
}


void RunQuantizer(qt)
nonlinRec **qt;
{
  double tmpIn;
  boolean done;
  long i;

  tmpIn = *(*qt)->in1 - *(*qt)->in2;
  i = 1;
  done = FALSE;
  while (!done && i <= (*qt)->branch->value.dim) {
    if (tmpIn >= (*qt)->branch->value.UU.x[i - 1])
      done = TRUE;
    i++;
    if (i > (*qt)->branch->value.dim)
      errorReport(ERROR_QUANTIZER, (*qt)->branch->name, ERR_VOID, 0);
    if (done)
      *(*qt)->src = (*qt)->branch->value.UU.x[i - 1];
  }
}


/************* General Nonlinear Stuff ****************/
void MakeNonlinList()
{
  /*goes through the completed branch list to find nonlinear elements*/
  nonlinRec *tmpNonlin;
  branchRec *tmpBranch;
  modelRec *tmpModel;

  tmpBranch = baseOfBranch;
  while (tmpBranch != NULL) {
    switch (tmpBranch->element) {

    case opamp:
      if (tmpBranch->value.dim > 1) {
        tmpNonlin = (nonlinRec *)c_malloc(sizeof(nonlinRec));
        GetModelByName(&tmpModel, tmpBranch->cname);
        tmpBranch->value.dim = tmpModel->value.dim;
 
        /* op amp gain */
        if (tmpModel->value.sv[0].is_symbol)
          tmpBranch->value.UU.x[0] = getSymbolValueByName(tmpModel->value.sv[0].sName);
        else
          tmpBranch->value.UU.x[0] = tmpModel->value.UU.x[0];
          
        /* slew rate */
        if (tmpModel->value.sv[0].is_symbol)
          tmpBranch->value.UU.x[1] = getSymbolValueByName(tmpModel->value.sv[1].sName);
        else
          tmpBranch->value.UU.x[1] = tmpModel->value.UU.x[1];

        tmpNonlin->branch = tmpBranch;
        tmpNonlin->next = baseOfNonlin;
        baseOfNonlin = tmpNonlin;
      }
      break;

    case quantizer:
      tmpNonlin = (nonlinRec *)c_malloc(sizeof(nonlinRec));
      GetModelByName(&tmpModel, tmpBranch->cname);
      tmpBranch->value.dim = tmpModel->value.dim;
      /* might have to fix ... RdH */
      tmpBranch->value.UU.x = tmpModel->value.UU.x;
      tmpNonlin->branch = tmpBranch;
      tmpNonlin->next = baseOfNonlin;
      baseOfNonlin = tmpNonlin;
      /* var_vector_s[tmpBranch->ID.UU.n[0]] = (double *)c_malloc(sizeof(double)); */
      /* call is redundant now ... RdH 1 Mar 92 */
      break;
    }
    tmpBranch = tmpBranch->next;
  }
}


void SetUpNonlins()
{
  nonlinRec *tmpNon;
  long bn, n1, n2, nc1, nc2;

  tmpNon = baseOfNonlin;
  while (tmpNon != NULL) {
    bn = tmpNon->branch->ID.UU.n[0];
    n1 = tmpNon->branch->ID.UU.n[1];
    n2 = tmpNon->branch->ID.UU.n[2];
    nc1 = tmpNon->branch->ID.UU.n[3];
    nc2 = tmpNon->branch->ID.UU.n[4];

    tmpNon->src = &vv_s[bn];

    tmpNon->out1 = &vv_x[n1];
    tmpNon->out2 = &vv_x[n2];
    tmpNon->in1 =  &vv_x[nc1];
    tmpNon->in2 =  &vv_x[nc2];
    tmpNon = tmpNon->next;
  }
}


void RunNonlins()
{
  nonlinRec *tmpN;

  tmpN = baseOfNonlin;
  while (tmpN != NULL) {
    switch (tmpN->branch->element) {

    case opamp:
      RunOpamp(&tmpN);
      break;

    case quantizer:
      RunQuantizer(&tmpN);
      break;
    }
    tmpN = tmpN->next;
  }
}


/********** Digital Stuff **********/
/************** Delay **************/
void MakeDelay(b)
branchRec **b;
{
  newBranch(b, 5L, 1L);
  (*b)->element = delay;
}


void readDelay(l)
char *l;
{
  /*@DXXXX  N_OUT  N_IN  NO_OF_TICKS_OF_DELAY*/
  branchRec *b;
  long nr;
  aWord tmpW;

  MakeDelay(&b);
  read2NodeValue(&b, l);
  b->ID.UU.n[3] = b->ID.UU.n[2];
  b->ID.UU.n[2] = 0;
  b->ID.UU.n[4] = 0;
  b->value.UU.x[0] = 0.0;
  GetWORD(tmpW,4L);
  if (isalpha(tmpW[0])) {
     nr = (long) parseSymbol(&b,0,4L);
    }
  else
    nr = atol(tmpW);
  if (nr <= 0)
    errorReport(ERROR_DELAY_ZERO, b->name, ERR_VOID, 0);
  b->value.dim = nr;
  b->value.UU.c = c_malloc(sizeof(double) * nr);
}


void SetUpDelay(dl)
digitalRec **dl;
{
  long bn, nc1;
  long new_size;
  long counter;

  /* get new dimension from symbol */
  if ((*dl)->branch->value.sv[0].is_symbol) {
    new_size = (long) (*dl)->branch->value.sv[0].delay;
    /* reallocate size */
    if (new_size != (*dl)->branch->value.dim) {
      (*dl)->branch->value.UU.c =
      	realloc((*dl)->branch->value.UU.c,sizeof(double) * new_size); 
      if ((*dl)->branch->value.UU.c == NULL)
        errorReport(ERROR_REALLOC_DELAY,0,ERR_VOID,0);
        
      /* causes realloc to "calloc" new region */
      for (counter = (*dl)->branch->value.dim; counter < new_size; counter++)
        (*dl)->branch->value.UU.x[counter] = (double) 0.0;
      (*dl)->branch->value.dim = new_size;
      }
    }
  bn = (*dl)->branch->ID.UU.n[0];
  nc1 = (*dl)->branch->ID.UU.n[3];
  (*dl)->out1 = &vv_s[bn];
  if (nc1 == 0)
    (*dl)->in1 = GND;
  else
    (*dl)->in1 = &vv_x[nc1];
}


void RunDelay(dl)
digitalRec **dl;
{
  long i;

  for (i = (*dl)->branch->value.dim; i >= 2; i--)
    (*dl)->branch->value.UU.x[i - 1] = (*dl)->branch->value.UU.x[i - 2];
  (*dl)->branch->value.UU.x[0] = *(*dl)->in1;
  *(*dl)->out1 = (*dl)->branch->value.UU.x[(*dl)->branch->value.dim - 1];
}


/************** Adder **************/
void MakeAdder(b)
branchRec **b;
{
  newBranch(b, 5L, 2L);
  (*b)->element = adder;
}


void readAdder(l)
char *l;
{
  /*@AXXXX  N_OUT  N_IN1  N_IN2  VAL_1  VAL_2*/
  branchRec *b;
  aWord tmp;
  long i;
  aWord TEMP,T2;

  long position, symbol_count, loop;

  MakeAdder(&b);
  GetWORD(tmp,1L);
  strcpy(b->name,tmp);
  b->ID.UU.n[0] = branchID();
  b->ID.UU.n[1] = nodeID(GetWORD(TEMP,2L));
  b->ID.UU.n[2] = 0;
  b->ID.UU.n[3] = nodeID(GetWORD(TEMP,3L));
  b->ID.UU.n[4] = nodeID(GetWORD(TEMP,4L));
   
  position = 5;
  symbol_count = 0;
  for (loop = 0; loop < 2; loop++) {
    GetWORD(T2,position);
    if (isalpha(T2[0])) {
      symbol_count++;
      b->value.UU.x[loop] = parseSymbol(&b,loop,position++);
      }
    else
      b->value.UU.x[loop] = gck_atod(T2);
    position++;
    }
  if (rcard.word_count < (6 + symbol_count)) 
    errorReport(ERROR_ADDER_CARD_BROKEN,0,ERR_VOID,0);

  b->next = baseOfBranch;
  baseOfBranch = b;
}


/************** Multiplier **************/
void MakeMult(b)
branchRec **b;
{
  newBranch(b, 5L, 2L);
  (*b)->element = multiplier;
}


void readMult(l)
char *l;
{
  /*@MXXXX  N_OUT  N_IN1  N_IN2*/
  branchRec *b;
  aWord tmp;
  long i;
  aWord TEMP;

  MakeMult(&b);
  GetWORD(tmp,1L);
  strcpy(b->name,tmp);
  b->ID.UU.n[0] = branchID();
  b->ID.UU.n[1] = nodeID(GetWORD(TEMP,2L));
  b->ID.UU.n[2] = 0;
  b->ID.UU.n[3] = nodeID(GetWORD(TEMP,3L));
  b->ID.UU.n[4] = nodeID(GetWORD(TEMP,4L));
  b->next = baseOfBranch;
  baseOfBranch = b;
}


void SetUpMult(mlt)
digitalRec **mlt;
{
  long bn, nc1, nc2;

  bn = (*mlt)->branch->ID.UU.n[0];
  nc1 = (*mlt)->branch->ID.UU.n[3];
  nc2 = (*mlt)->branch->ID.UU.n[4];
  /* var_vector_s[bn] = (double *)c_malloc(sizeof(double)); */
  /* (*mlt)->out1 = var_vector_s[bn]; */
  (*mlt)->out1 = &vv_s[bn];
  if (nc1 == 0)
    (*mlt)->in1 = GND;
  else
    /* (*mlt)->in1 = var_vector_x[nc1]; */
    (*mlt)->in1 = &vv_x[nc1];
  if (nc2 == 0)
    (*mlt)->in2 = GND;
  else
    /* (*mlt)->in2 = var_vector_x[nc2]; */
    (*mlt)->in2 = &vv_x[nc2];
}


void RunMult(mlt)
digitalRec **mlt;
{
  *(*mlt)->out1 = *(*mlt)->in1 * *(*mlt)->in2;
}


void readDigital(l)
char *l;
{
  aWord tmp;

  GetWORD(tmp,1L);
  switch (tmp[1]) {

  case 'D':
    readDelay(l);
    break;

  case 'A':
    readAdder(l);
    break;

  case 'M':
    readMult(l);
    break;

  default:
    errorReport(ERROR_DIGITAL_UNKNOWN, progName, ERR_VOID, 0);
    break;
  }
}


void MakeDigitalList()
{
  digitalRec *tmpDigital;
  branchRec *tmpBranch;

  tmpBranch = baseOfBranch;
  while (tmpBranch != NULL) {
    if (((1L << ((long)tmpBranch->element)) & digitals) != 0) {
      tmpDigital = (digitalRec *)c_malloc(sizeof(digitalRec));
      tmpDigital->branch = tmpBranch;
      tmpDigital->next = baseOfDigital;
      baseOfDigital = tmpDigital;
      }
    tmpBranch = tmpBranch->next;
  }
}


void SetUpDigital()
{
  digitalRec *tmpDigital;

  tmpDigital = baseOfDigital;
  while (tmpDigital != NULL) {
    switch (tmpDigital->branch->element) {

    case delay:
      SetUpDelay(&tmpDigital);
      break;

    case multiplier:
      SetUpMult(&tmpDigital);
      break;
    }
    tmpDigital = tmpDigital->next;
  }
}


void RunDigital()
{
  digitalRec *tmpN;

  tmpN = baseOfDigital;
  while (tmpN != NULL) {
    switch (tmpN->branch->element) {

    case delay:
      RunDelay(&tmpN);
      break;

    case multiplier:
      RunMult(&tmpN);
      break;
    }
    tmpN = tmpN->next;
  }
}


/***********************************************************/
/************* LOGIC ELEMENTS ******************************/
void readLogical(l)
char *l;
{
  /*$YYYY  n_out n_0 n_1 .. n_M <table_name> <0|1> <v_th> <v_low> <v_high>*/
  long i, bn, n_out, nn;
  iArray n_in;
  branchRec *b;
  aWord tmp, TEMP;
  long FORLIM;

  long position;
  long symbol_count;

/* figure out where the '1' or '0' is. */

/* minimum position for this is position 5.  An inverter */
for (position = 6; position < rcard.word_count; position++) {
  if ((strcmp(rcard.WORD[position-1],"1") == 0)
    || (strcmp(rcard.WORD[position-1],"0") == 0)
    || (strcmp(rcard.WORD[position-1],"H") == 0)
    || (strcmp(rcard.WORD[position-1],"L") == 0))
    break;
  }
if (position >= rcard.word_count) 
  errorReport(ERROR_LOGIC_CARD_BROKEN,0,ERR_VOID,0);
  
  GetWORD(tmp,1L);
  b = (branchRec *)c_malloc(sizeof(branchRec));
  strcpy(b->name,tmp);
  b->element = l_general;
  bn = branchID();
  n_out = nodeID(GetWORD(TEMP,2L));
  nn = 1;
  GetWORD(tmp,nn + 2);
  while (nn <= (position - 4)) {
    n_in[nn - 1] = nodeID(tmp);
    nn++;
    GetWORD(tmp,nn + 2);
  }
   
  strcpy(b->cname,tmp);
  /*bn, n_out, GND, nn-1 input nodes -> nn+2 nodes*/
  MakeIDList(&b->ID, nn + 2);
  b->ID.UU.n[0] = bn;
  b->ID.UU.n[1] = n_out;
  b->ID.UU.n[2] = 0;
  FORLIM = b->ID.dim;
  for (i = 4; i <= FORLIM; i++)
    b->ID.UU.n[i - 1] = n_in[i - 4];
  MakeValueList(&b->value, 4L);
  GetWORD(TEMP,nn + 3);
  if ((TEMP[0] == 'H') || (TEMP[0] == '1'))
    b->value.UU.x[0] = 1.0;
  else
    b->value.UU.x[0] = 0.0;
  symbol_count = 0;
  for (i = 2; i <= 4; i++) {
    GetWORD(TEMP,nn + i + 2 + symbol_count);
    if (isalpha(TEMP[0]))
      b->value.UU.x[i - 1] = parseSymbol(&b,i - 1,nn + i + 2 + symbol_count++);
    else
      b->value.UU.x[i - 1] = gck_atod(GetWORD(TEMP,nn + i + 2 + symbol_count));
    }
    
  b->next = baseOfBranch;
  baseOfBranch = b;

}


void readTable(f, firstLine)
FILE **f;
char *firstLine;
{
  /*.TABLE  <table_name>
    01..11
    11..01
    .
    .
   .END*/
  card l;
  aWord tmp;
  nameString tmpName;
  tableRec *tmpTable;
  iArray tmpEntry;
  long i, j, r, FORLIM;

  strcpy(l,firstLine);
  GetWORD(tmp,2L);
  strcpy(tmpName,tmp);
  tmpTable = baseOfTable;
  while (tmpTable != NULL) {
    if (strcmp(tmpTable->name, tmpName) == 0)
      errorReport(ERROR_DUPLICATE_TABLE, tmpName, ERR_VOID, 0);
    else
      tmpTable = tmpTable->next;
  }
  tmpTable = NULL;
  tmpTable = (tableRec *)c_malloc(sizeof(tableRec));
  tmpTable->next = baseOfTable;
  baseOfTable = tmpTable;
  strcpy(baseOfTable->name,tmpName);
  readCard(f, l);
  GetWORD(tmp,1L);
  i = 0;
  while (strncmp(tmp,".END",4) != 0) {
    i++;
    j = 1;
    r = 0;
    while (tmp[j - 1] != NULL_CHAR) {
      if (tmp[j - 1] == '1')
        r += binaryArray[j - 1];
      j++;
    }
    tmpEntry[i - 1] = r;
    readCard(f, l);
    GetWORD(tmp,1L);
  }
  baseOfTable->data.dim = i;
  baseOfTable->data.UU.c = c_malloc(sizeof(long) * i);

  FORLIM = baseOfTable->data.dim;
  for (j = 0; j < FORLIM; j++)
    baseOfTable->data.UU.n[j] = tmpEntry[j];

  
}


void GetTableByName(there, mname)
tableRec **there;
char *mname;
{
  /*Finds the table with name mname in the linked list*/
  boolean found;

  *there = baseOfTable;
  found = FALSE;
  while (*there != NULL && !found) {
    if (strcmp((*there)->name, mname) == 0)
      found = TRUE;
    else
      *there = (*there)->next;
  }
  if (!found)
    errorReport(ERROR_UNRESOLVED_TABLE, mname, ERR_VOID, 0);
}


void MakeLogicalList()
{
  logicRec *tmpLogical;
  branchRec *tmpBranch;
  tableRec *tmpTable;
  long bn;
  long counter;

  tmpBranch = baseOfBranch;
  while (tmpBranch != NULL) {
    if (((1L << ((long)tmpBranch->element)) & logicals) != 0) {
      tmpLogical = (logicRec *)c_malloc(sizeof(logicRec));
      tmpLogical->branch = tmpBranch;
      bn = GetID(tmpLogical->branch->ID, 1L);
      /*if (var_vector_s[bn] == NULL)
        var_vector_s[bn] = (double *)c_malloc(sizeof(double)); */
      /* changed dramatically */
      if (bn > NoOfVars) 
        errorReport(ERROR_LOGICAL_LIST_COMPILER_ERROR,0,ERR_VOID,0);
        
      tmpLogical->out = &vv_s[bn];
      GetTableByName(&tmpTable, tmpBranch->cname);
      tmpLogical->truthTable = tmpTable->data;
      if (tmpBranch->value.UU.x[0] != 0)
        tmpLogical->default_out = TRUE;
      else
        tmpLogical->default_out = FALSE;
      /* update symbols */
      for (counter = 1; counter <= 3; counter++) 
        if (tmpBranch->value.sv[counter].is_symbol)
          tmpBranch->value.UU.x[counter] = getSymbolValueByName(tmpBranch->value.sv[counter].sName);

      tmpLogical->next = baseOfLogic;
      baseOfLogic = tmpLogical;
    }
    tmpBranch = tmpBranch->next;
  }
}


void RunLogical()
{
  logicRec *tmpL;
  long i, inSig;
  double vth, vout;
  boolean done;
  long FORLIM;

  tmpL = baseOfLogic;
  while (tmpL != NULL) {
    inSig = 0;
    vth = tmpL->branch->value.UU.x[1];
    FORLIM = tmpL->branch->ID.dim;
    for (i = 4; i <= FORLIM; i++) {
      /* if (*var_vector_x[tmpL->branch->ID.UU.n[i - 1]] > vth) */
      if (vv_x[tmpL->branch->ID.UU.n[i - 1]] > vth)
        inSig += binaryArray[i - 4];
    }
    if (tmpL->default_out)
      vout = tmpL->branch->value.UU.x[2];
    else
      vout = tmpL->branch->value.UU.x[3];
    i = 1;
    done = FALSE;
    while (i <= tmpL->truthTable.dim && !done) {
      if (inSig == tmpL->truthTable.UU.n[i - 1]) {
        done = TRUE;
        if (tmpL->default_out)
          vout = tmpL->branch->value.UU.x[3];
        else
          vout = tmpL->branch->value.UU.x[2];
      }
      i++;
    }
    *tmpL->out = vout;
    tmpL = tmpL->next;
  }
}


/************* Building of the system matrices ******************/
void SetUpCircuit()
{
  branchRec *b;

  dsymbol_base(); 
  b = baseOfBranch;
  while (b != NULL) {
    if (b->element == subckt) {
      substituteSubckt(&b);
      }
    expandSymbols(&b);
    b = b->next;
  }
  b = baseOfBranch;
  while (b != NULL) {
    switch (b->element) {

    case switch_:
      SetUpClock(&b);
      break;

    case opamp:
    case quantizer:
      SetUpModel(&b);
      break;
    }
    b = b->next;
  }
  
  /* update symbols for step, period, time */
  if (deltaT_sv.is_symbol)
    deltaT = getSymbolValueByName(deltaT_sv.sName);
    
  if (periodT_sv.is_symbol)
    periodT = getSymbolValueByName(periodT_sv.sName);
    
  if (lastTime_sv.is_symbol)
    lastTime = getSymbolValueByName(lastTime_sv.sName);
  
  if (periodT > 0)
    deltaT = periodT / NoOfTicks;
}


 char *componentType_NAMES[] = {
  "RESISTOR", "CAPACITOR", "INDUCTOR", "SWITCH", "VS", "CS",
  "COUPLEDINDUCTOR", "VCSW", "VCVS", "VCCS", "CCVS", "CCCS", "OPAMP",
  "COMPARATOR", "QUANTIZER", "SUBCKT", "DELAY", "ADDER", "MULTIPLIER",
  "L_GENERAL"
} ;

/* RdH Prototype for Diagnostic Changed, due to new memory management
 * system for M, N, and B....It appears this is just debug code anyways.
 */
void Diagnostic()
/* double (*M)[], (*N)[], (*B)[]; */
{
  long i, j;
  /* RdH ... Due to case insensitivity, the variable b: branchPtr is replaced
   with bptr...removes collisions! */
  branchRec *bptr;
  float v;
  long FORLIM, FORLIM1;

  fprintf(stderr,"M = \n");
  FORLIM = NoOfVars;
  for (i = 0; i < FORLIM; i++) {
    FORLIM1 = NoOfVars;
    for (j = 0; j < FORLIM1; j++) {
      v = M[i][j];
      if (v != (double) 0.0) /* RdH */
        fprintf(stderr,"% .5E%c", v, TAB_CHAR);
    }
    fprintf(stderr,"\n");
  }
  fprintf(stderr,"\nN = \n");
  FORLIM = NoOfVars;
  for (i = 0; i < FORLIM; i++) {
    FORLIM1 = NoOfVars;
    for (j = 0; j < FORLIM1; j++) {
      v = N[i][j];
      if (v != (double) 0.0) /* RdH */
        fprintf(stderr,"% .5E%c", v, TAB_CHAR);
    }
    fprintf(stderr,"\n");
  }
  fprintf(stderr,"\nB = \n");
  FORLIM = NoOfVars;
  for (i = 0; i < FORLIM; i++) {
    FORLIM1 = NoOfVars;
    for (j = 0; j < FORLIM1; j++) {
      v = B[i][j];
      if (v != (double) 0.0) /* RdH */
        fprintf(stderr,"% .5E%c", v, TAB_CHAR);
    }
    fprintf(stderr,"\n");
  }
  bptr = baseOfBranch;
  while (bptr != NULL) {
    fprintf(stderr,"Branch : %.8s\n", bptr->name);
    fprintf(stderr,"  Type     : %s\n", componentType_NAMES[(long)bptr->element]);
    fprintf(stderr,"  Branch no: %12ld\n", GetID(bptr->ID, 1L));
    fprintf(stderr,"  Pos. node: %12ld\n", GetID(bptr->ID, 2L));
    fprintf(stderr,"  Neg. node: %12ld\n", GetID(bptr->ID, 3L));
    bptr = bptr->next;
  }

}



void SetUpVariables()
{
  long i, FORLIM;
  
  FORLIM = NoOfVars;
  vv_x = (double *) c_malloc((NoOfVars + 1) * sizeof(double));
  for (i = 1; i <= FORLIM; i++) {
    vv_x[i] = 0.0;
    }
  vv_x[0] = *GND;

}

void RunSystem(ps)
systemRec **ps;
{
  long i, j;
  /* sysVector y; 1 Mar 92 RdH */
  double *y;
  double N_i_j, B_i_j;
  long FORLIM, FORLIM1;

  y = (double *) c_malloc(NoOfVars * sizeof(double));

  FORLIM = NoOfVars;
  for (i = 0; i < FORLIM; i++) {
    y[i] = 0.0;
    FORLIM1 = NoOfVars;
    for (j = 0; j < FORLIM1; j++) {
      N_i_j = (*ps)->N[i][j];
      if (N_i_j != 0)
        y[i] += N_i_j * vv_x[j + 1];
    }
    FORLIM1 = NoOfVars;
    for (j = 0; j < FORLIM1; j++) {
      B_i_j = (*ps)->B[i][j];
      if (B_i_j != 0)
        y[i] += B_i_j * vv_s[j + 1];
    }
  }
  FORLIM = NoOfVars;
  for (i = 1; i <= FORLIM; i++)
    vv_x[i] = y[i - 1];

  free(y); /* RdH 1 Mar 92 */
}


/***** Reading the input file *****/
void readInputFile()
{
  card l;
  aWord tmp;

  strcpy(tmp,rfile.filename);
  strcat(tmp,".gck");

  object_stamp = FileAge(tmp);

  if (object_stamp == 0)
    up_to_date = FALSE;

  if (FileAge(rfile.filename) > object_stamp)
    up_to_date = FALSE;
  
  do {
  do {
    readCard(&(rfile.filePtr[rfile.depth]), l);

    GetWORD(tmp,1L);
    switch (tmp[0]) {

    case 'C':		readCapacitor(l);		break;
    case 'L':		readInductor(l);		break;
    case 'R':		readResistor(l);		break;
    case 'O':		readOpamp(l);			break;
    case 'Q':		readQuantizer(l);		break;
    case 'S':		readSwitch(l);			break;
    case 'V':
    case 'I':
      readSource(l);
      break;
    case 'E':		readVCVS(l);			break;
    case 'G':		readVCCS(l);			break;
    case 'H':		readCCVS(l);			break;
    case 'F':		readCCCS(l);			break;
    case 'X':		readXCard(l);			break;
    case '@':		readDigital(l);			break;
    case '$':		readLogical(l);			break;

    case '.':
      if ((strncmp(tmp,".LIB",4) == 0) || (strncmp(tmp,".INC",4) == 0))
        readLibrary();
      else if ((strncmp(tmp,".DEF",4) == 0) || (strncmp(tmp,".SYM",4) == 0))
        readSymbolDef();
      else if (strncmp(tmp,".CLOCK",6) == 0)
        readClock(l);
      else if (strncmp(tmp,".NODE",5) == 0)
        readNode(l);
      else if (strncmp(tmp,".MODEL",6) == 0)
        readModelSection(&(rfile.filePtr[rfile.depth]), l);
      else if (strncmp(tmp,".SUBCKT",7) == 0)
        openSubckt(l);
      else if (strncmp(tmp,".ENDSUB",7) == 0)
        closeSubckt(l);
      else if (strncmp(tmp,".PRINT",6) == 0)
        readPrint(l);
      else if (strncmp(tmp,".LPRINT",7) == 0) {
        shortPrint = FALSE;
        readPrint(l);
      } else if (strncmp(tmp,".NPRINT",7) == 0) {
        shortPrint = TRUE;
        timePrint = FALSE;
        readPrint(l);
      } else if (strncmp(tmp,".NLPRINT",8) == 0) {
        shortPrint = FALSE;
        timePrint = FALSE;
        readPrint(l);
      } else if (strncmp(tmp,".FFT",4) == 0) {
        readFFT();
      } else if (strncmp(tmp,".TIME",5) == 0)
        readTime(l);
      else if (strncmp(tmp,".SAMPLE",7) == 0)
        readSample(l);
      else if (strncmp(tmp,".STEP",5) == 0)
        readTimeStep(l);
      else if (strncmp(tmp,".PERIOD",7) == 0)
        readClockPeriod(l);
      else if (strncmp(tmp,".TABLE",6) == 0)
        readTable(&(rfile.filePtr[rfile.depth]), l);
      else if (strncmp(tmp,".DIAGNOSE",9) == 0) {
        runDiag = TRUE;

      }
      break;

    case '*':
    case '#':
      /* blank case */
      break;
    }
  } while (!P_eof(rfile.filePtr[rfile.depth]));
  fclose(rfile.filePtr[rfile.depth]);
  if (rfile.depth >= 0)
    rfile.depth--;
  } while (rfile.depth >= 0);
}

void exit_now()
{
/* place handlers for closing all possibly open files */

  exit(EXIT_SUCCESS);
}





These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.