%{
/* SccsId = "@(#)cmd_y.y 3.4 (TU-Delft) 11/23/92" */
/**********************************************************

Name/Version      : nspice/3.4

Language          : C
Operating system  : UNIX SYSTEM V
Host machine      : HP9000

Author(s)         : A.J. van Genderen
Creation date     : 8-June-1990
Modified by       :
Modification date :


        Delft University of Technology
        Department of Electrical Engineering
        Network Theory Section
        Mekelweg 4 - P.O.Box 5031
        2600 GA DELFT
        The Netherlands

        Phone : 015 - 786234

        COPYRIGHT (C) 1990 , All rights reserved
**********************************************************/

/* This file is a copy from sls but it has been stripped and modified */

/* SccsId = "@(#)cmd_y.y 3.7 (TU-Delft) 8/9/88" */
/**********************************************************

Name/Version      : sls/3.7

Language          : C
Operating system  : UNIX SYSTEM V
Host machine      : HP9000

Author(s)         : A.C. de Graaf, A.J. van Genderen
Creation date     : 10-Jul-1986
Modified by       : S. de Graaf
Modification date : 10-Jul-1986


        Delft University of Technology
        Department of Electrical Engineering
        Network Theory Section
        Mekelweg 4 - P.O.Box 5031
        2600 GA DELFT
        The Netherlands

        Phone : 015 - 786234

        COPYRIGHT (C) 1986 , All rights reserved
**********************************************************/
#include <stdio.h>
#include "define.h"
#include "type.h"

#define  TRUE   1
#define  FALSE  0

#define  MAXHIERAR        22
#define  MAXSTACKLENGTH  100

char name_space[128];   /* memory space for a name */

PATH_SPEC  pathspace[MAXHIERAR];  /* memory space for paths */
PATH_SPEC * fullpath;         /* first of the current full path specification */
PATH_SPEC * last_path = NULL;  /* last of the current full path specification */

STRING_REF * begin_str_list;
STRING_REF * end_str_list;

int sigcon;                /* boolean flag */

SIGNALELEMENT * sgn;
short lastval;
int * len_sp;
int len_stack[MAXSTACKLENGTH];
SIGNALELEMENT ** sgn_sp;
SIGNALELEMENT * sgn_stack[MAXSTACKLENGTH];

SIGNALELEMENT * copysgn ();

struct node *Begin_node;
struct node *End_node;

char *fn_cmd;

int sigendless;
int simperiod;
int sig_toffset;
int simlevel;
double sigtimeunit;
double outaccur;

double atof ();
STRING_REF * names_from_path ();

struct node_ref *Begin_print;
struct node_ref *End_print;

STRING_REF * str_list_el;

#ifdef YYBISON
extern char *yytext;
#endif

%}

%union		{
		    int ival;
		    int *pival;
		    char *sval;
		    char **psval;
		    double dval;
		    double *pdval;
		    struct signalelement *signal;
		    struct path_spec *pathsp;
		}

%token 		SET TILDE FROM FILL WITH PRINT PLOT OPTION SIMPERIOD DUMP AT 
%token 		DISSIPATION INITIALIZE SIGOFFSET RACES DEVICES STATISTICS 
%token 		ONLY CHANGES SLS_PROCESS SIGUNIT OUTUNIT OUTACC MAXPAGEWIDTH
%token 		MAXNVICIN MAXTVICIN MAXLDEPTH VH VMAXL VMINH
%token		TDEVMIN TDEVMAX STEP DISPERIOD
%token		DOT DOTDOT LPS RPS LSB RSB LCB RCB EQL
%token 		COMMA SEMICOLON COLON MULT EXCLAM NEWLINE
%token <ival>	LEVEL TOGGLE
%token <sval>	IDENTIFIER INT STRING
%token <dval>	POWER_TEN F_FLO 

%type  <ival>	duration index integer
%type  <dval>	pow_ten f_float
%type  <pival>	int_option
%type  <pdval>	pow_ten_option f_float_option
%type  <sval>	member_name 
%type  <signal>	value signal_exp value_exp
%type  <pathsp>	ref_item

