/****************************************************************/
/*								*/
/* GALAsm.c - enthält GAL-Assembler				*/
/*								*/
/* compilieren: cc GALAsm.c					*/
/*								*/
/****************************************************************/



#include "exec/types.h"
#include "exec/memory.h"
#include <ctype.h>
#include <stdio.h>
#include <functions.h>
#include "GALer.h"



extern	int	linenum, MaxFuseAdr;
extern	int	GenJedec, GenFuse, GenChip, GenPin;
extern	UBYTE	*actptr, *buffend, GadgetSBuff[60];

extern	struct	JedecStruct	Jedec;


struct	Pin		actPin;
struct	GAL_OLMC	OLMC[8];


			/*Diese Arrays geben an in welche Spalte der ent- */
			/*sprechende Pin eingekoppelt (bzw. rückgekoppelt)*/
			/*wird. Für die invertierende Einkopplung ist 1 zu*/
			/*addieren, um die entsprechende Spalte zu erhalten*/
			/* -1: keine Einkopplung auf Fuse-Matrix vorhanden */
			/*GAL16V8:*/
int	PinToFuse16Mode1[20]	= {  2, 0, 4, 8,12,16,20,24,28,-1,
				    30,26,22,18,-1,-1,14,10, 6,-1 };
int	PinToFuse16Mode2[20]	= {  2, 0, 4, 8,12,16,20,24,28,-1,
				    30,-1,26,22,18,14,10, 6,-1,-1 };
int	PinToFuse16Mode3[20]	= { -1, 0, 4, 8,12,16,20,24,28,-1,
				    -1,30,26,22,18,14,10, 6, 2,-1 };

			/*GAL20V8:*/
int	PinToFuse20Mode1[24]	= {  2, 0, 4, 8,12,16,20,24,28,32,36,-1,
				    38,34,30,26,22,-1,-1,18,14,10, 6,-1 };
int	PinToFuse20Mode2[24]	= {  2, 0, 4, 8,12,16,20,24,28,32,36,-1,
				    38,34,-1,30,26,22,18,14,10,-1, 6,-1 };
int	PinToFuse20Mode3[24]	= { -1, 0, 4, 8,12,16,20,24,28,32,36,-1,
				    -1,38,34,30,26,22,18,14,10, 6, 2,-1 };

			/*dieses Array gibt an in welcher Zeile der*/
			/*erste Eingang der OLMC-Zelle liegt*/
int	ToOLMC[8]		= { 56,48,40,32,24,16, 8, 0 };



UBYTE	PinNames[24][10];
UBYTE	ModeErrorStr[] = {"Modus x:  Pin xx"};



LONG	fsize;
UBYTE	*fbuff;

int	num_of_pins, num_of_col, modus, gal_type;
int	pinnameflag = 0;


