/***********************************************
 (C) Copyright 1992-1993; dit/upm
   Distributed under the conditions stated in the
   EPS General Public License (see file LICENSE)
 ***********************************************
 $Log: elib.c,v $
 * Revision 2.6  1995/01/12  14:52:02  eps
 * force numbers for %tokens
 *
 * Revision 2.5  1993/01/12  16:36:14  eps
 * portability issues
 *
 * Revision 2.4  1992/01/14  15:44:28  eps
 * distribution issues
 *
 * Revision 2.3  92/01/14  15:27:46  eps
 * adapt to case independent cast
 *
 * Revision 2.2  90/10/31  07:37:11  eps
 * fix symbol table traversal
 *
 * Revision 2.1  90/10/30  08:41:08  eps
 * lag + rag -> lag
 * allowed productions are simplified (i.e. reduced)
 *
 **********************************************/

#ifndef lint
static char rcsid[]= "$Id: elib.c,v 2.6 1995/01/12 14:52:02 eps Exp $";
#endif

# include "swbus.h"

/*****  private variables  *****/

/*****  private functions headers  *****/

/*****  private function bodies  *****/

/*****  public function bodies  *****/


PUBLIC	void
linkbrothers (nterms, type)
	int	nterms;
	int	type;
{
  /* KJT 22/01/23: added "int" type */
  register int i;

  type &= R_SEC_PH;
  for (i=1; i < nterms; i++)
   if (type){
     fprintf(fgrm, "\t if (sttype() == tNULL) stpop();\n");
     fprintf(fgrm, "\t else if (stpick(1)->type == tNULL)");
	     fprintf(fgrm, " {stswap(); stpop();}\n");
     fprintf(fgrm, "\t else stlrlink();\n");
   }
   else
     fprintf(fgrm, "\t stlrlink ();\n");
}

PUBLIC	void
psyntax	(rhs)
	TNODE*	rhs;
{
	TNODE*	tmp;

  if (rhs == NULL){
     fprintf(fgrm, "\t/* empty */\n");
     return;
  }
  switch (rhs->type){
   case trepp:
   case trepa:
   case trepp_sep:
	fprintf(fgrm, "\t %s\n", (char*)fdclr(c_intid, rhs, -1));
	break;
   case tsecuence:
	fprintf(fgrm,     "\t");
	for (tmp=rhs->sons; tmp != NULL; tmp= tmp->brothers)
	  if (tmp->type == toption)
	    fprintf(fgrm, " %s", (char*)fdclr(c_intid, tmp, -1));
	  else
	    fprintf(fgrm, " %s", SymbolTable->data[(int)fdclr(c_lexv, tmp, -1)]);
	fprintf(fgrm, "\n");
	break;
   default:
	break;
  }
}

PUBLIC	char*
/* KJT 22/01/23: added "int" type */
bintid	(int type)
{
	static int	intid= 1;
	char		buf[BUFSIZ];

  (void) sprintf(buf, "I%d", intid++);
  switch (type){
   case R_REPP    : (void) strcat (buf, "repp"); break;
   case R_REPA    : (void) strcat (buf, "repa"); break;
   case R_REPP_SEP: (void) strcat (buf, "repp_sep"); break;
   case R_REPA_SEP: (void) strcat (buf, "repa_sep"); break;
   case R_OPT     : (void) strcat (buf, "opt"); break;
  }
  return str_alloc(buf);
}

PUBLIC	void
grheader (lagh, start)
	char*	lagh;
	int	start;
{
	char*	header="%{\n\
# include \"swbus.h\"\n\
# define YYSTYPE         yystype\n\
# define putgrn(n)       (void)ITadd(n, gl)\n\
# define class(nt)       { cls= 0; xxc= nt-1;   \\\n\
	       for (xc= 0; xc < nt; xc++, xxc--)    \\\n\
			     if (stpick(xc)->type != tNULL) \\\n\
		 cls += (1 << xxc);}\n\
# define ndput(tp)   { stput(tp);   \\\n\
	       if (gn != NULL){gn->value0=  \\\n\
		  (CLR_TYPE)IAT_IT_add(gl, grnl); \\\n\
		  gl->size= 0;} \\\n\
	       gn= (sttype() == tNULL) ? NULL : sttop(); }\n\
# define ndterm(tp, val) { stput (tp);  \\\n\
		       staclr (c_lexv, (CLR_TYPE)val.name); \\\n\
		       staclr (c_line, (CLR_TYPE)val.line);}\n\n\
IT* gl;\n\
TNODE*  gn;\n\
int cls;\n\
int xc;\n\
int xxc;\n\n";
  /* KJT 22/01/23: added "int" type */
  register int i;

  fprintf(fgrm, "%s", header);
  if (lagh != NULL) fprintf(fgrm, "%s", lagh);
  fprintf(fgrm, "%%}\n\n");
  for (i= 0 ; i < term_lis->size; i++)
     fprintf(fgrm, "%%token %s %d\n",
	     SymbolTable->data[term_lis->data[i]],
	     260+i);
  fprintf(fgrm, "\n%%start %s\n\n", SymbolTable->data[start]);
  fprintf(fgrm, "\n%%%%\n\n");
}

