/*
 *  MODULE:  errecy.c
 *  error recovery operations
{*f  last modification:	26.06.92  16:17   }

 *  Tim 25.07.91 : patterncompiler moved into module 'patcompile.c'
 *  Tim 30.09.91 : ery_loahd has an argument now
 *  Uli 27.11.91 : binreadpats : search for pattern file.
 *  Tim 03.12.91 : exec_ops : special treatment when reporting operations
			      on constant and identifiers
 *  Uli 09.12.91 : exec_ops : "constant identifier" replaced by "constant"
		   exec_ops : "by" surrounded by \"
 *  Uli 20.12.91 : some not LINT_ARG corrected
 *  Tim 02.01.92 : ery_loahd : 'syntid' is assigned a reasonable value in
				any case
 *  Uli 03.01.92 : succ_patelm has shortint parameter instead of long
 *  Tim 24.01.92:  ALTLISTBEG and ALTLISTEND moved to errecy.h
                   binreadpats : ch is unsigned now
 *  Uli 11.02.92 : queuenext is void now.
 *  Tim 18.02.92 : "on_handling" check added.
 *  Uli 02.04.92 : std.h and seman.h not imported.
 *  Uli 06.04.92 : binreadpats: ov_handling added.
 *  Tim 25.06.92 : constant TOLERANCE added.
 *  PJ  31.03.95 : Added casts for ANSI compatibility.
                   #ifdef LINT_ARGS for bingetpatel, getpatslen added.

*/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include <ctype.h>
#include            "impor.t"
#include "sysutil.h"
#include "option.h"
#include "error.h"
#include "scan.h"
#include "symtab.h"
#include "idtab.h"
#include "optab.h"
#include "bintab.h"
#include "blktab.h"
/* #include "std.h" */
/* #include "seman.h" */

#include            "expor.t"
#include "errecy.h"

#include            "implemen.t"


#define MAX_RECUR   128
#define ALTSTOP     -1
#define ABCLEN      36
#define DEF_OFFS    1                    /* default offset in a pattern */
#define DEF_PATLEN  128                       /* default pattern length */
#define MAX_QU_NUMB  7    /* maximum of binqueue elements to be matched */
#define TOLERANCE    4    /* tolerance to avoid memory-faults in curops */
#define MAX_COST    117 / ( get_parsloc() >> BYTESIZE )
					    /* maximum of costs allowed */
#define BYTESIZE    8
#define SHORTSIZE   16


     /* data structure describing delete or insert operation on binqueue */
typedef struct  {  symctype symc;         /* Symbol code of symbol to be */
		  /* inserted, cNosym if symbol at 'pos'is to be deleted */
		   shortint pos;       /* position in binqueue, at which */
					  /* operation is to be executed */
		} ops, *opspt;

typedef struct  {  patternpt pathead;      /* data structure to describe */
		   shortint patind;             /* position in a pattern */
		 } patpos  /* *patpospt */;

#ifdef LINT_ARGS
local void init_match ( void);
local void queueput (binptr);
local void queuenext (void);
local binptr queueins(binptr, binptr);
local binptr queuedel(binptr);
local shortint getqueuelen( void);
local void bingetpatel (patternpt);
local boolean binreadpats (void);
local shortint alternatend( shortint);
local shortint alternatbeg( shortint);
local shortint succ_patelm( shortint);
local symctype mapsymc(symctype);
local shortint cost(symctype);
local patternpt findpattern(shortint);
local shortint find_err_pos( shortint);
local shortint find_cont_pos( void);
local shortint getpatslen (patternpt);
local void appops( symctype );
local void curops2lastops(void);
local void handlplain_patel(patternpt);
local void match_iterat ( patternpt, shortint);
local void match_alt ( shortint);
local void match_altlist ( shortint);
local void match_ref ( patternpt, shortint);
local void match_pat_queue ( shortint);
local void exec_ops (void);
local void startup_match (void);
local void dumppatlist (shortint, shortint);
#else
local void init_match ();
local void queueput ();
local void queuenext ();
local binptr queueins();
local binptr queuedel();
local shortint getqueuelen();
local void bingetpatel ();
local boolean binreadpats ();
local shortint alternatend();
local shortint alternatbeg();
local shortint succ_patelm();
local symctype mapsymc();
local shortint cost();
local patternpt findpattern();
local shortint find_err_pos();
local shortint find_cont_pos();
local shortint getpatslen ();
local void appops();
local void curops2lastops();
local void handlplain_patel();
local void match_iterat ();
local void match_alt ();
local void match_altlist ();
local void match_ref ();
local void match_pat_queue ();
local void exec_ops ();
local void startup_match ();
local void dumppatlist ();
#endif


static binptr  curqueue = NIL;                /* current binqueue pointer */
static binptr  queuelast ;          /* pointer to last symbol in binqueue */
static binptr  queuedum ;         /* pointer to dummy at head of binqueue */

static FILE * patfile = (FILE *)0;            /* file containing patterns */
static FILE * binpatfile = (FILE *)0;  /* binary file containing patterns */
static shortint patnumber = 0;
			/* number of elements in pat_list and pat_desc_li */

static shortint maxqunumb;         /* maximum of queue elements recovered */
static shortint del_mask;       /* determines wich elements of binque are */
       /* supposed to be deleted for one iterative run of match_pat_queue */

static opspt    lastops;        /* last list of error recovery operations */
static shortint lastopsend = 0;     /* shortint pointer at end of lastops */
static shortint lastcost ;
				/* last cost of error recovery operations */
static shortint curdelcost = 0;
			   /* deletion cost for last symbol to be deleted */

static opspt    curops;      /* current list of error recovery operations */
static shortint curopsend = 0;       /* shortint pointer at end of curops */
static shortint curcost = 0; /* current cost of error recovery operations */

static shortint curquind = 0;             /* current position in binqueue */
static symctype curqusymc;              /* current symbolcode in binqueue */

static patternpt curpathead;   /* pointer to beginning of current pattern */

static symctype expsymc = cNosym;               /* expected parser symbol */

static patpos   postrefs[ MAX_QU_NUMB * TOLERANCE];
			     /* stores positions after pattern references */
static shortint postrefsind = 0;
			   /* pointer to position after current reference */

					       /*-----------------------*/
					       /* d u m p p a t l i s t */
#ifdef LINT_ARGS
local void dumppatlist  (shortint index,shortint max_elem)
#else
local void dumppatlist ( index, max_elem)
	   /* dump one component of pat_list as far as max_elem */
