/****************************************************************/
/*								*/
/* Optimizer.c - dieses Modul enthält den Optimierer für	*/
/*		 die Booleschen Ausdrücke			*/
/*								*/
/* Funktionsweise des Optimierers:				*/
/* Zunächst wird das normale Source-File "name.pld" geladen	*/
/* und bis zu den Gleichungen so ausgewertet als ob es assem-	*/
/* bliert werden soll. Das heißt: Bei Verstößen gegen die	*/
/* Syntax wird abgebrochen.					*/
/* Wenn bis dahin kein Fehler aufgetreten ist, werden die	*/
/* Gleichungen codiert (Zahlen anstatt Strings) in den Speicher */
/* abgelegt. Wenn dabei kein Fehler auftrat, wird mit Hilfe	*/
/* des Quine-McCluskey - Algorithmus versucht, die Gleichungen	*/
/* zu vereinfachen.						*/
/* Zum Schluß werden die codierten (und vereinfachten) Gleich-	*/
/* ungen wieder in Textform zurückgewandelt und abgespeichert.	*/
/*								*/
/*								*/
/****************************************************************/


#include <exec/memory.h>
#include <libraries/dos.h>
#include <libraries/gadtools.h>
#include <libraries/reqtools.h>
#include <libraries/locale.h>
#include <intuition/intuition.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>

#include <proto/locale.h>
#include <proto/intuition.h>
#include <proto/gadtools.h>
#include <proto/exec.h>
#include <proto/reqtools.h>
#include <proto/graphics.h>
#include <proto/dos.h>

#include "GALer.h"
#include "Localize.h"



#define	TAKEIT_GADID	1
#define FORGETIT_GADID	2
#define WEITER_GADID	10




extern	struct  AppString { LONG   as_ID;
		 	    STRPTR as_Str;
			  };

extern	struct  AppString AppStrings[];

extern	int	num_of_pins, asmreadyflag, gal_type, num_of_col;
extern	LONG	fsize;
extern	UBYTE	*fbuff;
extern	UBYTE	*actptr, *buffend;
extern	UBYTE	PinNamesOpt[24][10];
extern	char	path[];
extern	APTR	VisualInfo;


extern	struct	Pin		actPin;
extern	struct	Screen		*screen;
extern	struct	Window		*window;
extern	struct	Menu		*mainmenu;
extern	struct	Gadget		*OptGList;
extern	struct	Catalog		*catalog;


struct	RastPort	*orp;		/*RastPort für Optimizer-Window*/
struct	Window		*optwin;


UBYTE	OptTxt1[28];


int	oypos, scrolls, reqflag;
int	num_of_ORs, num_of_ANDs;
int	numofpins_Opt;
				/*oypos: y-Pos. für Text im Optimizer-Window*/
				/*scrolls: wie oft gescrollt wurde*/
				/*reqflag: Scrollreq. ja oder nein ?*/

char	opttitle[] = {"Optimizer"};


UWORD OptGTypes[] = {
	BUTTON_KIND,
	BUTTON_KIND
};


struct NewGadget OptNGad[] = {
	389, 140, 99, 12, NULL, NULL, TAKEIT_GADID, PLACETEXT_IN, NULL, NULL,
	521, 140, 99, 12, NULL, NULL, FORGETIT_GADID, PLACETEXT_IN, NULL, NULL
};


ULONG OptGTags[] = {
	(TAG_DONE),
	(TAG_DONE)
};