%%

sim_cmd_list	: sim_cmd 
		| sim_cmd_list sim_cmd 
		;

sim_cmd		: set_cmd eoc
		| print_cmd eoc
		| plot_cmd eoc
		| dump_cmd eoc
		| dissip_cmd eoc
		| init_cmd eoc
		| fill_cmd eoc
		| option_cmd eoc
		| error eoc
		{
		    yyerrok;
		    last_path = NULL;
		}
		| /* empty */ eoc
		;

set_cmd		: SET node_refs EQL signal_exp
		{
		    assignExprToNodes ();

    		    len_sp = len_stack;  /* reset stacks for signal_exp */
    		    sgn_sp = sgn_stack;
		}
		| SET node_refs COLON 
		  node_refs FROM STRING
		;

signal_exp	: value_exp
		{
		    *++len_sp = $1 -> len;
		    $$ = *sgn_sp++ = $1;
		}
		| signal_exp value_exp
		{
		    if ($2 -> len < 0)
		        *len_sp = -1;
		    else
		        *len_sp += $2 -> len;
		    $1 -> sibling = $2;
		    $$ = $2;
		}
		;

value_exp	: value
		{   
		    /* default duration 1 unit */
		    $$ = $1;
		    if ($1 -> child)
		        $$ -> len = $1 -> child -> len;
		    else
		        $$ -> len = 1;
		}
		| value MULT duration
		{
		    $$ = $1;
		    if ($1 -> child)
		        $$ -> len = $1 -> child -> len * $3;
		    else
		        $$ -> len = $3;
		    if (sigcon && $3 < 0)
			sigendless = TRUE;
		}
		;

value		: LEVEL
		{
		    NEW ($$, 1, SIGNALELEMENT);
		    lastval = $$ -> val = $1;
		    sigcon = FALSE;
		}
		| LPS signal_exp RPS 
		{
		    NEW ($$, 1, SIGNALELEMENT);
		    NEW ($$ -> child, 1, SIGNALELEMENT);
		    $$ -> child -> sibling = *--sgn_sp;
		    $$ -> val = $$ -> child -> val = lastval;
		    $$ -> child -> len = *len_sp--;
		    sigcon = TRUE;
		}
		;

duration	: integer
		{
		    $$ = $1;
		}
		| TILDE
		{
		    $$ = -1;
		}
		;

print_cmd	: PRINT 
		  node_refs 
		;

plot_cmd	: PLOT 
		  node_refs 
		{
		    str_list_el = begin_str_list;
		    while (str_list_el) {
			if (Begin_print == NULL) {
			    NEW (Begin_print, 1, struct node_ref);
			    End_print = Begin_print;
			}
			else {
			    NEW (End_print -> next, 1, struct node_ref);
			    End_print = End_print -> next;
			}
			End_print -> name = str_list_el -> str;
			End_print -> next = NULL;
			str_list_el = str_list_el -> next;
		    }
		}
		;

dissip_cmd	: DISSIPATION 
		  dis_node_refs 
		;

dis_node_refs	: node_refs
		| /* empty */
		;

node_refs	: ref_item
		{
		    begin_str_list = NULL;

		    if ($1) {
			if (begin_str_list) {
			    end_str_list -> next 
			      = names_from_path (0, fullpath);
			    while (end_str_list -> next)
				end_str_list = end_str_list -> next;
			}
			else {
			    begin_str_list = 
			    end_str_list = names_from_path (0, fullpath);
			    while (end_str_list -> next)
				end_str_list = end_str_list -> next;
			}
		    }
		}
		| node_refs ref_item
		{
		    if ($2) {
			if (begin_str_list) {
			    end_str_list -> next 
			      = names_from_path (0, fullpath);
			    while (end_str_list -> next)
				end_str_list = end_str_list -> next;
			}
			else {
			    begin_str_list = 
			    end_str_list = names_from_path (0, fullpath);
			    while (end_str_list -> next)
				end_str_list = end_str_list -> next;
			}
		    }
		}
		;

