/****************************************************************/
/*								*/
/* Jedec.c - this file includes routines to load and save	*/
/*	     GAL datas in JEDEC format				*/
/* 								*/
/*								*/
/****************************************************************/



#include <exec/types.h>
#include <exec/memory.h>
#include <libraries/dos.h>
#include <libraries/locale.h>
#include <stdio.h>
#include <ctype.h>
#include <stdio.h>

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

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




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

extern	struct  AppString AppStrings[];

extern	int	MaxFuseAdr, RowSize, XORSize, GALType;
extern	char	path;

extern	struct	Configuration	Config;
extern	struct	Catalog		*catalog;

struct	JedecStruct	Jedec;


int	linenum, JedecSecurity, JedecGALType;
int	oldMaxFuseAdr, oldRowSize, oldXORSize;

UBYTE	*actptr, *buffend;




/* PutJedec:
   read GAL and generate JEDEC structure and write JEDEC file
   Syntax: PutJedec();
*/
void PutJedec(void)
{
 if (MyRequest(GALTYPE_REQ, AppStrings[MSG_READGAL_JED].as_Str)) {
     if (ReadGALParameter(YES))			/* get parameter or GAL */
       return;					/* error -> return */

     PrintText(AppStrings[MSG_READING_GAL].as_Str, 1);

     ReadGALToJedec();					/*read GAL*/

     PrintText(AppStrings[MSG_LOWER_OK].as_Str, 0);

     if (MyFileReq(AppStrings[MSG_WRITE_JED].as_Str, ".jed", YES, SAVE))
       WriteJedecFile(GALType);

  }
}






/* FileChecksum: calculate JEDEC-File-Checksum
		 start and end must be marked by <STX> and <ETX>!
   Syntax: checksum = FileChecksum(buff);
	   buff: ActBuffer structure of file buffer
   Result: checksum: 16-Bit checksum of JEDEC structure
*/
int FileChecksum(struct ActBuffer buff)
{
int checksum;

  checksum = 0;

  while (*buff.Entry != 0x2)			/* search for <STX> */
    IncPointer(&buff);

  while (*buff.Entry != 0x3) {			/* search for <ETX> and*/
    checksum += *buff.Entry;			/* add values */

    IncPointer(&buff);
  }

  checksum += 0x3;				/* add <ETX> too*/

  return(checksum);				/* ready */
}




/* FuseChecksum: calculate Fuse-Checksum of the JEDEC structure 
   Syntax: checksum = FuseChecksum(galtype);
	   int galtype: type of GAL
   Result: checksum: 16 bit checksum of JEDEC structure
*/
int FuseChecksum(int galtype)
{
int	checksum, byte, n;
BYTE	*ptr, *ptrXOR, *ptrS1;



  ptr = &Jedec.GALLogic[0] - 1L;
  ptrXOR = &Jedec.GALXOR[0];
  ptrS1  = &Jedec.GALS1[0];

  n = checksum = byte = 0;

  for (;;) {

    if (galtype == GAL16V8) {
      if (n == XOR16) {
        ptr = &Jedec.GALXOR[0];
      }
      else {
	if (n == XOR16+8) {
	  ptr = &Jedec.GALSig[0];
	}
	else {
	  if (n == NUMOFFUSES16)
	    break;
	  else
	    ptr++;
	}
      }
    }


    if (galtype == GAL20V8) {
      if (n == XOR20) {
        ptr = &Jedec.GALXOR[0];
      }
      else {
	if (n == XOR20+8) {
	  ptr = &Jedec.GALSig[0];
	}
	else {
	  if (n == NUMOFFUSES20)
	    break;
	  else
	    ptr++;
	}
      }
    }


    if (galtype == GAL22V10) {
      if ((n >= XOR22V10) && (n < XOR22V10 + 20)) {
	if (!(n % 2))
	  ptr = ++ptrXOR;
	else
	  ptr = ++ptrS1;
      }
      else {
	if (n == SIG22V10)
	  ptr = &Jedec.GALSig[0] - 1L;

	if (n == SIG22V10 + SIG_SIZE)
	  break;
	else
	  ptr++;
      }
    }


    if (galtype == GAL20RA10) {
      if (n == XOR20RA10) {
        ptr = &Jedec.GALXOR[0];
      }
      else {
	if (n == SIG20RA10 + SIG_SIZE)
	  break;
	else
	  ptr++;
      }
    }


    byte |= (*ptr << (n+8) % 8);

    if (!((n+9) % 8)) {
      checksum += byte;
      byte = 0;
    }

    n++;
  }

  checksum += byte;

  return(checksum); 
}