/* Optimizer  -   Boolesche Gleichungen vereinfachen
   Paramter: ---
   Ergegnis:  0: alles o.k.   sonst: Fehler oder Abbruch
*/
int Optimizer(void)
{
struct	IntuiMessage	*imsg;
struct	ActBuffer	AllEquas, OptEqua, FileEquas;
struct	Buffer		*FirstAllEquas, *FirstOptEqua, *FirstFileEquas;
ULONG	class;
USHORT	code, gadID;
UBYTE	*equastart, *equaend;		     /*Gleichungsanfang und -ende*/
int	n, equaflag, asmreadyflag2, gal_type2, num_of_pins2, num_of_col2;
int	notready;
char	statstrng[6];

				/*AllEquas:, Puffer, in dem alle Gleichungen*/
				/*codiert abgelegt sind*/
				/*FirstAllEquas: Zeiger auf den ersten Puffer*/
				/*in dem alle Gleichung stehen*/
				/*OptEqua:  Puffer in dem eine Gleichung*/
				/*optimiert wird*/
				/*FileEquas:  Puffer in dem Gleichungen in*/
				/*String-Form (!) abgelegt werden, um daraus*/
				/*dann ein neues Source-File zu erstellen*/
				/*FirstOptEquas: Zeiger auf den ersten Puffer*/
				/*in dem die Gleichung optimiert wird*/
 asmreadyflag2 = asmreadyflag;		/*die Variablen, die wichtig sind und*/
 gal_type2     = gal_type;		/*in "AssembleInputFile" verändert*/
 num_of_pins2  = num_of_pins;		/*werden, sichern*/
 num_of_col2   = num_of_col;
				    /*zum "Schein" assemblieren, dadurch spar*/
 n = AssembleInputFile(OPTIMIZER);  /*ich mir den Syntax-Check, da das der*/
				    /*Assembler jetzt macht*/
 numofpins_Opt = num_of_pins;
 asmreadyflag  = asmreadyflag2;		/*Variablen wieder herstellen*/
 num_of_pins   = num_of_pins2;
 num_of_col    = num_of_col2;

 if (gal_type == GAL22V10) {
   strcpy(&PinNamesOpt[24][0], "AR");	/* extra "Pins" für AR und SR */
   strcpy(&PinNamesOpt[25][0], "SP");		/* definieren */
   numofpins_Opt += 2;
 }

 gal_type      = gal_type2;




 if (!n) {
   equastart = actptr;

   if (!(FirstAllEquas = (struct Buffer *)AllocMem((long)sizeof(struct Buffer),MEMF_PUBLIC|MEMF_CLEAR))) {
     FreeMem(fbuff, fsize);		/*Puffer für zu optimierendes File*/
     ErrorReq(2);			/*kein Speicher mehr->Fehlermeldung*/
     return(-1);
   }

   AllEquas.ThisBuff = FirstAllEquas;
   AllEquas.Entry    = (UBYTE *)(&FirstAllEquas->Entries[0]);
   AllEquas.BuffEnd  = (UBYTE *)FirstAllEquas + (long)sizeof(struct Buffer);

   if (!TranslateEqua(&AllEquas)) {
     equaend = actptr;			/*Zeiger auf DESCRIPTION merken*/ 

     if (!(FirstFileEquas = (struct Buffer *)AllocMem((long)sizeof(struct Buffer),MEMF_PUBLIC|MEMF_CLEAR))) {
       FreeMem(fbuff, fsize);		/*Puffer für zu optimierendes File*/
       FreeBuffer(FirstAllEquas);	/*Puffer für Gleichungen*/
       ErrorReq(2);			/*kein Speicher mehr->Fehlermeldung*/
       return(-1);
     }

     FileEquas.ThisBuff = FirstFileEquas;
     FileEquas.Entry    = (UBYTE *)(&FirstFileEquas->Entries[0]);
     FileEquas.BuffEnd  = (UBYTE *)FirstFileEquas + (long)sizeof(struct Buffer);

     if (AddByte(&FileEquas, (UBYTE)0x0A)) {	/*vor den Gleichungen in*/
       FreeMem(fbuff, fsize);			/*String-From noch einige*/
       FreeBuffer(FirstAllEquas);		/*Returns einfügen*/
       FreeBuffer(FirstFileEquas);
       ErrorReq(2);
       return(-1);
     }

     if (AddByte(&FileEquas, (UBYTE)0x0A)) {
       FreeMem(fbuff, fsize);
       FreeBuffer(FirstAllEquas);
       FreeBuffer(FirstFileEquas);
       ErrorReq(2);
       return(-1);
     }



     if (!(optwin = OpenWindowTags( NULL,
				WA_Left,	 0,
				WA_Top,		 11,
				WA_Width,	 640,
				WA_Height,	 189,
				WA_IDCMP,	 BUTTONIDCMP|IDCMP_REFRESHWINDOW,
				WA_Flags,	 WFLG_DRAGBAR|WFLG_DEPTHGADGET|WFLG_SMART_REFRESH|WFLG_ACTIVATE,
				WA_Gadgets,	 OptGList,
				WA_Title,	 &opttitle,
				WA_CustomScreen, screen,
				TAG_DONE ))) {

       FreeMem(fbuff, fsize);		 /*Puffer für zu optimierendes File*/
       FreeBuffer(FirstAllEquas);	 /*Puffer für Gleichungen*/
       FreeBuffer(FirstFileEquas);	 /*Puffer Gleichungen in String-Form*/
       ErrorReq(12);
       return(-1);
     }

     GT_RefreshWindow(optwin, NULL);


     orp = optwin->RPort;


     DrawBevelBox(orp, 18L, 134L, 344L, 47L, GTBB_Recessed, TRUE, GT_VisualInfo, VisualInfo, TAG_DONE);

     ClearMenuStrip(window);		 /* Menü entfernen */

     n    = 0;
     AllEquas.ThisBuff = FirstAllEquas;
     AllEquas.Entry    = (UBYTE *)(&FirstAllEquas->Entries[0]);
     AllEquas.BuffEnd  = (UBYTE *)FirstAllEquas + (long)sizeof(struct Buffer);
     equaflag = TRUE;			/*Gleichungen vorhanden*/




     while (equaflag) {

       SetAPen(orp, 0L);
       RectFill(orp, 30L, 23L, 630L, 132L);	/*Bildschirm löschen*/
       SetAPen(orp, 2L);

       oypos   = 20;			/*Variablen initialisieren*/
       scrolls = 0;
       reqflag = TRUE;

       PrintOptText(AppStrings[MSG_OLD_EQU].as_Str);
       PrintEqua(AllEquas, NULL);

       Move(orp, 30L, 148L);
       Text(orp, AppStrings[MSG_STAT].as_Str, 38L);

       Move(orp, 30L, 160L);
       Text(orp, AppStrings[MSG_OLD_EQU].as_Str, 15L);
       sprintf((char *)&statstrng[0], "%4d", num_of_ORs);

       Move(orp, 206L, 160L);
       Text(orp, (char *)statstrng, 4L);
       sprintf((char *)&statstrng[0], "%4d", num_of_ANDs);

       Move(orp, 294L, 160L);
       Text(orp, (char *)statstrng, 4L);

       if (!(FirstOptEqua = (struct Buffer *)AllocMem((long)sizeof(struct Buffer),MEMF_PUBLIC|MEMF_CLEAR))) {
	 FreeMem(fbuff, fsize);		/*Puffer für zu optimierendes File*/
         FreeBuffer(FirstAllEquas);	/*Puffer für Gleichungen*/
         FreeBuffer(FirstFileEquas);   /*Puffer Gleichungen in String-Form*/
	 CloseWindow(optwin);
         ResetMenuStrip(window, mainmenu);
	 ErrorReq(2);			/*kein Speicher mehr->Fehlermeldung*/
	 return(-1);
       }

       OptEqua.ThisBuff = FirstOptEqua;
       OptEqua.Entry    = (UBYTE *)(&FirstOptEqua->Entries[0]);
       OptEqua.BuffEnd  = (UBYTE *)FirstOptEqua + (long)sizeof(struct Buffer);

				/*Gleichung in den Optimizer-Puffer kopieren*/
       if (CopyEqua(AllEquas,OptEqua)) {
	 FreeMem(fbuff, fsize);		/*Puffer für zu optimierendes File*/
         FreeBuffer(FirstAllEquas);	/*Puffer für Gleichungen*/
         FreeBuffer(FirstOptEqua);	/*Puffer für Optimierer*/
         FreeBuffer(FirstFileEquas);   /*Puffer Gleichungen in String-Form*/
	 CloseWindow(optwin);
	 ErrorReq(2);			/*kein Speicher mehr->Fehlermeldung*/
         ResetMenuStrip(window, mainmenu);
	 return(-1);
       }

       Move(orp, 30L, 170L);
       Text(orp, AppStrings[MSG_OPT_EQU].as_Str, 21L);
       sprintf(&statstrng[0],"   -");

       Move(orp, 206L, 170L);
       Text(orp, (char *)statstrng, 4L);
       sprintf(&statstrng[0],"   -");

       Move(orp, 294L, 170L);
       Text(orp, (char *)statstrng, 4L);

				/*versuche die Gleichung zu optimieren*/
       SetWindowTitles(optwin, AppStrings[MSG_OPT_WAIT].as_Str, (UBYTE *)-1L);

       if (OptimizeEqua(OptEqua)) {
	 FreeMem(fbuff, fsize);		/*Puffer für zu optimierendes File*/
         FreeBuffer(FirstAllEquas);	/*Puffer für Gleichungen*/
         FreeBuffer(FirstOptEqua);	/*Puffer für Optimierer*/
         FreeBuffer(FirstFileEquas);   /*Puffer Gleichungen in String-Form*/
	 CloseWindow(optwin);
	 ErrorReq(2);			/*kein Speicher mehr->Fehlermeldung*/
         ResetMenuStrip(window, mainmenu);
	 return(-1);
       }
       SetWindowTitles(optwin, opttitle, (char *)-1L);

       PrintOptText(AppStrings[MSG_OPT_EQU].as_Str);
       PrintEqua(OptEqua, NULL);

       Move(orp, 30L, 170L);
       Text(orp, AppStrings[MSG_OPT_EQU].as_Str, 21L);
       sprintf(&statstrng[0],"%4d",num_of_ORs);

       Move(orp, 206L, 170L);
       Text(orp, (char *)statstrng, 4L);
       sprintf(&statstrng[0],"%4d",num_of_ANDs);

       Move(orp, 294L, 170L);
       Text(orp, (char *)statstrng, 4L);

       n++;
       sprintf((char *)&OptTxt1[21], "%d", n);
       strcat((char *)&OptTxt1[0], ":");

       Move(orp,389L, 146L);
       Text(orp, (char *)&OptTxt1[0], (long)strlen((char *)&OptTxt1[0]));


       notready = 1;

       while (notready) {

	 Wait (1 << optwin->UserPort->mp_SigBit);

         while (imsg = GT_GetIMsg(optwin->UserPort)) {

	   class = imsg->Class;
	   code  = imsg->Code;

	   if (class == GADGETUP)
	     gadID = ((struct Gadget *)imsg->IAddress)->GadgetID;


	   GT_ReplyIMsg(imsg);


	   if (class == GADGETUP) {

	     if (gadID == TAKEIT_GADID) {	/*Übernehmen*/
	       PrintEqua(OptEqua, &FileEquas);
	       notready = 0;
	     }

	     if (gadID == FORGETIT_GADID) {	/*Verwerfen*/
	       PrintEqua(AllEquas, &FileEquas);
	       notready = 0;
	     }

	   }
         }
       }

       FreeBuffer(FirstOptEqua);

       equaflag = GetNextEqua(&AllEquas);
     }


     CloseWindow(optwin);
     ResetMenuStrip(window, mainmenu);

					/*neues Source-File erstellen*/
     FileEquas.ThisBuff = FirstFileEquas;
     FileEquas.Entry    = (UBYTE *)(&FirstFileEquas->Entries[0]);
     FileEquas.BuffEnd  = (UBYTE *)FirstFileEquas + (long)sizeof(struct Buffer);

     if (MyFileReq(AppStrings[MSG_WRITE_SOURCE].as_Str, ".pld", YES, SAVE)) {
       PrintText(AppStrings[MSG_WRITE_OPTSOURCE].as_Str, 1);

       if (WriteNewSource(FileEquas, equastart, equaend)) {
	 PrintText(AppStrings[MSG_ERROR].as_Str,0);
         MyRequest(ERR_REQ, AppStrings[MSG_WRITE_ERR].as_Str);
       }
       else
	 PrintText(AppStrings[MSG_LOWER_OK].as_Str, 0);

     }
     FreeMem(fbuff, fsize);		/*Puffer für zu optimierendes File*/
     FreeBuffer(FirstFileEquas);	/*Puffer Gleichungen in String-Form*/
   }
   FreeBuffer(FirstAllEquas);
 }

 return(0);

}



