#include MUT_H 
#include MLO_H 
#include MLU_H
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include "max.h"
#include "erreur.h"
#include "extern.h"
#include "fonc.h"
#include "foncspi.h"

#define	SEEK_CUR	1
#ident "@(#)SPICE<->MBK parser-driver, V607 by Payam KIANI"


/*****************************************************************************/
/*                                                                           */
/*                                   ERREUR                                  */
/*                                                                           */
/*****************************************************************************/
/*                                                                           */
/* Affiche l'mbkspice_erreur rencontree, et exit le programme                */
/*                                                                           */
/* ENTREE : le numero de l'mbkspice_erreur                                   */
/* RETOUR : aucun                                                            */
/*                                                                           */
/*****************************************************************************/
void	mbkspice_erreur(num_err)
int	num_err;
{

	fprintf(stderr, "\n******** Parser spice error ********\n");
	fprintf(stderr, "ligne %d : %s\n", numlig, tab_err[ num_err ]);
        fflush(stderr) ;
	exit(-1);
}


/*****************************************************************************/
/*                                                                           */
/*                                   WARNING                                 */
/*                                                                           */
/*****************************************************************************/
/*                                                                           */
/* Affiche le warning rencontre                                              */
/*                                                                           */
/* ENTREE : le numero du warning                                             */
/* RETOUR : aucun                                                            */
/*                                                                           */
/*****************************************************************************/
void	warning(num_warning)
int	num_warning;
{

	fprintf(stderr, "\n******** Warning de parser spice ********\n");
	fprintf(stderr, "ligne %d : %s\n", numlig, tab_err[ num_warning ]);
}

/*****************************************************************************/
/*                                                                           */
/*                                  FORMATER_LIGNE                           */
/*                                                                           */
/*****************************************************************************/
/*                                                                           */
/* Met la ligne en minuscule, et supprime tous les blancs et tabs inutiles   */
/*                                                                           */
/* ENTREE : la ligne a traiter                                               */
/* RETOUR : aucun                                                            */
/*                                                                           */
/*                                                                           */
/*****************************************************************************/
void	formater_ligne(ligne)
char	ligne[];
{
	char		bid[ MAXLIG + 1];
	register int	lg, cpt_lig, i, j;

	cpt_lig = 0;
	strcpy(bid, ligne);
	lg = strlen(bid) - 1; /* - 1, car on ne veut pas le '\n'*/

	/* enleve les blancs de debut */
	for(i = 0; (i < lg) && (isspace(bid[ i ])); ++i) ;

	for(j = i; j < lg; ++j)
	{
		if (isspace(bid[ j ])) /* si on a trouve un espace */
		{
			for(; (j < lg) && isspace(bid[ j ]); ++j);
			--j;
			/* 1 seul espce enttre deux mots */
			ligne[ cpt_lig++ ] = ' ';
		}
		else
			if (isalpha(bid[ j ])) /* si c'est une lettre */
				/* mise en minuscule */
				ligne[ cpt_lig++ ] = tolower(bid[ j ]);
			else
				ligne[ cpt_lig++ ] = bid[ j ];
	}
	ligne[ cpt_lig ] = '\0';

	/* on enleve les blancs de la fin de ligne */
	for(i = strlen(ligne) - 1; (i > 0) && (isspace(ligne[ i ])); --i)
		ligne[ i ] = '\0';
	
}

/*****************************************************************************/
/*                                                                           */
/*                               ENLEVE_BLANCS_EGAL                          */
/*                                                                           */
/*****************************************************************************/
/*                                                                           */
/* Enleve les blancs autour des signes '='                                   */
/*                                                                           */
/* ENTREE : la ligne a traiter                                               */
/* RETOUR : aucun                                                            */
/*                                                                           */
/*                                                                           */
/*****************************************************************************/
void	enleve_blancs_egal(ligne)
char	ligne[];
{
	char		bid[ MAXLIG + 1];
	register int	lg, cpt_lig, i;
	
	cpt_lig = 0;
	strcpy(bid, ligne);
	lg = strlen(bid);

	for(i = 0; i < lg; ++i)
	{
		/* on a trouve la chaine ' = ' */
		if (!strncmp(&bid[ i ], " = ", 3))
		{
			ligne[ cpt_lig++ ] = '=';
			i+=2;
		}
		else
		/* on a trouve la chaine '= ' */
		if (!strncmp(&bid[ i ], "= ", 2))
		{
			ligne[ cpt_lig++ ] = '=';
			i++;
		}
		else
		/* on a trouve la chaine ' =' */
		if (!strncmp(&bid[ i ], " =", 2))
		{
			ligne[ cpt_lig++ ] = '=';
			i++;
		}
		else /* on n'a pas trouve de chaine avec un egal et espace */
		{
			ligne[ cpt_lig++ ] = bid[ i ];
		}
	}
	ligne[ cpt_lig ] = '\0';
}

/*****************************************************************************/
/*                                                                           */
/*                                 TROUVER_PLUS                              */
/*                                                                           */
/*****************************************************************************/
/*                                                                           */
/* Recherche si la ligne suivante contient un plus                           */
/* Si c'est le cas, il faut la concatener a celle deja lue                   */
/*                                                                           */
/* ENTREE : la ligne deja lue                                                */
/* RETOUR : aucun                                                            */
/*                                                                           */
/*                                                                           */
/*****************************************************************************/
void	trouver_plus(ligne)
char	ligne[];
{
	char	car;	

	while( (car=fgetc(infile)) == '+')
	{
		concat_ligne(ligne);
		++numlig;
	}

	if (car != EOF)
		fseek(infile, -1, SEEK_CUR);

}

