static char *SccsId = "@(#)binfil.c 4.5 (TU-Delft) 07/27/92";
/**********************************************************

Name/Version      : sls/4.5

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 : 15-Jan-1988


        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-1988 , All rights reserved
**********************************************************/
#include "extern.h"

extern DM_PROJECT *dmproject;

binfil () 
{
    int i;
    int j;
    FUNCDESCR FDT;
    FUNCVAR FVT;
    int FDT_cnt;
    int fvx;
    int fvtx;
    long fremember;
    int cnt;
    int l;
    char * p;
    int intval;
    char mark[15];
    DM_STREAM * dsp_bin;
    DM_CELL * model_key;
    PRE_NODE ePRE_N;
    PRE_TRANSISTOR ePRE_T;
    int size;
    struct stat buf;
    int checkBinEndmark ();

    if (monitoring) monitime ("B inbinfile");

    model_key = dmCheckOut (dmproject, netwname, WORKING, 
			    DONTCARE, CIRCUIT, ATTACH);

    if (dmStat (model_key, "sls", &buf) != 0) {
	slserror (NULL, 0, ERROR2, "no binary file for", netwname);
	die (1);
    }
    dsp_bin = dmOpenStream (model_key, "sls", "r");

    if (checkBinEndmark (dsp_bin)) {
	slserror (NULL, 0, ERROR2, "Incompatible binary file for", netwname);
	die (1);
    }
    dmSeek (dsp_bin, (long)0, 0);   /* rewind */

    inint (dsp_bin, &size);
    dmSeek (dsp_bin, (long)size, 1); 

    inint (dsp_bin, &size);
    FDT_cnt = size / sizeof (FUNCDESCR);
    for (i = 0; i < FDT_cnt; i++) {
        fread ((char *)&FDT, sizeof (FUNCDESCR), 1 ,dsp_bin -> dmfp);
        fremember = dmTell (dsp_bin);
        if ((FD[i].help = functype (FDT.name )) < 0)  /* use help as redir */
	    slserror (NULL, 0, ERROR2, FDT.name,
            "is an undefined function in the simulator");
        if (FD[ FD[i].help ].fvx_cnt != FDT.fvx_cnt)
	    slserror (NULL, 0, ERROR2, FDT.name,
            "is not equally defined in network and simulator");
        fvx = FD[ FD[i].help ].fvx;
        fvtx = FDT.fvx;
        if (fvtx >= 0) 
            dmSeek (dsp_bin, 
            (long) (sizeof (int) + fvtx * sizeof (FUNCVAR)), 0);
        for (j = 0; j < FDT.fvx_cnt; j++) {
            fread ((char *)&FVT, sizeof (FUNCVAR), 1 ,dsp_bin -> dmfp);
            if (strcmp (FVT.name, FV[ fvx + j ].name) != 0
            || FVT.type != FV[ fvx + j ].type
            || FVT.ind[0] != FV[ fvx + j ].ind[0]
            || FVT.ind[1] != FV[ fvx + j ].ind[1])
	        slserror (NULL, 0, ERROR2, FDT.name, 
                "is not equally defined in network and simulator");
         }
         dmSeek (dsp_bin, fremember, 0);
    }
            
    intab (dsp_bin, &ST, &ST_cnt, sizeof(char));
    intab (dsp_bin, (char **)&MT, &MT_cnt, sizeof(MODELTABLE));
    intab (dsp_bin, (char **)&NT, &NT_cnt, sizeof(NAMETABLE));
    intab (dsp_bin, (char **)&CTT, &CTT_cnt, sizeof(CONTEXTTABLE));
    intab (dsp_bin, (char **)&MCT, &MCT_cnt, sizeof(MODELCALLTABLE));
    intab (dsp_bin, (char **)&XT, &XT_cnt, sizeof(int));
    intab (dsp_bin, (char **)&XX, &XX_cnt, sizeof(int));

    inint (dsp_bin, &size);
    N_cnt = size / sizeof (PRE_NODE);
    PALLOC (N, N_cnt, NODE);
    for (cnt = 0; cnt < N_cnt; cnt++) {

        inelem (dsp_bin, (char *)&ePRE_N, sizeof (PRE_NODE));

        N[cnt].ntx = ePRE_N.ntx;
        N[cnt].dsx = ePRE_N.dsx;
        N[cnt].cx = ePRE_N.cx;
        N[cnt].statcap = ePRE_N.statcap;
        N[cnt].dyncap = ePRE_N.statcap;
        N[cnt].funcoutp = ePRE_N.funcoutp;
        N[cnt].redirect = ePRE_N.redirect;

        N[cnt].type = Normal; 
        N[cnt].inp = FALSE;
        N[cnt].outp = FALSE;
        N[cnt].breaksig = FALSE;
        N[cnt].linked = FALSE;
        N[cnt].flag = FALSE;
	N[cnt].dissip = FALSE;
        N[cnt].plot = 0;
        N[cnt].print = 0;
        N[cnt].forcedinfo = NULL;
        if (N[cnt].funcoutp)
            N[cnt].type = Forced;
    }

    intab (dsp_bin, (char **)&DS, &DS_cnt, sizeof(int));
    intab (dsp_bin, (char **)&C, &C_cnt, sizeof(CONTROL));

    inint (dsp_bin, &size);
    T_cnt = size / sizeof (PRE_TRANSISTOR);
    PALLOC (T, T_cnt, TRANSISTOR);
    for (cnt = 0; cnt < T_cnt; cnt++) {

        inelem (dsp_bin, (char *)&ePRE_T, sizeof (PRE_TRANSISTOR));

        T[cnt].gate = ePRE_T.gate;
        T[cnt].source = ePRE_T.source;
        T[cnt].drain = ePRE_T.drain;
        T[cnt].type = ePRE_T.type;
        T[cnt].width = ePRE_T.width;
        T[cnt].length = ePRE_T.length;
    }

    intab (dsp_bin, (char **)&F, &F_cnt, sizeof(FUNCTION));
    intab (dsp_bin, (char **)&I, &I_cnt, sizeof(INTERCAP));
    intab (dsp_bin, (char **)&FI, &FI_cnt, sizeof(int));
    intab (dsp_bin, (char **)&FR, &FR_cnt, sizeof(int));
    intab (dsp_bin, (char **)&FO, &FO_cnt, sizeof(FUNCOUT));
    intab (dsp_bin, (char **)&FS, &FS_cnt, sizeof(char));

    dmCloseStream (dsp_bin, COMPLETE);
    dmCheckIn (model_key, COMPLETE);

    for (i =0; i < F_cnt; i++) {
        if (F[i].type < 1000)
            F[i].type = FD[ F[i].type ].help;
    }

    for (p = FS; p - FS < FS_cnt; p++) {
        if (*p == '*') {
            p += SIZE_PTR_INT;
            if ((p - FS) % SIZE_PTR_INT != 0)
                p += SIZE_PTR_INT - ((p - FS) % SIZE_PTR_INT);
            cnt = *(int *)p;  
            p += SIZE_PTR_INT;
            while (cnt-- > 0) {
                intval = *(int *)p; /* intval gives the offset of the pointer */
                *(char **)p = p + intval;
                p += SIZE_PTR_INT;
            }
        }
    }

    if (monitoring) monitime ("E inbinfile");
}