/* GetProdTermStart: sucht den Anfang des Produktterms in den "pos" zeigt

   Aufruf   :	prodpos = GetProdTermStart(pos);
   Parameter:   pos : ActBuffer-Struktur für Produktterm, dessen Anfang
		      gesucht werden soll
   Ergebnis :   prodpos : ActBuffer-Struktur für den Produkttermanfang

*/
struct ActBuffer GetProdTermStart(struct ActBuffer pos)
{

 while(*pos.Entry) {
   if (IsOR(*pos.Entry)) {
     IncPointer(&pos);
     return(pos);
    }
   DecPointer(&pos);
  }

 IncPointer(&pos);
 return(pos);

}



/* KillProdTerm: löscht einen Produktterm "term" aus der Gleichung,
		 indem der Term mit EQUASKIP überschrieben wird
   Aufruf    : KillProdTerm(term);
   Parameter : term: ActBuffer-Struktur für den Produktterm
   Ergebnis  : ---
*/
void KillProdTerm(term)
struct ActBuffer term;
{
struct	ActBuffer  start;

 start = term;
 while((*term.Entry) && (!IsOR(*term.Entry))) {
   *term.Entry = EQUASKIP;
   IncPointer(&term);
  }

 if (IsOR(*term.Entry))
   *term.Entry = EQUASKIP;

 if (!*term.Entry) {
   while((*start.Entry) && (!IsOR(*start.Entry)))
     DecPointer(&start);
   if (IsOR(*start.Entry))
     *start.Entry = EQUASKIP;
  }
}




/* OptimizeEqua: Dies ist die eigentliche Routine, mit der die
   Boolesche Gleichung vereinfacht wird.

   Aufruf   : result = OptimizeEqua(buff);

   Parameter: buff: ActBuffer-Struktur der zu optimierenden Gleichung
   Ergebnis : result =  0:  alles o.k.
		     = -1:  Fehler: kein freier Speicher mehr
*/
int OptimizeEqua(buff)
struct ActBuffer buff;
{
struct	ActBuffer	optend, pos1, pos2, prodterm1, prodterm2;
UBYTE	merker;
int	varfound, prodfound, result;

 optend = buff;
 while (*optend.Entry != EQUAEND)	/*Gleichungsende suchen*/
   IncPointer (&optend);
 *optend.Entry = 0;			/*Gleichungsende anstatt mit EQUAEND*/
					/*mit 0 kennzeichnen*/

					/*Gleichungsanfang durch '0'*/
					/*kennzeichnen*/
 IncPointer (&buff);			/*erster Eintrag ist Ausgangspin*/
 if (!(*buff.Entry == 'T' || *buff.Entry == 'R' || *buff.Entry == 'E'
     ||*buff.Entry == 'C' || *buff.Entry == 'S' || *buff.Entry == 'P'))
   DecPointer (&buff);			/* Suffix berücksichtigen */

 merker = *buff.Entry;			/*Zeichen merken*/
 *buff.Entry = 0;			/*Markierung setzen*/
					/*optend = Gleichungsende*/
 IncPointer (&buff);			/*Zeiger auf erstes Zeichen*/

 if (!*buff.Entry) {			/*kein Zeichen da?*/
   if (AddByte(&buff, (UBYTE)(numofpins_Opt/2))) /*GND eintragen*/
     return(-1);			/*und Gleichungsende*/ 
   *buff.Entry = EQUAEND;
   DecPointer(&buff);
   DecPointer(&buff);
   *buff.Entry = merker;
   return(0);				/*fertig*/
  }   