shortint index;             /* index of component */
shortint max_elem;          /* number of elements to be dumped */
#endif
{ /* dumppatlist */
   char *string;
   shortint count_elem;      /* position in one component of pat_list */
   shortint pdesc;                              /* pattern descriptor */
   long psymc;
   boolean palternat;           /* alternat flag of a pattern element */
   patternpt *palipt;                            /* a pattern pointer */

   pdesc = pat_desc_li[index];
   printf("Description of Pattern number %d: Block %d, %s \n",
	   index,
	   pdesc >> BYTESIZE,
	   symptext[pdesc & 0x0ff] );
   palipt = &pat_list [index];
   for (count_elem = 0; count_elem <= max_elem; count_elem++) {
      psymc = ((*palipt) + count_elem)->symc;
      palternat = ((*palipt) + count_elem)->alternat;
      if ( psymc <= cHighest )  {
	 if ( psymc == ALTLISTBEG )
	    string = "ALTLISTBEG";
	 else if ( psymc == ALTLISTEND )
	    string = "ALTLISTEND";
	 else
	    string = symptext[psymc];
	       /* dump a pattern element with mere symbolcode in psymc */
	 printf ("%d %s %s %d \n",count_elem,
	 string,
	 symptext[cFALSE + palternat],
	 ((*palipt) + count_elem)->jumpindex)   ;
      }
      else       {                         /* dump a pattern reference */
	 pdesc = psymc;
	 psymc = (pat_desc_li[pdesc >> BYTESIZE] << BYTESIZE );
	 pdesc = pat_list[pdesc >> BYTESIZE][(pdesc & 0xff) - 1].symc;
	 psymc += pdesc;
	 if ( (psymc & 0x0ff) == cHighest )
	    printf ("%d Block:%d %s-pattern after 'PSTRT' %s %d\n",
	    count_elem,
	    psymc >>(2 * BYTESIZE),
	    symptext[(psymc & 0x0ff00)>>BYTESIZE],
	    symptext[cFALSE + palternat],
	    ((*palipt) + count_elem)->jumpindex);
	 else
	    printf ("%d Block:%d %s-pattern after %s %s %d \n",count_elem,
	    psymc >>(2 * BYTESIZE),
	    symptext[(psymc & 0x0ff00)>>BYTESIZE],
	    symptext[(psymc & 0x0ff)],
	    symptext[cFALSE + palternat],
	    ((*palipt) + count_elem)->jumpindex);
      }
   }
} /* dumppatlist */
					       /* d u m p p a t l i s t */
					       /*-----------------------*/


					   /* ---------------------*/
					   /* i n i t p a r s l o c */
#ifdef LINT_ARGS
global void initparsloc (                        )
#else
global void initparsloc()   /* Initialization of locating flags for */
			    /* parser */
#endif
{
   shortint i;

   for (i = 0; i < MAXUN; i++)
      parsloc.stop[i] = true;
   parsloc.stackptr = 0;
   for (i = 0; i < MAX_RECUR; i++)
      parsloc.synspec[i] = cNosym;

} /* initparsloc */                       /* i n i t p a r s l o c */
					   /* ---------------------*/

					   /* ---------------------*/
					   /* s e t p a r s l o c */
#ifdef LINT_ARGS
global void setparsloc (  shortint syntid,symctype syntspec)
#else
global void setparsloc( syntid, syntspec )
/* sets stack with syntactic symbols to facilitate error-recovery
 avoiding tree-operations */

shortint syntid;                     /* defining syntactic level */
symctype syntspec;  /* symbolcode describing syntactic unit */
#endif
{
   /* setting flag to locate parser for error recovery */

      parsloc.stop[syntid] = false;
      parsloc.synspec[++(parsloc.stackptr)] =
	    (shortint)syntspec + (syntid<<BYTESIZE);
	  /* store syntactic level and unit in synspec */
}  /* setparsloc */
					   /* s e t p a r s l o c */
					   /* ---------------------*/

					   /* ----------------------*/
					   /* s e t s t o p p a r s */
#ifdef LINT_ARGS
global void setstoppars (  shortint syntid)
#else
global void setstoppars( syntid )
	/* setting stop flag of specified syntactic unit to 'true' */
shortint syntid;                     /* defining syntactic level */
#endif
{
      parsloc.stop[syntid] = true;
}  /* setstoppars */
					   /* s e t s t o p p a r s */
					   /* ----------------------*/

					   /* ---------------------*/
					   /* r e s e t p a r s l o c */
#ifdef LINT_ARGS
global void resetparsloc (  shortint syntid)
#else
global void resetparsloc( syntid )
/* resets stack with syntactic symbols setting  stackptr-component
 in parsloc to "0" */

shortint syntid;  /* defining syntactic level */
#endif
{
   shortint recu;

     /* resetting flags locating parser for error recovery */

      parsloc.stop[syntid] = true;
      parsloc.stackptr--;

}  /* resetparsloc */
					   /* r e s e t p a r s l o c */
					   /* ---------------------*/

					   /* ---------------------*/
					   /*   c o n t p a r s    */
#ifdef LINT_ARGS
global void contpars ( shortint syntid)
#else
global void contpars(syntid)
shortint syntid;
#endif
{
   parsloc.stop[syntid] = false;
}
					   /*   c o n t p a r s    */
					   /* ---------------------*/


					   /* ---------------------*/
					   /*   s t o p _ c h k    */
#ifdef LINT_ARGS
global boolean stop_chk ( void)
#else
global boolean stop_chk() /* decides in dependence of stop flag of */
#endif                  /* current syntactic unit wether 'chkc' or */
					/* 'chkid' report an error */
{
   shortint i;

   i = get_parsloc() >> BYTESIZE;  /* get current syntactic unit */
   return ( parsloc.stop[i] ); }
					   /*   s t o p _ c h k    */
					   /* ---------------------*/


					   /* ---------------------*/
					   /*   s t o p p a r s    */
#ifdef LINT_ARGS
global boolean stoppars ( shortint syntid)
#else
global boolean stoppars(syntid)     /* returns true in dependence on */
	 /* stop flag of parsloc taking block structure into account */
shortint syntid;
#endif
{
   boolean stop;

   switch (syntid) {
      case DECL:
	   return( parsloc.stop[DECL]);
      case STM:
	   stop =  parsloc.stop[STM] || parsloc.stop[DECL];
	   return( stop);        /* STM is stopped by DECL */
      case SYNTAX:
	   stop =  parsloc.stop[SYNTAX] || parsloc.stop[STM] ||
		      parsloc.stop[DECL];
	   return( stop);   /* SYNTAX is stopped by STM or DECL */
      default:
	   printf("Illegal parameter in stoppars.\n");
	   return(true);
    }
}
					   /*   s t o p p a r s    */
					   /* ---------------------*/


					   /* ---------------------*/
					  /* p o p _ p a r s l o c */
#ifdef LINT_ARGS
global void pop_parsloc ( void)
#else
global void pop_parsloc( )
	 /* counts down pointer to last symbol of parsing stack */
#endif
{
   parsloc.stackptr-- ;
}  /* pop_parsloc */
					   /* p o p _ p a r s l o c */
					   /* ---------------------*/

					   /* ---------------------*/
					  /* g e t _ p a r s l o c */
#ifdef LINT_ARGS
global shortint get_parsloc ( void)
#else
global shortint get_parsloc ( )
		      /* returns symbol of parsing-stack */
		    /* specified by syntid and stackmove */
#endif
{
   symctype psymc;
   shortint pos;

   pos = parsloc.stackptr ;
   if ( pos <= 0 )                           /* stack is empty ? */
      return( 0 );
   else
      return (parsloc.synspec[pos]);
}  /* get_parsloc */
					   /* g e t _ p a r s l o c */
					   /*-----------------------*/

					     /*---------------------*/
					     /* i n i t _ m a t c h */