/* MakeJedecBuff: generate the JEDEC file in a ram-buffer
   Syntax:   result = MakeJedecBuff(buff);
   	     buff:    ActBuffer structure for the ram-buffer
   Result:  int result:  0: o.k.
		 	-1: not enough free memory
*/
int MakeJedecBuff(struct ActBuffer buff, int galtype)
{
UBYTE	mystrng[10];
struct	ActBuffer buff2;
int	n, m, bitnum, bitnum2, flag;
int	MaxFuseAdr, RowSize, XORSize;


  switch (galtype) {

    case  GAL16V8:
	MaxFuseAdr = MAX_FUSE_ADR16;		/* This variables are defined  */
	RowSize    = ROW_SIZE_16V8;		/* both globally AND locally!  */
	XORSize    = 8;				/* All assignments concern to  */
	break;					/* the locale variables!!!!    */

    case GAL20V8:
	MaxFuseAdr = MAX_FUSE_ADR20;
	RowSize    = ROW_SIZE_20V8;
	XORSize    = 8;
	break;

    case GAL22V10:
	MaxFuseAdr = MAX_FUSE_ADR22V10;
	RowSize    = ROW_SIZE_22V10;
	XORSize    = 10;
	break;


    case GAL20RA10:
	MaxFuseAdr = MAX_FUSE_ADR20RA10;
	RowSize    = ROW_SIZE_20RA10;
	XORSize    = 10;
	break;

  }




  buff2 = buff;

  if (Config.JedecFileChk)
    if (AddString(&buff, (UBYTE *)"\2\n"))			/*<STX>*/
      return(-1);

					/*** make header of JEDEC file ***/
  if (AddString(&buff, (UBYTE *)"Used Program:   GALer V1.5\n"))
    return(-1);

  if (AddString(&buff, (UBYTE *)"GAL-Assembler:  GALer V1.5\n"))
    return(-1);

  if (galtype == GAL16V8) {
    if (AddString(&buff, (UBYTE *)"Device:         GAL16V8\n\n"))
      return(-1);
  }
  if (galtype == GAL20V8) {
    if (AddString(&buff, (UBYTE *)"Device:         GAL20V8\n\n"))
      return(-1);
  }
  if (galtype == GAL20RA10) {
    if (AddString(&buff, (UBYTE *)"Device:         GAL20RA10\n\n"))
      return(-1);
  }
  if (galtype == GAL22V10) {
    if (AddString(&buff, (UBYTE *)"Device:         GAL22V10\n\n"))
      return(-1);
  }


  if (AddString(&buff, (UBYTE *)"*F0\n"))	/* default value of fuses */
    return(-1);

  if (Config.JedecSecBit) {			/* Security-Bit */
    if (AddString(&buff, (UBYTE *)"*G1\n"))
      return(-1);
  }
  else
    if (AddString(&buff, (UBYTE *)"*G0\n"))
      return(-1);


  if (galtype == GAL16V8)			/* number of fuses */
    if (AddString(&buff, (UBYTE *)"*QF2194\n"))
      return(-1);

  if (galtype == GAL20V8)
    if (AddString(&buff, (UBYTE *)"*QF2706\n"))
      return(-1);
      
  if (galtype == GAL20RA10)
    if (AddString(&buff, (UBYTE *)"*QF3274\n"))
      return(-1);

  if (galtype == GAL22V10)
    if (AddString(&buff, (UBYTE *)"*QF5892\n"))
      return(-1);

						/*** make fuse-matrix ***/

  bitnum = 0;

  for (m = 0; m < RowSize; m++) {
    flag = 0;

    bitnum2 = bitnum;

    for (n = 0; n <= MaxFuseAdr; n++) {
      if (Jedec.GALLogic[bitnum2]) {
        flag = 1;
        break;
      }

      bitnum2++;
    }

    if (flag) {
      sprintf((char *)&mystrng[0], "*L%04d \0", bitnum);

      if (AddString(&buff, (UBYTE *)&mystrng[0]))
        return(-1);

      for (n=0; n<=MaxFuseAdr; n++) {
        if (AddByte(&buff, (UBYTE)(Jedec.GALLogic[bitnum] + '0')))
          return(-1);
        bitnum++;
      }

      if (AddByte(&buff, (UBYTE)'\n'))
        return(-1);

    }
    else
      bitnum = bitnum2;
  }

  if (!flag)
    bitnum = bitnum2;


						/*** XOR-Bits ***/
  sprintf((char *)&mystrng[0], "*L%04d \0", bitnum);	/* add fuse adr. */
  if (AddString(&buff, (UBYTE *)&mystrng[0]))
    return(-1);

  for (n = 0; n < XORSize; n++) {
    if (AddByte(&buff, (UBYTE)(Jedec.GALXOR[n] + '0')))
      return(-1);
    bitnum++;

    if (galtype == GAL22V10) {			/*** S1 of 22V10 ***/
        if (AddByte(&buff, (UBYTE)(Jedec.GALS1[n] + '0')))
          return(-1);
        bitnum++;
    }
  }

  if (AddByte(&buff, (UBYTE)'\n'))
    return(-1);


						/*** Signature ***/
  sprintf((char *)&mystrng[0], "*L%04d \0", bitnum);

  if (AddString(&buff, (UBYTE *)&mystrng[0]))
    return(-1);

  for (n = 0; n < SIG_SIZE; n++) {
    if (AddByte(&buff, (UBYTE)(Jedec.GALSig[n] + '0')))
      return(-1);
    bitnum++;
  }

  if (AddByte(&buff, (UBYTE)'\n'))
    return(-1);



  if ((galtype == GAL16V8) || (GALType == GAL20V8)) {
							/*** AC1-Bits ***/
    sprintf((char *)&mystrng[0], "*L%04d \0", bitnum);
    if (AddString(&buff, (UBYTE *)&mystrng[0]))
      return(-1);

    for (n = 0; n < AC1_SIZE; n++) {
      if (AddByte(&buff, (UBYTE)(Jedec.GALAC1[n] + '0')))
        return(-1);
      bitnum++;
    }

    if (AddByte(&buff, (UBYTE)'\n'))
      return(-1);


							/*** PT-Bits ***/
    sprintf((char *)&mystrng[0], "*L%04d \0", bitnum);
    if (AddString(&buff, (UBYTE *)&mystrng[0]))
      return(-1);

    for (n = 0; n < PT_SIZE; n++) {
      if (AddByte(&buff, (UBYTE)(Jedec.GALPT[n] + '0')))
        return(-1);
      bitnum++;
    }

    if (AddByte(&buff, (UBYTE)'\n'))
      return(-1);


							/*** SYN-Bit ***/
    sprintf((char *)&mystrng[0], "*L%04d \0", bitnum);

    if (AddString(&buff, (UBYTE *)&mystrng[0]))
      return(-1);

    if (AddByte(&buff, (UBYTE)(Jedec.GALSYN + '0')))
      return(-1);

    if (AddByte(&buff, (UBYTE)'\n'))
      return(-1);

    bitnum++;


							/*** AC0-Bit ***/
    sprintf((char *)&mystrng[0], "*L%04d \0", bitnum);

    if (AddString(&buff, (UBYTE *)&mystrng[0]))
      return(-1);

    if (AddByte(&buff, (UBYTE)(Jedec.GALAC0 + '0')))
      return(-1);

    if (AddByte(&buff, (UBYTE)'\n'))
      return(-1);

  }



  if (Config.JedecFuseChk) {			/* add fuse-checksum */
    sprintf((char *)&mystrng[0], "*C%04x\n\0", FuseChecksum(GALType));
    if (AddString(&buff, (UBYTE *)&mystrng[0]))
      return(-1);
   }


  if (AddString(&buff, (UBYTE *)"*\n"))			/* closing '*' */
    return(-1);


  if (Config.JedecFileChk) {
    if (AddByte(&buff, (UBYTE)0x3))			/* <ETX> */
      return(-1);
    sprintf((char *)&mystrng[0], "%04x\n\0", FileChecksum(buff2));
    if (AddString(&buff, (UBYTE *)&mystrng[0]))
      return(-1);
  }


  return(0);
}