/*****************************************************************************/
/*                                                                           */
/*                                 CONCAT_LIGNE                              */
/*                                                                           */
/*****************************************************************************/
/*                                                                           */
/* Concatene la ligne lue a la ligne existante                               */
/*                                                                           */
/* ENTREE : la ligne deja lue                                                */
/* RETOUR : aucun                                                            */
/*                                                                           */
/*                                                                           */
/*****************************************************************************/
void	concat_ligne(ligne)
char	ligne[];
{
	char	bid[ MAXLIG + 1 ];	

	fgets(bid, MAXLIG, infile);
	formater_ligne(bid);
	strcat(ligne, " ");
	strcat(ligne, bid);
}

/*****************************************************************************/
/*                                                                           */
/*                                 DICO_CADENCE                              */
/*                                                                           */
/*****************************************************************************/
/*                                                                           */
/* Recherche si la ligne courante est de la forme "* net <num> = <nom>"      */
/*                                                                           */
/* ENTREE : la ligne lue                                                     */
/* RETOUR : 1 si c'est une ligne de type cadence                             */
/*          0 sinon                                                          */
/*                                                                           */
/*****************************************************************************/
int	dico_cadence(ligne)
char	ligne[];
{
	char	*ptr, *mot;
	char	bid[ MAXLIG + 1 ];

	strcpy(bid, ligne);

	ptr = bid;
	mot = strtok(ptr, " "); /* on a le caractere '*' */
	if (mot == (char *)0)
		return(0);
	if (*mot != '*')
		return(0);
	ptr = (char *)0;
	mot = strtok(ptr, " "); /* on a le 'net' */
	if (mot == (char *)0)
		return(0);
	if (strcmp(mot, "net"))
		return(0);
	mot = strtok(ptr, " "); /* on a le nombre */
	if (mot == (char *)0)
		return(0);
	if (!is_num(mot))
		return(0);
	mot = strtok(ptr, " "); /* on a le '=' */
	if (mot == (char *)0)
		return(0);
	if (*mot != '=')
		return(0);
	mot = strtok(ptr, " "); /* on a le nom */
	if (mot == (char *)0)
		return(0);
	if (strtok(ptr, " ") != (char *)0) /* syntaxe mauvaise */
		return(0);
	return(1);
}

/*****************************************************************************/
/*                                                                           */
/*                                 DICO_DAX                                  */
/*                                                                           */
/*****************************************************************************/
/*                                                                           */
/* Recherche si la ligne courante est '************* nodes *************     */
/*                                                                           */
/* ENTREE : la ligne lue                                                     */
/* RETOUR : 1 si c'est une ligne de type dax                                 */
/*          0 sinon                                                          */
/*                                                                           */
/*****************************************************************************/
int	dico_dax(ligne)
char	ligne[];
{
	return( !strcmp(ligne, DICO_DAX) );
}

/*****************************************************************************/
/*                                                                           */
/*                                 DICO_VTI                                  */
/*                                                                           */
/*****************************************************************************/
/*                                                                           */
/* Recherche si la ligne courante est '*  and synonyms'                      */
/*                                                                           */
/* ENTREE : la ligne lue                                                     */
/* RETOUR : 1 si c'est une ligne de type vti                                 */
/*          0 sinon                                                          */
/*                                                                           */
/*****************************************************************************/
int	dico_vti(ligne)
char	ligne[];
{
	return( !strcmp(ligne, DICO_VTI) );
}

/*****************************************************************************/
/*                                                                           */
/*                                 DICO_ELDO                                 */
/*                                                                           */
/*****************************************************************************/
/*                                                                           */
/* Recherche si la ligne courante commence par '.connect'                    */
/*                                                                           */
/* ENTREE : la ligne lue                                                     */
/* RETOUR : 1 si c'est une ligne de type eldo                                */
/*          0 sinon                                                          */
/*                                                                           */
/*****************************************************************************/
int	dico_eldo(ligne)
char	ligne[];
{
	register int	num, i, lg;
	char		nom[ MAX_NOM + 1];
	char		*ptr, *mot;
	char		bid[ MAXLIG + 1 ];

	strcpy(bid, ligne);
	ptr = bid;
	mot = strtok(ptr, " "); /* on passe le .connect */
	if (mot == (char *)0)
		return(0);
	if (strcmp(mot, ".connect"))
		return(0);
	ptr = (char *)0;

	mot = strtok(ptr, " "); /* on a soit le nom, soit le num */
	if (mot == (char *)0)
		return(0);

	if (isalpha(*mot)) /* cas du nom, syntaxe .connect nom num */
	{
		mot = strtok(ptr, " "); /* recuperation du num */
		if ( (mot == (char *)0) || (!isdigit(*mot)) )
			return(0);
		
	}
	else /* cas du nom, syntaxe .connect num nom */
	{
		mot = strtok(ptr, " "); /* recuperation du nom */
		if ( (mot == (char *)0) || (!isalpha(*mot)) )
			return(0);
	}

	return(1);
}