#ifdef LINT_ARGS
local void init_match ( void)
#else
local void init_match()      /* initializing data for match_pat_queue */
#endif
{
   shortint queuelen;

   queuelen = getqueuelen();
   maxqunumb = queuelen < MAX_QU_NUMB ?  queuelen : MAX_QU_NUMB ;
   lastops  = (opspt ) malloc(MAX_QU_NUMB * TOLERANCE * sizeof(opspt) );
   curops   = (opspt ) malloc(MAX_QU_NUMB * TOLERANCE * sizeof(opspt) );
   lastcost = MAX_COST  ;
				    /* Maximum of error recovery costs */
}
					     /* i n i t _ m a t c h */
					     /*---------------------*/

				       /*---------------------------*/
				       /* f i n i s h _ e r r e c y */
#ifdef LINT_ARGS
global void finish_errecy ( void)
#else
global void finish_errecy()      /* deleting error recovery data */
#endif
{
   shortint i;

   for (i = 0; i < patnumber; i++)
      free( pat_list[i] );
   patfile = (FILE *)0;
}
				      /* f i n i s h _ e r r e c y */
				      /*---------------------------*/


					     /*--------------------*/
					     /*  q u e u e p u t   */
#ifdef LINT_ARGS
local void queueput  ( binptr binerr)
#else
local void queueput (binerr)
binptr binerr;                 /* lookahead node to be entered */
#endif
{
   if ( sym_is [binsymc(binerr)].identifier == true )  {
      binchange (binerr, cCsymbol) ; /* identifier stored as C-symbol */
      binupsym (binerr, sym);        /* symbol pointer for id-name */
   }
   if (queuelast)  {         /* there is something written in binqueue */
       queuelast = binappend(queuelast,binerr);  /* append new node */
		    /* at end of list and have queuelast pointed at it */
   }
   else   {
      curqueue = binerr;        /* during creation of lookahead list */
			 /* curqueue points at beginning of binqueue */
      queuelast = binerr;                 /* set last element of list */


   }
}
					       /*  q u e u e p u t   */
					       /*--------------------*/


					       /*--------------------*/
					       /*  q u e u e n e x t */
#ifdef LINT_ARGS
local void queuenext  ( void)
#else
local void queuenext ()
	     /* returns next valid binpointer stored after curqueue */
#endif
{
   binptr next;

   curqueue = binright(curqueue);             /* next list-element */
   curquind++;
   if ( curqueue &&  0x1 << curquind-1  & del_mask  )
			/* symbol in binqueue supposed to be deleted */
      do {
	 curdelcost = cost( mapsymc( binsymc(curqueue) ) );
	 curcost += curdelcost;
			 /* add cost: deletion cost == insertion cost */
	 appops(cNosym );
      /* append deletion operation in ops, insert cNosym means delete */

	 curqueue = binright(curqueue);          /* next list-element */
	 curquind++;
      } while ( curqueue && ( (0x1 << (curquind - 1)) & del_mask ) ) ;

   if ( curqueue )  /* is there still a valid element in binqueue */
      curqusymc = mapsymc( binsymc (curqueue) );
		 /* assign default symbolcode facilitating comparison */
}
						  /*  q u e u e n e x t */
						  /*--------------------*/

						    /*------------------*/
						    /*  q u e u e d e l */
#ifdef LINT_ARGS
local binptr queuedel ( binptr runqueue)
#else
local binptr queuedel(runqueue)
binptr    runqueue;                 /* binpointer of entry to be deleted */
#endif               /* deletes listpointer and returns next listpointer */
{
     binptr rqueue;

     rqueue = binright(runqueue);

     bindelete( runqueue );             /* delete list element from queue */

     return(rqueue);            /* return symbol following deleted symbol */
}
						   /*  q u e u e d e l */
						   /*------------------*/

						 /*--------------------*/
						 /*  q u e u e i n s   */

#ifdef LINT_ARGS
local binptr queueins (binptr insqueue, binptr runqueue)
#else
local binptr queueins(insqueue, runqueue)
			      /* inserts insqueue in front of runqueue */
binptr insqueue;                 /* node to be inserted */
binptr    runqueue;
#endif
{
   binptr insfather;                /* father of node to be inserted */

   if (sym_is [binsymc(insqueue)].identifier)  { /* identifier */
      symptr sym;                  /* name of identifier, if any */
      sym = idsym (binid (insqueue)) ;
      
      binchange (insqueue, cCsymbol);
      binupsym(insqueue, sym);         /* change identifier to symbol */
   }
   if ( binsymc(insqueue) == cIcon )       /* default integer constant */
      binupvalue ( insqueue,(long int ) 100);
   
   binuppos( insqueue, binpos(runqueue) );
   if (binfather ( runqueue ) ) {  /* node to be inserted has a father */
						    /* and a right son */
      insfather = binfather ( runqueue);      /* store father position */
      binrlink(insfather, (binptr)NULL) ;
      binappend(insqueue, runqueue);    /* append runqueue at insqueue */
      binappend(insfather, insqueue);  /* append insqueue at insfather */
   }
   else
      binappend (insqueue, runqueue) ;
   return(insqueue);
}
						/*  q u e u e i n s   */
						/*--------------------*/


					      /*-----------------------*/
					      /* g e t q u e u e l e n */
#ifdef LINT_ARGS
local shortint getqueuelen( void)
#else
local shortint getqueuelen( )
#endif                          /* computes current length of binqueue */
{
     binptr rqueue = binqueue;
     shortint len = 1;

     while ( rqueue != queuelast)  {       /* while not end of binqueue */
	rqueue = binright(rqueue);
	len++;
     }
     return(len);
}
					      /* g e t q u e u e l e n */
					      /*-----------------------*/



						     /*-------------------*/
						     /* e r y _ l o a h d */
#ifdef LINT_ARGS
global void ery_loahd  ( shortint exp_symc )
#else
global void ery_loahd ( exp_symc)    /* performs error recovery lookahead */
	 /* reading erroneous source-code as far as the next stop symbol, */
       /* stores the former in binqueue and calls error-recovery routines */