/* AssembleInputFile:
   Eingabe-Datei assemblieren
   Aufruf: AssembleInputFile();
*/
AssembleInputFile()
{
UBYTE	chr, filenamebuff[64];
UBYTE	*bool_start;
char	prevOp;
int	i, j, k, l, n, m;
int	oldMaxFuseAdr, max_chr;
int	pass, pin_num, bool_linenum;
int	actOLMC, row_offset;


 if (MyRequest(LOAD_REQ,(UBYTE *)"Bitte Namen des Source-Files eingeben")) {
   strcpy(&filenamebuff,&GadgetSBuff);		/*.pld an Dateinamen anfügen*/
   strcat(&filenamebuff,(UBYTE *)".pld");

   fsize=FileSize(&filenamebuff);
   switch (fsize) {
     case -1L: {
       ErrorReq(1);
       return(-1);
       break;
      }
     case -2L: {
       ErrorReq(2);
       return(-2);
       break;
      }
     case 0L: {
       ErrorReq(4);
       return(-4);
       break;
      }
    }
   if ((fbuff=(UBYTE *)AllocMem(fsize,MEMF_PUBLIC))) {
     if ((ReadFile(&filenamebuff,fsize,fbuff))) {
       PrintText((UBYTE *)"Datei ist geladen");


       actptr  = fbuff;
       buffend = fbuff+fsize;
       linenum = 1;

       for (n=0; n<sizeof(Jedec); n++) {	/*Jedec-Sruktur zurücksetzen*/
	 if (n < LOGIC20_SIZE)
	   Jedec.GALLogic[n] = 1;		/*Fuse-Matrix auf 1*/
	 else
	   Jedec.GALLogic[n] = 0;		/*ACW, PT usw. auf 0*/
	}

       for (n=0; n<8; n++) {			/*OLMC-Sruktur auf 0 setzen*/
	 OLMC[n].Active  = 0;
	 OLMC[n].PinType = 0;
	 OLMC[n].TriCon  = 0;
	 OLMC[n].LineNum = 0;
	}
					/*GAL-Typ feststellen*/
       if (!strncmp(actptr,(UBYTE *)"GAL16V8",7)) {
	 num_of_pins = 20;			/*Anzahl der Pins   */
	 num_of_col  = MAX_FUSE_ADR16 + 1;	/*Anzahl der Spalten*/
	 gal_type    = GAL16V8;
        }
       else
         if (!strncmp(actptr,(UBYTE *)"GAL20V8",7)) {
	   num_of_pins = 24;			/*Anzahl der Pins   */
	   num_of_col  = MAX_FUSE_ADR20 + 1;	/*Anzahl der Spalten*/
	   gal_type    = GAL20V8;
	  }
	 else {
	   AsmError(1);
	   return(-1);
	  }

					/*Signatur (8 Bytes der 2.Zeile) in Puffer schreiben*/
       if (GetNextLine()) {			/*Datei-Ende erreicht?*/
	 AsmError(2);				/*ja, dann Fehler*/
	 return(-1);
	}
       n = m = 0;
       while((*actptr!=0x0A) && (n<8)) {	/*Signatur in Jedec-Stuktur schreiben*/
	 chr = *actptr;
	 for (m=0; m<8; m++) {
	   Jedec.GALSig[n*8+m] = (chr>>(7-m)) & 0x1; 
	  }
	 actptr++;
	 n++;
	 if (actptr>buffend) {			/*Fileende erreicht ?*/
	   AsmError(2);				/*ja, dann Fehler*/
	   return(-1);
	  }
	} 

					/*Pin-Namen in "PinNames" eintragen*/
       pinnameflag = 0;					/*Pinnamen ungültig*/
       GetNextLine();
       for (n=0; n<num_of_pins; n++) {
	  if (GetNextChar(FALSE)) {			/*Dateiende?*/
	    AsmError(2);				/*ja, dann Fehler*/
	    return(-1);
	   }
	  m = 0;
	  chr = *actptr;
	  if (chr == '/')
	    max_chr = 10;
	  else
	    max_chr = 9;
	  if (!(isalpha(chr) || isdigit(chr) || chr=='/')) {
	    AsmError(5);
	    return(-1);
	   }
	  k = 0;
	  while (isalpha(chr) || isdigit(chr) || chr=='/') {
	     if ((chr == '/') && (k != 0)) {	/* '/' nicht am Anfang des Pinnamens?*/
	       AsmError(10);
	       return(-1);
	      }
	     k = 1;
	     actptr++;
	     if ((chr=='/') && (!(isalpha(*actptr) || isdigit(*actptr)))) {
	       AsmError(3);
	       return(-1);
	      }
	     PinNames[n][m] = chr;
	     m++;
	     chr = *actptr;
	     if (m == max_chr) {		/*zuviele Buchstaben?*/
	       AsmError(4);
	       return(-1);
	      }
	    }
	  PinNames[n][m] = 0;			/*Stringende kennzeichnen*/

	  for (l=0; l<n; l++) {			/*Pinname doppelt?*/
	    if (strcmp(&PinNames[l],(UBYTE *)"NC")) {
	      i = j = 0;
	      if (PinNames[l][0] == '/') i = 1;
	      if (PinNames[n][0] == '/') j = 1;
	      if (!strcmp(&PinNames[l][i],&PinNames[n][j])) {
		AsmError(9);
		return(-1);
	       }
	     }
	   }
						/*GND an entsprechenden Pin?*/
	  if (!strcmp(&PinNames[n][0],(UBYTE *)"GND")) {
	    if (n+1 != num_of_pins/2) {
	      AsmError(6);
	      return(-1);
	     }
	   }
	  if (n+1 == num_of_pins/2) {
	    if (strcmp(&PinNames[n][0],(UBYTE *)"GND")) {
	      AsmError(8);
	      return(-1);
	     }
	   }
						/*VCC an entsprechenden Pin?*/
	  if (!strcmp(&PinNames[n][0],(UBYTE *)"VCC")) {
	    if (n+1 != num_of_pins) {
	      AsmError(6);
	      return(-1);
	     }
	   }
	  if (n+1 == num_of_pins) {
	    if (strcmp(&PinNames[n][0],(UBYTE *)"VCC")) {
	      AsmError(7);
	      return(-1);
	     }
	   }
	}
/* Boolean-Equations auswerten:
   Dabei werden die Boolean-Equations zweimal untersucht. Beim ersten
   Durchlauf werden die OLMC-Pins ausgewertet und die OLMC-Struktur ge-
   füllt. Mit Hilfe dieser Struktur läßt sich auf den notwendigen Modus
   (1, 2 oder 3) schließen. Beim zweiten Durchlauf wird dann die
   Fuse-Matrix erstellt.
 */

       if (GetNextChar(FALSE)) {		/*Dateiende?*/
	 AsmError(2);				/*ja, dann Fehler*/
	 return(-1);
	}

       bool_start   = actptr;			/*Zeiger auf Anfang der Equations*/
       bool_linenum = linenum;			/*Zeilennummer merken*/

       for (pass=0; pass<2; pass++) {		/*2 Durchläufe*/
	 if (pass) {			/*2. Durchlauf?->ACW erstellen*/
	   modus = 0;			/*und Modus bestimmen*/
	   for (n=0; n<8; n++) {		/*alle OLMCs untersuchen*/
	     if (OLMC[n].PinType == REGOUT) {	/*OLMC als Reg. vorhanden?*/
	       modus = MODE3;			/*ja, dann MUß Mode3 vorliegen*/
	       Jedec.GALSYN = 0;		/*SYN- und AC0-Bit setzen*/
	       Jedec.GALAC0 = 1;
	       break;
	      }
	    }

	   if (!modus) {
	     for (n=0; n<8; n++) {
	       if (OLMC[n].PinType == TRIOUT) {	/*OLMC als Tri. vorhanden?*/
	         modus = MODE2;			/*ja, dann Mode2*/
	         Jedec.GALSYN = 1;		/*SYN- und AC0-Bit setzen*/
	         Jedec.GALAC0 = 1;
		 break;
	        }
	      }
	    }

	   if (!modus) {
	     modus = MODE1;			/*noch kein Mode? dann Mode1*/
	     Jedec.GALSYN = 1;			/*SYN- und AC0-Bit setzen*/
	     Jedec.GALAC0 = 0;
	    }
					/*falls Modus 1 voliegt alle*/
					/*Ausgänge deren Typ nicht an-*/
					/*gegeben wurde in komb. Ausgänge*/
					/*umwandeln*/
					/*falls Modus 2 oder 3 vorliegt*/
					/*alle Ausgänge deren Typ nicht an-*/
					/*gegeben wurde in Tristate mit per-*/
	   for (n=0; n<8; n++) {	/*manenter Freischaltung umwandeln*/
	     if (OLMC[n].PinType == COM_TRI_OUT) {
	       if (modus == MODE1) {
		 OLMC[n].PinType = COMOUT;
		}
	       else {
	         OLMC[n].PinType = TRIOUT;
	         OLMC[n].TriCon  = TRI_VCC;
		}
	      }
	    }
					/*überprüfen ob Verstöße gegen den*/
					/*ermittelten Modus vorliegen*/
	   if (modus == MODE1) {
	     for (n=0; n<8; n++) {
	       if (OLMC[n].PinType == INPUT) {
	         if (gal_type == GAL16V8) {
		   pin_num = n + 12;
	           if ((pin_num == 15) || (pin_num == 16)) {
		     linenum = OLMC[n].LineNum;
		     AsmError(18);
		     return(-1);
	            }
	          }
	         if (gal_type == GAL20V8) {
		   pin_num = n + 15;
	           if ((pin_num == 18) || (pin_num == 19)) {
		     linenum = OLMC[n].LineNum;
		     AsmError(19);
		     return(-1);
	            }
	          }
	        }
	      }
	    }

	   if (modus == MODE2) {
	     for (n=0; n<8; n++) {
	       if (OLMC[n].PinType == INPUT) {
	         if (gal_type == GAL16V8) {
		   pin_num = n + 12;
	           if ((pin_num == 12) || (pin_num == 19)) {
		     linenum = OLMC[n].LineNum;
		     AsmError(20);
		     return(-1);
	            }
	          }
	         if (gal_type == GAL20V8) {
		   pin_num = n + 15;
	           if ((pin_num == 15) || (pin_num == 22)) {
		     linenum = OLMC[n].LineNum;
		     AsmError(21);
		     return(-1);
	            }
	          }
	        }
	      }
	    }
					/*ACW erstellen: SYN und AC0 sind*/
					/*bereits festgelegt*/
	   for (n=0; n<PT_SIZE; n++)		/*Produkftermfreigabe auf 1*/
	     Jedec.GALPT[n] = 1;

					/*AC1-Bits bestimmen*/
	   for (n=0; n<AC1_SIZE; n++) {
	     if ((OLMC[n].PinType == INPUT) || (OLMC[n].PinType == TRIOUT))
	       Jedec.GALAC1[AC1_SIZE-1-n] = 1;
	    }

	   for (n=0; n<XOR_SIZE; n++) {		/*XOR-Bits bestimmen*/
	     if (((OLMC[n].PinType == COMOUT) ||
		  (OLMC[n].PinType == TRIOUT) ||
		  (OLMC[n].PinType == REGOUT)) &&
		  (OLMC[n].Active  == ACTIVE_HIGH))
	       Jedec.GALXOR[XOR_SIZE-1-n] = 1;
	    }

	  }


	 actptr  = bool_start;
	 linenum = bool_linenum;
         goto label1;

loop1:	 if (GetNextChar(FALSE)) {			/*Dateiende?*/
	   AsmError(2);					/*ja, dann Fehler*/
	   return(-1);
	  }
	 chr = 0x00;
	 if (*actptr == '.') {
	   actptr++;
	   chr = *actptr;
	   if (!((chr == 'T') || (chr == 'E') || (chr == 'R'))) {
	     AsmError(13);
	     return(-1);
	    }	     
	   actptr++;
	   if (GetNextChar(FALSE)) {			/*Dateiende?*/
	     AsmError(2);				/*ja, dann Fehler*/
	     return(-1);
	    }
	  }

	 actOLMC = (int)actPin.p_Pin;		/*OLMC-Offset merken*/
	 if (gal_type == GAL16V8)
	   actOLMC -= 12;
	 else
	   actOLMC -= 15;
	 row_offset  = 0;			/*Offset für OR am OLMC*/
	 prevOp	     = 0;			/*vorherige Verknüpfung*/
						/*chr enthält T,R,E oder 0x00*/
	 if (!pass) {				/*Pass 1?*/
	   if ( ((gal_type == GAL16V8)		/*OLMC-Pin?*/
		 && (actPin.p_Pin >= 12) && (actPin.p_Pin <= 19)) ||
		((gal_type == GAL20V8)
		 && (actPin.p_Pin >= 15) && (actPin.p_Pin <= 22)) ) {
	     if (gal_type == GAL16V8)
	       n=actPin.p_Pin-12;
	     if (gal_type == GAL20V8)
	       n=actPin.p_Pin-15;
	     if (chr != 'E') {			/*keine Tristate-Freigabe?*/
						/*mehrfache Zuweisung?*/
	       if ((!OLMC[n].PinType) || (OLMC[n].PinType == INPUT)) {
		 if (actPin.p_Neg)
		   OLMC[n].Active = ACTIVE_LOW;
		 else
		   OLMC[n].Active = ACTIVE_HIGH;

		 switch (chr) {
		   case 'T': { OLMC[n].PinType = TRIOUT;
			       break;
			     }
		   case 'R': { OLMC[n].PinType = REGOUT;
			       break;
			     }
		   case 0x00:{ OLMC[n].PinType = COM_TRI_OUT;
			       break;
			     }
		  }
		}
	       else {
		 AsmError(16);
		 return(-1);
		}
	      }
	     else {
	       if (OLMC[n].PinType == TRIOUT) {
		 if (actPin.p_Neg) {		/*kein '/' bei Tri.-Kontr.!*/
		   AsmError(32);
		   return(-1);
		  }
		 if (OLMC[n].TriCon) {		/*Tri.-Kontrolle doppelt?*/
		   AsmError(22);
		   return(-1);
		  }
		 OLMC[n].TriCon = TRICON;	/*Tri.-Kontrolle angegeben*/
		}
	       if ((!OLMC[n].PinType) || (OLMC[n].PinType == INPUT)) {
		 AsmError(17);			/*zuerst Tri.Kon.?*/
		 return(-1);			/*dann Fehler*/
		}
	       if (OLMC[n].PinType == REGOUT) { /*Register? dann Fehler*/
		 AsmError(23);
		 return(-1);
		}
	       if (OLMC[n].PinType == COM_TRI_OUT) { /*kein klares .T?*/
		 AsmError(24);
		 return(-1);
		}
	      }
	    }
	   else {
	     AsmError(15);
	     return(-1);
	    }
	  }



	 if (*actptr != '=') {				/* '=' ?*/
	   AsmError(14);				/*nein, dann Fehler*/
	   return(-1);
	  }	     
loop2:
	 actptr++;
	 if (GetNextChar(FALSE)) {			/*Dateiende?*/
	   AsmError(2);					/*ja, dann Fehler*/
	   return(-1);
    	  }
	 IsPinName();
	 if (!actPin.p_Pin) {				/*Pinname?*/
	   AsmError(11);				/*nein, dann Fehler*/
	   return(-1);
	  }
	 if (actPin.p_Pin==NC_PIN) {			/*NC als Pinname?*/
	   AsmError(12);				/*ja, dann Fehler*/
	   return(-1);
	  }
	 if (GetNextChar(FALSE)) {			/*Dateiende?*/
	   AsmError(2);					/*ja, dann Fehler*/
	   return(-1);
	  }
							/*kein Vcc/GND in den*/
							/*Boolean-Gleichungen*/
	 if ((actPin.p_Pin == num_of_pins) || (actPin.p_Pin == num_of_pins/2)) {
	   if (chr != 'E') {
	     AsmError(25);				/*Vcc/GND dann Fehler*/
	     return(-1);
	    }
	  }



	 if (!pass) {					/*Pass 1?*/
	   if ( ((gal_type == GAL16V8)			/*OLMC-Pin?*/
		 && (actPin.p_Pin >= 12) && (actPin.p_Pin <= 19)) ||
		((gal_type == GAL20V8)
		 && (actPin.p_Pin >= 15) && (actPin.p_Pin <= 22)) ) {
	     if (gal_type == GAL16V8)
	       n=actPin.p_Pin-12;
	     if (gal_type == GAL20V8)
	       n=actPin.p_Pin-15;
	     if (!OLMC[n].PinType) {			/*OLMC bereits def.?*/
	       OLMC[n].PinType = INPUT;			/*nein, dann Eingang*/
	       OLMC[n].LineNum  = linenum;		/*Zeile merken*/
	      }
	    }
	  }
					/*im 2.Durchlauf Fuse-Matrix*/
					/*erstellen; chr = T,R,E oder 0x00*/
	 if (pass) {
	   if (chr != 'E') {
	     if (!row_offset) {			/*Zeilenoffset noch 0?*/
	       if ( (modus != MODE1) && (OLMC[actOLMC].PinType != REGOUT)) {
	         row_offset = 1;
	        }
	      }
	    }
					/*auf Verstoß gegen Modus prüfen*/
	   pin_num = actPin.p_Pin;
	   if (modus == MODE1) {		/*Verstoß gegen Mode 1?*/
	     if ((gal_type==GAL16V8) && ((pin_num==15) || (pin_num==16))) {
	       AsmError(18);
	       return(-1);
	      }
	     if ((gal_type==GAL20V8) && ((pin_num==18) || (pin_num==19))) {
	       AsmError(19);
	       return(-1);
	      }
	    }
	   if (modus == MODE2) {		/*Verstoß gegen Mode 2?*/
	     if ((gal_type==GAL16V8) && ((pin_num==12) || (pin_num==19))) {
	       AsmError(20);
	       return(-1);
	      }
	     if ((gal_type==GAL20V8) && ((pin_num==15) || (pin_num==22))) {
	       AsmError(21);
	       return(-1);
	      }
	    }
	   if (modus == MODE3) {		/*Verstoß gegen Mode 3?*/
	     if ((gal_type==GAL16V8) && ((pin_num==1) || (pin_num==11))) {
	       AsmError(26);
	       return(-1);
	      }
	     if ((gal_type==GAL20V8) && ((pin_num==1) || (pin_num==13))) {
	       AsmError(27);
	       return(-1);
	      }
	    }
					/*wenn Tristate-Kontrolle und GND*/
					/*dann Fuse-Zeile auf 0 setzen   */
	   if (chr == 'E') {

	     if (prevOp == '+') {		/*max. 1 Produktterm*/
	       AsmError(29);			/*mehr, dann Fehler*/
	       return(-1);
	      }
	     if ((pin_num == num_of_pins) || (pin_num == num_of_pins/2)) {
	       if (!prevOp && (*actptr != '*' ) && (*actptr != '+')) {
		 if (pin_num == num_of_pins/2) {
		   m = ToOLMC[actOLMC] * num_of_col;
		   for (n=m; n<m+num_of_col; n++)
		     Jedec.GALLogic[n] = 0;
		  }
	        }
	       else {
	         AsmError(28);
	         return(-1);
	        }
	      }
	     else {				/*UND-Verknüpfung erstellen*/
	       SetAND(ToOLMC[actOLMC], pin_num, actPin.p_Neg);
	      }
	    }
	   else {
	     if (prevOp == '+') {		/*ODER-Verknüpfung?*/
	       row_offset++;			/*ja, dann nächste Zeile*/
	       if (row_offset == MAX_OR) {	/*zuviele Produktterme?*/
		 if ((modus != MODE1) && (OLMC[actOLMC].PinType != REGOUT)) {
		   AsmError(31);
		   return(-1);
		  }
		 else {
		   AsmError(30);
		   return(-1);
		  }
		}
	      }					/*UND-Verknüpfung setzen*/
	     SetAND(ToOLMC[actOLMC]+row_offset, pin_num, actPin.p_Neg);
	    }
						/*kommt noch eine Verknüpfung?*/
	   if ((*actptr != '+') && (*actptr != '*') && (chr != 'E')) { /*nein*/
	     row_offset++;				/*Rest der OLMC- */
	     if (row_offset != MAX_OR) {		/*Zeilen auf 0    */
	       m = (ToOLMC[actOLMC] + row_offset) * num_of_col;
	       for (n=m; n<m+(MAX_OR-row_offset) * num_of_col; n++)
		 Jedec.GALLogic[n] = 0;
	      }
	    }
	  }


	 if ((*actptr == '+') || (*actptr == '*')) {
	   prevOp = *actptr;
	   goto loop2;
	  }


	 if (strncmp(actptr,(UBYTE *)"DESCRIPTION",11)) {
label1:	   IsPinName();
	   if (!actPin.p_Pin) {				/*Pinname?*/
	     AsmError(11);				/*nein, dann Fehler*/
	     return(-1);
	    }
	   if (actPin.p_Pin==NC_PIN) {			/*NC als Pinname?*/
	     AsmError(12);				/*ja, dann Fehler*/
	     return(-1);
	    }
	   goto loop1;
	  }

	}
					/*Fuse-Matrix der nichtverwendeten*/
					/*OLMCs und der OLMCs die als Eingang*/
					/*programmiert sind auf 0 setzen*/
       for (n=0; n<8; n++) {
	 if ((OLMC[n].PinType == NOTUSED) || (OLMC[n].PinType == INPUT)) {
	   l = ToOLMC[n];
	   l = l * num_of_col;
	   m = l + 8 * num_of_col;
	   for (k=l; k<m; k++)
		Jedec.GALLogic[k] = 0;
	  }
	}
					/*Jedec-Struktur ist fertig (jubel)*/

       pinnameflag = 1;			/*Pinnamen sind gültig*/

       FreeMem(fbuff, fsize);		/*Puffer für File .pld*/

					/* angewählte Files erstellen*/
       if (GenJedec==YES) {
         if (MyRequest(SAVE_REQ,(UBYTE *)"Bitte Namen für Jedec-Datei eingeben")) {
	   oldMaxFuseAdr = MaxFuseAdr;
	   if (gal_type == GAL16V8) 
	     MaxFuseAdr = MAX_FUSE_ADR16;
	   else
	     MaxFuseAdr = MAX_FUSE_ADR20;
	   WriteJedecFile();
	   MaxFuseAdr = oldMaxFuseAdr;
	  }
	}
       if (GenFuse==YES)
	 WriteFuseFile(); 
       if (GenChip==YES)
 	 WriteChipFile();
       if (GenPin==YES)
	 WritePinFile();
       return(0);				/*kein Fehler aufgetreten*/
      }
     else {
       ErrorReq(3);				/*Lesefehler*/
       FreeMem(fbuff,fsize);
       return(-2);
      }
    }
   else {
     ErrorReq(2);				/*kein Speicher*/
     return(-2);
    }
  }
}