/*****************************************************************************/
/*                                                                           */
/*                                TRAITE_DICO_DAX                            */
/*                                                                           */
/*****************************************************************************/
/*                                                                           */
/* Lecture de tous les noeuds et remplissage du dictionnaire                 */
/*                                                                           */
/* ENTREE : la ligne lue                                                     */
/* RETOUR : aucun                                                            */
/*                                                                           */
/*****************************************************************************/
int	traite_dico_dax(ligne)
char	ligne[];
{
	char		bid[ MAXLIG + 1], nom[ MAX_NOM + 1];
	register int	pas_fin_dico = 1, lg, num, i;

	while ( (pas_fin_dico) && (fgets(bid, MAXLIG, infile) != (char *)0) )
	{
		formater_ligne(bid);
		pas_fin_dico = strncmp(bid, FIN_DICO_DAX, strlen(FIN_DICO_DAX));
		if (pas_fin_dico)
		{
			lg = strlen(bid);
			num = atoi(bid + 2);
			if (num < 0)
			/*----------------------------------------------*/
			/* on se deplace jusqu'a l'espace, ou la fin de */
			/* la ligne                                     */
			/*----------------------------------------------*/
				mbkspice_erreur(MAUVAIS_CARDINAL);
			for(i = 3; (bid[ i ] != ' ') && (i < lg); ++i);
			if (i >= lg)
				mbkspice_erreur(MAUVAIS_DICO);

			if (strlen(bid + i + 1) >  MAX_NOM)
				mbkspice_erreur(NOM_TROP_GRAND);

			/* on commence apres l'espace */
			strcpy(nom, bid + i + 1);
			verif_nom(nom);
			maj_dic(nom, num);
			
		}
		++numlig;
	}
	if ( pas_fin_dico )
		mbkspice_erreur(DICO_DAX_PAS_TERMINE);
}

/*****************************************************************************/
/*                                                                           */
/*                                TRAITE_DICO_CADENCE                        */
/*                                                                           */
/*****************************************************************************/
/*                                                                           */
/* Lecture de tous les noeuds et remplissage du dictionnaire                 */
/*                                                                           */
/* ENTREE : la ligne lue                                                     */
/* RETOUR : aucun                                                            */
/*                                                                           */
/*****************************************************************************/
int	traite_dico_cadence(ligne)
char	ligne[];
{
	register int	num, i, lg;
	char		nom[ MAX_NOM + 1];


	lg = strlen(ligne);
	num = atoi(ligne + 6);


	if (num <0)
		mbkspice_erreur(MAUVAIS_CARDINAL);

	/* on se deplace jusqu'au '=' ou la fin de la ligne */
	for(i = 8; (ligne[ i ] != '=') && (i < lg); ++i);
	if (i >= lg)
		mbkspice_erreur(MAUVAIS_DICO);

	if (strlen(ligne + i + 2) >  MAX_NOM)
		mbkspice_erreur(NOM_TROP_GRAND);

	strcpy(nom, ligne + i + 2); /* on commence apres le '=' et l'espace */
	verif_nom(nom);
	maj_dic(nom, num);
}

/*****************************************************************************/
/*                                                                           */
/*                                TRAITE_DICO_VTI                            */
/*                                                                           */
/*****************************************************************************/
/*                                                                           */
/* Lecture de tous les noeuds et remplissage du dictionnaire                 */
/*                                                                           */
/* ENTREE : la ligne lue                                                     */
/* RETOUR : aucun                                                            */
/*                                                                           */
/*****************************************************************************/
int	traite_dico_vti(ligne)
char	ligne[];
{
	char		bid[ MAXLIG + 1], nom[ MAX_NOM + 1];
	register int	pas_fin_dico = 1, lg, num, i;

	fgets(bid, MAXLIG, infile); /* lecture bidon de la premiere ligne */
	while ( (pas_fin_dico) && (fgets(bid, MAXLIG, infile) != (char *)0) )
	{
		formater_ligne(bid);
		pas_fin_dico = strcmp(bid, FIN_DICO_VTI);
		if (pas_fin_dico)
		{
			lg = strlen(bid);
			num = atoi(bid + 2);
			if (num < 0)
			/*-------------------------------------------*/
			/* on se deplace jusqu'a l'espace, ou la fin */
			/* de la ligne                               */
			/*-------------------------------------------*/
				mbkspice_erreur(MAUVAIS_CARDINAL);
			for(i = 3; (bid[ i ] != ' ') && (i < lg); ++i);
			if (i >= lg)
				mbkspice_erreur(MAUVAIS_DICO);

			if (strlen(bid + i + 1) >  MAX_NOM)
				mbkspice_erreur(NOM_TROP_GRAND);

			/* on commence apres l'espace */
			strcpy(nom, bid + i + 1);
			verif_nom(nom);
			maj_dic(nom, num);
		}
		++numlig;
	}
	if ( pas_fin_dico )
		mbkspice_erreur(DICO_VTI_PAS_TERMINE);
	++numlig;
}

/*****************************************************************************/
/*                                                                           */
/*                                TRAITE_DICO_ELDO                           */
/*                                                                           */
/*****************************************************************************/
/*                                                                           */
/* Lecture de tous les noeuds et remplissage du dictionnaire                 */
/*                                                                           */
/* ENTREE : la ligne lue                                                     */
/* RETOUR : aucun                                                            */
/*                                                                           */
/*****************************************************************************/
int	traite_dico_eldo(ligne)
char	ligne[];
{
	register int	num, i, lg;
	char		nom[ MAX_NOM + 1];
	char		*ptr, *mot;

	
	ptr = ligne;
	mot = strtok(ptr, " "); /* on passe le .connect */
	ptr = (char *)0;

	mot = strtok(ptr, " "); /* on a soit le nom, soit le num */

	if (isalpha(*mot)) /* cas du nom, syntaxe .connect nom num */
	{
		if (strlen(mot) >  MAX_NOM)
			mbkspice_erreur(NOM_TROP_GRAND);
		strcpy(nom, mot); 
		mot = strtok(ptr, " "); /* recuperation du num */
		num = atoi(mot);
		if (num <0)
			mbkspice_erreur(MAUVAIS_CARDINAL);
		
	}
	else /* cas du nom, syntaxe .connect num nom */
	{
		num = atoi(mot);
		if (num <0)
			mbkspice_erreur(MAUVAIS_CARDINAL);
		mot = strtok(ptr, " "); /* recuperation du nom */
		if (strlen(mot) >  MAX_NOM)
			mbkspice_erreur(NOM_TROP_GRAND);
		strcpy(nom, mot); 
	}

	verif_nom(nom);
	maj_dic(nom, num);
}