shortint exp_symc;                              /* symbol, parser expects */
#endif
{
   idptr idp;
   shortint stackelem, syntid;

   /* P.J. 31.03.95  Cast to symctype added */
   expsymc = (symctype) exp_symc;
   stackelem = get_parsloc( );
   lastcost = MAX_COST;

   if ( binqueue ) {  /* there are queue elements supposed to be matched */
      syntid = stackelem >> BYTESIZE;
      parsloc.stop[ syntid] = true;

      binqueue = queueins ( bincopy (bincurr), binqueue);
					 /* reinsert contents of bincurr */
      startup_match ();                        /* special error recovery */
   }   /* binqueue already exists */
						       /* create binqueue */
   else {
      queuelast = curqueue = (binptr) NULL;
      if (not stoppars(SYNTAX) && (stackelem >> BYTESIZE) == SYNTAX ) {
	syntid = SYNTAX;                       /* error in syntax */
	while ( not (prio[binsymc(bincurr) ] < priopar ||
		   sym_is[binsymc(bincurr)].std_procdre) )  {
	   queueput(bincurr);
	   bincurr = (binptr) NULL;                 /* reset bincurr */
	   binget();
	}
	parsloc.stop[SYNTAX] = true;   /* syntax stopped but still active */
				    /* (deactivated by resetparsloc) */
      }
      else if ( not stoppars(STM) && not (stackelem>>BYTESIZE == SYNTAX)){
	syntid = STM;                             /* error in statement */
	while (not (sym_is[binsymc(bincurr)].stmstopper ||
		    sym_is[binsymc(bincurr)].std_procdre)  ) {
	   queueput(bincurr);
	   bincurr = (binptr ) NULL;                 /* reset bincurr */
	   binget();
	}

	parsloc.stop[STM] = true;                     /* stm stopped */
      }
      else if ( not stoppars(DECL) && not (stackelem >> BYTESIZE == STM ) ) {
	syntid = DECL;               /* error in declaration part */
	do {
	   if ( prio[ binsymc(bincurr) ] == priobegin )
	      if ( binsymc(bincurr) != cEndofSrc)  {
		   /* parsing to be resumed at another syntactic unit in */
				   /* declarations or in statement block */
		 parsloc.stop[DECL] = true;
		 break;
	      }
	      else {
		 errput (5002, binpos(bincurr), NULL);
					      /* unexpected end of source */
		 finish(-3);
	      }
	    else {
		queueput(bincurr );
		     bincurr = (binptr ) NULL;        /* reset bincurr */
		     binget();
	    }
	}  while ( true);
      }  /* violated block structure */
      queueput(bincurr);             /* store stop symbol in binqueue too */
      bincurr = (binptr ) NULL;       /* release bincurr */
      binqueue = curqueue;
				/* binqueue points at first queued symbol */
      if ( not queuedum)
	 queuedum = queueins( bincreate(cComma), binqueue);
				      /* insert dummy at head of binqueue */
      else binappend ( queuedum, binqueue);
	  /* queuedum points at dummy facilitating deletion or insertion */

      if (not patnumber)   {        /* patterns already read and stored? */
	 if ( binreadpats() )  /* Only if there is a binary pattern file */
	    startup_match ();      /* special error recovery is executed */
	 else patnumber = 1;            /* once in vain is enough */
      }
      else if ( patnumber > 1)
	 startup_match ();
   }  /* create binqueue */

   if ( lastcost >= MAX_COST ) {                  /* successless match */
      errput(13, pos, NULL);          /* Too many errors, not properly */
	    /* recovered. Source code skipped as far as shown position */
      bincurr = bincopy(queuelast);      /* set bincurr by stop symbol */
      symc = binsymc(bincurr);
      binqueue = (binptr ) NULL;
      if (queuedum) {         /* useless code is to be removed */
	 bintdelete(&queuedum );
      }
      queuelast = queuedum ;
      binqueue = queuedum;
      curqueue = queuedum;              /* clean up */
      return;     /* no lookahead necessary */
   }
   else   {
      parsloc.stop[syntid] = false; /* parse on in specified syntax block */
      binqueue = binright ( queuedum );
      binget();                               /* get recovered symbolcode */
      if ( syntid == SYNTAX && (stackelem & 0xFF) != cDot )
	 if ( not (prio[binsymc(bincurr) ] < priopar ||
		sym_is[binsymc(bincurr)].std_procdre)  )
	    binget();    /* skip symbol since it is recovered in 'syntax' */
	 else
	    setstoppars(SYNTAX);
   }
}  /* ery_loahd */
						  /* e r y _ l o a h d */
						  /*-------------------*/

					       /*-----------------------*/
					       /* s u c c _ p a t e l m */
#ifdef LINT_ARGS
local shortint  succ_patelm  ( shortint patelmsymc)
#else
local shortint succ_patelm ( patelmsymc)
    /* computes position of symbol after symbol with patelmsymc in symc */
shortint patelmsymc;
#endif
{ /* succ_patelm */
   shortint i;
   long psymc;
   boolean found;
   boolean ref_search;        /* decides wether successor of a pattern */
			     /* reference or a symbol code is searched */
   if ( patelmsymc == cHighest) {
      return(1);     /* cHighest node is dummy at beginning of a pattern */
   }

   ref_search = patelmsymc > cHighest;

   i = 1;
   psymc = (curpathead + i)->symc;
   found = psymc == patelmsymc;
   while ( not found &&
	   not (psymc == cHighest && (curpathead + i)->jumpindex == 0)) {
      if ( ref_search && pat_desc_li [psymc >> BYTESIZE] == patelmsymc ) {
				/* pattern reference searched and found */
	 found = true;
	 break;
      }
      i++;
      psymc = (curpathead + i)->symc;
      found = psymc == patelmsymc;
   }
   if ( found  )
      if ( (curpathead + i)->alternat == true )
	 return ( alternatend(i) + 1 );    /* position after alternatives */
      else
	 return ( i + 1);
		       /* return position of next symbol after patelmsymc */
   else
      return( 0 );

} /* succ_patelm */
						/* s u c c _ p a t e l m */
						/*-----------------------*/


					       /*-----------------------*/
					       /* a l t e r n a t b e g */
#ifdef LINT_ARGS
local shortint alternatbeg ( shortint curpatind )
#else
local shortint alternatbeg( curpatind )
shortint curpatind;
   /* computes and returns beginning of */
   /* alternatives in pattern */
#endif
{ /* alternatbeg */
   shortint j = curpatind - 1;       /* offset before end of alternatives */

   while ( (curpathead + j)->alternat == true
	&& (curpathead + j)->jumpindex == 0) {
      j--;
   }
   return(j + 1);                                       /* recounting one */

} /* alternatbeg */
						 /* a l t e r n a t b e g */
						 /*-----------------------*/

					       /*-----------------------*/
					       /* a l t e r n a t e n d */
#ifdef LINT_ARGS
local shortint alternatend ( shortint curpatind )
#else
local shortint alternatend( curpatind )
shortint curpatind;
   /* computes and returns end of */
   /* alternatives in pattern */
#endif
{ /* alternatend */
   shortint j = curpatind;

   while ( (curpathead + j)->alternat == true )  {
      if ( (curpathead + j)->jumpindex != 0 )
	 break;            /* end found */
      else
	 j++;
   }
   return(j);
} /* alternatend */
						 /* a l t e r n a t e n d */
						 /*-----------------------*/

						       /*---------------*/
						       /* m a p s y m c */
#ifdef LINT_ARGS
local symctype mapsymc (  symctype ssymc)
#else
local symctype mapsymc(ssymc)
  /* returns default symbolcode corresponding to symbolcode from source */
symctype ssymc;         /* source symbolcode */
#endif
{
   if ( sym_is[ssymc].identifier || ssymc == cCsymbol)
      return(cIdent);
   else if ( sym_is[ssymc].Operator && ssymc >= cReldmy )
      switch (ssymc) {
	 case cRelop :
	 case cAddop :
	 case cMulop :  return(cDiv);
			break;
	 case cMonop :  return(cNOT);
		   /* default Operators for userdefined Operator symbols */
      }

   else
      switch (ssymc) {
	 case cDot   :
	 case cDotN  :
	 case cDotD  :
	 case cDotU  :
	 case cDotS  :  return( cDot);
			break;
      default     :  return(ssymc);
      }
}
							 /* m a p s y m c */
							 /*---------------*/

							       /*---------*/
							       /* c o s t */
#ifdef LINT_ARGS
local shortint cost ( symctype ssymc )
#else
local shortint cost ( ssymc )
 /* computes deletion and insertion costs of a symbol
 /* with symbolcode ssymc */