/* setze eine UND-Verknüpfung (=0) in der Fuse-Matrix
   row     :  Zeile in der die UND-Verknüpfung entstehen soll
   pinnum  :  Pin der UND-verknüpft werden soll
   negation:  0: Pin nicht negiert; 1: Pin negiert ('/')
*/
SetAND(row, pinnum, negation)
int    row, pinnum, negation;
{
int column;

 if (gal_type == GAL16V8) {
   if (modus == MODE1)
     column = PinToFuse16Mode1[pinnum - 1];
   if (modus == MODE2)
     column = PinToFuse16Mode2[pinnum - 1];
   if (modus == MODE3)
     column = PinToFuse16Mode3[pinnum - 1];
  }
 else {
   if (modus == MODE1)
     column  =  PinToFuse20Mode1[pinnum - 1];
   if (modus == MODE2)
     column  =  PinToFuse20Mode2[pinnum - 1];
   if (modus == MODE3)
     column  =  PinToFuse20Mode3[pinnum - 1];
  }
 Jedec.GALLogic[row * num_of_col + column + negation] = 0;
}




/* Überprüfe ob bei "actptr" ein Pinname steht der in "PinNames" eingetragen
   ist und der kein NC (not connected) ist.
   "actptr" wird auf erstes Zeichen hinter den Pinnamen gestellt
   actPin.p_Pin: Pinnummer oder NC_PIN; 0: kein Pinname
   actPin.p_Neg: bei active low = 0; bei active high = 1
*/
IsPinName()
{
int	i, k, n;
UBYTE	*oldactptr;

 actPin.p_Neg = 0;		/*Pin-Struktur zurücksetzen*/
 actPin.p_Pin = 0;

 if (*actptr == '/' ) {		/*Negation?*/
   actptr++;
   actPin.p_Neg = 1;
  }

 n = 0;				/*Länge des möglichen Pinnamens ermitteln*/
 oldactptr = actptr;
 while (isalpha(*actptr) || isdigit(*actptr)) {
   actptr++;
   n++;
  }

 if (n)
   if ((n == 2 ) && !strncmp(oldactptr,(UBYTE *)"NC",2))  /*NC ?*/
     actPin.p_Pin = NC_PIN;				/*ja, dann NC-Pin*/
   else
     for (k=0; k<num_of_pins; k++) {	 /*List der Pinnamen durchsuchen*/
       i = 0;
       if (PinNames[k][0] == '/')
         i = 1;
       if (n == strlen(&PinNames[k][i]))	/*Stringlängen gleich?*/       
         if (!(strncmp(oldactptr,&PinNames[k][i],n))) {	 /*ja, dann Strings*/
	   actPin.p_Pin = k+1;				 /*vergeichen      */
	   break;
          }
      }
}