/*****************************************************************************/
/*                                                                           */
/*                                 DEBUT_SUBCKT                              */
/*                                                                           */
/*****************************************************************************/
/*                                                                           */
/* Recherche si la ligne courante commence par '.subckt'                     */
/*                                                                           */
/* ENTREE : la ligne lue                                                     */
/* RETOUR : 1 si c'est une ligne commencant par '.subckt'                    */
/*          0 sinon                                                          */
/*                                                                           */
/*****************************************************************************/
int	debut_subckt(ligne)
char	ligne[];
{
	return( !strncmp(ligne, DEB_SUBCKT, strlen(DEB_SUBCKT)) );
}

/*****************************************************************************/
/*                                                                           */
/*                              TRAITE_DEBUT_SUBCKT                          */
/*                                                                           */
/*****************************************************************************/
/*                                                                           */
/* Traitement du debut de subckt                                             */
/*                                                                           */
/* ENTREE : la ligne lue                                                     */
/* RETOUR : aucun                                                            */
/*                                                                           */
/*****************************************************************************/
void	traite_debut_subckt(ptlofig,ligne)
lofig_list *ptlofig ;
char	   ligne[];
{
	char		*mot;
	register int	num;
	struct locon	*ptaux_locon;
	lofig_list	*ptf;

	
	mot = strtok(ligne, " "); /* on passe le mot '.subckt' */
	mot = strtok(NULL, " "); /* recuperation du nom du subckt */
	if (mot == (char *)0)
		mbkspice_erreur(MANQUE_NOM_SUBCKT);
	if (!isalpha(mot[0]))
		mbkspice_erreur(MAUVAIS_NOM_SUBCKT_MBK);

	strcpy(nom_subckt, mot); /* sauvegarde du nom */

	/* figure mere */
	flag_dico = fig_pere = (!strcmp(nom_subckt, yy_figname));

	/* figure inconnue */
	if ( (ptf = spi_findlofig(namealloc(nom_subckt))) == NULL )
	{
		spi_ptfig = addlofig(nom_subckt);
		fig_loaded = 1;
	}
	else
	if ( !strcmp(yy_figname, nom_subckt)) /* figure pere */
	{
		ptlofig->NEXT = spi_ptfig ;
		spi_ptfig = ptlofig;
		fig_loaded = 1;
	}
	else /* figure existante et non pere */
	{
		dellofig(spi_ptfig);
		addlofig(nom_subckt);
		warning(FIG_CANCELLED);
		fprintf(stderr, "Name figure is %s\n", nom_subckt);
		fig_loaded = 1;
	}
		
	while ( (mot = strtok(NULL, " ")) != (char *)0)
	{
		if (isdigit(*mot) && (atoi(mot) == 0))
			mbkspice_erreur(NOEUD_ZERO);
		spi_addlocname(spi_ptfig, namealloc(mot), ptdic);
	}
}

/*****************************************************************************/
/*                      fonction main_gdt()                                  */
/* dit si la ligne contient le "* start main cell %s": c'est le debut de la  */
/* description de la figure mere.                                            */
/*****************************************************************************/
short main_gdt(ptfig,ligne)
lofig_list *ptfig  ;
char       ligne[] ;

{
char  name[100]     ;
short flag      = 0 ;

flag = sscanf(ligne,"* start main cell %s",name) ;

/* si c'est la figure principale, c'est le nom de la figure mere */
if(flag == 1)
    {
    ptfig->NAME = namealloc(name) ;
    ptfig->NEXT = spi_ptfig ;
    spi_ptfig = ptfig ;
    fig_loaded = 1 ;
    }

return(flag) ;
}


/*****************************************************************************/
/*                                  dico_gdt()                               */
/* traite le dictionnaire format GDT dans lequel les correspondances         */
/* nom-signal sont a l'interieur du subckt. Cette fonction dit seulement si  */
/* la ligne est de ce format ou non.                                         */
/*****************************************************************************/
short dico_gdt(ligne)
char ligne[] ;