symctype ssymc;
#endif
{ /* cost */
   shortint cost, i, runind ;
   if ( sym_is [ ssymc].identifier )
			      /* special treatment for identifiers */
      cost = prioleaf * 2;
   else
      switch (ssymc) {   /* special treatment for certain symbolcodes */
	 case cRParent :
	    cost = (prioleaf + 1 - priopar) *2;
	    break;
	 case  cRBrack :
	    cost = (prioleaf + 1 - prioindex) *2;
	    break;
	 default :
	    cost = (prioleaf +1- symprio(ssymc)) * 2;
      }
   cost += strlen( symptext[ssymc] );
   return(cost);

} /* cost */
							       /* c o s t */
							       /*---------*/

						 /*-----------------------*/
						 /* f i n d p a t t e r n */
#ifdef LINT_ARGS
local patternpt findpattern ( shortint pat_desc)
#else
local patternpt findpattern(pat_desc)
 /* searches and returns index of an element of patlist specified by its */
      /* parameter; null if search operation failed */
shortint pat_desc;             /* describing pattern */
#endif
{  /* findpattern */
   shortint high, low, mid, desc;

   desc = pat_desc;
   if ( (desc >> BYTESIZE) == SYNTAX
     && (desc & 0xff) != cDot )
      desc = (SYNTAX << BYTESIZE) + cIdent;

   low = 0;
   high = patnumber - 1;
   while ( low <= high )  {
      mid = (low + high) / 2;
      if ( desc < pat_desc_li[ mid ] )
	 high = mid - 1;
      else if ( desc > pat_desc_li[ mid ] )
	 low = mid + 1;
      else                                /* successful search */
	 return( *(pat_list + mid) );
   }
   return((patternpt) NULL);                         /* failure */

}  /* findpattern */
						 /* f i n d p a t t e r n */
						 /*-----------------------*/

					       /*-------------------------*/
					       /* f i n d _ e r r _ p o s */
#ifdef LINT_ARGS
local shortint find_err_pos ( shortint offset )
#else
local shortint find_err_pos( offset)
shortint offset;
	   /* searches and returns position of bcsymc in pattern stored */
		       /* after bpsymc, null if search operation failed */
#endif
{  /* find_err_pos */
   binptr runtree = binprev;
   symctype bpsymc;                    /* usually symbolcode of binprev */
   symctype bcsymc;                    /* usually symbolcode of bincurr */
   symctype psymc;
   shortint i = offset;

   bcsymc = mapsymc(expsymc);
   bpsymc = mapsymc( binsymc(binprev) );
   /* PJ 31.03.95  Cast to symctype added */
   psymc = (symctype) (curpathead + i)->symc;

   while ( psymc != bpsymc && psymc != cHighest)  {
						     /* search bpsymc */
      i++;                                               /* search on */
      /* PJ 31.03.95  cast to symctype added */
      psymc = (symctype) (curpathead + i)->symc;
   }
   if ( bpsymc == psymc )                           /* bpsymc found ? */
      offset = i ;
   else {                                  /* resume search operation */
      i = offset;
      psymc = cNosym;
   }

   if ( binright( runtree) ) {        /* is there another symbol after */
      do                                /* binprev inserted into tree ? */
	 runtree = binright( runtree);
      while ( binright( runtree) );
      bpsymc = mapsymc( binsymc( runtree) );
					   /* switch default symbolcode */
      while ( psymc != bpsymc && psymc != cHighest)  {
					     /* same procedure as above */
	 i++;
         /* PJ 31.03.95  cast to symctype added */
	 psymc = (symctype) (curpathead + i)->symc;
      }
      if ( psymc == cHighest )   {
	 i = offset;                          /* resume search operation */
	 psymc = cNosym;
      }
   }

   if (bcsymc == bpsymc ) i++;

   /* PJ 31.03.95  cast to symctype added */
   psymc = (symctype) (curpathead + i)->symc;    /* search expected symbol */
   while ( psymc != bcsymc && psymc != cHighest ) {
      i++;
      /* PJ 31.03.95  cast to symctype added */
      psymc = (symctype) ( curpathead + i)->symc;
   }
   if ( psymc == cHighest )
      return ( 0 );
   else {
      if ( ( curpathead + i - 1)->jumpindex > 0 &&
	   ( curpathead + i - 1)->jumpindex < i ) {
		   /* jumpindex found immediately before found position */
	 if ( ( curpathead + i - 1)->alternat == true )
		 /* alternative iteration symbol e.g. a dyadic Operator */
	    i = alternatbeg( i - 1 );
	 else
	    i -= 1;
      }
      return ( i );
   }
}  /* find_err_pos */
					     /* f i n d _ e r r _ p o s */
					     /*-------------------------*/



					   /*---------------------------*/
					   /* f i n d _ c o n t _ p o s */
#ifdef LINT_ARGS
local shortint find_cont_pos ( )
#else
local shortint find_cont_pos( )
#endif
			 /* setting statics to provide next pattern that */
					 /* can be matched with binqueue */
     /* !!!!!!!!!!!sideeffects on curpathead !!!!!!!!!!!!!!*/
{  /* find_cont_pos */
   shortint laststackel;
   shortint pos;
   patternpt temppat;

   laststackel = get_parsloc();
   pop_parsloc();
   if ( parsloc.stackptr == 0 )
      return((shortint)0);
   curpathead = findpattern( get_parsloc() );

   if ( (laststackel >> BYTESIZE) == SYNTAX
     && (laststackel & 0xff) != cDot ) {
			    /* 'cIdent' pattern in SYNTAX */
      pos = succ_patelm ( laststackel & 0xff );
				/* get position of pattern reference */
      if ( (curpathead + pos)->alternat == true )
	 pos = alternatend(pos) + 1;
      else
	 pos++;          /* get next pattern element after reference */
			      /* to 'cIdent' pattern */
   }
   else
      pos = succ_patelm ( laststackel );
				    /* get next element after reference */
   return ( pos );

}  /* find_cont_pos */
					   /* f i n d _ c o n t _ p o s */
					   /*---------------------------*/

					       /*-----------------------*/
#ifdef LINT_ARGS
local boolean binreadpats ( void )             /* b i n r e a d p a t s */
#else
local boolean binreadpats ( )
#endif
		 /* reads pat_list from a binary file */
{
   unsigned char ch;
   shortint shi, i, j, len;
   patternpt palipt;
   char * p , fn [FILENAME_MAX] ;

   binpatfile = NULL ;

   if  (ov_handling == 0)   return( false);
   /* 06.04.92  errecy disabled by compiler option h0 */

/**/ binpatfile = fopen ("patterns.bin", "r") ;

/**/if ( binpatfile == NULL ) {
   p = getenv (P88SYS) ;
   if  (p)  then
    begin
      strcpy (fn, p) ;
      strcat (fn, patterns) ;
      binpatfile = fopen (fn, "r");
    end ;
   if ( binpatfile == NULL )
    begin
      strcpy (fn, sysdir) ;
      strcat (fn, patterns) ;
      binpatfile = fopen (fn, "r");
    end ;
   }
   if ( binpatfile == NULL )  {
      if ( on_handling)
         errput(14 ,pos, patterns);
    /* Pattern file @ not found; this will cause simple error recovery. */
      return( false);
   }
   patnumber = getc ( binpatfile);       /* get first byte of patnumber */
   if ( patnumber == EOF) {
      if (on_handling)  
         errput(19 ,pos, NULL);
	  /* Pattern file is empty; please recompile with 'patcompile'. */
      return( false);
   }
   patnumber = (patnumber << BYTESIZE);
   ch = getc ( binpatfile);               /* get last byte of patnumber */
   patnumber = patnumber + ch;

   for ( i = 0; i < patnumber; i++)   {
      ch = getc ( binpatfile);           /* get descriptor for syntactic */
      shi = (ch << BYTESIZE);                         /* level */
      ch = getc ( binpatfile);           /* get pattern descriptor */
      shi = shi + ch;
      pat_desc_li[i] = shi;
      ch = getc ( binpatfile);        /* get length of patterns */
      len = (shortint) ch;
      pat_list[i] = (pat_elem *) malloc ( (len + 1) * sizeof(pat_elem) );
      palipt = pat_list[i];
      for ( j = 0; j <= len; j++)
	 bingetpatel( palipt + j );   /* get pattern elements */
   }
   for ( i = 0; i < patnumber; i++)

   fclose(binpatfile);              /* clean up */
   return(true);

}
					       /* b i n r e a d p a t s */
					       /*-----------------------*/