 if (result = Resolvente(buff, optend, buff)) {	/*Resolventen bilden*/
   if (result == -1)				/*Fehler aufgetreten?*/
     return(-1);				/*ja, dann Fehlercode*/
   else {
     if (AddByte(&buff, (UBYTE)numofpins_Opt))	/*VCC eintragen*/
       return(-1);				/*und Gleichungsende*/ 
     *buff.Entry = EQUAEND;
     DecPointer(&buff);
     DecPointer(&buff);
     *buff.Entry = merker;
     return(0);					/*fertig*/
    }
  }


 optend = buff;
 while (*optend.Entry)			/*Gleichungsende suchen*/
   IncPointer(&optend);

		/*Absorptions-Gesetz anwenden: a + a * b <=> a */
		/*Prinzip: Es wird der Produktterm "prodterm1" mit allen*/
		/*andern ("prodterm2") verglichen und untersucht, ob einer*/
		/*ein Teil von diesem ist. Wenn ja, wird der andere Produkt-*/
		/*term gelöscht (mit EQUASKIP).*/

 pos1 = prodterm1 = buff;

 for (;;) {
   pos2 = buff;
   while (*pos2.Entry == EQUASKIP)	/*gelöschte Prod.terme*/
     IncPointer(&pos2);			/*überspringen*/
   for(;;) {
     varfound = 0;
     while (*prodterm1.Entry == EQUASKIP)	/*gelöschte Prod.terme*/
       IncPointer(&prodterm1);			/*überspringen*/
     while (*pos2.Entry) {			/*in der Gleichung nach der*/
       if (*pos2.Entry == *prodterm1.Entry) {	/*Variable suchen, die als*/
	 varfound = 1;				/*erstes im Prod.term steht*/
	 break;
	}
       IncPointer(&pos2);
      }
     if (!varfound)			/*for-Schleife abbrechen, wenn*/
       break;				/*keine entsprechende Variable*/
					/*gefunden wurde*/
     prodterm2 = GetProdTermStart(pos2);	/*Prod.term-Anfang suchen*/
     while (*prodterm2.Entry == EQUASKIP)	/*gelöschte Prod.terme*/
       IncPointer(&prodterm2);			/*überspringen*/
     if ((prodterm1.Entry != prodterm2.Entry) ||
	 (prodterm1.ThisBuff != prodterm2.ThisBuff) ||
	 (prodterm1.BuffEnd != prodterm2.BuffEnd)) {
       pos1 = prodterm1;		/*Prod.terme miteinander vergleichen*/
       for (;;) {
	 pos2      = prodterm2;
	 prodfound = 0;
	 for (;;) {
	   if (*pos1.Entry == *pos2.Entry) {
	     prodfound = 1;
	     break;
	    }
	   IncPointer(&pos2);
	   if ((*pos2.Entry) && (!IsOR(*pos2.Entry)) && (*pos2.Entry != EQUASKIP))
	     IncPointer(&pos2);
	   else
	     break;
	  }
	 if (!prodfound)
	   break;
	 IncPointer(&pos1);
	 if ((*pos1.Entry) && (!IsOR(*pos1.Entry)) && (*pos1.Entry != EQUASKIP))
	   IncPointer(&pos1);
	 else
	   break;
	}
       if (prodfound)
	 KillProdTerm(prodterm2);
      }
     if (*pos2.Entry)
       IncPointer(&pos2);
    }

   while((!IsOR(*pos1.Entry)) && (*pos1.Entry))  /*nächsten Prod.term suchen*/
     IncPointer(&pos1);
   if (!*pos1.Entry)				/*kein Prod.term mehr da*/
     break;					/*dann fertig*/
   IncPointer(&pos1);
   prodterm1 = pos1;
  }

 DecPointer(&buff);
 *buff.Entry = merker;			/*Gleichung wieder herstellen*/

 if (AddByte(&optend, (UBYTE)EQUAEND))	/*Gleichungsende wieder durch*/
   return(-1);				/*EQUAEND markieren*/
 if (AddByte(&optend, (UBYTE)0))
   return(-1);

 return(0);
}




/* Resolvente:	hängt eine neue Schicht von Resolventen an die
		zu optimierende Gleichung an

   Aufruf   :	result = Resolvente(optstart,optend,alteSchicht);

   Parameter:   optstart: ActBuffer-Struktur für Gleichungsanfang
		optend  : ActBuffer-Struktur für Gleichungsende
		alteSchicht: ActBuffer-Stuktur für vorherige Schicht
   Ergebnis :	result =  0: alles o.k.
		       =  1: A + /A (VCC) gefunden=>Gleichung immer erfüllt
		       = -1: Fehler (kein freier Speicher mehr) 
*/
int Resolvente(optstart, optend, alteSchicht)
struct ActBuffer optstart, optend, alteSchicht;
{
struct	ActBuffer	pos1, pos2, neueSchicht;
int	result, flag, resflag;		/*resflag: neue Resolvente*/
UBYTE	var;				/*gefunden?*/
					/*neueSchicht: zeigt auf Stelle, an*/
					/*der weitere Resolventen angefügt*/
					/*werden können (Ende)*/

 if ((IsOR(*alteSchicht.Entry)) || (IsAND(*alteSchicht.Entry)))
   IncPointer(&alteSchicht);
 resflag     = 0;			/*lokale Variablen initialisieren*/
 pos1	     = alteSchicht;
 neueSchicht = optend;


 for (;;) {
   var  = *pos1.Entry;			/*Variable (Pinnummer) holen*/
   if (var & NEGATION)			/*Variable negieren*/
     var = var & (~NEGATION);
   else
     var = var | NEGATION;

   pos2 = optstart;			/*suche nach "/var"*/
   for(;;) {
      if (!SearchVar(&pos2,neueSchicht,var)) {
	result = AddResolvente(pos1,pos2,optstart,&optend);
	flag = 0;				  /*wenn die Variable ge-*/
	while (pos2.Entry != neueSchicht.Entry) { /*funden wurde, wird pos2*/
	  if (IsOR(*pos2.Entry)) {	/*auf den nächsten Produktterm ge-*/
	    flag = 1;			/*stellt. Wenn keiner da ist, bleibt*/
	    IncPointer(&pos2);		/*flag 0 und weiter unten erfolgt*/
	    break;			/*dann der Abbruch (if (!flag)..)*/
	   }
	  IncPointer (&pos2);
	 }
        if (!result)
          resflag = 1;
        else {
	  if (result == 2)		/*A + /A gefunden? => Ausdruck wahr*/
	    return(1);			/*dann fertig*/
	  if (result == -1)
	    return(-1);
	 }
        if (!flag)			/*kein Produktterm mehr da?*/
	  break;			/*dann Abbruch*/
      }
     else
       break;
  }

   IncPointer(&pos1);			/*Operator überspringen und pos1*/
   if (pos1.Entry != neueSchicht.Entry) /*auf nächste Variable, falls nicht*/
     IncPointer(&pos1);			/*bereits der neue Schichtanfang*/
   else					/*erreicht wurde, sonst Abbruch*/
     break;
 }