{
char aux[50]   ,
     nom[100]  ,
     index[50] ;
long ind       ;

ind = sscanf(ligne,"*.%s %s %s",aux,nom,index) ;

if(ind == 3)
    {
    if((strcmp(aux,"in" ) == 0) || (strcmp(aux,"out") == 0) ||
       (strcmp(aux,"vdd") == 0) || (strcmp(aux,"gnd") == 0)   )
    if((ind = atoi(index)) != 0)
        {
        losig_list *losig = givelosig(spi_ptfig,ind) ;
        locon_list *locon                            ;
        char       *name  = namealloc(nom)           ;

        losig->NAMECHAIN = addchain(losig->NAMECHAIN,name) ;

        /*------------------------------------------------------------*/
        /* si la variable spi_main_gdt est positionnee, c'est que les */
        /* .in, .out, etc... sont les connecteurs. Alors il faut non  */
        /* pas les chercher dans la liste des connecteurs, mais creer */
        /* les connecteurs.                                           */
        /*------------------------------------------------------------*/
        if(spi_main_gdt == 1)
            {
            for(locon = spi_ptfig->LOCON ;
                (locon != NULL) && (locon->SIG != losig) ;
                locon = locon->NEXT) ;

            if(locon == NULL)
                {
                spi_ptfig->LOCON = addlocon(spi_ptfig,name,losig,UNKNOWN) ;
                losig->TYPE = 'E' ;
                }
            }
        /* sinon recherche du nom de connecteur */
        else
            {
            sprintf(aux,"mbk.%s",index) ;

            for(locon = spi_ptfig->LOCON ;
                (locon != NULL) && (strcmp(locon->NAME,aux) != 0) ;
                locon = locon->NEXT) ;

            if(locon != NULL)
            locon->NAME = name ;
            }

        return(1) ;
        }
    }

return(0) ;
}


/*****************************************************************************/
/*                                                                           */
/*                                   FIN_SUBCKT                              */
/*                                                                           */
/*****************************************************************************/
/*                                                                           */
/* Recherche si la ligne courante commence par '.ends'                       */
/*                                                                           */
/* ENTREE : la ligne lue                                                     */
/* RETOUR : 1 si c'est une ligne commencant par '.ends'                      */
/*          0 sinon                                                          */
/*                                                                           */
/*****************************************************************************/
int	fin_subckt(ligne)
char	ligne[];
{
	return( !strncmp(ligne, FIN_SUBCKT, strlen(FIN_SUBCKT)) );
}

/*****************************************************************************/
/*                                                                           */
/*                              TRAITE_FIN_SUBCKT                            */
/*                                                                           */
/*****************************************************************************/
/*                                                                           */
/* Traitement de la fin de subckt                                            */
/*                                                                           */
/* ENTREE : la ligne lue                                                     */
/* RETOUR : aucun                                                            */
/*                                                                           */
/*****************************************************************************/
void	traite_fin_subckt(ligne)
char	ligne[];
{
	struct locon	*ptaux_locon   ;

	if (strcmp(ligne + 6, nom_subckt))
		mbkspice_erreur(MAUVAIS_NOM_SUBCKT);

	for(ptaux_locon = spi_ptfig -> LOCON;
            ptaux_locon; ptaux_locon = ptaux_locon -> NEXT)
		ptaux_locon -> SIG -> TYPE = 'E';

	spi_clear_hash();
	spi_index = 2;
}

/*****************************************************************************/
/*                                                                           */
/*                                   TRANSISTOR                              */
/*                                                                           */
/*****************************************************************************/
/*                                                                           */
/* Recherche si la ligne courante commence par 'm'                           */
/*                                                                           */
/* ENTREE : la ligne lue                                                     */
/* RETOUR : 1 si c'est une ligne commencant par 'm'                          */
/*          0 sinon                                                          */
/*                                                                           */
/*****************************************************************************/
int	transistor(ligne)
char	ligne[];
{
/*	return( ligne[0] == 'm' );*/
/* MODIF PAYAM POUR LECTURE DES TRANSISTORS ASGA */
return((ligne[0] == 'm') || (ligne[0] == 'j')) ;
}