/* WriteJedecFile:   write JEDEC file
   Syntax:  WriteJedecFile(galtype);
  	    int galtype: type of GAL

*/
void WriteJedecFile(int galtype)
{
struct	ActBuffer	mybuff;
struct	Buffer		*first_buff;
BPTR	fh;
extern	char	path;
UBYTE	*filebuffer, *filebuffer2;
long	result;



  if (!(first_buff = (struct Buffer *)AllocMem((long)sizeof(struct Buffer),MEMF_PUBLIC|MEMF_CLEAR))) {
    ErrorReq(2);				/* out of memory? */
    return;
  }

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



  if (MakeJedecBuff(mybuff, galtype)) {		/* put JEDEC in ram-buffer */
    FreeBuffer(first_buff);			/* error? */
    ErrorReq(2);
    return;
  }

  PrintText(AppStrings[MSG_WRITING_JED].as_Str, 1);

  if ((fh = Open(&path, (long)MODE_NEWFILE))) {
    for (;;) {
      filebuffer = filebuffer2 = mybuff.Entry;

      while (filebuffer2 < mybuff.BuffEnd) {	/* get size of buffer */
        if (!*filebuffer2) 
	  break;
        filebuffer2++;
      }
						/* save buffer */
      result = Write(fh, (char *)filebuffer, (long)(filebuffer2-filebuffer));

      if (result == -1L) {			/* write error? */
        Close(fh);
        FreeBuffer(first_buff);
        PrintText(AppStrings[MSG_ERROR].as_Str ,0);
        ErrorReq(13);
        return;
      }

      if (!mybuff.ThisBuff->Next)		/* more buffers here? */
        break;					/* no, then cancel */

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

    Close(fh);
  }
  else {
    FreeBuffer(first_buff);			/* error?, then cancel*/
    PrintText(AppStrings[MSG_ERROR].as_Str ,0);
    ErrorReq(13);				/* can't open file */
    return;
  }

  PrintText(AppStrings[MSG_LOWER_OK].as_Str, 0);
  FreeBuffer(first_buff);
}





/* SearchNextChar: increment pointer to next character which is no TAB,
		   SPACE, CR ist - start searching at actptr + 1
   Syntax:   result = SearchNextChar();
   Result:   result = 0: no character found
		    =-1: no more characters (end of file)
*/
int SearchNextChar(void)
{

  actptr++;
  while (*actptr) {
    switch (*actptr) {
      case  ' ':

      case 0x09: break;

      case 0x0A: linenum++;
		 break;
      default  : return(0);
    }
    actptr++;
  } 
  return(-1);

}


/* SearchNextAsterix: search for '*' up to the end of the file - starts
		      search at actptr
   Syntax:   result = SearchNextAsterix();
   Result:   result = 0: found a '*'
		    =-1: no more character (end of file)
*/
int SearchNextAsterix(void)
{
  while (*actptr) {
    if (*actptr == '*')
      return(0);
    if (*actptr == 0x0A)
      linenum++;
    actptr++;
   }
  return(-1);
}



/* GetJedec:
   read JEDEC file, check it and generate Jedec-structure

   Syntax: error=GetJedec(jedecfile);
	   UBYTE* jedecfile  : pointer to name of file (".jed")
   Result: error: >0 : error
                   0 : no error 
*/
int GetJedec(UBYTE *jedecfile)
{
extern	char	path;
LONG	filesize;
UBYTE	*filebuff, *ptr, *jedbuff, *jedptr;
int	n;
int	QFflag, QPflag, Fflag, Gflag, Cflag;
int	Lflag, STXflag, ETXflag, FCHKflag;
int	errornum, fuse_chk, file_chk;
unsigned int	num, fuse;
unsigned int	QF, QP, F;


  JedecGALType = NOT_SPECIFIED;

  filesize = FileSize(jedecfile);
  switch (filesize) {
    case -1L:
      ErrorReq(1);
      return(-1);
      break;

   case -2L:
     ErrorReq(2);
     return(-2);
     break;

   case 0L:
     ErrorReq(4);
     return(-4);
     break;
  }


 if ((filebuff = (UBYTE *)AllocMem(filesize+2L, MEMF_PUBLIC|MEMF_CLEAR))) {

   if ((ReadFile(jedecfile, filesize, filebuff))) {

     PrintText(AppStrings[MSG_FILE_LOADED].as_Str, 1);
     actptr = filebuff;				/* initialize variables */
     linenum  = 1;
     errornum = 0;
     fuse     = 0;
     QFflag = QPflag = Fflag = Gflag = Cflag = Lflag = STXflag = ETXflag = 0;
     FCHKflag = 0;

     if (!(jedbuff = (UBYTE *)AllocMem((long)sizeof(Jedec), MEMF_PUBLIC|MEMF_CLEAR))) {
       FreeMem(filebuff, filesize);
       ErrorReq(2);				/* no more free memory */
       return(-2);
     }
     jedptr = jedbuff;


     if (SearchNextAsterix()) {			/* point to first instruction */
       FreeMem(jedbuff, (long)sizeof(Jedec));	/* buffer for Jedec-structure */
       FreeMem(filebuff, filesize);
       JedecError(1, YES);			/* unexpected end of file*/
       return(1);
     }


     for (;;) {
       if (SearchNextChar())			/*is there any character left?*/
	 break;					/*no, then end this loop      */

       switch (*actptr) {
	 case 'Q':			/*instructions introduced by Q*/
	   actptr++;
	   if (*actptr == 'F') {	/*number of fuses in this file*/
	     if (QFflag) {			/*Befehl darf innerhalb des*/
	       errornum = 7;			/*Jedec-Files nur einmal*/
	       break;				/*vorkommen*/
	     }
	     actptr++;

	     if (!isdigit(*actptr)) {		/*is there a number?*/
	       errornum = 4;			/*no, then error*/
	       break;
	     }

	     if (!sscanf((char *)actptr, "%d", &QF)) {
	       errornum = 3;
	       break;
	     }

	     while (isdigit(*actptr))		/* skip number */
	       actptr++;

	     QFflag = 1;

	     if ((QF != 2194) && (QF != 2706) && (QF != 3274) && (QF != 5892)) {
	       errornum = 22;			/* unknown QF, then error */
	       break;
	     }

	     if (QF == 2194)			/* get out of *QF type of GAL */
	       JedecGALType = GAL16V8;

	     if (QF == 2706)
	       JedecGALType = GAL20V8;

	     if (QF == 5892)
	       JedecGALType = GAL22V10;

	     if (QF == 3274)
	       JedecGALType = GAL20RA10;

	     break;
	   }

	   if (*actptr == 'P') {		/* number of pins */
	     if (QPflag) {			/*this instructions is allowed*/
	       errornum = 8;			/*just once*/
	       break;
	     }
	     actptr++;

	     if (!isdigit(*actptr)) {		/*is there a number?*/
	       errornum = 4;			/*no, then error*/
	       break;
	     }

	     if (!sscanf((char *)actptr, "%d", &QP)) {
	       errornum = 3;
	       break;
	     }

	     while (isdigit(*actptr))		/*skip number*/
	       actptr++;

	     QPflag = 1;
	     break;
	   }
	   errornum = 2;			/*no QF,QP, then error*/
	   break;


	 case 'F':			/*** Fuse-Default ***/
	   actptr++;
	   if (*actptr == '0')
	     F = 0;
	   else
	     if (*actptr == '1')
	       F = 1;
	     else {				/*no 0 or 1 after F*/
	       errornum = 5;			/*then error*/
	       break;
	     }

	   for (n=fuse; n<sizeof(Jedec); n++)	/*default value*/
	     *(jedbuff + (long)n) = F;
	   Fflag = 1;
	   break;


	 case 'P':				/*pins for test vectors*/
	 case 'V':				/*test vector*/
	 case 'N':				/*comment*/
	   break;				/*do nothing*/


	 case 'C':			/*** Fuse-Checksum ***/
	   if (Cflag) {				/* only one fuse-chk. allowed*/
	     errornum = 24;
	     break;
	   }
	   actptr++;

	   if (!isxdigit(*actptr)) {		/*is there a hex. number?*/
	     errornum = 4;			/*no, then error*/
	     break;
	   }

	   if (!sscanf((char *)actptr, "%x", &fuse_chk)) {
	     errornum = 3;
	     break;
	   }

	   while (isxdigit(*actptr))		/* skip hex. number*/
	     actptr++;
	   Cflag = 1;
	   break;


	 case 'L':			/*** Fuse-Adresse ***/
	   if (Cflag) {				/*after *C no *L allowed*/
	     errornum = 10;
	     break;
	   }
	   actptr++;

	   if (!isdigit(*actptr)) {		/*is there a dez. number?*/
	     errornum = 4;			/*no, then error*/
	     break;
	    }

	   if (!sscanf((char *)actptr, "%d", &num)) {
	     errornum = 3;
	     break;
	    }

	   while (isdigit(*actptr))		/*skip dez. number*/
	     actptr++;

	   if (num < fuse) {			/* is fuse adr. too low?*/
	     errornum = 17;
	     break;
	   }

	   if ((num > fuse) && !Fflag) {	/* skip fuse address */
	     errornum = 18;			/* was there a *F? */
	     break;				/* no, then error  */
	   }

	   if (SearchNextChar()) {		/*no more characters?*/
	     errornum = 1;			/*then unexpected end of file*/
	     break;
	   }

	   fuse = num;
	   for (;;) {				/*examine fuses*/
	     if ((*actptr == '1') || (*actptr == '0')) {
	       *(jedbuff + (long)fuse) = *actptr - '0';
	     }
	     else {
	       if (*actptr == '*')		/*next instruction?*/
		 break;				/*yes, then ready*/
	       else {				/*no, then error '*' expected*/
		 errornum = 19;
		 break;
	       }
	     }

	     if (SearchNextChar()) {		/*no more characters?*/
	       errornum = 1;			/*then unexpected end of file*/
	       break;
	     }
	     fuse++;

	   }
	   Lflag = 1;
	   break;


	 case 'G':			/*** Security ***/
	   if (QPflag) {			/*this instruction my appear*/
	     errornum = 8;			/*just one time in the file */
	     break;
	   }
	   actptr++;

	   if (*actptr == '0')
	     JedecSecurity = 0;
	   else
	     if (*actptr == '1')
	       JedecSecurity = 1;
	     else {				/*no 0 nor 1 after G?*/
	       errornum = 5;			/*then error*/
	       break;
	     }
	   Gflag = 1;
	   break;


	 case 0x02:			/*** <STX> ***/
	   break;


	 case 0x03:			/*** <ETX> then File-Checksum ***/
	   ptr = filebuff;
	   file_chk = 0;
	   while (*ptr) {
	     if (*ptr == 0x02) {			/* multiple <STX> */
	       if (STXflag) {
		 errornum = 12;
		 break;
	       }
	       if (ETXflag) {				/* STX before ETX? */
		 errornum = 14;
		 break;
	       }
	       STXflag = 1;
	      }

	     if (*ptr == 0x03) {			/* <ETX> */
	       if (ETXflag) {				/* mulitple? */
		 errornum = 13;
		 break;
	       }
	       if (!STXflag) {				/* STX vor ETX? */
		 errornum = 14;
		 break;
	       }
	       ETXflag = 1;
	     }

	     if (STXflag && !ETXflag)			/*add to checksum*/
	       file_chk += *ptr;
	     ptr++;
	   }
	   file_chk += 0x03;				/* add ETX */
	   actptr++;

	   if (!isxdigit(*actptr)) {		/*is there a hex. number?*/
	     errornum = 4;			/*no, then error*/
	     break;
	   }

	   if (!sscanf((char *)actptr, "%x", &num)) {
	     errornum = 3;
	     break;
	   }

	   while (isxdigit(*actptr))		    /*skip hex. number*/
	     actptr++;
	   if (file_chk != num) {
	     if (!MyRequest(CONT_REQ, AppStrings[MSG_BAD_FILECHK].as_Str)) {
	       errornum = 16;
	       break;
	     }
	   }
	   FCHKflag = 1;
	   break;
       }


       if (errornum) {			/*was there an error? yes, then end*/
         FreeMem(jedbuff, (long)sizeof(Jedec));	/*free buffer of JEDEC structure*/
	 FreeMem(filebuff,filesize);		/*free buffer of JEDEC file*/
	 JedecError(errornum,YES);
	 return(errornum);
       }

       if (FCHKflag)				/*File-Checksum?*/
	 break;					/*yes, then break loop*/

       if (SearchNextAsterix()) 		/*search for final '*'*/
	 errornum = 9;

     }


     if (!Lflag && !Fflag) {			/*no fuses?*/
       FreeMem(filebuff, filesize);		/*then error*/
       FreeMem(jedbuff, (long)sizeof(Jedec));	/*free buffer of JEDEC structure*/
       JedecError(21, NO);
       return(21);
     }

     if (QFflag) {				/*does *L.. fit to *QF?*/
       if (((fuse != QF) && !Fflag) || (fuse > QF)) {
	 FreeMem(filebuff, filesize);		/*no, then error*/
         FreeMem(jedbuff, (long)sizeof(Jedec));	/*free buffer of JEDEC structure*/
	 JedecError(20, NO);
	 return(20);
       }
     }
     else {
       if (Fflag) {				/* try to identify the type of */
	 if ((fuse > 3274) && (fuse <= 5892))   /* GAL for which this JEDEC file */
	   JedecGALType = GAL20RA10;		/* is */

	 if (fuse <= 2194)			/* less than 2194 fuses => 16V8 */
	   JedecGALType = GAL16V8;

	 if (fuse > 5892) {			/* too many fuses for the known */
           FreeMem(jedbuff, (long)sizeof(Jedec)); /* types of GALs => error */
	   FreeMem(filebuff, filesize);
	   JedecError(6, NO);
	   return(23);
	 }
       }
       else {
         if ((fuse != 2194) && (fuse != 2706) && (fuse !=5892) && (fuse != 3274)) {
           FreeMem(jedbuff, (long)sizeof(Jedec));
	   FreeMem(filebuff, filesize);
	   JedecError(6, NO);
	   return(6);
	 }

         if (fuse == 2194)			/* if there was no QF and no */
	   JedecGALType = GAL16V8;		/* F instruction, identify type */
						/* of GAL by the last fuse */
         if (fuse == 2706)			/* address */
	   JedecGALType = GAL20V8;

	 if (fuse == 5892)
	   JedecGALType = GAL22V10;

	 if (fuse == 3274)
	   JedecGALType = GAL20RA10;

       }
     }

     if (FCHKflag)				/*file checksum?*/
       if (!SearchNextChar()) {			/*are there any more characters?*/
	 FreeMem(filebuff, filesize);		/*yes, then error*/
         FreeMem(jedbuff, (long)sizeof(Jedec));	/*free buffer of JEDEC structure*/
	 JedecError(15, YES);
	 return(15);
       }


					/*** initialize JEDEC structure ***/
     for (n = 0; n < sizeof(Jedec); n++) {

       if (JedecGALType == GAL16V8) {		/*** GAL16V8 ***/

	 if ((n < 2048) || (n > 5807 && n < 5816) || (n > 5817 && n < 5956)) {
 	   Jedec.GALLogic[n] = *jedptr;		/* get matrix, XOR, signature*/
	   jedptr++;				/* AC1, PT, SYN and AC0 */
	 }
	 else
	   Jedec.GALLogic[n] = 0;

       }

       if (JedecGALType == GAL20V8) {		/*** GAL20V8 ***/

	 if ((n < 2560) || (n > 5807 && n < 5816) || (n > 5817 && n < 5956)) {
 	   Jedec.GALLogic[n] = *jedptr;		/* get matrix, XOR, signature */
	   jedptr++;				/* AC1, PT, SYN and AC0 */
	 }
	 else
	   Jedec.GALLogic[n] = 0;

       }


       if (JedecGALType == GAL22V10) {		/*** GAL22V10 ***/

	 if ((n < 5808) || (n > 5817 && n < 5882)) {
 	   Jedec.GALLogic[n] = *jedptr;		/* get matrix, signature */
	   jedptr++;
	 }
	 else {
	   if (n > 5807 && n < 5818) {
 	     Jedec.GALXOR[n - 5808] = *jedptr;		/* get XORs */
	     jedptr++;

 	     Jedec.GALS1[n - 5808] = *jedptr;		/* get S1 */
	     jedptr++;
	   }
	   else
	     if (n < 5956 || n > 5965)			/* don't erase S1 */
	       Jedec.GALLogic[n] = 0;			/* it's set when n>5807 */
	 }
       }


       if (JedecGALType == GAL20RA10) {		/*** GAL20RA10 ***/

	 if ((n < 3200) || (n > 5807 && n < 5882)) {	/* get matrix, XOR */
 	   Jedec.GALLogic[n] = *jedptr;			/* and signature  */
	   jedptr++;
	 }
	 else
	   Jedec.GALLogic[n] = 0;

       }


     }


     if (Cflag) {			/* test whether checksum is o.k. or not */
       if (fuse_chk != FuseChecksum(JedecGALType)) {
         if (!MyRequest(CONT_REQ, AppStrings[MSG_BAD_FUSECHK].as_Str)) {
	   FreeMem(filebuff, filesize);
           FreeMem(jedbuff, (long)sizeof(Jedec));
	   JedecError(11, NO);			/* bad fuse checksum */
	   return(11);
	 }
       }
     }

     FreeMem(jedbuff, (long)sizeof(Jedec));	/*free buffer of JEDEC structure*/
     FreeMem(filebuff, filesize);		/*free buffer of JEDEC file*/
     return(0);					/*no error occured*/

   }
   else {
     ErrorReq(3);				/*read error*/
     FreeMem(filebuff, filesize);
     return(-2);
   }

 }
 else {
   ErrorReq(2);					/*not enough free momory*/
   return(-2);
 }

}







/*print error messages
  flag signs whether there should be printed a line number too or not
*/
void JedecError(int errornum, int flag)
{
 if (flag)
   PrintErrorLine(linenum);

 switch (errornum) {
   case  1: { PrintText(AppStrings[MSG_ERR_JED1].as_Str, 1);
	      break;
	    }
   case  2: { PrintText(AppStrings[MSG_ERR_JED2].as_Str, 1);
	      break;
	    }
   case  3: { PrintText(AppStrings[MSG_ERR_JED3].as_Str, 1);
	      break;
	    }
   case  4: { PrintText(AppStrings[MSG_ERR_JED4].as_Str, 1);
	      break;
	    }
   case  5: { PrintText(AppStrings[MSG_ERR_JED5].as_Str, 1);
	      break;
	    }
   case  6: { PrintText(AppStrings[MSG_ERR_JED6].as_Str, 1);
	      break;
	    }
   case  7: { PrintText(AppStrings[MSG_ERR_JED7].as_Str, 1);
	      break;
	    }
   case  8: { PrintText(AppStrings[MSG_ERR_JED8].as_Str, 1);
	      break;
	    }
   case  9: { PrintText(AppStrings[MSG_ERR_JED9].as_Str, 1);
	      break;
	    }
   case 10: { PrintText(AppStrings[MSG_ERR_JED10].as_Str, 1);
	      break;
	    }
   case 11: { PrintText(AppStrings[MSG_ERR_JED11].as_Str, 1);
	      break;
	    }
   case 12: { PrintText(AppStrings[MSG_ERR_JED12].as_Str, 1);
	      break;
	    }
   case 13: { PrintText(AppStrings[MSG_ERR_JED13].as_Str, 1);
	      break;
	    }
   case 14: { PrintText(AppStrings[MSG_ERR_JED14].as_Str, 1);
	      break;
	    }
   case 15: { PrintText(AppStrings[MSG_ERR_JED15].as_Str, 1);
	      break;
	    }
   case 16: { PrintText(AppStrings[MSG_ERR_JED16].as_Str, 1);
	      break;
	    }
   case 17: { PrintText(AppStrings[MSG_ERR_JED17].as_Str, 1);
	      break;
	    }
   case 18: { PrintText(AppStrings[MSG_ERR_JED18].as_Str, 1);
	      break;
	    }
   case 19: { PrintText(AppStrings[MSG_ERR_JED19].as_Str, 1);
	      break;
	    }
   case 20: { PrintText(AppStrings[MSG_ERR_JED20].as_Str, 1);
	      break;
	    }
   case 21: { PrintText(AppStrings[MSG_ERR_JED21].as_Str, 1);
	      break;
	    }
   case 22: { PrintText(AppStrings[MSG_ERR_JED22].as_Str, 1);
	      break;
	    }
   case 23: { PrintText(AppStrings[MSG_ERR_JED23].as_Str, 1);
	      break;
	    }
   case 24: { PrintText(AppStrings[MSG_ERR_JED24].as_Str, 1);
	      break;
	    }
   case 25: { PrintText(AppStrings[MSG_ERR_JED25].as_Str, 1);
	      break;
	    }
  }
 ErrorReq(5);

}