ref_item	: full_node_ref
		{
		    $$ = fullpath;

		    last_path = NULL;  /* for the next call */
		}
		| COMMA
		{
		    $$ = NULL;
		}
		;
		    
full_node_ref 	: member_ref
		| EXCLAM member_ref
		| full_node_ref DOT member_ref
		;

member_ref	: member_name 
		{
		    if (last_path == NULL) {     
			/* this is the leftmost (the first) member of a path */
			last_path = pathspace;
			fullpath = last_path;
		    }
		    else {
			last_path -> next = last_path + 1;
		        last_path = last_path -> next;
		    }
		    last_path -> next = NULL;
		    last_path -> also = NULL;
		    strcpy (last_path -> name, $1); 
		}
		  ref_indices
		;

member_name	: INT
		{
		    strcpy (name_space, $1);   /* copying is necessary */
		    $$ = name_space;
		}
		| IDENTIFIER
		{
		    strcpy (name_space, $1);
		    $$ = name_space;
		}
		| keyword
		{
		    strcpy (name_space, yytext);
		    $$ = name_space;
		}
		;

keyword		: SET
		| LEVEL
		| FROM
		| FILL
		| WITH
		| PRINT
		| PLOT
		| OPTION
		| SIMPERIOD
		| DISPERIOD
		| DISSIPATION
		| DUMP
		| AT
		| INITIALIZE
		| SIGOFFSET
		| RACES
		| DEVICES
		| STATISTICS
		| ONLY
		| CHANGES
		| SLS_PROCESS
		| SIGUNIT
		| OUTUNIT
		| OUTACC
		| MAXPAGEWIDTH
		| MAXNVICIN
		| MAXTVICIN
		| MAXLDEPTH
		| VH
		| VMAXL
		| VMINH
		| TDEVMIN
		| TDEVMAX
		| TOGGLE
		| STEP
		;

ref_indices	: /* empty */
		{
		    last_path -> xarray[0][0] = 0;
		}
		| LSB 
		{
		    last_path -> xarray[0][0] = 0;
		}
		  index_list RSB
		;

index_list	: index
		| index_list COMMA index
		;

index		: integer
		{
		    last_path -> xarray[0][0]++;
		    last_path -> xarray[last_path -> xarray[0][0]][0] = $1;
		    last_path -> xarray[last_path -> xarray[0][0]][1] = $1;
		}
		| integer DOTDOT integer
		{
		    last_path -> xarray[0][0]++;
		    last_path -> xarray[last_path -> xarray[0][0]][0] = $1;
		    last_path -> xarray[last_path -> xarray[0][0]][1] = $3;
		}
		;

option_cmd	: OPTION option 
		| option_cmd option
		;

option		: toggle_option EQL TOGGLE
		| int_option EQL integer
		{
		    if ($1) *$1 = $3;
		}
		| pow_ten_option EQL pow_ten
		{
		    if ($1) *$1 = $3;
		}
		| f_float_option EQL f_float
		{
		    if ($1) *$1 = $3;
		}
		| string_option EQL STRING
		;

toggle_option	: STEP
		| PRINT RACES
		| ONLY CHANGES
		| PRINT DEVICES
		| PRINT STATISTICS
		;

int_option	: SIMPERIOD
		{
		    $$ = &simperiod;
		}
		| DISPERIOD
		{
		    $$ = NULL;
		}
		| MAXNVICIN
		{
		}
		| MAXTVICIN
		{
		    $$ = NULL;
		}
		| MAXLDEPTH
		{
		    $$ = NULL;
		}
		| MAXPAGEWIDTH
		{
		    $$ = NULL;
		}
		| LEVEL
		{
		    $$ = &simlevel;
		}
		| SIGOFFSET
		{
		    $$ = &sig_toffset;
		}
		;

pow_ten_option	: OUTUNIT
		{
		    $$ = NULL;
		}
		| OUTACC
		{
		    $$ = &outaccur;
		}
		;

pow_ten		: INT
		{
		    $$ = atof ($1);
		}
		| POWER_TEN
		{
		    $$ = $1;
		}
		;