/*****************************************************************************/
/*                                                                           */
/*                              TRAITE_TRANSISTOR                            */
/*                                                                           */
/*****************************************************************************/
/*                                                                           */
/* Traitement du transistor                                                  */
/*                                                                           */
/* ENTREE : la ligne lue                                                     */
/* RETOUR : aucun                                                            */
/*                                                                           */
/*****************************************************************************/
void	traite_transistor(ligne)
char	ligne[];
{
	losig_list *drain  ,
		   *grid   ,
		   *source ;
	char       l[ MAX_NOM + 1 ] ,
		   w[ MAX_NOM + 1 ] ,
		   ps[ MAX_NOM + 1 ],
		   pd[ MAX_NOM + 1 ],
		   as[ MAX_NOM + 1 ],
		   ad[ MAX_NOM + 1 ],
		   type_trans       ,
	     	   *ptr             ,
		   *mot             ,
		   *name            ;
	long	wr = 0, xs = 0, xd = 0;
	int	flw, fas, fad, fps, fpd;


	flw = fas = fad = fps = fpd = 0;


	ptr = ligne;
	mot = strtok(ptr, " "); /* on passe le nom du transistor */
	if (mot == (char *)0)
		mbkspice_erreur(MAUVAISE_DEF_TRANS);
	ptr = (char *)0;
	mot = strtok(ptr, " "); /* 1 er identificateur = DRAIN */
	if (mot == (char *)0)
		mbkspice_erreur(MAUVAISE_DEF_TRANS_DRAIN);
	/*drain = givelosig(spi_ptfig, (long)spi_giveindex(mot));*/
	drain = spi_addsigname(mot);
	mot = strtok(ptr, " "); /* 2 eme identificateur = GRID */
	if (mot == (char *)0)
		mbkspice_erreur(MAUVAISE_DEF_TRANS_GRID);
	/*grid = givelosig(spi_ptfig, (long)spi_giveindex(mot));*/
	grid = spi_addsigname(mot);
	mot = strtok(ptr, " "); /* 3 eme identificateur = SOURCE */
	if (mot == (char *)0)
		mbkspice_erreur(MAUVAISE_DEF_TRANS_SOURCE);
	/*source = givelosig(spi_ptfig, (long)spi_giveindex(mot));*/
	source = spi_addsigname(mot);
	mot = strtok(ptr, " "); /* 4 eme identificateur = BULK */
	if (mot == (char *)0)
		mbkspice_erreur(MAUVAISE_DEF_TRANS_BULK);
	mot = strtok(ptr, " "); /* 5 eme identificateur = TYPE */
	if (mot == (char *)0)
		mbkspice_erreur(MAUVAISE_DEF_TRANS_TYPE);
	name = namealloc(mot);

	if (!strcmp(name, modn))
		type_trans = TRANSN;
	else
		if (!strcmp(name, modp))
			type_trans = TRANSP;
		else
			mbkspice_erreur(MAUVAIS_TRANS_TYPE);

	/* parcours de param_list + geo_list */
	while((mot = strtok(ptr, " ")) != (char *)0)
	{
		verif_unite(mot);
		switch(*mot)
		{
			case	'w' :
					if (flw)
					mbkspice_erreur(MAUVAISE_DEF_TRANS_WL);
					if ( (mot + 2) == NULL)
					mbkspice_erreur(MAUVAISE_DEF_TRANS_WL);
					strcpy(w, mot + 2);
					mot = strtok(ptr, " ");
					if ( (mot == (char *)0) ||
					     (*mot != 'l')        )
					mbkspice_erreur(MAUVAISE_DEF_TRANS_WL);
					if ( (mot + 2) == NULL)
					mbkspice_erreur(MAUVAISE_DEF_TRANS_WL);
					strcpy(l, mot + 2);
					flw = 1;
					break;
			case	'l' :
					if (flw)
					mbkspice_erreur(MAUVAISE_DEF_TRANS_WL);
					if ( (mot + 2) == NULL)
					mbkspice_erreur(MAUVAISE_DEF_TRANS_WL);
					strcpy(l, mot + 2);
					mot = strtok(ptr, " ");
					if ( (mot == (char *)0) ||
					   (*mot != 'w')          )
					mbkspice_erreur(MAUVAISE_DEF_TRANS_WL);
					if ( (mot + 2) == NULL)
					mbkspice_erreur(MAUVAISE_DEF_TRANS_WL);
					strcpy(w, mot + 2);
					flw = 1;
					break;
			case	'a' :
					if (mot[ 1 ] == 's')
					{
						if (fas)
						mbkspice_erreur(MAUVAISE_DEF_TRANS_ASD);
						if ( (mot + 3) == NULL)
						mbkspice_erreur(MAUVAISE_DEF_TRANS_ASD);
						strcpy(as, mot + 3);
						fas = 1;
					}
					else
					if (mot[ 1 ] == 'd')
					{
						if (fad)
						mbkspice_erreur(MAUVAISE_DEF_TRANS_ASD);
						if ( (mot + 3) == NULL)
						mbkspice_erreur(MAUVAISE_DEF_TRANS_ASD);
						strcpy(ad, mot + 3);
						fad = 1;
					}
					else
					mbkspice_erreur(MAUVAISE_DEF_TRANS_ASD);
					break;
			case	'p' :
					if (mot[ 1 ] == 's')
					{
						if (fps)
						mbkspice_erreur(MAUVAISE_DEF_TRANS_PSD);
						if ( (mot + 3) == NULL)
						mbkspice_erreur(MAUVAISE_DEF_TRANS_PSD);
						strcpy(ps, mot + 3);
						fps = 1;
					}
					else
					if (mot[ 1 ] == 'd')
					{
						if (fpd)
						mbkspice_erreur(MAUVAISE_DEF_TRANS_PSD);
						if ( (mot + 3) == NULL)
						mbkspice_erreur(MAUVAISE_DEF_TRANS_PSD);
						strcpy(pd, mot + 3);
						fpd = 1;
					}
					else
					mbkspice_erreur(MAUVAISE_DEF_TRANS_PSD);
					break;
			case	'n' :
					if ( mot[ 1 ] != 'r' || 
					     (mot[ 2 ] != 's' && mot[ 2 ] != 'd')
					   ) mbkspice_erreur(MAUVAISE_DEF_TRANS_NRSD);
					break;
			default	:
					mbkspice_erreur(MAUVAISE_DEF_TRANS);
		}
	}
	wr = spi_givelong(w);
	if (wr)
	{
		xs = spi_givearea(as, wr);
		xd = spi_givearea(ad, wr);
	}
	addlotrs(spi_ptfig,type_trans,0,0,(unsigned short)spi_givelong(w),(unsigned short)spi_givelong(l),(unsigned short)spi_givelong(ps),(unsigned short)spi_givelong(pd),(unsigned short)xs,(unsigned short)xd, grid,source,drain);
}

/*****************************************************************************/
/*                                                                           */
/*                                   CAPACITE                                */
/*                                                                           */
/*****************************************************************************/
/*                                                                           */
/* Recherche si la ligne courante commence par 'c'                           */
/*                                                                           */
/* ENTREE : la ligne lue                                                     */
/* RETOUR : 1 si c'est une ligne commencant par 'c'                          */
/*          0 sinon                                                          */
/*                                                                           */
/*****************************************************************************/
int	capacite(ligne)
char	ligne[];
{
	return( ligne[0] == 'c' );
}