/*suche ab "actptr" das nächste Zeichen das kein Space, TAB, LF ist
  Aufruf:   linefeed=TRUE: return auch bei 0x0A, FALSE: kein return bei 0x0A
  Ergebins: 0:Zeichen gefunden, actptr=Zeiger auf dieses Zeichen
	    1:kein Zeichen mehr da
*/
GetNextChar(linefeed)
int	linefeed;
{
 for(;;) {
   switch (*actptr) {
     case 0x0A: {				/*LineFeed*/
       actptr++;
       linenum++;
       if (linefeed==TRUE) return(0);
       break;
      }
     case  ' ':					/*Space*/
     case 0x09: {				/*TAB*/
       actptr++;
       break;
      }
     default  : {
       if ((*actptr>' ') && (*actptr<='~')) return(0);	/*Zeichen gefunden?*/
       else actptr++;
      }
    }
   if (actptr>buffend) return(1);			/*Fileende erreicht?*/
  }
}


/*Zeiger auf zächste Zeile holen
  Ergebins: 0:Zeile gefunden, actptr=Zeiger auf diese Zeile
	    1:File-Ende erreicht
*/
GetNextLine()
{
 for(;;) {
   if (*actptr == 0x0A) {
     actptr++;
     linenum++;
     return(0);
    }
   if (actptr>buffend) return(1);			/*Fileende erreicht*/
   actptr++;
  }
}