 if (!resflag)				/*wurde neue Resolvente gefunden?*/
   return(0);				/*nein, dann fertig*/
 else {					/*ja, dann Rekursion*/
   return (Resolvente(optstart, optend, neueSchicht));
  }
}




/* NumOfVar: gibt die Anzahl der Variablen im Produktterm zurück

   Aufruf   : vars = NumOfVar(term);
   Parameter: term: ActBuffer-Struktur auf Produktterm-Anfang
   Ergebnis : vars: Integer-Variable - enthält die Anzahl
*/
int NumOfVar(term)
struct ActBuffer term;
{
int	numofvar;

 numofvar = 0;
 for (;;) {
   numofvar++;
   IncPointer(&term);
   if (!*term.Entry || (IsOR(*term.Entry)))
     break;
   IncPointer(&term);
  }
 return(numofvar);

}




/* AddResolvente: Fügt die beiden Produktterme in die "pos1" und "pos2"
	zeigt zusammen, wobei die Variablen (Pinnummern) die unter "pos1"
	und "pos2" stehen nicht berücksichtigt werden. Dann wird untersucht,
	ob der neuentstandene Produktterm schon in der Gleichung steht.
	Wenn nicht, wird der Produktterm an "equaend" angehängt.
	Eine neue Resolvente ist geboren - welch' Dramatik.

   Aufruf:	result = AddResolvente(pos1,pos2,equastart,equaend);
   Parameter:	pos1, pos2	: ActBuffer-Struktur
		equastart	: ActBuffer-Struktur für Gleichungsanfang
		equaend		: Zeiger(!) auf ActBuffer-Struktur
		Parametererklärung siehe obigen Text
   Ergebnis :	result =  0: es wurde eine Resolvente gebildet und angehängt
			     equaend zeigt auf neues Ende
		       =  1: keine Resolvente
		       =  2: A + /A wurde gefunden (VCC -> fertig)
		       = -1: Fehler, kein Speicher
*/
int AddResolvente(pos1, pos2, equastart, equaend)
struct ActBuffer pos1, pos2, equastart, *equaend;
{
struct	 ActBuffer  pos, res, res1, res2, prodterm, nextprodterm;
int	 n, i, numofvar, numofvar1, numofvar2;
int	 found;
UBYTE	 *termbuff, *term, entry;


 res1 = GetProdTermStart(pos1);		/*ActBuffer-Struktur für den*/
 res2 = GetProdTermStart(pos2);		/*jeweiligen Produkttermanfang holen*/

 if ((res1.Entry == res2.Entry) &&
     (res1.ThisBuff == res2.ThisBuff) &&
     (res1.BuffEnd == res1.BuffEnd))
   return(1);

 numofvar1 = NumOfVar(res1);		/*Anzahl der benötigten Bytes*/
 numofvar2 = NumOfVar(res2);		/*für die beiden Prod.terme holen*/

 if (!(termbuff = (UBYTE *)AllocMem((long)(numofvar1+numofvar2+1),MEMF_PUBLIC|MEMF_CLEAR)))
   return(-1);

					/*hier werden die beiden Produktterme*/
 numofvar = numofvar1;			/*res1 und res2 zusammengehängt und*/
 res      = res1;			/*in "termbuff" abgelegt (ohne '*'!)*/
 pos      = pos1;
 for (i=0; i<2; i++) {			/*zwei Produktterme*/
   for (n=0; n<numofvar; n++) {
     if (res.Entry != pos.Entry) {
       term  = termbuff;		/*keine doppelten Pins zulassen*/
       entry = *res.Entry;
       found = 0;
       while (*term) {
	 if (entry & NEGATION) {	/* "a * /a" nicht zulassen*/
	   if (*term == (entry & (~NEGATION))) {
	     FreeMem(termbuff, (long)(numofvar1+numofvar2+1));
	     return(1);
	    }
	  }
	 else {
	   if (*term == (entry | NEGATION)) {
	     FreeMem(termbuff, (long)(numofvar1+numofvar2+1));
	     return(1);
	    }
	  }
	 if (*term == entry)
	   found = 1;

	 term++;
	}

       if (!found)
	 *term = entry;
      }
     IncPointer(&res);
     IncPointer(&res);
    }
   numofvar = numofvar2;
   res      = res2;
   pos	    = pos2;
  }

 if (!*termbuff)			/*wenn termbuff leer ist, dann*/
   *termbuff = numofpins_Opt;		/*war A+/A in der Gleichung => VCC*/
				/*untersuchen, ob der neue Prod.term*/
				/*"termbuff"  schon existiert*/
 pos   = equastart;
 found = 0;
 for(;;) {
   prodterm = pos;
   while ((!IsOR(*pos.Entry)) && (entry = *pos.Entry)) {
     term  = termbuff;
     found = 0;
     while (*term) {
       if (*term == entry) {
	 found = 1;
	 break;
	}
       term++;
      }
     if (!found)
       break;
     IncPointer(&pos);
     if (IsAND(*pos.Entry))		/*'*' überspringen, falls vorhanden*/
       IncPointer(&pos);
    }


   while ((!IsOR(*pos.Entry)) && (*pos.Entry))	/*nächsten Prod.term suchen*/
     IncPointer(&pos);

   nextprodterm = pos;

   if (found) {
     term = termbuff;
     while (*term) {
       pos   = prodterm;
       found = 0;
       while ((!IsOR(*pos.Entry)) && (entry = *pos.Entry)) {
	 if (entry == *term) {
	   found = 1;
	   break;
	  }
         IncPointer(&pos);
	 if (IsAND(*pos.Entry))
	   IncPointer(&pos);
        }
       if (!found)
	 break;
       term++;
      }
    }
   if (found)
     break;				/*for-Schleife verlassen*/

   pos = nextprodterm;
   if (!*pos.Entry)
     break;

   IncPointer(&pos);
  }


 if (!found) {				/*existiert Prod.term schon ?*/
   if (AddByte(equaend, (UBYTE)'+')) {	/*nein, dann an Gleichung anhängen*/
     FreeMem(termbuff, (long)(numofvar1+numofvar2+1));
     return(-1);
    }
   term = termbuff;
   while (*term) {
     if (AddByte(equaend, (UBYTE)*term)) {
       FreeMem(termbuff, (long)(numofvar1+numofvar2+1));
       return(-1);
      }
     if (AddByte(equaend, (UBYTE)'*')) {
       FreeMem(termbuff, (long)(numofvar1+numofvar2+1));
       return(-1);
      }
     term++;
    }
   DecPointer(equaend);
   *equaend->Entry = 0;				/*Endmarkierung*/
   entry = *termbuff;
   FreeMem(termbuff, (long)(numofvar1+numofvar2+1));
   if (entry == numofpins_Opt)			/*wenn VCC gefunden wurde,*/
     return(2);					/*dann 2 zurückgeben*/
   else
     return(0);
  }