/* PJ 31.03.95  #ifdef LINT_ARGS added */
					       /*-----------------------*/
					       /* b i n g e t p a t e l */
#ifdef LINT_ARGS
local void bingetpatel( patternpt palipt )
#else
local void bingetpatel( palipt )
	  /* gets one element from binpatfile and enters it into palipt */
patternpt palipt;
#endif
{
   long symc;
   unsigned char ch ;

   ch = getc( binpatfile);
   if ( ch > 0 )  {        /* pattern descriptor found */
      symc = (long) ( ch << BYTESIZE );      /* index in pat_list */
      ch = getc( binpatfile);
      symc += (ch & 0xff);         /* index of patternelement */
      palipt->symc = symc;
   }
   else  {
      ch = getc( binpatfile);
      switch (ch) {
	 case 254: palipt->symc = ALTLISTBEG;
		   break;
			     /* (254 == -2 since ch is a character ) */
	 case 253: palipt->symc = ALTLISTEND;
		   break;
			     /* (253 == -3 since ch is a character ) */
	 default : palipt->symc = (long) ch;
      }
   }
   palipt->alternat = getc( binpatfile);            /* alternat flag */
   ch = getc( binpatfile);
   palipt->jumpindex =  ch == 255 ? ALTSTOP : ch;
	       /* and jumpindex (255 == -1 since ch is a character ) */
}
						 /* b i n g e t p a t e l */
						 /*-----------------------*/

/* PJ 31.03.95  #ifdef LINT_ARGS added */
						   /*---------------------*/
						   /* g e t p a t s l e n */
#ifdef LINT_ARGS
local shortint getpatslen( patternpt palipt )
#else
local shortint getpatslen(palipt)
		    /* returns index of last element of palipt */
patternpt palipt;
#endif
{
   return( palipt->jumpindex );
}
					       /* g e t p a t s l e n */
					       /*---------------------*/

						       /*-------------*/
						       /* a p p o p s */
#ifdef LINT_ARGS
local void appops ( symctype symc )
#else
local void appops ( symc)
symctype symc ;
#endif
     /* appends description of one error recovery operation at curops */

{
   curops[curopsend].symc = symc;
   curops[curopsend].pos = curquind;
   curopsend++;
}
						       /* a p p o p s */
						       /*-------------*/

					  /*-----------------------------*/
					  /* c u r o p s 2 l a s t o p s */
#ifdef LINT_ARGS
local void curops2lastops ( void)
#else
local void curops2lastops ( )
#endif
	       /* assigning contents of current operation list to lastops */
{
   shortint i;

   for ( i = 0; i < curopsend; i++ )
      lastops[ i ] = curops[ i ];
   lastopsend = curopsend;
}

					  /* c u r o p s 2 l a s t o p s */
					  /*-----------------------------*/

				      /*---------------------------------*/
				      /* h a n d l p l a i n _ p a t e l */
#ifdef LINT_ARGS
local void handlplain_patel ( patternpt curpatpt )
#else
local void handlplain_patel ( curpatpt )

patternpt curpatpt;                 /* pointer to current pattern element */
#endif
{
   shortint inscost, delcost;             /* deletion and insertion costs */
   symctype psymc;

   /* PJ 31.03.95  cast to symctype added */
   psymc = ( symctype ) curpatpt->symc;
   if ( psymc == curqusymc )                          /* curqusymc found */
      queuenext();                         /* next element from binqueue */
   else {
      inscost = cost( psymc);
      if ( curops[curopsend - 1].symc == cNosym &&
	   curops[curopsend - 1].pos == curquind - 1)  {
			   /* deletion before insertion i.e. replacement */

	 curcost += ( curdelcost > inscost ? curdelcost : inscost) -
		      curdelcost;
			  /* add maximum of deletion and insertion costs */
			     /* curdelcost was added before in queuenext */
      }
      else
	 curcost += inscost;
      appops( psymc);                                 /* store operation */
   }
}


				       /* h a n d l p l a i n _ p a t e l */
				       /*---------------------------------*/

						/*------------------------*/
						/* m a t c h_ i t e r a t */

#ifdef LINT_ARGS
local void match_iterat ( patternpt curpatpt, shortint curpatind)
#else
local void match_iterat (curpatpt, curpatind )
				   /* directs match of alternative lists */
patternpt curpatpt;                 /* pointer to current pattern element */
shortint  curpatind;                  /* index of current pattern element */
#endif
{
   match_pat_queue( curpatind + 1 );
			   /* continue after element containing jumpindex */
   match_pat_queue( curpatpt->jumpindex );
      /* go back and start all over again until best possibility is found */
}
						/* m a t c h_ i t e r a t */
						/*------------------------*/

						      /*------------------*/
						      /* m a t c h_ a l t */

#ifdef LINT_ARGS
local void match_alt ( shortint curpatind )
#else
local void match_alt ( curpatind )
	    /* matches one-symbol (terminal or nonterminal) alternatives */
shortint curpatind;                  /* index of current pattern element */
#endif
{
   patternpt temppat;
   shortint  temppatind;
   shortint altend;
   shortint jumpback;
   shortint offset;
   boolean iterat = false, optional = false;
   boolean found = false;
   shortint temppostrefsind = postrefsind;
   patpos temppostrefs[MAX_QU_NUMB * TOLERANCE];

   altend = alternatend( curpatind);
					  /* compute end of alternatives */
   jumpback = (curpathead + altend)->jumpindex;
   if ( jumpback > 0 && jumpback < curpatind )
						/* alternative jump back */
      iterat = true;
   else if ( (curpathead + altend)->symc == cNosym )
						     /* optional symbols */
      optional = true;
   temppatind = curpatind;
   if ( iterat )  {
      match_pat_queue ( altend + 1);
	    /* match after alternatives first, compare to match_iterat */
      offset = jumpback;
			   /* directing further calls of match_pat_queue */
   }
   else
      offset = altend + 1;

   while ( temppatind <= altend  ) {
      temppat = curpathead + temppatind;
      if ( temppat->symc > cHighest )  {
						    /* pattern reference */
	 match_ref(temppat, offset);
      }
      else if ( temppat->symc == curqusymc)  {
		    /* pattern symbol matches current symbol in binqueue */
	 found = true;
		 /* there can still be pattern references, thus no break */
      }
      temppatind++;
   }
   if ( found ) {
      queuenext();                            /* next symbol in binqueue */
      match_pat_queue ( offset);   /* continue match depending on offset */
   }
   else if ( optional && not iterat)
      match_pat_queue ( offset);   /* continue match depending on offset */
   else  {
			 /* there must be inserted one alternative symbol */
      temppatind = curpatind;
	    /* search symbol to be inserted from beginning of alternative */
      while ( temppatind <= altend &&
	      (curpathead + temppatind)->symc > cHighest )
			   /* search first terminal symbol in alternative */
	 temppatind++;
      if ( temppatind <= altend &&
		       (curpathead + temppatind)->symc != cNosym )  {
    /* mark insertion of a terminal symbol into binqueue, if there is one */
         if ( (curpathead + temppatind)->symc == cComma && curpatind == 2)
            altend = altend;
	 handlplain_patel(curpathead + temppatind );
	 match_pat_queue ( offset);                 /* and continue match */
      }
   }
}
						      /* m a t c h_ a l t */
						      /*------------------*/


					      /*--------------------------*/
					      /* m a t c h_ a l t l i s t */