/* gibt Fehlermeldungen des GAL-Assemblers aus
   und gibt Speicher für File-Puffer wieder frei
*/
AsmError(errornum)
int	errornum;
{
 FreeMem(fbuff,fsize);
 MyRequest(ERR_REQ,(UBYTE *)"Fehler in der Eingabe-Datei");
 PrintErrorLine(linenum);
 switch (errornum) {
   case  1: {
     PrintText((UBYTE *)"Zeile 1: GAL-Typ erwartet");
     break;
    }
   case  2: {
     PrintText((UBYTE *)"unerwartetes Ende der Eingabe-Datei");
     break;
    }
   case  3: {
     PrintText((UBYTE *)"habe nach '/' Pinnamen erwartet");
     break;
    }
   case  4: {
     PrintText((UBYTE *)"Pinname hat mehr als 8 Buchstaben und Ziffern");
     break;
    }
   case  5: {
     PrintText((UBYTE *)"unerlaubtes Zeichen bei Pin-Definition");
     break;
    }
   case  6: {
     PrintText((UBYTE *)"VCC/GND-Zuweisung nur an den entsprechenden Pins erlaubt");
     break;
    }
   case  7: {
     PrintText((UBYTE *)"für VCC-Pin Zuweisung VCC erwartet");
     break;
    }
   case  8: {
     PrintText((UBYTE *)"für GND-Pin Zuweisung GND erwartet");
     break;
    }
   case  9: {
     PrintText((UBYTE *)"gleicher Pinname kommt mehrfach vor");
     break;
    }
   case 10: {
     PrintText((UBYTE *)"unerlaubte Verwendung von '/'");
     break;
    }
   case 11: {
     PrintText((UBYTE *)"unbekannter Pin-Name in den Boolean-Gleichungen");
     break;
    }
   case 12: {
     PrintText((UBYTE *)"NC (Not Connected) in Boolean-Gleichungen nicht erlaubt");
     break;
    }
   case 13: {
     PrintText((UBYTE *)"nach '.' wird ein 'T', 'E' oder 'R' erwartet");
     break;
    }
   case 14: {
     PrintText((UBYTE *)"'=' wurde erwartet");
     break;
    }
   case 15: {
     PrintText((UBYTE *)"Pin kann nicht als Ausgang programmiert werden");
     break;
    }
   case 16: {
     PrintText((UBYTE *)"gleicher Pin ist mehrfach als Ausgang definiert worden");
     break;
    }
   case 17: {
     PrintText((UBYTE *)"Tristate-Kontrolle: Tristate-Ausgang noch nicht definiert");
     break;
    }
   case 18: {
     PrintText((UBYTE *)"Betriebsmodus 1: Pins 15,16 können nicht als Eingang verwendet werden");
     break;
    }
   case 19: {
     PrintText((UBYTE *)"Betriebsmodus 1: Pins 18,19 können nicht als Eingang verwendet werden");
     break;
    }
   case 20: {
     PrintText((UBYTE *)"Betriebsmodus 2: Pins 12,19 können nicht als Eingang verwendet werden");
     break;
    }
   case 21: {
     PrintText((UBYTE *)"Betriebsmodus 2: Pins 15,22 können nicht als Eingang verwendet werden");
     break;
    }
   case 22: {
     PrintText((UBYTE *)"Tristate-Kontrolle wurde mehrfach angegeben");
     break;
    }
   case 23: {
     PrintText((UBYTE *)"Tristate-Kontrolle wurde auf Registerausgang angewendet");
     break;
    }
   case 24: {
     PrintText((UBYTE *)"Tristate-Kontrolle ohne vorheriges '.T'");
     break;
    }
   case 25: {
     PrintText((UBYTE *)"Ausdrücke VCC und GND nur zur Tristate-Kontrolle erlaubt (x.E = ...)");
     break;
    }
   case 26: {
     PrintText((UBYTE *)"Betriebsmodus 3: Pins 1,11 für 'Clock' und '/OE' reserviert");
     break;
    }
   case 27: {
     PrintText((UBYTE *)"Betriebsmodus 3: Pins 1,13 für 'Clock' und '/OE' reserviert");
     break;
    }
   case 28: {
     PrintText((UBYTE *)"VCC und GND nicht in boolschen Ausdrücken erlaubt");
     break;
    }
   case 29: {
     PrintText((UBYTE *)"bei der Tristate-Kontrolle ist nur EIN Produktterm erlaubt");
     break;
    }
   case 30: {
     PrintText((UBYTE *)"maximal 8 Produktterme erlaubt");
     break;
    }
   case 31: {
     PrintText((UBYTE *)"maximal 7 Produktterme erlaubt");
     break;
    }
   case 32: {
     PrintText((UBYTE *)"vor 'name.E' ist kein '/' erlaubt");
     break;
    }
  }
}