 FreeMem(termbuff, (long)(numofvar1+numofvar2+1));
 return(1);
}








/* SearchVar: suche ab "pos" den Pin "var" bis nach "end"
	      Die Pinnummern werden jetzt als Variablen bezeichnet, da
	      sie ab jetzt wie Boolesche Variablen behandelt werden.
   Aufruf   : result = SearchVar(pos,end,var);

   Parameter: pos : Zeiger auf ActBuffer-Struktur - Startposition ab
		    der gesucht werden soll
	      end : ActBuffer-Stuktur für Ende
	      var : Variable nach der gesucht werden soll
   Ergebnis : result =  0: gefunden, pos zeigt auf Zeichen
		     = -1: nicht gefunden
*/
int SearchVar(register struct ActBuffer *pos, register struct ActBuffer end, register UBYTE var)
{

 while (pos->Entry != end.Entry) {	/*bis zum Ende suchen*/
   if (*pos->Entry == var)
     return(0);
   IncPointer(pos);
  }
 return(-1);

}







/* WriteNewSource: Erstellt aus dem alten Source-File und der Liste der
		   neuen Gleichungen (optimiert) ein neues Source-File.
		   Dabei werden die Gleichungen aus dem alten Source-File
		   durch die neuen ersetzt.
  Aufruf:   result = WriteNewSource(buff, equastart, equaend);
  Parameter: file:  ActBuffer-Struktur für Liste der Gleichungen
		    in String-Form
	     equastart: Zeiger auf die Stelle im original Source-File,
			an der die Gleichungen beginnen
	     equaend  : Zeiger auf die Stelle im original Source-File,
			an der die Gleichungen enden (DESCRIPTION)
  Ergebnis : result =  0: alles o.k.
		    = -1: Fehler beim Schreiben
*/
int WriteNewSource(buff, equastart, equaend)
struct ActBuffer buff;
UBYTE *equastart;
UBYTE *equaend;
{
long	result;
BPTR	fh;
UBYTE	*filebuffer, *filebuffer2;


 if ((fh = Open(&path[0], (long)MODE_NEWFILE))) {
					/*Header des Source-Files schreiben*/
   result = Write(fh, (char *)fbuff, (long)(equastart-fbuff));
   if (result == -1L) {				/*Fehler beim Schreiben?*/
     Close(fh);					/*ja, dann Ende*/
     return(-1);
    }
					/*Gleichungen schreiben*/
   for (;;) {
     filebuffer = filebuffer2 = buff.Entry;

     while (filebuffer2 < buff.BuffEnd) {	/*Größe des Puffers bestimmen*/
       if (!*filebuffer2) 
	 break;
       filebuffer2++;
      }

     result = Write(fh, (char *)filebuffer, (long)(filebuffer2-filebuffer));
     if (result == -1L) {			/*Fehler beim Schreiben?*/
       Close(fh);				/*ja, dann Ende*/
       return(-1);
      }

     if (!buff.ThisBuff->Next)			/*noch ein Puffer da?*/
       break;					/*nein, dann for(;;)-Ende*/
     buff.ThisBuff = buff.ThisBuff->Next;
     buff.Entry    = (UBYTE *)(&buff.ThisBuff->Entries[0]);
     buff.BuffEnd  = (UBYTE *)buff.ThisBuff + (long)sizeof(struct Buffer);
    }

					/*Teil ab DESCRIPTION schreiben*/
   result = Write(fh, (char *)equaend, (long)(fbuff+fsize-equaend));
   if (result == -1L) {				/*Fehler beim Schreiben?*/
     Close(fh);					/*ja, dann Ende*/
     return(-1);
    }

   Close(fh);
  }
 else
   return(-1);

 return(0);
}





/* CopyEqua:  Kopiert eine Gleichung aus dem Puffer from_buff in den
	      Puffer to_buff. Dabei werden unsinnige Konstruktionen
	      wie  A*A*B*A, A * /A * B bereits voroptimiert.
   Aufruf  :  result = CopyEqua(from_buff, to_buff);
   Paramter:  from_buff: ActBuffer-Struktur der Quelle (kein Zeiger!!!)
	      to_buff  : ActBuffer-Struktur des Ziels  (kein Zeiger!!!)
   Ergebnis:  0: alles o.k.     sonst: Fehler (kein Speicher)
*/
int CopyEqua(from_buff, to_buff)
struct ActBuffer from_buff, to_buff;
{
struct	 ActBuffer	equastart, prodtermstart, pos;
UBYTE	 entry, pins[2*24];
register int	n;


 if (AddByte(&to_buff, (UBYTE)*from_buff.Entry)) /*Ausganspin kopieren*/
   return(-1);

 IncPointer(&from_buff);
 entry = *from_buff.Entry;
 if (entry == 'T' || entry == 'R' || entry == 'E' ||
     entry == 'C' || entry == 'S' || entry == 'P') {

   if (AddByte(&to_buff, (UBYTE)entry))		/*T,R,E kopieren*/
     return(-1);
   IncPointer(&from_buff);
  }