/*****************************************************************************/
/*                                                                           */
/*                              TRAITE_CAPACITE                              */
/*                                                                           */
/*****************************************************************************/
/*                                                                           */
/* Traitement de la capacite                                                 */
/*                                                                           */
/* ENTREE : la ligne lue                                                     */
/* RETOUR : aucun                                                            */
/*                                                                           */
/*****************************************************************************/
void	traite_capacite(ligne)
char	ligne[];
{
	char	   *ptr, *mot;
	double	   capa;
	losig_list *ptsigx ,
		   *ptsigy ;


	ptr = ligne;
	mot = strtok(ptr, " "); /* on passe le nom de la capacite */
	if (mot == (char *)0)
		mbkspice_erreur(MAUVAISE_DEF_CAPA);
	ptr = (char *)0;
	mot = strtok(ptr, " "); /* 1 er identificateur */
	if (mot == (char *)0)
		mbkspice_erreur(MAUVAISE_DEF_CAPA);
	/*ptsigx = givelosig(spi_ptfig, (long)spi_giveindex(mot));*/
	ptsigx = spi_addsigname(mot);
	mot = strtok(ptr, " "); /* 2 eme identificateur */
	if (mot == (char *)0)
		mbkspice_erreur(MAUVAISE_DEF_CAPA);
	/*ptsigy = givelosig(spi_ptfig, (long)spi_giveindex(mot));*/
	ptsigy = spi_addsigname(mot);
	mot = strtok(ptr, " "); /* la valeur */
	if (mot == (char *)0)
		mbkspice_erreur(MAUVAISE_DEF_CAPA);
	verif_unite(mot);
	capa = spi_givefloat_capa(mot);
	spi_addcapa(ptsigx, ptsigy, capa);
}

/*****************************************************************************/
/*                                                                           */
/*                                   INSTANCE                                */
/*                                                                           */
/*****************************************************************************/
/*                                                                           */
/* Recherche si la ligne courante commence par 'x'                           */
/*                                                                           */
/* ENTREE : la ligne lue                                                     */
/* RETOUR : 1 si c'est une ligne commencant par 'x'                          */
/*          0 sinon                                                          */
/*                                                                           */
/*****************************************************************************/
int	instance(ligne)
char	ligne[];
{
	return( ligne[0] == 'x' );
}

/*****************************************************************************/
/*                                                                           */
/*                              TRAITE_INSTANCE                              */
/*                                                                           */
/*****************************************************************************/
/*                                                                           */
/* Traitement de l' instance                                                 */
/*                                                                           */
/* ENTREE : la ligne lue                                                     */
/* RETOUR : aucun                                                            */
/*                                                                           */
/*****************************************************************************/
void	traite_instance(ligne)
char	ligne[];
{
	char	   nom[ MAX_NOM + 1 ]            ,
	    	   inst_nom[ MAX_NOM + 1 ]       ,
		   *inst_name                    ,
		   *name                         ,
		   *ptr                          ,
		   *mot                          ;
	chain_list *ptchain               = NULL ;


	ptr = ligne;
	mot = strtok(ptr, " "); /* le nom de l'instance */

	if (mot == (char *)0)
		mbkspice_erreur(MAUVAISE_DEF_INSTANCE);

	if (strlen(mot) >  MAX_NOM)
		mbkspice_erreur(NOM_TROP_GRAND);

	strcpy(nom, mot+1);
	verif_nom(nom);
	name = namealloc(nom);
	ptr = (char *)0;

	/* parcours de l'ident_list */
	while( (mot = strtok(ptr, " ")) != (char *)0)
	{
		losig_list *ptinstsig ;

		if (strlen(mot) >  MAX_NOM)
			mbkspice_erreur(NOM_TROP_GRAND);
		/*ptinstsig = givelosig(spi_ptfig, (long)spi_giveindex(mot));*/
		ptinstsig = spi_addsigname(mot);
		ptchain = addchain(ptchain, ptinstsig);
		strcpy(inst_nom, mot);
		inst_name = namealloc(inst_nom);
	}
	verif_nom(inst_nom);
	dellosig(spi_ptfig, spi_giveindex(inst_name));
	ptchain = delchain(ptchain, ptchain);
	addloins(spi_ptfig, name, getlofig(inst_name, 'A'), ptchain, NULL);
	freechain(ptchain);
	ptchain = NULL;
}

/*****************************************************************************/
/*                                                                           */
/*                              VERIF_NOM                                    */
/*                                                                           */
/*****************************************************************************/
/*                                                                           */
/* Regarde si la premier caractere est une lettre                            */
/*                                                                           */
/* ENTREE : le mot a traiter                                                 */
/* RETOUR : aucun                                                            */
/*                                                                           */
/*****************************************************************************/
void	verif_nom(nom)
char	nom[];
{
	char	*name_clean;

	name_clean = cleaname(nom);
	if (!isalpha(*name_clean))
		mbkspice_erreur(MAUVAIS_NOM_MBK);
}

/*****************************************************************************/
/*                                                                           */
/*                              VERIF_UNITE                                  */
/*                                                                           */
/*****************************************************************************/
/*                                                                           */
/* Regarde si la premiere lettre de l'unite est : m, u, n, p, ou f           */
/*                                                                           */
/* ENTREE : le mot a traiter                                                 */
/* RETOUR : aucun                                                            */
/*                                                                           */
/*****************************************************************************/
void	verif_unite(mot)
char	*mot;
{
	char	*pt;

	pt = mot + strlen(mot) - 1; /* pt pointe sur le dernier caractere */

	if (isdigit(*pt)) /* pas d'unite */
		return;

	/* on recule tant qu'il y a une lettre */
	while( (isalpha(*pt)) && (pt != mot))
		--pt;

	/* si il n'y avait pas de chiffre */
	if ( (pt == mot) && (!isdigit(*pt)) )
		mbkspice_erreur(MAUVAISE_VALEUR);

	++pt; /* on se repositionne sur la premiere lettre */
	if ( (*pt != 'm') && (*pt != 'u') && (*pt != 'p') && (*pt != 'f') )
		mbkspice_erreur(MAUVAISE_UNITE);
}