PUBLIC	void
grtail	()
{
	char*	tail="\n\
PRIVATE int\n\
yylex ()\n\
{\n\
    token *tk;\n\
\n\
   tk = gtk ();\n\
   yylval = tk->yylval;\n\
   return tk->type;\n\
}\n\
\n\
PUBLIC TNODE*\n\
bast ()\n\
{\n\
   gl= ITcreate (4, 2, 1);\n\
   gn= NULL;\n\
   (void)yyparse();\n\
   if (gn != NULL) gn->value0= (CLR_TYPE)IAT_IT_add(gl, grnl);\n\
   return sttop();\n\
}\n";

  fprintf(fgrm, "%%%%\n");
  fprintf(fgrm, "%s", tail);
}

PUBLIC	int
buildgrc (lhs, ngrc, nrule, ndid)
	int	lhs;
	int	ngrc;
	int	nrule;
	int	ndid;
{
  char	buf[BUFSIZ];

  if (ndid == -1)
    (void) sprintf(buf, "# define %s_%d %d\n",
		   SymbolTable->data[lhs], ngrc, nrule);
  else
    (void) sprintf(buf, "# define _%s_%d %d\n",
		   SymbolTable->data[lhs], ngrc, nrule);
  return STadd(buf, grcl, FALSE);
}

PUBLIC	int
lastgrc (nrule)
	int	nrule;
{
	char	buf[BUFSIZ];

  (void) sprintf(buf, "# define LAST_RULE %d\n", nrule);
  return STadd(buf, grcl, FALSE);
}

PUBLIC	void
actions	(lhs, rhs)
	TNODE*	lhs;
	TNODE*	rhs;
{
	int	rtype;
	int	nterms;
	int	i;

  rtype= (rhs != NULL) ? (int)fdclr(c_type, rhs, -1) : 0;
  nterms= (rhs != NULL) ? (int)fdclr(c_nterms, rhs, -1) : 0;
  if ((int)fdclr(c_type, lhs, -1) == R_NODE){
    if (rhs != NULL){
      if (rtype & R_REPA)
      {
       fprintf(fgrm, "\t if (sttype() == tNULL){\n");
       fprintf(fgrm, "\t\tclass(0);\n");
       fprintf(fgrm, "\t\tstpop();\n");
       fprintf(fgrm, "\t }\n");
       fprintf(fgrm, "\t else class(1);\n");
      }
      else if ((nterms == 1) && (rtype & R_SEC_PH)){
       fprintf(fgrm, "\t if (sttype() == tNULL){\n");
       fprintf(fgrm, "\t\tclass(0);\n");
       fprintf(fgrm, "\t\tstpop();\n");
       fprintf(fgrm, "\t }\n");
       fprintf(fgrm, "\t else class(1);\n");
      }
      else if (nterms > 0){
       fprintf(fgrm, "\t class(%d);\n", nterms);
       if (rtype & R_SEC_PH)
	 for (i=1; i < nterms; i++){
	  fprintf(fgrm, "\t if (sttype() == tNULL) stpop();\n");
	  fprintf(fgrm, "\t else if (stpick(1)->type == tNULL)");
		  fprintf(fgrm, " {stswap(); stpop();}\n");
	  fprintf(fgrm, "\t else stlrlink();\n");
	 }
       else
	 for (i=1; i < nterms; i++)
	  fprintf(fgrm, "\t stlrlink ();\n");
      }
      fprintf(fgrm,  "\t ndput(t%s);\n",
		     SymbolTable->data[(int)fdclr(c_lexv, lhs, -1)]);
      if (rtype & R_REPA)
      {
       fprintf(fgrm, "\t sttop()->value1= (CLR_TYPE)cls;\n");
       fprintf(fgrm, "\t if (cls == 1) stsflink ();\n");
      }
      else if ((nterms == 1) && (rtype & R_SEC_PH)){
       fprintf(fgrm, "\t sttop()->value1= (CLR_TYPE)cls;\n");
       fprintf(fgrm, "\t if (cls == 1) stsflink ();\n");
      }
      else if (nterms > 0){
       fprintf(fgrm, "\t sttop()->value1= (CLR_TYPE)cls;\n");
       fprintf(fgrm, "\t if (stpick(1)->type == tNULL)\n");
       fprintf(fgrm, "\t      {stswap(); stpop();}\n");
       fprintf(fgrm, "\t else stsflink ();\n");
      }
      else{
       fprintf(fgrm, "\t staclr (c_lexv, (CLR_TYPE)$1.name);\n");
       fprintf(fgrm, "\t staclr (c_line, (CLR_TYPE)$1.line);\n");
      }
    }
    else fprintf(fgrm,    "\t ndput(t%s);\n",
			  SymbolTable->data[(int)fdclr(c_lexv, lhs,
			  -1)]);
  }
  else if (rhs == NULL || nterms == 0)
    fprintf(fgrm, "\t ndput(tNULL);\n");
}

PUBLIC void
opena ()
{
  fprintf(fgrm,"\t{\n");
  fprintf(fgrm,"\tif (errorcount == 0)\n\t{\n");
}

PUBLIC void
closea()
{
  fprintf(fgrm,"\t}\n");
  fprintf(fgrm,"\t}\n");
}