/****************************************************************/
/* ab hier stehen die Routinen, die für der Erstellung der      */
/* Dokumentations-Files zuständig sind				*/
/****************************************************************/


/* erstelle das Chip-File*/
WriteChipFile()
{
UBYTE	filenamebuff[64];
FILE	*fp;
int	n;

   if (MyRequest(SAVE_REQ,(UBYTE *)"Bitte Namen für Chip-Datei eingeben")) {
     strcpy(&filenamebuff,&GadgetSBuff);		/*.chp an Dateinamen anfügen*/
     strcat(&filenamebuff,(UBYTE *)".chp");
     if (fp=fopen(&filenamebuff,(UBYTE *)"w")) {
       fprintf(fp,"\n\n");
       WriteSpaces(fp,32);
       if (gal_type == GAL16V8)	fprintf(fp,"GAL16V8\n\n");
       else fprintf(fp,"GAL20V8\n\n");
       WriteSpaces(fp,26);
       fprintf(fp,"-------\\___/-------\n");

       for (n=0; n<num_of_pins/2; n++) {
	 WriteSpaces(fp,25-strlen(&PinNames[n][0]));
	 fprintf(fp,"%s | %2d           %2d | %s\n",&PinNames[n][0],n+1,num_of_pins-n,&PinNames[num_of_pins-n-1][0]);
	 if (n<num_of_pins/2-1) {
	   WriteSpaces(fp,26);
	   fprintf(fp,"|                 |\n");
	  }
	}

       WriteSpaces(fp,26);
       fprintf(fp,"-------------------\n");

       if (fclose(fp)==EOF) ErrorReq(8);		/*Datei läßt sich nicht schließem*/
      }
    }
}