/*****************************************************************************/
/*                                                                           */
/*                                    IS_NUM                                 */
/*                                                                           */
/*****************************************************************************/
/*                                                                           */
/* Regarde si le mot passe est un nombre                                     */
/*                                                                           */
/* ENTREE : le mot a traiter                                                 */
/* RETOUR : 1 si le mot est pas un nombre                                    */
/*          0 sinon                                                          */
/*                                                                           */
/*****************************************************************************/
int	is_num(mot)
char	*mot;
{
	while (*mot != '\0')
	{
		if (!isdigit(*mot))
			return(0);
		++mot;
	}
	return(1);
}

/*****************************************************************************/
/*                                                                           */
/*                                   TRAITE_DICOS                            */
/*                                                                           */
/*****************************************************************************/
/*                                                                           */
/* Parcours tout le fichier et creation du dictionnaire                      */
/*                                                                           */
/* ENTREE : Aucune                                                           */
/* RETOUR : Aucun                                                            */
/*                                                                           */
/*****************************************************************************/
void	traite_dicos()
{
	register int	eldo, cadence, vti, dax;
	char		ligne[ MAXLIG + 1 ];

	eldo = cadence = vti = dax = 0;

	numlig = 1;

	while ( fgets(ligne, MAXLIG, infile) != (char *)0)
	{
		formater_ligne(ligne);
		trouver_plus(ligne);

		if (dico_cadence(ligne))
		{
			if (dax | vti | eldo)
				mbkspice_erreur(DEUX_DICOS);
			traite_dico_cadence(ligne);
			cadence = 1;
		}
		else
		if (dico_dax(ligne))
		{
			if (cadence | vti | eldo)
				mbkspice_erreur(DEUX_DICOS);
			traite_dico_dax(ligne);
			dax = 1;
		}
		else
		if (dico_vti(ligne))
		{
			if (dax | cadence | eldo)
				mbkspice_erreur(DEUX_DICOS);
			traite_dico_vti(ligne);
			vti = 1;
		}
		else
		if (dico_eldo(ligne))
		{
			if (dax | vti | cadence)
				mbkspice_erreur(DEUX_DICOS);
			traite_dico_eldo(ligne);
			eldo = 1;
		}
		++numlig;
	}
	rewind(infile);
}

/*****************************************************************************/
/*                                                                           */
/*                                     MAJ_DIC                               */
/*                                                                           */
/*****************************************************************************/
/*                                                                           */
/* Met a jour la liste chainee du dictionnaire                               */
/*                                                                           */
/* ENTREE : Le nom et le numero du connecteur                                */
/* RETOUR : Aucun                                                            */
/*                                                                           */
/*****************************************************************************/
void	maj_dic(nom, num)
char	nom[];
int	num;
{
spi_triplet_list *ptaux_dic = ptdic ;

	ptdic = spi_create_triplet(nom, (num-MAXSIGINDEX));
	ptdic -> next = ptaux_dic;
}

/*****************************************************************************/
/*                                                                           */
/*                                   TRAITE_DICOS_2                          */
/*                                                                           */
/*****************************************************************************/
/*                                                                           */
/* Parcours tous les connecteurs et signaux de la figure mere,               */
/* si le nom de signal commence par mbk, recuperation du numero qui suit     */
/* recherche dans le dico du bon nom                                         */
/*                                                                           */
/* ENTREE : Aucune                                                           */
/* RETOUR : Aucun                                                            */
/*                                                                           */
/*****************************************************************************/
void	traite_dicos_2(ptfig)
lofig_list *ptfig;
{
	locon_list 		*ptaux_locon;
	losig_list 		*ptaux_losig;
	register int		num         ;
	char                    *str        ;

	/* parcours de tous les connecteurs */


	for(ptaux_locon = ptfig -> LOCON; ptaux_locon;
	    ptaux_locon = ptaux_locon -> NEXT)
		{
		if (!strncmp(ptaux_locon -> NAME, "mbk", 3)) /* mbk trouve */
			{
			num = atoi(ptaux_locon -> NAME + 4);
			str=spi_getdicname(num,ptdic);
			if(str) ptaux_locon->NAME = str;
			}
		else
			{
		num = spi_getdicindex(ptaux_locon->NAME,ptdic);
		if(num !=0 && num<MAXSIGINDEX) ptaux_locon->SIG->INDEX = num;
			}
		}
	/* parcours des signaux */

	for(ptaux_losig= ptfig->LOSIG;ptaux_losig!=NULL;
	    ptaux_losig=ptaux_losig->NEXT)
	{
		if(ptaux_losig->NAMECHAIN)
		{
		str = (char *) ptaux_losig->NAMECHAIN->DATA;
		if (!strncmp(str, "mbk", 3)) /* mbk trouve */
			{
		num = atoi(str + 4);
		str = spi_getdicname(num,ptdic);
		if(str) ptaux_losig->NAMECHAIN->DATA = (void *)str;
			}
		else
			{
		num = spi_getdicindex(str,ptdic);
		if(num) ptaux_losig->INDEX = num;
			}
		}
                else
                {
		str = spi_getdicname(ptaux_losig->INDEX,ptdic);
		if(str)
                ptaux_losig->NAMECHAIN = addchain(ptaux_losig->NAMECHAIN,(void *)str);
                }
	}	

}