						/*Gleichung kopieren*/
 equastart = prodtermstart = to_buff;
 for (;;) {
   for (n=0; n<2*24; pins[n++]=0);

   for (;;) {
     entry = *from_buff.Entry;

     if (entry & NEGATION) {
       if (pins[(entry&~NEGATION)-1]) {		/* A * /A ? */
	 pos = prodtermstart;			/*ja, dann Term im to_buff*/
	 while (pos.Entry != to_buff.Entry) {	/*löschen und im from_buff*/
	   *pos.Entry = EQUASKIP;		/*überspringen*/
	   IncPointer(&pos);
	  }
	 to_buff = prodtermstart;
	 while ((!IsOR(*from_buff.Entry)) && (*from_buff.Entry != EQUAEND))
	   IncPointer(&from_buff);
	 DecPointer(&from_buff);
	}
       else {
	 if (!pins[(entry&~NEGATION)-1+24]) {	/*Pin mehrmals im Produktterm?*/
	   pins[(entry&~NEGATION)-1+24] = 1;	/*nein, dann kopieren*/
 	   if (AddByte(&to_buff, (UBYTE)entry))	/*Pinnummer kopieren*/
	     return(-1);
	  }
	}
      }
     else {
       if (pins[entry-1+24]) {			/* A * /A ? */
	 pos = prodtermstart;			/*ja, dann Term im to_buff*/
	 while (pos.Entry != to_buff.Entry) {	/*löschen und im from_buff*/
	   *pos.Entry = EQUASKIP;		/*überspringen*/
	   IncPointer(&pos);
	  }
	 to_buff = prodtermstart;
	 while ((!IsOR(*from_buff.Entry)) && (*from_buff.Entry != EQUAEND))
	   IncPointer(&from_buff);
	 DecPointer(&from_buff);
	}
       else {
	 if (!pins[entry-1]) {			/*Pin mehrmals im Produktterm?*/
	   pins[entry-1] = 1;			/*nein, dann kopieren*/
 	   if (AddByte(&to_buff, (UBYTE)entry))	/*Pinnummer kopieren*/
	     return(-1);
	  }
	}
      }


     IncPointer(&from_buff);			/*Zeiger auf Operator oder */
     entry = *from_buff.Entry;			/*EQUAEND und in to_buff*/

     if (entry == EQUAEND) {			/*Ende erreicht?*/
       DecPointer(&to_buff);			/*ja, dann fertig*/
       if (!( IsOR(*to_buff.Entry) || IsAND(*to_buff.Entry) ))
	 IncPointer(&to_buff);			/* +,* am Ende wegmachen*/
       if (AddByte(&to_buff, (UBYTE)EQUAEND))	/*Endmarkierung setzen*/
	 return(-1);
       return(0);
      }

     if (to_buff.Entry != equastart.Entry) {	/*noch am Anfang?*/
       DecPointer(&to_buff);
       if (!IsOR(*to_buff.Entry)) {
	 if (!IsAND(*to_buff.Entry)) {
	   IncPointer(&to_buff);
	   if (AddByte(&to_buff, (UBYTE)entry))
	     return(-1);
	  }
	 else {
	   if (IsOR(entry))
	     *to_buff.Entry = '+';
	   IncPointer(&to_buff);
	  }
	}
       else
	 IncPointer(&to_buff);
      }


     if (IsOR(entry))				/*Produkttermende?*/
       break;					/*for-Schleife verlassen*/


     IncPointer(&from_buff);			/*Zeiger auf Pinnamen*/
    }

   prodtermstart = to_buff;

   IncPointer(&from_buff);
  }

}




/* PrintEqua:

 prints coded equation which ends with ENDEQUAS or ENDEQUA

 Call:       result = PrintEqua(buff, flag);
 Parameter:  buff: ActBuffer structure (no pointer!!!)
	     filebuff = 0: prints equation into window
		      = pointer to ActBuffer structure: put the optimized
			equations in a buffer (ActBuffer) which is than used
			to generate the source file
 Result:     result = 0: o.k.    else: error (no memory)
	     num_of_ORs, num_of_ANDs: number of ORs and ANDs
*/
int PrintEqua(buff, filebuff)
struct ActBuffer buff, *filebuff;
{
char	estrng[SIZE_OF_EQUASTRING];
int	n, entry, xoffset, notready;


  num_of_ORs = num_of_ANDs = 0;
  estrng[0] = 0;				/* clear string */

  entry = *buff.Entry;

  if (entry & NEGATION) {
    strcat((char *)&estrng[0], "/");
    entry = entry & (~NEGATION);
  }

  if (IsNEG(PinNamesOpt[entry-1][0]))
    strcat((char *)&estrng[0], (char *)&PinNamesOpt[entry-1][1]); /* output */
  else
    strcat((char *)&estrng[0], (char *)&PinNamesOpt[entry-1][0]);

  entry = GetNext(&buff);

  if (entry == 'T') {
    entry = GetNext(&buff);
    strcat ((char *)&estrng[0], ".T");		/* print suffix */
  }
  else
    if (entry == 'E') {
      entry = GetNext(&buff);
      strcat ((char *)&estrng[0], ".E");
    }
    else
      if (entry == 'R') {
        entry = GetNext(&buff);
        strcat ((char *)&estrng[0], ".R");
      }
      else
	if (entry == 'C') {
	  entry = GetNext(&buff);
	  strcat ((char *)&estrng[0], ".CLK");
	}
        else
	  if (entry == 'S') {
	    entry = GetNext(&buff);
	    strcat ((char *)&estrng[0], ".ARST");
	  }
          else
	    if (entry == 'P') {
	      entry = GetNext(&buff);
	      strcat ((char *)&estrng[0], ".APRST");
	    }



  strcat ((char *)&estrng[0], " = ");		/* add '=' */

  xoffset = strlen(&estrng[0]);			/* save length of string*/

  notready = TRUE;

  while (notready) {
    while (strlen(&estrng[0]) < (SIZE_OF_EQUASTRING - 15)) {

      if (entry & NEGATION) {
        strcat((char *)&estrng[0], "/");
        entry = entry & (~NEGATION);
      }

      if (IsNEG(PinNamesOpt[entry-1][0]))		/* get pin name */
        strcat ((char *)&estrng[0], (char *)&PinNamesOpt[entry-1][1]);
      else
        strcat ((char *)&estrng[0], (char *)&PinNamesOpt[entry-1][0]);

      if ((entry = GetNext(&buff)) == EQUAEND) {
        notready = FALSE;
        break;
      }

      if (IsOR(entry)) {
        strcat((char *)&estrng[0], " + ");	/* get op. */
        num_of_ORs++;
      }
      else {
        strcat((char *)&estrng[0], "*");
        num_of_ANDs++;
      }

      if ((entry = GetNext(&buff)) == EQUAEND) {
        notready = FALSE;
        break;
      }

    }

    if (!filebuff)
      PrintOptText((UBYTE *)&estrng[0]);	/* print one line */
    else {
      n = 0;					/* put string into list */
      while (estrng[n]) {
        if (AddByte(filebuff, (UBYTE)estrng[n]))
          return(-1);
        n++;
      }
      if (AddByte(filebuff, (UBYTE)0x0A))	 /*add a return*/
        return(-1);
    }

    for (n=0; n<xoffset; n++)			/*add spaces ' ' up to */
      estrng[n] = ' ';				/*xoffset*/
    estrng[xoffset] = 0;			/*clear the rest of string*/
  }

  if (filebuff)					/*make file list?*/
    if (AddByte(filebuff, (UBYTE)0x0A))		/*add a return at the end*/
      return(-1);				/*of an equation*/

  return(0);
}








/* GetNext:
 get next entry from the buffer which is no EQUASKIP

 Call:  entry = GetNext(buff);
 Parameter: buff: pointer to ActBuffer structure
 Result:    entry: next entry which is no EQUASKIP
*/
int GetNext(buff)
struct ActBuffer *buff;
{