#ifdef LINT_ARGS
local void match_altlist ( shortint curpatind )
#else
local void match_altlist ( curpatind )
				   /* directs match of alternative lists */
shortint curpatind;                   /* index of current pattern element */
#endif
{
   patternpt temppat;
   shortint afterlastalt, tempind;

   temppat = curpathead + (curpathead + curpatind)->jumpindex ;
	   /* temppat points at end delimiter of first alternative list */
   afterlastalt = temppat->jumpindex;
			   /* determine position after all alternatives */
   temppat = curpathead + afterlastalt - 1;
	/* now temppat points at end delimiter of last alternative list */
   if ( temppat->alternat )
				       /* alternative list may be empty */
      match_pat_queue( afterlastalt );
				      /* skip all alternatives for once */

   tempind = curpatind;              /* restore old position in pattern */
   while ( (curpathead + tempind )->symc == ALTLISTBEG )  {
				  /* while there is an alternative list */
      match_pat_queue ( tempind + 1 );
				     /* run through current alternative */
      tempind = (curpathead + tempind)->jumpindex + 1;
		       /* beginning of next list, skipping 'ALTLISTEND' */
   }
}
					     /* m a t c h_ a l t l i s t */
					     /*--------------------------*/

						    /*-------------------*/
						    /* m a t c h _ r e f */
#ifdef LINT_ARGS
local void match_ref( patternpt curpatpt, shortint postrefind )
#else
local void match_ref( curpatpt, postrefind )
				   /* tries to match one pattern referred */
     /* to in curpatpt and stops at its end. Returns false if match fails */
patternpt curpatpt;    /* pointer to pattern element containing reference */
shortint postrefind;    /* position in pattern to be continued with after */
					    /* reference has been matched */
#endif
{
   long psymc;

   postrefs[++postrefsind].pathead = curpathead;
   postrefs[postrefsind].patind = postrefind;
					 /* save infos of current pattern */
   psymc = curpatpt->symc;
   curpathead = pat_list[ psymc >> BYTESIZE];
   match_pat_queue ( psymc & 0xff);           /* match referenced pattern */

   curpathead = postrefs[postrefsind--].pathead ;
						    /* restore curpathead */
}
						     /* m a t c h _ r e f */
						     /*-------------------*/

				       /*-------------------------------*/
				       /* m a t c h _ p a t _ q u e u e */
#ifdef LINT_ARGS
local void match_pat_queue( shortint patind )
#else
local void match_pat_queue( patind )
     /* tries to match patterns and erroneous lookahead */

shortint patind;                      /* index of current pattern element */
#endif
{ /* match_pat_queue */
   shortint curpatind = patind;                 /*                        */
   shortint i, tempopsend = curopsend ;         /*                        */
   shortint tempcost   = curcost ;              /*                        */
   binptr   tempqueue  = curqueue ;             /* temporary variables to */
   shortint tempquind  = curquind ;             /* save statics           */
   symctype tempqusymc  = curqusymc ;           /*                        */
   shortint temppostrefsind = postrefsind;
   patternpt temppat = curpathead;
   shortint t_stackptr = parsloc.stackptr;    /* save stackpointer, since */
			     /* stack may be searched modifying .stackptr */
   patpos temppostrefs[MAX_QU_NUMB * TOLERANCE];

   patternpt curpatpt;   /* we need some variable of that type, don't we? */
   long psymc;                    /* normally .symc component of curpatpt */

   for (i = 1; i <= postrefsind; i++)    /* save stack of positions after */
      temppostrefs[i ] = postrefs[ i];              /* pattern references */


   curpatpt = curpathead + curpatind;
   while ( curcost < lastcost && curquind <= maxqunumb )  {
      psymc = curpatpt->symc;
      if ( psymc > cNosym )
			      /* normal symbolcode or pattern reference */
	 if ( psymc < cHighest && not curpatpt->alternat ) {
					     /* plain normal symbolcode */
	    handlplain_patel(curpatpt++);
	    curpatind++;
	 }
	 else if ( curpatpt->alternat ) {
			    /* single-patternelement alternatives found */
	    match_alt( curpatind ); break;
	 }
	 else if ( psymc > cHighest) {
			     /* non-alternative pattern reference found */
	    match_ref(curpatpt, curpatind + 1); break;
	 }
	 else
	      /* anything else means cHighest i.e. end of current pattern */
	    if ( not postrefsind )  {
		     /* end of pattern and no pattern address to continue */
	       curpatind = find_cont_pos();
				    /* curpathead is set in find_cont_pos */
	       if ( not curpatind ) break;
	       curpatpt = curpathead + curpatind;
	    }
	    else {
	       curpathead = postrefs[postrefsind].pathead;
	       curpatind = postrefs[postrefsind--].patind;
	       curpatpt = curpathead + curpatind;
	    }
      else if ( psymc == ALTLISTBEG)  {
					     /* alternative lists found */
	 match_altlist( curpatind ); break;
				/* let somebody else do the tough stuff */
      }
      else if ( psymc == ALTLISTEND ) {
				    /* end of an alternative list found */
	 curpatind = curpatpt->jumpindex;
	   /* get index of patternelement stored after end of last list */
	 curpatpt = curpathead + curpatind;
				     /* continue after end of last list */
      }
      else if ( curpatpt->jumpindex > 0 && curpatpt->jumpindex < curpatind )
	 {                            /* address for jumping back found */
	 match_iterat( curpatpt, curpatind ); break;
      }
   }

   if (curcost < lastcost && curquind > maxqunumb )  {
		       /* cheaper error recovery operations in this run */
      curops2lastops();               /* save last optimum of operations */
      lastcost = curcost;                       /* and cost */
   }
   curopsend = tempopsend;             /* restore old values of statics */
   curcost   = tempcost  ;
   curqueue   = tempqueue  ;
   curquind = tempquind;
   curqusymc = tempqusymc;
   curpathead = temppat;
   parsloc.stackptr = t_stackptr;           /* restore stackpointer */
   for (i = 1; i <= temppostrefsind; i++)
      postrefs[i ] = temppostrefs[ i];
   postrefsind = temppostrefsind;
} /* match_pat_queue */
				       /* m a t c h _ p a t _ q u e u e */
				       /*-------------------------------*/

						     /*-----------------*/
						     /* e x e c _ o p s */