/* erstelle das Pin-File*/
WritePinFile()
{
UBYTE	filenamebuff[64];
FILE	*fp;
int	k, n, flag;

   if (MyRequest(SAVE_REQ,(UBYTE *)"Bitte Namen für Pin-Datei eingeben")) {
     strcpy(&filenamebuff,&GadgetSBuff);		/*.pin an Dateinamen anfügen*/
     strcat(&filenamebuff,(UBYTE *)".pin");
     if (fp=fopen(&filenamebuff,(UBYTE *)"w")) {
       fprintf(fp,"\n\n");
       fprintf(fp," Pin # | Name     | Pin Type\n");
       fprintf(fp,"-----------------------------\n");

       for (n=1; n<=num_of_pins; n++) {
	 fprintf(fp,"  %2d   | ",n);
	 fprintf(fp,"%s",PinNames[n-1]);
	 WriteSpaces(fp,9-strlen(PinNames[n-1]));

	 flag = 0;
	 if (n == num_of_pins/2) {
	   fprintf(fp,"| GND\n");
	   flag = 1;
	  }
	 if (n == num_of_pins) {
	   fprintf(fp,"| VCC\n\n");
	   flag = 1;
	  }
	 if ((modus == MODE3) && (n == 1)) {
	   fprintf(fp,"| Clock\n");
	   flag = 1;
	  }
	 if (modus == MODE3) {
	   if ((gal_type == GAL16V8) && (n == 11)) {
	     fprintf(fp,"| /OE\n");
	     flag = 1;
	    }
	   if ((gal_type == GAL20V8) && (n == 13)) {
	     fprintf(fp,"| /OE\n");
	     flag = 1;
	    }
	  }
							/*OLMC-Pin?*/
	 if ( ((gal_type == GAL16V8) && (n >= 12) && (n <= 19)) ||
	      ((gal_type == GAL20V8) && (n >= 15) && (n <= 22)) ) {
	   if (gal_type == GAL16V8)
	     k = n-12;
	   else
	     k = n-15;
	   if (OLMC[k].PinType != INPUT)
	     if (OLMC[k].PinType)
	       fprintf(fp,"| Output\n");
	     else
	       fprintf(fp,"| NC\n");
	   else
	     fprintf(fp,"| Input\n");
	  }
	 else {
	   if (!flag) 
	     fprintf(fp,"| Input\n");
	  }
	}
       if (fclose(fp)==EOF) ErrorReq(8);		/*Datei läßt sich nicht schließem*/
      }
    }
}