  do
    IncPointer(buff);
  while (*buff->Entry == EQUASKIP);

  return(*buff->Entry);
}




/*GetNextEqua:
 searchs next coded equation

 Call:     result = GetNextEqua(buff);
 Parameter:  buff :  pointer to ActBuffer structure
 Result:      FALSE :  no more equations
	      TRUE  :  one equation found
	      buff  :  actuell pointer to ActBuffer structure
*/
int GetNextEqua(buff)
struct ActBuffer *buff;
{

  while (*buff->Entry != EQUAEND)
    IncPointer(buff);

  IncPointer(buff);

  if (*buff->Entry == EQUASEND)
    return(FALSE);
  else
    return(TRUE);

}
 





/* PrintOptText:
  prints text in optimizer's window
  scrolls automatically when the bottom of the window is reached

   Parameter:  txt: pointer to string
	       global variable: oypos: y-pos. for the text
   Result : ---
*/
void PrintOptText(txt)
UBYTE *txt;
{

  if (oypos < 130)
    oypos += 10;
  else {
    if (reqflag) {
      ScrollRequester();
      reqflag = FALSE;
    }
    scrolls++;
    ScrollRaster(orp,0L,10L,30L,23L,630L,132L);
  }

  Move(orp, 30L, (long)oypos);
  Text(orp, (char *)txt, (long)strlen((char *)txt));

  if (scrolls == 11) {
    scrolls = 1;
    ScrollRequester();
  }

}





/*ScrollRequester :   pops up a requester and waits for a key stroke
		      or a selection of the "Continue" gadget
  Parameter:  --
  Result :    --
*/
void ScrollRequester(void)
{

  rtEZRequestTags(AppStrings[MSG_PAUSE].as_Str,
		  AppStrings[MSG_CONT_GAD].as_Str,
		  NULL, NULL, RT_ReqPos, REQPOS_CENTERSCR, TAG_END);

}





/* TranslateEqua:
  Translate all Boolean equations from the ASCII form into a coded form.
  Now it's easier to deal with the equations.

  Code: pinname  ->  pin number
       /pinname  ->  pin number and bit 7 set
 	T,R,E,+,*  ->  T,R,E,+,* 
        CLK, ARST, APRST -> C, S, P
	CR,LF,'.','=' are skiped

   Call   : result = TranslateEqua(buff)
   Parameter: buff : pointer to ActBuffer structure
   Result:  0: o.k.    else: error
	      actptr: points to the end of the equations
*/
int TranslateEqua(buff)
struct ActBuffer *buff;
{
int	n;
UBYTE	chr, entry;
char	suffix_strn[MAX_SUFFIX_SIZE];


  if (GetNextChar()) {				/*end of file?*/
    AsmError(2, 0);				/*yes, then end*/
    return(-1);
  }
						/*is there an equation?*/
  if (!strncmp((char *)actptr, "DESCRIPTION", (size_t)11)) {
    AsmError(33, 0);				/*no, then error*/
    return(-1);
  }

  for (;;) {
    IsPinName((UBYTE *)&PinNamesOpt[0], numofpins_Opt);
    if (!actPin.p_Pin) {			/*pin name?*/
      AsmError(11, 0);				/*no, then error*/
      return(-1);
    }

    if (actPin.p_Neg)
      entry = actPin.p_Pin | NEGATION;
    else
      entry = actPin.p_Pin;
    if (AddByte(buff, (UBYTE)entry))
      return(-1);


    if (*actptr == '.') {			/* get suffix */

      actptr++;

      n = 0;
      while (isalpha(*actptr)) {		/* copy suffix string into */
	if (n < MAX_SUFFIX_SIZE)	 	/* suffix array */
	  suffix_strn[n++] = *actptr++;
	else {					/* string too long, then */
	  AsmError(13, 0);			/* unknown suffix */
	  return(-1);
	}
      }

      suffix_strn[n] = 0;			/* mark end of string */

      if (!strcmp(&suffix_strn[0], "T"))
	chr = 'T';
      else
	if (!strcmp(&suffix_strn[0], "R"))
	  chr = 'R';
	else
	  if (!strcmp(&suffix_strn[0], "E"))
	    chr = 'E';
	  else
	    if (!strcmp(&suffix_strn[0], "CLK"))
	      chr = 'C';
	    else
	      if (!strcmp(&suffix_strn[0], "ARST"))
		chr = 'S';
	      else
	 	if (!strcmp(&suffix_strn[0], "APRST"))
		  chr = 'P';
		else {
		  AsmError(13, 0);
		  return(-1);
		}

      if (AddByte(buff, (UBYTE)chr))		/* add code of suffix */
        return(-1);
    }


    if (GetNextChar()) {			/*end of file?*/
      AsmError(2, 0);
      return(-1);
    }

    if (*actptr != '=') {			/* '='?*/
      AsmError(14, 0);				/*no, then error*/
      return(-1);
    }	     

    actptr++;

    if (GetNextChar()) {			/*end of file?*/
      AsmError(2, 0);				/*yes, then error*/
      return(-1);
    }

    for (;;) {
      IsPinName((UBYTE *)&PinNamesOpt[0], numofpins_Opt);
      if (!actPin.p_Pin) {			/*pin name?*/
        AsmError(11, 0);			/*no, then error*/
        return(-1);
      }

      if (actPin.p_Neg)
        entry = actPin.p_Pin | NEGATION;
      else
        entry = actPin.p_Pin;
      if (AddByte(buff, (UBYTE)entry))
        return(-1);

      if (GetNextChar()) {		/*end of file?*/
        AsmError(2, 0);			/*yes, then error*/
        return(-1);
      }

      if (!( IsOR(*actptr) || IsAND(*actptr) )) {	   /*OR or AND?*/
        if (strncmp((char *)actptr, "DESCRIPTION", (size_t)11)) { /*DESCRIPTION? */
	  if (AddByte(buff, (UBYTE)EQUAEND))  /*set mark for the end of the*/
	    return(-1);			      /*equation*/
          break;				/*no OR nor AND, then end*/
	}
        else {
	  if (AddByte(buff, (UBYTE)EQUAEND))  /*set mark for the end of the*/
	    return(-1);			      /*equation*/
	  if (AddByte(buff, (UBYTE)EQUASEND)) /*set mark for the end of all*/
	    return(-1);		    /*equations (after this mark DESCRIPTION)*/
	  return(0);		    /*follows). Now all equations are*/
	}			    /* translated */
      }

      if (AddByte(buff, (UBYTE)*actptr))
        return(-1);

      actptr++;

      if (GetNextChar()) {		/*unexpected end of file?*/
        AsmError(2, 0);
        return(-1);
      }
    }
  }
}