intab (dsp, tabref, cnt, type_size)
DM_STREAM * dsp;
char ** tabref;
int   *cnt, type_size;
{
    int size;

    fread ((char *)&size, sizeof(int), 1, dsp -> dmfp);
    PALLOC (*tabref, size, char);
    fread ((char *)(*tabref), size, 1, dsp -> dmfp);
    *cnt = size / type_size;
}

inint (dsp, var)
DM_STREAM * dsp;
int * var;
{
    fread((char *)var, sizeof(int), 1, dsp -> dmfp);
}

inelem (dsp, elem, type_size)
DM_STREAM * dsp;
char * elem;
int   type_size;
{
    fread (elem, type_size, 1, dsp -> dmfp);
}

int functype (name)
char * name;
{
    int i;

    for (i = 0; i < FD_cnt; i++) {
        if (strcmp (name, FD[i].name) == 0)
            break;
    }

    if (i < FD_cnt)
        return (i);
    else
        return (-1);
}

int checkBinEndmark (dsp)
DM_STREAM *dsp;
{
    BINREF BR;

    dmSeek (dsp, -(long) sizeof (BINREF), 2);
    fread ((char *)&BR, sizeof (BINREF), 1, dsp -> dmfp);

    if (BR.a != 1234
    || BR.b != -1234
    || BR.c != 86
    || BR.d != 0
    || BR.e != -456
    || strcmp (BR.f, "qwertyuiopa") != 0
    || BR.g < 0.99999 || BR.g > 1.00001
    || BR.h < -20.02010 || BR.h > -20.01990
    || BR.i != 5
    || BR.j != 13
    || BR.k != 18
    || BR.l != 255
    || BR.m != 28282)
        return (1);
    else
        return (0);
}