/* erstelle das Fuse-File*/
WriteFuseFile()
{
UBYTE	filenamebuff[64];
FILE	*fp;
int	n,   row, col, pin;
int	xor, ac1;

   if (MyRequest(SAVE_REQ,(UBYTE *)"Bitte Namen für Fuse-Datei eingeben")) {
     strcpy(&filenamebuff,&GadgetSBuff);		/*.fus an Dateinamen anfügen*/
     strcat(&filenamebuff,(UBYTE *)".fus");
     if (fp=fopen(&filenamebuff,(UBYTE *)"w")) {
       if (gal_type == GAL16V8)
	 pin = 19;
       else
	 pin = 22;
       for (row=0; row<ROW_SIZE; row++) {
	 if (!((row) % 8)) {
	   fprintf(fp,"\n\nPin %2d = ",pin);
	   fprintf(fp,"%s",PinNames[pin-1]);
	   WriteSpaces(fp,13-strlen(PinNames[pin-1]));
	   if (gal_type == GAL16V8) {
	     xor = Jedec.GALXOR[19-pin];
	     ac1 = Jedec.GALAC1[19-pin];
	    }
	   else {
	     xor = Jedec.GALXOR[22-pin];
	     ac1 = Jedec.GALAC1[22-pin];
	    }
	   fprintf(fp,"XOR = %1d   AC1 = %1d",xor,ac1);
	   pin--;	
	  }
	 fprintf(fp,"\n%2d ",row);
	 for (col=0; col<num_of_col; col++) {
	   if (!( (col) % 4) )
	     fprintf(fp," ");
	   if (Jedec.GALLogic[row * num_of_col + col])
	     fprintf(fp,"-");
	   else
	     fprintf(fp,"x");
	  }
	}
       fprintf(fp,"\n\n");
       if (fclose(fp)==EOF) ErrorReq(8);		/*Datei läßt sich nicht schließem*/
      }
    }
}





/* schreibt Anzahl "numof" Spaces in File "fp"*/
WriteSpaces(fp, numof)
FILE	*fp;
int	numof;
{
int n;

 for (n=0; n<numof; n++)
   fprintf(fp," ");
}