#ifdef LINT_ARGS
local void exec_ops( void)
#else
local void exec_ops( )
#endif
		      /* executes and reports error recovery operations */
{
   char infostring[MAX_QU_NUMB * ( SYMSIZE + 4)];
   char argstring [ SYMSIZE + 4 ];
   shortint lastpos;
	/* storing position of last element of binqueue to be recovered */
   shortint i, queuecount = 1;
   shortint opsexe = 0;                 /* counting executed operations */
   shortint opsrep = 1;                 /* counting reported operations */

   binptr tempqueue = binqueue;
   symctype osymc;                    /* symbolcode to be operated with */
   symctype tempsymc;
   boolean replace = false;

   strcpy(infostring, "" );
   for ( i = lastopsend; i < MAX_QU_NUMB * TOLERANCE;i++) {
      lastops[i].symc = cNosym;
      lastops[i].pos = 0;
   }
   while ( opsexe < lastopsend ) {
			 /* list of operations not completely executed */
      lastpos = lastops[opsexe].pos;
      osymc = lastops[opsexe].symc;
      while ( queuecount < lastpos ) {
	 tempqueue = binright( tempqueue );
	 queuecount++;
      }
		 /* find position in binqueue corresponding to lastpos */
      tempsymc = binsymc(tempqueue);

      if ( osymc != cNosym ) {                      /* insert operation */
	 while ( lastpos == lastops[opsexe].pos ) {
		 /* executing every insert operation admitted at lastpos */
	    osymc = lastops[opsexe++].symc;
	    if ( sym_is [ osymc].constant )  {
		     /* constant identifier stands for any constant type */
	       queueins ( binsycreate ( symNIL ), tempqueue ) ;
	       strcat(infostring, " " );
	       strcat(infostring, "constant" );
	    }
	    else  {
	       queueins( bincreate (osymc), tempqueue);
					      /* insert before tempqueue */
	       strcat(infostring, " " );
	       strcat(infostring, symptext[osymc] );
	    }
	 }
         if ( on_handling )
	    errput(16, binpos(tempqueue), infostring );
			   /* recovery action was to insert 'infostring' */
	 opsrep++;                                   /* report only once */
	 strcpy(infostring, "");
      }
      else if ( lastops[opsexe + 1].pos == lastpos + 1 &&
		lastops[opsexe + 1].symc != cNosym ) {
	   /* insertion operation at next position i.e. replacement op.*/
	 osymc = lastops[++opsexe].symc;
	 switch ( tempsymc ) {
			      /* report value of constant to be deleted */
	    case cCcon :
	       sprintf (argstring, "'%c' ", binvalue ( tempqueue) );
	       break;
	    case cIcon :
	       sprintf (argstring, "%d ", binvalue ( tempqueue) );
	       break;
	    case cScon :
	       sprintf (argstring, "'%s' ", bincharp ( tempqueue) );
	       break;
	    case cRcon :
	       sprintf (argstring, "%s ", bincharp ( tempqueue) );
	       break;
	    case cCsymbol :
	       sprintf (argstring, "%s ", symtext( binsym(tempqueue) ));
	       break;
	    default :
	       strcpy( argstring, symptext[tempsymc]);
	 }
	 strcat ( infostring, argstring );
	 strcat( infostring, " \" by \" " );
	 if ( sym_is [ osymc].constant )
	    strcat(infostring, "constant" );
	 else
	    strcat( infostring, symptext[osymc]);
	 if (on_handling)  
            errput(17, binpos(tempqueue), infostring );
  /* recovery action was to replace symptext[tempsymc] by symptext[osymc] */

	 strcpy(infostring, "");                       /* free infostring */
	 opsrep++;
	 tempqueue = queuedel (tempqueue);
						      /* delete tempqueue */
	 if ( sym_is [ osymc].constant )
		  /* constant identifier stands for any constant type */
	    queueins ( binsycreate ( symNIL ), tempqueue );
	 else
	    queueins( bincreate (osymc), tempqueue);
					   /* insert before tempqueue */
	 opsexe ++;
	 queuecount++;                /* count deleted symbol in binqueue */
      }
      else {                                          /* delete operation */
	 do {
			      /* concatenate string of subsequent symbols */
		 /* which are supposed to be deleted, none to be replaced */
	    if ( lastops[opsexe + 1].pos == lastops[opsexe ].pos + 1 &&
		 lastops[opsexe + 1].symc != cNosym )
	       break;          /* next operation is permitted replacement */
	    switch ( tempsymc ) {
				 /* report value of constant to be deleted */
	       case cCcon :
		  sprintf (argstring, "'%c' ", binvalue ( tempqueue) );
		  break;
	       case cIcon :
		  sprintf (argstring, "%d ", binvalue ( tempqueue) );
		  break;
	       case cScon :
		  sprintf (argstring, "'%s' ", bincharp ( tempqueue) );
		  break;
	       case cRcon :
		  sprintf (argstring, "%s ", bincharp ( tempqueue) );
		  break;
	       case cCsymbol :
		  sprintf (argstring, "%s ", symtext( binsym(tempqueue) ));
		  break;
	       default :
		  strcpy( argstring, symptext[tempsymc]);
	    }
	    strcat ( infostring, argstring );
	    strcat( infostring, " ");
	    tempqueue = queuedel( tempqueue);
				    /* remove single symbol from binqueue */
	    tempsymc = binsymc ( tempqueue);
	    opsexe++;
	    queuecount++;             /* count deleted symbol in binqueue */
	 } while ( lastops[opsexe ].symc == cNosym && opsexe < lastopsend);

         if ( on_handling )
	    errput (15, binpos(tempqueue), infostring);
	    /* recovery action was to delete <infostring> . */
	 strcpy(infostring, "");                       /* free infostring */
	 opsrep++;
      }

   } /* while .. < lastopsend .. */

}
						     /* e x e c _ o p s */
						     /*-----------------*/

					   /*---------------------------*/
					   /* s t a r t u p _ m a t c h */
#ifdef LINT_ARGS
local void startup_match( void)
#else
local void startup_match( )
#endif
{
   shortint i, t_stackptr = parsloc.stackptr;

   init_match();
   curpathead = findpattern ( get_parsloc() );
   i = find_err_pos( DEF_OFFS);                   /* get right position */
   if ( !i )  {
      curpathead = findpattern ( get_parsloc( ) );
      i = find_err_pos(find_cont_pos() );         /* get right position */
      if ( !i ) {
	 parsloc.stackptr = t_stackptr;         /* restore stackpointer */
	 if (on_handling)  
	    errput(18, pos, NULL );
	      /* No suitable pattern position to present symbols found. */
		   /* Switching to simple error recovery ( panic mode). */
	 return ;
      }
   }
   for ( del_mask = 0; del_mask < ( 1 << maxqunumb - 1); del_mask++ )  {
		      /* try every permutation of delete operations */
      curqueue = queuedum; curcost = 0; curquind = 0;  /* reset statics */
      curopsend = 0; curqusymc = mapsymc(binsymc(curqueue) );

      queuenext();                /* get next element not to be deleted */
      match_pat_queue( i );
   }
   parsloc.stackptr = t_stackptr;             /* restore stackpointer */
   if ( lastcost < MAX_COST )
      exec_ops();
   free(lastops);                                         /* clean up */
   free(curops);
}
					 /* s t a r t u p _ m a t c h */
					 /*---------------------------*/

