/*{{{}}}*/
/*{{{  #includes*/
#define _POSIX_SOURCE   1
#define _POSIX_C_SOURCE 2

#include <assert.h>
#include <ctype.h>
#include <errno.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "cat.h"
#include "eval.h"
#include "func.h"
#include "misc.h"
#include "scanner.h"
#include "sheet.h"
/*}}}  */

/*{{{  tcopy     -- return copy of token*/
Token tcopy(Token n)
{
  /*{{{  result*/
  Token result;
  /*}}}  */

  result=n;
  if (result.type==STRING) result.u.string=strcpy(malloc(strlen(n.u.string)+1),n.u.string);
  else if (result.type==EEK) result.u.err=strcpy(malloc(strlen(n.u.err)+1),n.u.err);  
  else if (result.type==IDENT) result.u.ident=strcpy(malloc(strlen(n.u.ident)+1),n.u.ident);
  return result;
}
/*}}}  */
/*{{{  tfree     -- free dynamic data of token*/
void tfree(Token *n)
{
  if (n->type==STRING)
  {
    free(n->u.string);
    n->u.string=(char*)0;
  }
  else if (n->type==EEK)
  {
    free(n->u.err);
    n->u.err=(char*)0;
  }
  else if (n->type==IDENT)
  {
    free(n->u.ident);
    n->u.ident=(char*)0;
  }
}
/*}}}  */
/*{{{  tvecfree  -- free a vector of pointer to tokens entirely*/
void tvecfree(Token **tvec)
{
  if (tvec!=(Token**)0)
  {
    /*{{{  variables*/
    Token **t;
    /*}}}  */
      
    for (t=tvec; *t!=(Token*)0; ++t)
    {
      tfree(*t);
      free(*t);
    }
    free(tvec);
  }
}      
/*}}}  */
/*{{{  tadd      -- + operator*/
Token tadd(Token l, Token r)
{
  /*{{{  variables*/
  Token result;
  const char *msg;
  /*}}}  */

  if (l.type==EEK)
  /*{{{  return left error*/
  return tcopy(l);
  /*}}}  */
  else if (r.type==EEK)
  /*{{{  return right error*/
  return tcopy(r);
  /*}}}  */
  else if (l.type==INT && r.type==INT)
  /*{{{  result is int sum of two ints*/
  {
    result.type=INT;
    result.u.integer=l.u.integer+r.u.integer;
  }
  /*}}}  */
  else if (l.type==STRING && r.type==STRING)
  /*{{{  result is concatenated strings*/
  {
    result.type=STRING;
    result.u.string=malloc(strlen(l.u.string)+strlen(r.u.string)+1);
    strcpy(result.u.string,l.u.string);
    strcat(result.u.string,r.u.string);
  }
  /*}}}  */
  else if (l.type==EMPTY && (r.type==INT || r.type==STRING || r.type==FLOAT || r.type==EMPTY)) 
  /*{{{  return right argument*/
  return tcopy(r);
  /*}}}  */
  else if ((l.type==INT || l.type==STRING || l.type==FLOAT) && r.type==EMPTY) 
  /*{{{  return left argument*/
  return tcopy(l);
  /*}}}  */
  else if (l.type==INT && r.type==FLOAT)
  /*{{{  result is float sum of int and float*/
  {
    result.type=FLOAT;
    result.u.flt=((double)l.u.integer)+r.u.flt;
  }
  /*}}}  */
  else if (l.type==FLOAT && r.type==INT)
  /*{{{  result is float sum of float and int*/
  {
    result.type=FLOAT;
    result.u.flt=l.u.flt+((double)r.u.integer);
  }
  /*}}}  */
  else if (l.type==FLOAT && r.type==FLOAT)
  /*{{{  result is float sum of float and float*/
  {
    result.type=FLOAT;
    result.u.flt=l.u.flt+r.u.flt;
  }
  /*}}}  */
  else
  /*{{{  result is type error*/
  {
    result.type=EEK;
    result.u.err=strcpy(malloc(strlen(ADDTYPE)+1),ADDTYPE);
  }
  /*}}}  */
  if (result.type==FLOAT && (msg=isfinite(result.u.flt))!=(const char*)0)
  /*{{{  result is error*/
  {
    result.type=EEK;
    result.u.err=malloc(strlen(msg)+4);
    strcpy(result.u.err,"+: ");
    strcat(result.u.err,msg);
  }
  /*}}}  */
  return result;
}
/*}}}  */
/*{{{  tsub      -- binary - operator*/
Token tsub(Token l, Token r)
{
  /*{{{  variables*/
  Token result;
  const char *msg;
  /*}}}  */

  if (l.type==EEK)
  /*{{{  return left error*/
  return tcopy(l);
  /*}}}  */
  else if (r.type==EEK)
  /*{{{  return right error*/
  return tcopy(r);
  /*}}}  */
  else if (l.type==INT && r.type==INT)
  /*{{{  result is int difference between left int and right int*/
  {
    result.type=INT;
    result.u.integer=l.u.integer-r.u.integer;
  }
  /*}}}  */
  else if (l.type==FLOAT && r.type==FLOAT)
  /*{{{  result is float difference between left float and right float*/
  {
    result.type=FLOAT;
    result.u.flt=l.u.flt-r.u.flt;
  }
  /*}}}  */
  else if (l.type==EMPTY)
  /*{{{  return negated right argument*/
  return tneg(r);
  /*}}}  */
  else if ((l.type==INT || l.type==FLOAT) && r.type==EMPTY)
  /*{{{  return left argument*/
  return tcopy(l);
  /*}}}  */
  else if (l.type==INT && r.type==FLOAT)
  /*{{{  result is float difference of left integer and right float*/
  {
    result.type=FLOAT;
    result.u.flt=((double)l.u.integer)-r.u.flt;
  }
  /*}}}  */
  else if (l.type==FLOAT && r.type==INT)
  /*{{{  result is float difference between left float and right integer*/
  {
    result.type=FLOAT;
    result.u.flt=l.u.flt-((double)r.u.integer);
  }
  /*}}}  */
  else
  /*{{{  result is difference type error*/
  {
    result.type=EEK;
    result.u.err=strcpy(malloc(strlen(SUBTYPE)+1),SUBTYPE);
  }
  /*}}}  */
  if (result.type==FLOAT && (msg=isfinite(result.u.flt))!=(const char*)0)
  /*{{{  result is error  */
  {
    result.type=EEK;
    result.u.err=malloc(strlen(msg)+4);
    strcpy(result.u.err,"-: ");
    strcat(result.u.err,msg);
  }
  /*}}}  */
  return result;
}
/*}}}  */
/*{{{  tdiv      -- / operator*/
Token tdiv(Token l, Token r)
{
  /*{{{  variables*/
  Token result;
  const char *msg;
  /*}}}  */

  if (l.type==EEK)
  /*{{{  return left error*/
  return tcopy(l);
  /*}}}  */
  else if (r.type==EEK)
  /*{{{  return right error*/
  return tcopy(r);
  /*}}}  */
  else if ((r.type==INT && r.u.integer==0) || (r.type==FLOAT && r.u.flt==0.0) || (r.type==EMPTY))
  /*{{{  result is division by 0 error*/
  {
    result.type=EEK;
    result.u.err=strcpy(malloc(strlen(DIV0)+1),DIV0);
  }
  /*}}}  */
  else if (l.type==INT && r.type==INT)
  /*{{{  result is quotient of left int and right int*/
  {
    result.type=INT;
    result.u.integer=l.u.integer/r.u.integer;
  }
  /*}}}  */
  else if (l.type==FLOAT && r.type==FLOAT)
  /*{{{  result is quotient of left float and right float*/
  {
    result.type=FLOAT;
    result.u.flt=l.u.flt/r.u.flt;
  }
  /*}}}  */
  else if (l.type==EMPTY && r.type==INT)
  /*{{{  result is 0*/
  {
    result.type=INT;
    result.u.integer=0;
  }
  /*}}}  */
  else if (l.type==EMPTY && r.type==FLOAT)
  /*{{{  result is 0.0*/
  {
    result.type=FLOAT;
    result.u.flt=0.0;
  }  
  /*}}}  */
  else if (l.type==INT && r.type==FLOAT)
  /*{{{  result is float quotient of left int and right float*/
  {
    result.type=FLOAT;
    result.u.flt=((double)l.u.integer)/r.u.flt;
  }
  /*}}}  */
  else if (l.type==FLOAT && r.type==INT)
  /*{{{  result is float quotient of left float and right int*/
  {
    result.type=FLOAT;
    result.u.flt=l.u.flt/((double)r.u.integer);
  }
  /*}}}  */
  else
  /*{{{  result is quotient type error*/
  {
    result.type=EEK;
    result.u.err=strcpy(malloc(strlen(DIVTYPE)+1),DIVTYPE);
  }
  /*}}}  */
  if (result.type==FLOAT && (msg=isfinite(result.u.flt))!=(const char*)0)
  /*{{{  result is error  */
  {
    result.type=EEK;
    result.u.err=malloc(strlen(msg)+4);
    strcpy(result.u.err,"/: ");
    strcat(result.u.err,msg);
  }
  /*}}}  */
  return result;
}
/*}}}  */
/*{{{  tmul      -- * operator*/
Token tmul(Token l, Token r)
{
  /*{{{  variables*/
  Token result;
  const char *msg;
  /*}}}  */

  if (l.type==EEK)
  /*{{{  return left error*/
  result=tcopy(l);
  /*}}}  */
  else if (r.type==EEK)
  /*{{{  return right error*/
  result=tcopy(r);
  /*}}}  */
  else if (l.type==INT && r.type==INT)
  /*{{{  result is int product of left int and right int*/
  {
    result=l;
    result.u.integer=l.u.integer*r.u.integer;
  }
  /*}}}  */
  else if (l.type==FLOAT && r.type==FLOAT)
  /*{{{  result is float product of left float and right float*/
  {
    result.type=FLOAT;
    result.u.flt=l.u.flt*r.u.flt;
  }
  /*}}}  */
  else if ((l.type==EMPTY && r.type==INT) || (l.type==INT && r.type==EMPTY))
  /*{{{  result is 0*/
  {
    result.type=INT;
    result.u.integer=0;
  }
  /*}}}  */
  else if ((l.type==EMPTY && r.type==FLOAT) || (l.type==FLOAT && r.type==EMPTY))
  /*{{{  result is 0.0*/
  {
    result.type=FLOAT;
    result.u.flt=0.0;
  }
  /*}}}  */
  else if (l.type==INT && r.type==FLOAT)
  /*{{{  result is float product of left int and right float*/
  {
    result.type=FLOAT;
    result.u.flt=((double)l.u.integer)*r.u.flt;
  }
  /*}}}  */
  else if (l.type==FLOAT && r.type==INT)
  /*{{{  result is float product of left float and right int*/
  {
    result.type=FLOAT;
    result.u.flt=l.u.flt*((double)r.u.integer);
  }
  /*}}}  */
  else
  /*{{{  result is product type error*/
  {
    result.type=EEK;
    result.u.err=strcpy(malloc(strlen(MULTYPE)+1),MULTYPE);
  }
  /*}}}  */
  if (result.type==FLOAT && (msg=isfinite(result.u.flt))!=(const char*)0)
  /*{{{  result is error  */
  {
    result.type=EEK;
    result.u.err=malloc(strlen(msg)+4);
    strcpy(result.u.err,"*: ");
    strcat(result.u.err,msg);
  }
  /*}}}  */
  return result;
}
/*}}}  */
/*{{{  tneg      -- monadic - operator*/
Token tneg(Token x)
{
  /*{{{  variables*/
  Token result;
  /*}}}  */

  if (x.type==EEK)
  /*{{{  return error*/
  return tcopy(x);
  /*}}}  */
  else if (x.type==INT)
  /*{{{  result is negated int argument*/
  {
    result.type=INT;
    result.u.integer=-x.u.integer;
  }
  /*}}}  */
  else if (x.type==FLOAT)
  /*{{{  result is negated float argument*/
  {
    result.type=FLOAT;
    result.u.flt=-x.u.flt;
  }
  /*}}}  */
  else if (x.type==EMPTY)
  /*{{{  result is argument itself*/
  {
    result=tcopy(x);
  }
  /*}}}  */
  else 
  /*{{{  result is negation error*/
  {
    result.type=EEK;
    result.u.err=strcpy(malloc(strlen(NEGTYPE)+1),NEGTYPE);
  }
  /*}}}  */
  return result;
}
/*}}}  */
/*{{{  tpow      -- ^ operator*/
Token tpow(Token l, Token r)
{
  /*{{{  variables*/
  Token result;
  const char *msg;
  /*}}}  */

  if (l.type==EEK)
  /*{{{  return left error*/
  return tcopy(l);
  /*}}}  */
  else if (r.type==EEK)
  /*{{{  return right error*/
  return tcopy(r);
  /*}}}  */
  else if ((l.type==INT || l.type==FLOAT || l.type==EMPTY) && (r.type==INT || r.type==FLOAT || l.type==EMPTY))
  /*{{{  do the real work*/
  {
    if ((l.type==INT || l.type==EMPTY) && ((r.type==INT && r.u.integer>=0) || r.type==EMPTY))
    /*{{{  int^int, return int or error if 0^0*/
    {
      long x,y;

      if (l.type==EMPTY) x=0;
      else x=l.u.integer;
      if (r.type==EMPTY) y=0;
      else y=r.u.integer;
      if (x==0 && y==0)
      {
        result.type=EEK;
        result.u.err=strcpy(malloc(strlen(POW00)+1),POW00);
      }
      else
      {
        long i;

        result.type=INT;
        if (x==0) result.u.integer=0;
        else if (y==0) result.u.integer=1;
        else for (result.u.integer=x,i=1; i<y; ++i) result.u.integer*=x;
      }
    }
    /*}}}  */
    else
    /*{{{  float^float*/
    {
      double x,y;

      switch (l.type)
      {
        case INT: x=(double)l.u.integer; break;
        case FLOAT: x=l.u.flt; break;
        case EMPTY: x=0.0; break;
        default: assert(0);
      }
      switch (r.type)
      {
        case INT: y=(double)r.u.integer; break;
        case FLOAT: y=r.u.flt; break;
        case EMPTY: y=0.0; break;
        default: assert(0);
      }
      result.type=FLOAT;
      errno=0; /* there is no portable EOK :( */
      result.u.flt=pow(x,y);
      switch (errno)
      {
        case 0: result.type=FLOAT; break;
        case EDOM: result.type=EEK; result.u.err=strcpy(malloc(strlen(POWDOM)+1),POWDOM); break;
        default: assert(0);
      }
    }
    /*}}}  */
  }
  /*}}}  */
  else
  /*{{{  result is type error*/
  {
    result.type=EEK;
    result.u.err=strcpy(malloc(strlen(POWTYPE)+1),POWTYPE);
  }
  /*}}}  */
  if (result.type==FLOAT && (msg=isfinite(result.u.flt))!=(const char*)0)
  /*{{{  result is error*/
  {
    result.type=EEK;
    result.u.err=malloc(strlen(msg)+4);
    strcpy(result.u.err,"^: ");
    strcat(result.u.err,msg);
  }
  /*}}}  */
  return result;
}
/*}}}  */
/*{{{  tfuncall  -- function operator*/
Token tfuncall(Token *ident, int argc, Token argv[])
{
  /*{{{  variables*/
  Tfunc *p;
  Token result;
  /*}}}  */

  for (p=tfunc; p->name!=(const char*)0 && strcmp(ident->u.ident,p->name); ++p);
  if (p->name==(const char*)0)
  /*{{{  result is no such function error*/
  {
    result.type=EEK;
    result.u.err=strcpy(malloc(strlen(NOFUNC)+1),NOFUNC);
  }
  /*}}}  */
  else
  /*{{{  result is result of called function*/
  result=p->func(argc, argv);
  /*}}}  */
  return result;
}
/*}}}  */
/*{{{  tlt       -- < operator*/
Token tlt(Token l, Token r)
{
  /*{{{  variables*/
  Token result;
  /*}}}  */

  if (l.type==EEK)
  /*{{{  return left error argument*/
  return tcopy(l);
  /*}}}  */
  if (r.type==EEK)
  /*{{{  return right error argument*/
  return tcopy(r);
  /*}}}  */
  if (l.type==INT && r.type==INT)
  /*{{{  return left int < right int*/
  {
    result.type=INT;
    result.u.integer=l.u.integer<r.u.integer;
  }
  /*}}}  */
  else if (l.type==STRING && r.type==STRING)
  /*{{{  return left string < right string*/
  {
    result.type=INT;
    result.u.integer=(strcmp(l.u.string,r.u.string)<0);
  }
  /*}}}  */
  else if (l.type==FLOAT && r.type==FLOAT)
  /*{{{  return left float < right float*/
  {
    result.type=INT;
    result.u.integer=l.u.flt<r.u.flt;
  }
  /*}}}  */
  else if (l.type==FLOAT && r.type==INT)
  /*{{{  return left float < right float*/
  {
    result.type=INT;
    result.u.integer=l.u.flt<((double)r.u.integer);
  }  
  /*}}}  */
  else if (l.type==INT && r.type==FLOAT)
  /*{{{  return left int < right float*/
  {
    result.type=INT;
    result.u.integer=((double)l.u.integer)<r.u.flt;
  }    
  /*}}}  */
  else
  /*{{{  return < type error*/
  {
    result.type=EEK;
    result.u.err=strcpy(malloc(strlen(RELTYPE)+1),RELTYPE);
  }
  /*}}}  */
  return result;
}
/*}}}  */
/*{{{  tle       -- <= operator*/
Token tle(Token l, Token r)
{
  /*{{{  variables*/
  Token result;
  /*}}}  */

  if (l.type==EEK)
  /*{{{  return left error argument*/
  return tcopy(l);
  /*}}}  */
  if (r.type==EEK)
  /*{{{  return right error argument*/
  return tcopy(r);
  /*}}}  */
  if (l.type==INT && r.type==INT)
  /*{{{  result is left int <= right int*/
  {
    result.type=INT;
    result.u.integer=l.u.integer<=r.u.integer;
  }
  /*}}}  */
  else if (l.type==STRING && r.type==STRING)
  /*{{{  result is left string <= right string*/
  {
    result.type=INT;
    result.u.integer=(strcmp(l.u.string,r.u.string)<=0);
  }
  /*}}}  */
  else if (l.type==FLOAT && r.type==FLOAT)
  /*{{{  result is left float <= right float*/
  {
    result.type=INT;
    result.u.integer=l.u.flt<=r.u.flt;
  }
  /*}}}  */
  else if (l.type==FLOAT && r.type==INT)
  /*{{{  result is left float <= (double)right int*/
  {
    result.type=INT;
    result.u.integer=l.u.flt<=((double)r.u.integer);
  }  
  /*}}}  */
  else if (l.type==INT && r.type==FLOAT)
  /*{{{  result is (double)left int <= right float*/
  {
    result.type=INT;
    result.u.integer=((double)l.u.integer)<=r.u.flt;
  }    
  /*}}}  */
  else if (l.type==EMPTY)
  /*{{{  return 1*/
  {
    result.type=INT;
    result.u.integer=1;
  }
  /*}}}  */
  else if (r.type==EMPTY)
  /*{{{  return 0*/
  {
    result.type=INT;
    result.u.integer=0;
  }
  /*}}}  */
  else
  /*{{{  result is <= type error*/
  {
    result.type=EEK;
    result.u.err=strcpy(malloc(strlen(RELTYPE)+1),RELTYPE);
  }
  /*}}}  */
  return result;
}
/*}}}  */
/*{{{  tge       -- >= operator*/
Token tge(Token l, Token r)
{
  /*{{{  variables*/
  Token result;
  /*}}}  */

  if (l.type==EEK)
  /*{{{  return left error argument*/
  return tcopy(l);
  /*}}}  */
  if (r.type==EEK)
  /*{{{  return right error argument*/
  return tcopy(r);
  /*}}}  */
  if (l.type==INT && r.type==INT)
  /*{{{  return left int >= right int*/
  {
    result.type=INT;
    result.u.integer=l.u.integer>=r.u.integer;
  }
  /*}}}  */
  else if (l.type==STRING && r.type==STRING)
  /*{{{  return left string >= right string*/
  {
    result.type=INT;
    result.u.integer=(strcmp(l.u.string,r.u.string)>=0);
  }
  /*}}}  */
  else if (l.type==FLOAT && r.type==FLOAT)
  /*{{{  return left float >= right float*/
  {
    result.type=INT;
    result.u.integer=l.u.flt>=r.u.flt;
  }
  /*}}}  */
  else if (l.type==FLOAT && r.type==INT)
  /*{{{  return left float >= (double) right int*/
  {
    result.type=INT;
    result.u.integer=l.u.flt>=((double)r.u.integer);
  }  
  /*}}}  */
  else if (l.type==INT && r.type==FLOAT)
  /*{{{  return (double) left int >= right float*/
  {
    result.type=INT;
    result.u.integer=((double)l.u.integer)>=r.u.flt;
  }    
  /*}}}  */
  else
  /*{{{  return >= type error*/
  {
    result.type=EEK;
    result.u.err=strcpy(malloc(strlen(RELTYPE)+1),RELTYPE);
  }
  /*}}}  */
  return result;
}
/*}}}  */
/*{{{  tgt       -- <= operator*/
Token tgt(Token l, Token r)
{
  Token result;

  if (l.type==EEK) return tcopy(l);
  if (r.type==EEK) return tcopy(r);
  if (l.type==INT && r.type==INT)
  {
    result.type=INT;
    result.u.integer=l.u.integer>r.u.integer;
  }
  else if (l.type==STRING && r.type==STRING)
  {
    result.type=INT;
    result.u.integer=(strcmp(l.u.string,r.u.string)>0);
  }
  else if (l.type==FLOAT && r.type==FLOAT)
  {
    result.type=INT;
    result.u.integer=l.u.flt>r.u.flt;
  }
  else if (l.type==FLOAT && r.type==INT)
  {
    result.type=INT;
    result.u.integer=l.u.flt>((double)r.u.integer);
  }  
  else if (l.type==INT && r.type==FLOAT)
  {
    result.type=INT;
    result.u.integer=((double)l.u.integer)>r.u.flt;
  }    
  else
  {
    result.type=EEK;
    result.u.err=strcpy(malloc(strlen(RELTYPE)+1),RELTYPE);
  }
  return result;
}
/*}}}  */
/*{{{  teq       -- == operator*/
Token teq(Token l, Token r)
{
  Token result;

  if (l.type==EEK) return tcopy(l);
  else if (r.type==EEK) return tcopy(r);
  else if (l.type==FLOAT && r.type==INT)
  {
    result.type=INT;
    result.u.integer=l.u.flt==((double)r.u.integer);
  }  
  else if (l.type==INT && r.type==FLOAT)
  {
    result.type=INT;
    result.u.integer=((double)l.u.integer)==r.u.flt;
  }    
  else if (l.type!=r.type)
  {
    result.type=INT;
    result.u.integer=0;
  }
  else if (l.type==INT)
  {
    result.type=INT;
    result.u.integer=l.u.integer==r.u.integer;
  }
  else if (l.type==STRING)
  {
    result.type=INT;
    result.u.integer=(strcmp(l.u.string,r.u.string)==0);
  }
  else if (l.type==FLOAT)
  {
    result.type=INT;
    result.u.integer=l.u.flt==r.u.flt;
  }
  else if (l.type==EMPTY)
  {
    result.type=INT;
    result.u.integer=1;
  }
  else
  {
    result.type=EEK;
    result.u.err=strcpy(malloc(strlen(RELTYPE)+1),RELTYPE);
  }
  return result;
}
/*}}}  */
/*{{{  tne       -- != operator*/
Token tne(Token l, Token r)
{
  Token result;

  if (l.type==EEK) return tcopy(l);
  else if (r.type==EEK) return tcopy(r);
  else if (l.type==FLOAT && r.type==INT)
  {
    result.type=INT;
    result.u.integer=l.u.flt!=((double)r.u.integer);
  }  
  else if (l.type==INT && r.type==FLOAT)
  {
    result.type=INT;
    result.u.integer=((double)l.u.integer)!=r.u.flt;
  }    
  else if (l.type!=r.type)
  {
    result.type=INT;
    result.u.integer=1;
  }
  else if (l.type==INT)
  {
    result.type=INT;
    result.u.integer=l.u.integer!=r.u.integer;
  }
  else if (l.type==STRING)
  {
    result.type=INT;
    result.u.integer=(strcmp(l.u.string,r.u.string)!=0);
  }
  else if (l.type==FLOAT)
  {
    result.type=INT;
    result.u.integer=l.u.flt!=r.u.flt;
  }
  else if (l.type==EMPTY)
  {
    result.type=INT;
    result.u.integer=0;
  }
  else
  {
    result.type=EEK;
    result.u.err=strcpy(malloc(strlen(RELTYPE)+1),RELTYPE);
  }
  return result;
}
/*}}}  */