f_float_option	: SIGUNIT
		{
		    $$ = &sigtimeunit;
		}
		| VH
		{
		    $$ = NULL;
		}
		| VMAXL
		{
		    $$ = NULL;
		}
		| VMINH
		{
		    $$ = NULL;
		}
		| TDEVMIN
		{
		    $$ = NULL;
		}
		| TDEVMAX
		{
		    $$ = NULL;
		}
		;

f_float		: INT
		{
		    $$ = atof ($1);
		}
		| POWER_TEN
		{
		    $$ = $1;
		}
		| F_FLO
		{
		    $$ = $1;
		}
		;

string_option	: SLS_PROCESS
		;

dump_cmd	: DUMP AT integer
		;

init_cmd	: INITIALIZE FROM STRING
		;

fill_cmd	: FILL full_node_ref WITH
		  fillvals
		;

fillvals	: fillchars
		| fillvals fillchars
		| fillint
		| fillvals fillint
		| fillfloat
		| fillvals fillfloat
		;

fillchars	: STRING
		;

fillint		: integer
		;

fillfloat	: F_FLO
		;

integer		: INT
		{
		    $$ = atoi ($1);
		}
		;

eoc		: SEMICOLON
		| NEWLINE
		;

%%
#include "cmd_l.c"

cmdinits ()
{
    len_sp = len_stack;
    sgn_sp = sgn_stack;

    sigendless = FALSE;
    simperiod = -1;
    sig_toffset = -1;
    sigtimeunit = -1;

    Begin_node = NULL;
    End_node = NULL;
}

yyerror (s)
char *s;
{
    cslserror (s, "");
}

cslserror (s1, s2)
char * s1;
char * s2;
{
    char buf[264];
    int lineno = yylineno;

    if (yychar == NEWLINE)
        lineno--;

    sprintf (buf, "%s, line %d: %s %s\n", fn_cmd, lineno, s1, s2);
    message (buf);
}

SIGNALELEMENT * copysgn (sgn)
SIGNALELEMENT * sgn;
{
    SIGNALELEMENT *newsgn;

    NEW (newsgn, 1, SIGNALELEMENT);
    newsgn -> val = sgn -> val;
    newsgn -> len = sgn -> len;

    if (sgn -> sibling)
	newsgn -> sibling = copysgn (sgn -> sibling);
    if (sgn -> child)
	newsgn -> child = copysgn (sgn -> child);

    return (newsgn);
}

assignExprToNodes ()
{
    STRING_REF *str_ref;
    struct node *n;
    SIGNALELEMENT *sgn;
    SIGNALELEMENT *head, *tail;

    NEW (sgn,1,SIGNALELEMENT);
    sgn -> sibling = *--sgn_sp;
    sgn -> val = lastval;
    sgn -> len = *len_sp;

    str_ref = begin_str_list;
    while (str_ref) {

	/* perform linear search to find node */

	n = Begin_node;
	while (n && strcmp (str_ref -> str, n -> name) != 0) {
	    n = n -> next;
	}

        /* add expression to current expression of node or create new node */

	if (n) {
	    head = tail = n -> expr;
	    if (tail -> len >= 0) {
		while (tail -> sibling) {
		    if (tail == sgn -> sibling) {
			cslserror ("signal multipally connected to same node",
			NULL);
		    }
		    tail = tail -> sibling;
		}
		tail -> sibling = sgn -> sibling;
		if (sgn -> len < 0)
		    head -> len = -1;
		else
		    head -> len += sgn -> len;
		head -> val = sgn -> val;
	    }
	}
	else {
	    NEW (n, 1, struct node);
	    n -> name = str_ref -> str;
	    n -> expr = sgn;
	    n -> next = NULL;
	    if (End_node) {
		End_node -> next = n;
		End_node = n;
	    }
	    else {
		Begin_node = End_node = n;
	    }
	}

	str_ref = str_ref -> next;
    }
}

/*
int isdigit (c)
char c;
{
    if (c >= '0' && c <= '9')
	return (1);
    else
	return (0);
}
*/
