"Fossies" - the Fresh Open Source Software Archive

Member "teapot-2.3.0/eval.c" (6 Feb 2012, 27738 Bytes) of package /linux/privat/old/teapot-2.3.0.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "eval.c" see the Fossies "Dox" file reference documentation.

    1 /* #includes */ /*{{{C}}}*//*{{{*/
    2 #ifndef NO_POSIX_SOURCE
    3 #undef _POSIX_SOURCE
    4 #define _POSIX_SOURCE   1
    5 #undef _POSIX_C_SOURCE
    6 #define _POSIX_C_SOURCE 2
    7 #endif
    8 
    9 #ifdef DMALLOC
   10 #include "dmalloc.h"
   11 #endif
   12 
   13 #include <assert.h>
   14 #include <ctype.h>
   15 #include <errno.h>
   16 #include <float.h>
   17 #include <limits.h>
   18 #include <math.h>
   19 #include <stdio.h>
   20 #include <stdlib.h>
   21 #include <string.h>
   22 
   23 
   24 #include "default.h"
   25 #include "eval.h"
   26 #include "func.h"
   27 #include "main.h"
   28 #include "misc.h"
   29 #include "scanner.h"
   30 #include "sheet.h"
   31 /*}}}*/
   32 
   33 /* tcopy     -- return copy of token */ /*{{{*/
   34 Token tcopy(Token n)
   35 {
   36   /* result */ /*{{{*/
   37   Token result;
   38   /*}}}*/
   39 
   40   result=n;
   41   if (result.type==STRING) result.u.string=strcpy(malloc(strlen(n.u.string)+1),n.u.string);
   42   else if (result.type==EEK) result.u.err=strcpy(malloc(strlen(n.u.err)+1),n.u.err);  
   43   else if (result.type==LIDENT) result.u.lident=strcpy(malloc(strlen(n.u.lident)+1),n.u.lident);
   44   return result;
   45 }
   46 /*}}}*/
   47 /* tfree     -- free dynamic data of token */ /*{{{*/
   48 void tfree(Token *n)
   49 {
   50   if (n->type==STRING)
   51   {
   52     free(n->u.string);
   53     n->u.string=(char*)0;
   54   }
   55   else if (n->type==EEK)
   56   {
   57     free(n->u.err);
   58     n->u.err=(char*)0;
   59   }
   60   else if (n->type==LIDENT)
   61   {
   62     free(n->u.lident);
   63     n->u.lident=(char*)0;
   64   }
   65 }
   66 /*}}}*/
   67 /* tvecfree  -- free a vector of pointer to tokens entirely */ /*{{{*/
   68 void tvecfree(Token **tvec)
   69 {
   70   if (tvec!=(Token**)0)
   71   {
   72     /* variables */ /*{{{*/
   73     Token **t;
   74     /*}}}*/
   75       
   76     for (t=tvec; *t!=(Token*)0; ++t)
   77     {
   78       tfree(*t);
   79       free(*t);
   80     }
   81     free(tvec);
   82   }
   83 }      
   84 /*}}}*/
   85 /* tadd      -- + operator */ /*{{{*/
   86 Token tadd(Token l, Token r)
   87 {
   88   /* variables */ /*{{{*/
   89   Token result;
   90   const char *msg;
   91   /*}}}*/
   92 
   93   if (l.type==EEK)
   94   /* return left error */ /*{{{*/
   95   return tcopy(l);
   96   /*}}}*/
   97   else if (r.type==EEK)
   98   /* return right error */ /*{{{*/
   99   return tcopy(r);
  100   /*}}}*/
  101   else if (l.type==INT && r.type==INT)
  102   /* result is int sum of two ints */ /*{{{*/
  103   {
  104     result.type=INT;
  105     result.u.integer=l.u.integer+r.u.integer;
  106   }
  107   /*}}}*/
  108   else if (l.type==STRING && r.type==STRING)
  109   /* result is concatenated strings */ /*{{{*/
  110   {
  111     result.type=STRING;
  112     result.u.string=malloc(strlen(l.u.string)+strlen(r.u.string)+1);
  113     (void)strcpy(result.u.string,l.u.string);
  114     (void)strcat(result.u.string,r.u.string);
  115   }
  116   /*}}}*/
  117   else if (l.type==EMPTY && (r.type==INT || r.type==STRING || r.type==FLOAT || r.type==EMPTY)) 
  118   /* return right argument */ /*{{{*/
  119   return tcopy(r);
  120   /*}}}*/
  121   else if ((l.type==INT || l.type==STRING || l.type==FLOAT) && r.type==EMPTY) 
  122   /* return left argument */ /*{{{*/
  123   return tcopy(l);
  124   /*}}}*/
  125   else if (l.type==INT && r.type==FLOAT)
  126   /* result is float sum of int and float */ /*{{{*/
  127   {
  128     result.type=FLOAT;
  129     result.u.flt=((double)l.u.integer)+r.u.flt;
  130   }
  131   /*}}}*/
  132   else if (l.type==FLOAT && r.type==INT)
  133   /* result is float sum of float and int */ /*{{{*/
  134   {
  135     result.type=FLOAT;
  136     result.u.flt=l.u.flt+((double)r.u.integer);
  137   }
  138   /*}}}*/
  139   else if (l.type==FLOAT && r.type==FLOAT)
  140   /* result is float sum of float and float */ /*{{{*/
  141   {
  142     result.type=FLOAT;
  143     result.u.flt=l.u.flt+r.u.flt;
  144   }
  145   /*}}}*/
  146   else if (l.type==EMPTY && r.type==EMPTY)
  147   /* result is emty */ /*{{{*/
  148   {
  149     result.type=EMPTY;
  150   }
  151   /*}}}*/
  152   else
  153   /* result is type error */ /*{{{*/
  154   {
  155     result.type=EEK;
  156     result.u.err=strcpy(malloc(strlen(_("wrong types for + operator"))+1),_("wrong types for + operator"));
  157   }
  158   /*}}}*/
  159   if (result.type==FLOAT && (msg=dblfinite(result.u.flt))!=(const char*)0)
  160   /* result is error */ /*{{{*/
  161   {
  162     result.type=EEK;
  163     result.u.err=malloc(strlen(msg)+4);
  164     (void)strcpy(result.u.err,"+: ");
  165     (void)strcat(result.u.err,msg);
  166   }
  167   /*}}}*/
  168   return result;
  169 }
  170 /*}}}*/
  171 /* tsub      -- binary - operator */ /*{{{*/
  172 Token tsub(Token l, Token r)
  173 {
  174   /* variables */ /*{{{*/
  175   Token result;
  176   const char *msg;
  177   /*}}}*/
  178 
  179   if (l.type==EEK)
  180   /* return left error */ /*{{{*/
  181   return tcopy(l);
  182   /*}}}*/
  183   else if (r.type==EEK)
  184   /* return right error */ /*{{{*/
  185   return tcopy(r);
  186   /*}}}*/
  187   else if (l.type==INT && r.type==INT)
  188   /* result is int difference between left int and right int */ /*{{{*/
  189   {
  190     result.type=INT;
  191     result.u.integer=l.u.integer-r.u.integer;
  192   }
  193   /*}}}*/
  194   else if (l.type==FLOAT && r.type==FLOAT)
  195   /* result is float difference between left float and right float */ /*{{{*/
  196   {
  197     result.type=FLOAT;
  198     result.u.flt=l.u.flt-r.u.flt;
  199   }
  200   /*}}}*/
  201   else if (l.type==EMPTY)
  202   /* return negated right argument */ /*{{{*/
  203   return tneg(r);
  204   /*}}}*/
  205   else if ((l.type==INT || l.type==FLOAT) && r.type==EMPTY)
  206   /* return left argument */ /*{{{*/
  207   return tcopy(l);
  208   /*}}}*/
  209   else if (l.type==INT && r.type==FLOAT)
  210   /* result is float difference of left integer and right float */ /*{{{*/
  211   {
  212     result.type=FLOAT;
  213     result.u.flt=((double)l.u.integer)-r.u.flt;
  214   }
  215   /*}}}*/
  216   else if (l.type==FLOAT && r.type==INT)
  217   /* result is float difference between left float and right integer */ /*{{{*/
  218   {
  219     result.type=FLOAT;
  220     result.u.flt=l.u.flt-((double)r.u.integer);
  221   }
  222   /*}}}*/
  223   else
  224   /* result is difference type error */ /*{{{*/
  225   {
  226     result.type=EEK;
  227     result.u.err=strcpy(malloc(strlen(_("wrong types for - operator"))+1),_("wrong types for - operator"));
  228   }
  229   /*}}}*/
  230   if (result.type==FLOAT && (msg=dblfinite(result.u.flt))!=(const char*)0)
  231   /* result is error  */ /*{{{*/
  232   {
  233     result.type=EEK;
  234     result.u.err=malloc(strlen(msg)+4);
  235     (void)strcpy(result.u.err,"-: ");
  236     (void)strcat(result.u.err,msg);
  237   }
  238   /*}}}*/
  239   return result;
  240 }
  241 /*}}}*/
  242 /* tdiv      -- / operator */ /*{{{*/
  243 Token tdiv(Token l, Token r)
  244 {
  245   /* variables */ /*{{{*/
  246   Token result;
  247   const char *msg;
  248   /*}}}*/
  249 
  250   if (l.type==EEK)
  251   /* return left error */ /*{{{*/
  252   return tcopy(l);
  253   /*}}}*/
  254   else if (r.type==EEK)
  255   /* return right error */ /*{{{*/
  256   return tcopy(r);
  257   /*}}}*/
  258   else if ((r.type==INT && r.u.integer==0) || (r.type==FLOAT && r.u.flt==0.0) || (r.type==EMPTY))
  259   /* result is division by 0 error */ /*{{{*/
  260   {
  261     result.type=EEK;
  262     result.u.err=strcpy(malloc(strlen(_("division by 0"))+1),_("division by 0"));
  263   }
  264   /*}}}*/
  265   else if (l.type==INT && r.type==INT)
  266   /* result is quotient of left int and right int */ /*{{{*/
  267   {
  268     result.type=INT;
  269     result.u.integer=l.u.integer/r.u.integer;
  270   }
  271   /*}}}*/
  272   else if (l.type==FLOAT && r.type==FLOAT)
  273   /* result is quotient of left float and right float */ /*{{{*/
  274   {
  275     result.type=FLOAT;
  276     result.u.flt=l.u.flt/r.u.flt;
  277   }
  278   /*}}}*/
  279   else if (l.type==EMPTY && r.type==INT)
  280   /* result is 0 */ /*{{{*/
  281   {
  282     result.type=INT;
  283     result.u.integer=0;
  284   }
  285   /*}}}*/
  286   else if (l.type==EMPTY && r.type==FLOAT)
  287   /* result is 0.0 */ /*{{{*/
  288   {
  289     result.type=FLOAT;
  290     result.u.flt=0.0;
  291   }  
  292   /*}}}*/
  293   else if (l.type==INT && r.type==FLOAT)
  294   /* result is float quotient of left int and right float */ /*{{{*/
  295   {
  296     result.type=FLOAT;
  297     result.u.flt=((double)l.u.integer)/r.u.flt;
  298   }
  299   /*}}}*/
  300   else if (l.type==FLOAT && r.type==INT)
  301   /* result is float quotient of left float and right int */ /*{{{*/
  302   {
  303     result.type=FLOAT;
  304     result.u.flt=l.u.flt/((double)r.u.integer);
  305   }
  306   /*}}}*/
  307   else
  308   /* result is quotient type error */ /*{{{*/
  309   {
  310     result.type=EEK;
  311     result.u.err=strcpy(malloc(strlen(_("wrong types for / operator"))+1),_("wrong types for / operator"));
  312   }
  313   /*}}}*/
  314   if (result.type==FLOAT && (msg=dblfinite(result.u.flt))!=(const char*)0)
  315   /* result is error  */ /*{{{*/
  316   {
  317     result.type=EEK;
  318     result.u.err=malloc(strlen(msg)+4);
  319     (void)strcpy(result.u.err,"/: ");
  320     (void)strcat(result.u.err,msg);
  321   }
  322   /*}}}*/
  323   return result;
  324 }
  325 /*}}}*/
  326 /* tmod      -- % operator */ /*{{{*/
  327 Token tmod(Token l, Token r)
  328 {
  329   /* variables */ /*{{{*/
  330   Token result;
  331   const char *msg;
  332   /*}}}*/
  333 
  334   if (l.type==EEK) /* return left error */ /*{{{*/
  335   return tcopy(l);
  336   /*}}}*/
  337   else if (r.type==EEK) /* return right error */ /*{{{*/
  338   return tcopy(r);
  339   /*}}}*/
  340   else if ((r.type==INT && r.u.integer==0) || (r.type==FLOAT && r.u.flt==0.0) || (r.type==EMPTY)) /* result is modulo 0 error */ /*{{{*/
  341   {
  342     result.type=EEK;
  343     result.u.err=strcpy(malloc(strlen(_("modulo 0"))+1),_("modulo 0"));
  344   }
  345   /*}}}*/
  346   else if (l.type==INT && r.type==INT) /* result is remainder of left int and right int */ /*{{{*/
  347   {
  348     result.type=INT;
  349     result.u.integer=l.u.integer%r.u.integer;
  350   }
  351   /*}}}*/
  352   else if (l.type==FLOAT && r.type==FLOAT) /* result is remainder of left float and right float */ /*{{{*/
  353   {
  354     result.type=FLOAT;
  355     result.u.flt=fmod(l.u.flt,r.u.flt);
  356   }
  357   /*}}}*/
  358   else if (l.type==EMPTY && r.type==INT) /* result is 0 */ /*{{{*/
  359   {
  360     result.type=INT;
  361     result.u.integer=0;
  362   }
  363   /*}}}*/
  364   else if (l.type==EMPTY && r.type==FLOAT) /* result is 0.0 */ /*{{{*/
  365   {
  366     result.type=FLOAT;
  367     result.u.flt=0.0;
  368   }  
  369   /*}}}*/
  370   else if (l.type==INT && r.type==FLOAT) /* result is float remainder of left int and right float */ /*{{{*/
  371   {
  372     result.type=FLOAT;
  373     result.u.flt=fmod((double)l.u.integer,r.u.flt);
  374   }
  375   /*}}}*/
  376   else if (l.type==FLOAT && r.type==INT) /* result is float remainder of left float and right int */ /*{{{*/
  377   {
  378     result.type=FLOAT;
  379     result.u.flt=fmod(l.u.flt,(double)r.u.integer);
  380   }
  381   /*}}}*/
  382   else /* result is remainder type error */ /*{{{*/
  383   {
  384     result.type=EEK;
  385     result.u.err=strcpy(malloc(strlen(_("wrong types for % operator"))+1),_("wrong types for % operator"));
  386   }
  387   /*}}}*/
  388   if (result.type==FLOAT && (msg=dblfinite(result.u.flt))!=(const char*)0) /* result is error  */ /*{{{*/
  389   {
  390     result.type=EEK;
  391     result.u.err=malloc(strlen(msg)+4);
  392     (void)strcpy(result.u.err,"%: ");
  393     (void)strcat(result.u.err,msg);
  394   }
  395   /*}}}*/
  396   return result;
  397 }
  398 /*}}}*/
  399 /* tmul      -- * operator */ /*{{{*/
  400 Token tmul(Token l, Token r)
  401 {
  402   /* variables */ /*{{{*/
  403   Token result;
  404   const char *msg;
  405   /*}}}*/
  406 
  407   if (l.type==EEK)
  408   /* return left error */ /*{{{*/
  409   result=tcopy(l);
  410   /*}}}*/
  411   else if (r.type==EEK)
  412   /* return right error */ /*{{{*/
  413   result=tcopy(r);
  414   /*}}}*/
  415   else if (l.type==INT && r.type==INT)
  416   /* result is int product of left int and right int */ /*{{{*/
  417   {
  418     result=l;
  419     result.u.integer=l.u.integer*r.u.integer;
  420   }
  421   /*}}}*/
  422   else if (l.type==FLOAT && r.type==FLOAT)
  423   /* result is float product of left float and right float */ /*{{{*/
  424   {
  425     result.type=FLOAT;
  426     result.u.flt=l.u.flt*r.u.flt;
  427   }
  428   /*}}}*/
  429   else if ((l.type==EMPTY && r.type==INT) || (l.type==INT && r.type==EMPTY))
  430   /* result is 0 */ /*{{{*/
  431   {
  432     result.type=INT;
  433     result.u.integer=0;
  434   }
  435   /*}}}*/
  436   else if ((l.type==EMPTY && r.type==FLOAT) || (l.type==FLOAT && r.type==EMPTY))
  437   /* result is 0.0 */ /*{{{*/
  438   {
  439     result.type=FLOAT;
  440     result.u.flt=0.0;
  441   }
  442   /*}}}*/
  443   else if (l.type==INT && r.type==FLOAT)
  444   /* result is float product of left int and right float */ /*{{{*/
  445   {
  446     result.type=FLOAT;
  447     result.u.flt=((double)l.u.integer)*r.u.flt;
  448   }
  449   /*}}}*/
  450   else if (l.type==FLOAT && r.type==INT)
  451   /* result is float product of left float and right int */ /*{{{*/
  452   {
  453     result.type=FLOAT;
  454     result.u.flt=l.u.flt*((double)r.u.integer);
  455   }
  456   /*}}}*/
  457   else if (l.type==EMPTY && r.type==EMPTY)
  458   /* result is empty */ /*{{{*/
  459   {
  460     result.type=EMPTY;
  461   }
  462   /*}}}*/
  463   else
  464   /* result is product type error */ /*{{{*/
  465   {
  466     result.type=EEK;
  467     result.u.err=strcpy(malloc(strlen(_("wrong types for * operator"))+1),_("wrong types for * operator"));
  468   }
  469   /*}}}*/
  470   if (result.type==FLOAT && (msg=dblfinite(result.u.flt))!=(const char*)0)
  471   /* result is error  */ /*{{{*/
  472   {
  473     result.type=EEK;
  474     result.u.err=malloc(strlen(msg)+4);
  475     (void)strcpy(result.u.err,"*: ");
  476     (void)strcat(result.u.err,msg);
  477   }
  478   /*}}}*/
  479   return result;
  480 }
  481 /*}}}*/
  482 /* tneg      -- monadic - operator */ /*{{{*/
  483 Token tneg(Token x)
  484 {
  485   /* variables */ /*{{{*/
  486   Token result;
  487   /*}}}*/
  488 
  489   if (x.type==EEK)
  490   /* return error */ /*{{{*/
  491   return tcopy(x);
  492   /*}}}*/
  493   else if (x.type==INT)
  494   /* result is negated int argument */ /*{{{*/
  495   {
  496     result.type=INT;
  497     result.u.integer=-x.u.integer;
  498   }
  499   /*}}}*/
  500   else if (x.type==FLOAT)
  501   /* result is negated float argument */ /*{{{*/
  502   {
  503     result.type=FLOAT;
  504     result.u.flt=-x.u.flt;
  505   }
  506   /*}}}*/
  507   else if (x.type==EMPTY)
  508   /* result is argument itself */ /*{{{*/
  509   {
  510     result=tcopy(x);
  511   }
  512   /*}}}*/
  513   else 
  514   /* result is negation error */ /*{{{*/
  515   {
  516     result.type=EEK;
  517     result.u.err=strcpy(malloc(strlen(_("wrong type for - operator"))+1),_("wrong type for - operator"));
  518   }
  519   /*}}}*/
  520   return result;
  521 }
  522 /*}}}*/
  523 /* tpow      -- ^ operator */ /*{{{*/
  524 Token tpow(Token l, Token r)
  525 {
  526   /* variables */ /*{{{*/
  527   Token result;
  528   const char *msg;
  529   /*}}}*/
  530 
  531   if (l.type==EEK) /* return left error */ /*{{{*/
  532   return tcopy(l);
  533   /*}}}*/
  534   else if (r.type==EEK) /* return right error */ /*{{{*/
  535   return tcopy(r);
  536   /*}}}*/
  537   else if ((l.type==INT || l.type==FLOAT || l.type==EMPTY) && (r.type==INT || r.type==FLOAT || l.type==EMPTY)) /* do the real work */ /*{{{*/
  538   {
  539     if ((l.type==INT || l.type==EMPTY) && ((r.type==INT && r.u.integer>=0) || r.type==EMPTY))
  540     /* int^int, return int or error if 0^0 */ /*{{{*/
  541     {
  542       long x,y;
  543 
  544       if (l.type==EMPTY) x=0;
  545       else x=l.u.integer;
  546       if (r.type==EMPTY) y=0;
  547       else y=r.u.integer;
  548       if (x==0 && y==0)
  549       {
  550         result.type=EEK;
  551         result.u.err=strcpy(malloc(strlen(_("0^0 is not defined"))+1),_("0^0 is not defined"));
  552       }
  553       else
  554       {
  555         long i;
  556 
  557         result.type=INT;
  558         if (x==0) result.u.integer=0;
  559         else if (y==0) result.u.integer=1;
  560         else for (result.u.integer=x,i=1; i<y; ++i) result.u.integer*=x;
  561       }
  562     }
  563     /*}}}*/
  564     else
  565     /* float^float */ /*{{{*/
  566     {
  567       double x=0.0,y=0.0;
  568 
  569       switch (l.type)
  570       {
  571         case INT: x=(double)l.u.integer; break;
  572         case FLOAT: x=l.u.flt; break;
  573         case EMPTY: x=0.0; break;
  574         default: assert(0);
  575       }
  576       switch (r.type)
  577       {
  578         case INT: y=(double)r.u.integer; break;
  579         case FLOAT: y=r.u.flt; break;
  580         case EMPTY: y=0.0; break;
  581         default: assert(0);
  582       }
  583       result.type=FLOAT;
  584       errno=0; /* there is no portable EOK :( */
  585       result.u.flt=pow(x,y);
  586       switch (errno)
  587       {
  588         case 0: result.type=FLOAT; break;
  589         case ERANGE:
  590         case EDOM: result.type=EEK; result.u.err=strcpy(malloc(strlen(_("^ caused a domain error"))+1),_("^ caused a domain error")); break;
  591         default: assert(0);
  592       }
  593     }
  594     /*}}}*/
  595   }
  596   /*}}}*/
  597   else /* result is type error */ /*{{{*/
  598   {
  599     result.type=EEK;
  600     result.u.err=strcpy(malloc(strlen(_("wrong types for ^ operator"))+1),_("wrong types for ^ operator"));
  601   }
  602   /*}}}*/
  603   if (result.type==FLOAT && (msg=dblfinite(result.u.flt))!=(const char*)0) /* result is error */ /*{{{*/
  604   {
  605     result.type=EEK;
  606     result.u.err=malloc(strlen(msg)+4);
  607     (void)strcpy(result.u.err,"^: ");
  608     (void)strcat(result.u.err,msg);
  609   }
  610   /*}}}*/
  611   return result;
  612 }
  613 /*}}}*/
  614 /* tfuncall  -- function operator */ /*{{{*/
  615 Token tfuncall(Token *ident, int argc, Token argv[])
  616 {
  617   return tfunc[ident->u.fident].func(argc, argv);
  618 }
  619 /*}}}*/
  620 /* tlt       -- < operator */ /*{{{*/
  621 Token tlt(Token l, Token r)
  622 {
  623   /* variables */ /*{{{*/
  624   Token result;
  625   static char empty[]="";
  626   /*}}}*/
  627 
  628   if (l.type==EEK) /* return left error argument */ /*{{{*/
  629   return tcopy(l);
  630   /*}}}*/
  631   if (r.type==EEK) /* return right error argument */ /*{{{*/
  632   return tcopy(r);
  633   /*}}}*/
  634   if (l.type==EMPTY) /* try to assign 0 element of r.type */ /*{{{*/
  635   {
  636     l.type=r.type;
  637     switch (r.type)
  638     {
  639       case INT: l.u.integer=0; break;
  640       case FLOAT: l.u.flt=0.0; break;
  641       case STRING: l.u.string=empty; break;
  642       default: ;
  643     }
  644   }
  645   /*}}}*/
  646   if (r.type==EMPTY) /* try to assign 0 element of l.type */ /*{{{*/
  647   {
  648     r.type=l.type;
  649     switch (l.type)
  650     {
  651       case INT: r.u.integer=0; break;
  652       case FLOAT: r.u.flt=0.0; break;
  653       case STRING: r.u.string=empty; break;
  654       default: ;
  655     }  
  656   }
  657   /*}}}*/
  658   if (l.type==INT && r.type==INT) /* return left int < right int */ /*{{{*/
  659   {
  660     result.type=INT;
  661     result.u.integer=l.u.integer<r.u.integer;
  662   }
  663   /*}}}*/
  664   else if (l.type==STRING && r.type==STRING) /* return left string < right string */ /*{{{*/
  665   {
  666     result.type=INT;
  667     result.u.integer=(strcmp(l.u.string,r.u.string)<0);
  668   }
  669   /*}}}*/
  670   else if (l.type==FLOAT && r.type==FLOAT) /* return left float < right float */ /*{{{*/
  671   {
  672     result.type=INT;
  673     result.u.integer=l.u.flt<r.u.flt;
  674   }
  675   /*}}}*/
  676   else if (l.type==FLOAT && r.type==INT) /* return left float < right float */ /*{{{*/
  677   {
  678     result.type=INT;
  679     result.u.integer=l.u.flt<((double)r.u.integer);
  680   }  
  681   /*}}}*/
  682   else if (l.type==INT && r.type==FLOAT) /* return left int < right float */ /*{{{*/
  683   {
  684     result.type=INT;
  685     result.u.integer=((double)l.u.integer)<r.u.flt;
  686   }    
  687   /*}}}*/
  688   else /* return < type error */ /*{{{*/
  689   {
  690     result.type=EEK;
  691     result.u.err=strcpy(malloc(strlen(_("type mismatch for relational operator"))+1),_("type mismatch for relational operator"));
  692   }
  693   /*}}}*/
  694   return result;
  695 }
  696 /*}}}*/
  697 /* tle       -- <= operator */ /*{{{*/
  698 Token tle(Token l, Token r)
  699 {
  700   /* variables */ /*{{{*/
  701   Token result;
  702   static char empty[]="";
  703   /*}}}*/
  704 
  705   if (l.type==EEK) /* return left error argument */ /*{{{*/
  706   return tcopy(l);
  707   /*}}}*/
  708   if (r.type==EEK) /* return right error argument */ /*{{{*/
  709   return tcopy(r);
  710   /*}}}*/
  711   if (l.type==EMPTY) /* try to assign 0 element of r.type */ /*{{{*/
  712   {
  713     l.type=r.type;
  714     switch (r.type)
  715     {
  716       case INT: l.u.integer=0; break;
  717       case FLOAT: l.u.flt=0.0; break;
  718       case STRING: l.u.string=empty; break;
  719       default: ;
  720     }
  721   }
  722   /*}}}*/
  723   if (r.type==EMPTY) /* try to assign 0 element of l.type */ /*{{{*/
  724   {
  725     r.type=l.type;
  726     switch (l.type)
  727     {
  728       case INT: r.u.integer=0; break;
  729       case FLOAT: r.u.flt=0.0; break;
  730       case STRING: r.u.string=empty; break;
  731       default: ;
  732     }  
  733   }
  734   /*}}}*/
  735   if (l.type==INT && r.type==INT) /* result is left int <= right int */ /*{{{*/
  736   {
  737     result.type=INT;
  738     result.u.integer=l.u.integer<=r.u.integer;
  739   }
  740   /*}}}*/
  741   else if (l.type==STRING && r.type==STRING) /* result is left string <= right string */ /*{{{*/
  742   {
  743     result.type=INT;
  744     result.u.integer=(strcmp(l.u.string,r.u.string)<=0);
  745   }
  746   /*}}}*/
  747   else if (l.type==FLOAT && r.type==FLOAT) /* result is left float <= right float */ /*{{{*/
  748   {
  749     result.type=INT;
  750     result.u.integer=l.u.flt<=r.u.flt;
  751   }
  752   /*}}}*/
  753   else if (l.type==FLOAT && r.type==INT) /* result is left float <= (double)right int */ /*{{{*/
  754   {
  755     result.type=INT;
  756     result.u.integer=l.u.flt<=((double)r.u.integer);
  757   }  
  758   /*}}}*/
  759   else if (l.type==INT && r.type==FLOAT) /* result is (double)left int <= right float */ /*{{{*/
  760   {
  761     result.type=INT;
  762     result.u.integer=((double)l.u.integer)<=r.u.flt;
  763   }    
  764   /*}}}*/
  765   else if (l.type==EMPTY && r.type==EMPTY) /* result is 1 */ /*{{{*/
  766   {
  767     result.type=INT;
  768     result.u.integer=1;
  769   }
  770   /*}}}*/
  771   else /* result is <= type error */ /*{{{*/
  772   {
  773     result.type=EEK;
  774     result.u.err=strcpy(malloc(strlen(_("type mismatch for relational operator"))+1),_("type mismatch for relational operator"));
  775   }
  776   /*}}}*/
  777   return result;
  778 }
  779 /*}}}*/
  780 /* tge       -- >= operator */ /*{{{*/
  781 Token tge(Token l, Token r)
  782 {
  783   /* variables */ /*{{{*/
  784   Token result;
  785   static char empty[]="";
  786   /*}}}*/
  787 
  788   if (l.type==EEK) /* return left error argument */ /*{{{*/
  789   return tcopy(l);
  790   /*}}}*/
  791   if (r.type==EEK) /* return right error argument */ /*{{{*/
  792   return tcopy(r);
  793   /*}}}*/
  794   if (l.type==EMPTY) /* try to assign 0 element of r.type */ /*{{{*/
  795   {
  796     l.type=r.type;
  797     switch (r.type)
  798     {
  799       case INT: l.u.integer=0; break;
  800       case FLOAT: l.u.flt=0.0; break;
  801       case STRING: l.u.string=empty; break;
  802       default: ;
  803     }
  804   }
  805   /*}}}*/
  806   if (r.type==EMPTY) /* try to assign 0 element of l.type */ /*{{{*/
  807   {
  808     r.type=l.type;
  809     switch (l.type)
  810     {
  811       case INT: r.u.integer=0; break;
  812       case FLOAT: r.u.flt=0.0; break;
  813       case STRING: r.u.string=empty; break;
  814       default: ;
  815     }  
  816   }
  817   /*}}}*/
  818   if (l.type==INT && r.type==INT) /* result is left int >= right int */ /*{{{*/
  819   {
  820     result.type=INT;
  821     result.u.integer=l.u.integer>=r.u.integer;
  822   }
  823   /*}}}*/
  824   else if (l.type==STRING && r.type==STRING) /* return left string >= right string */ /*{{{*/
  825   {
  826     result.type=INT;
  827     result.u.integer=(strcmp(l.u.string,r.u.string)>=0);
  828   }
  829   /*}}}*/
  830   else if (l.type==FLOAT && r.type==FLOAT) /* return left float >= right float */ /*{{{*/
  831   {
  832     result.type=INT;
  833     result.u.integer=l.u.flt>=r.u.flt;
  834   }
  835   /*}}}*/
  836   else if (l.type==FLOAT && r.type==INT) /* return left float >= (double) right int */ /*{{{*/
  837   {
  838     result.type=INT;
  839     result.u.integer=l.u.flt>=((double)r.u.integer);
  840   }  
  841   /*}}}*/
  842   else if (l.type==INT && r.type==FLOAT) /* return (double) left int >= right float */ /*{{{*/
  843   {
  844     result.type=INT;
  845     result.u.integer=((double)l.u.integer)>=r.u.flt;
  846   }    
  847   /*}}}*/
  848   else /* return >= type error */ /*{{{*/
  849   {
  850     result.type=EEK;
  851     result.u.err=strcpy(malloc(strlen(_("type mismatch for relational operator"))+1),_("type mismatch for relational operator"));
  852   }
  853   /*}}}*/
  854   return result;
  855 }
  856 /*}}}*/
  857 /* tgt       -- <= operator */ /*{{{*/
  858 Token tgt(Token l, Token r)
  859 {
  860   /* variables */ /*{{{*/
  861   Token result;
  862   static char empty[]="";
  863   /*}}}*/
  864   
  865   if (l.type==EEK) /* return left error argument */ /*{{{*/
  866   return tcopy(l);
  867   /*}}}*/
  868   if (r.type==EEK) /* return right error argument */ /*{{{*/
  869   return tcopy(r);
  870   /*}}}*/
  871   if (l.type==EMPTY) /* try to assign 0 element of r.type */ /*{{{*/
  872   {
  873     l.type=r.type;
  874     switch (r.type)
  875     {
  876       case INT: l.u.integer=0; break;
  877       case FLOAT: l.u.flt=0.0; break;
  878       case STRING: l.u.string=empty; break;
  879       default: ;
  880     }
  881   }
  882   /*}}}*/
  883   if (r.type==EMPTY) /* try to assign 0 element of l.type */ /*{{{*/
  884   {
  885     r.type=l.type;
  886     switch (l.type)
  887     {
  888       case INT: r.u.integer=0; break;
  889       case FLOAT: r.u.flt=0.0; break;
  890       case STRING: r.u.string=empty; break;
  891       default: ;
  892     }  
  893   }
  894   /*}}}*/
  895   if (l.type==INT && r.type==INT) /* result is left int > right int */ /*{{{*/
  896   {
  897     result.type=INT;
  898     result.u.integer=l.u.integer>r.u.integer;
  899   }
  900   /*}}}*/
  901   else if (l.type==STRING && r.type==STRING) /* result is left string > right string */ /*{{{*/
  902   {
  903     result.type=INT;
  904     result.u.integer=(strcmp(l.u.string,r.u.string)>0);
  905   }
  906   /*}}}*/
  907   else if (l.type==FLOAT && r.type==FLOAT) /* result is left float > right float */ /*{{{*/
  908   {
  909     result.type=INT;
  910     result.u.integer=l.u.flt>r.u.flt;
  911   }
  912   /*}}}*/
  913   else if (l.type==FLOAT && r.type==INT) /* result is left float > (double) right int */ /*{{{*/
  914   {
  915     result.type=INT;
  916     result.u.integer=l.u.flt>((double)r.u.integer);
  917   }  
  918   /*}}}*/
  919   else if (l.type==INT && r.type==FLOAT) /* result is left int > right float */ /*{{{*/
  920   {
  921     result.type=INT;
  922     result.u.integer=((double)l.u.integer)>r.u.flt;
  923   }    
  924   /*}}}*/
  925   else /* result is relation op type error */ /*{{{*/
  926   {
  927     result.type=EEK;
  928     result.u.err=mystrmalloc(_("type mismatch for relational operator"));
  929   }
  930   /*}}}*/
  931   return result;
  932 }
  933 /*}}}*/
  934 /* teq       -- == operator */ /*{{{*/
  935 Token teq(Token l, Token r)
  936 {
  937   /* variables */ /*{{{*/
  938   Token result;
  939   static char empty[]="";
  940   /*}}}*/
  941   
  942   if (l.type==EEK) return tcopy(l);
  943   else if (r.type==EEK) return tcopy(r);
  944   if (l.type==EMPTY)
  945   /* try to assign 0 element of r.type */ /*{{{*/
  946   {
  947     l.type=r.type;
  948     switch (r.type)
  949     {
  950       case INT: l.u.integer=0; break;
  951       case FLOAT: l.u.flt=0.0; break;
  952       case STRING: l.u.string=empty; break;
  953       default: ;
  954     }
  955   }
  956   /*}}}*/
  957   if (r.type==EMPTY)
  958   /* try to assign 0 element of l.type */ /*{{{*/
  959   {
  960     r.type=l.type;
  961     switch (l.type)
  962     {
  963       case INT: r.u.integer=0; break;
  964       case FLOAT: r.u.flt=0.0; break;
  965       case STRING: r.u.string=empty; break;
  966       default: ;
  967     }  
  968   }
  969   /*}}}*/
  970   if (l.type==FLOAT && r.type==INT)
  971   {
  972     result.type=INT;
  973     result.u.integer=l.u.flt==((double)r.u.integer);
  974   }  
  975   else if (l.type==INT && r.type==FLOAT)
  976   {
  977     result.type=INT;
  978     result.u.integer=((double)l.u.integer)==r.u.flt;
  979   }    
  980   else if (l.type!=r.type)
  981   {
  982     result.type=INT;
  983     result.u.integer=0;
  984   }
  985   else if (l.type==INT)
  986   {
  987     result.type=INT;
  988     result.u.integer=l.u.integer==r.u.integer;
  989   }
  990   else if (l.type==STRING)
  991   {
  992     result.type=INT;
  993     result.u.integer=(strcmp(l.u.string,r.u.string)==0);
  994   }
  995   else if (l.type==FLOAT)
  996   {
  997     result.type=INT;
  998     result.u.integer=l.u.flt==r.u.flt;
  999   }
 1000   else if (l.type==EMPTY)
 1001   {
 1002     result.type=INT;
 1003     result.u.integer=1;
 1004   }
 1005   else
 1006   {
 1007     result.type=EEK;
 1008     result.u.err=strcpy(malloc(strlen(_("type mismatch for relational operator"))+1),_("type mismatch for relational operator"));
 1009   }
 1010   return result;
 1011 }
 1012 /*}}}*/
 1013 /* tabouteq  -- ~= operator */ /*{{{*/
 1014 Token tabouteq(Token l, Token r)
 1015 {
 1016   /* variables */ /*{{{*/
 1017   Token result;
 1018   /*}}}*/
 1019   
 1020   if (l.type==EEK) return tcopy(l);
 1021   else if (r.type==EEK) return tcopy(r);
 1022   if (l.type==EMPTY)
 1023   /* try to assign 0 element of r.type */ /*{{{*/
 1024   {
 1025     l.type=r.type;
 1026     switch (r.type)
 1027     {
 1028       case FLOAT: l.u.flt=0.0; break;
 1029       default: ;
 1030     }
 1031   }
 1032   /*}}}*/
 1033   if (r.type==EMPTY)
 1034   /* try to assign 0 element of l.type */ /*{{{*/
 1035   {
 1036     r.type=l.type;
 1037     switch (l.type)
 1038     {
 1039       case FLOAT: r.u.flt=0.0; break;
 1040       default: ;
 1041     }  
 1042   }
 1043   /*}}}*/
 1044   if (l.type==FLOAT && r.type==FLOAT)
 1045   {
 1046     result.type=INT;
 1047     result.u.integer=(fabs(l.u.flt-r.u.flt)<=DBL_EPSILON);
 1048   }
 1049   else
 1050   {
 1051     result.type=EEK;
 1052     result.u.err=strcpy(malloc(strlen(_("type mismatch for relational operator"))+1),_("type mismatch for relational operator"));
 1053   }
 1054   return result;
 1055 }
 1056 /*}}}*/
 1057 /* tne       -- != operator */ /*{{{*/
 1058 Token tne(Token l, Token r)
 1059 {
 1060   /* variables */ /*{{{*/
 1061   Token result;
 1062   static char empty[]="";
 1063   /*}}}*/
 1064   
 1065   if (l.type==EEK) return tcopy(l);
 1066   else if (r.type==EEK) return tcopy(r);
 1067   if (l.type==EMPTY)
 1068   /* try to assign 0 element of r.type */ /*{{{*/
 1069   {
 1070     l.type=r.type;
 1071     switch (r.type)
 1072     {
 1073       case INT: l.u.integer=0; break;
 1074       case FLOAT: l.u.flt=0.0; break;
 1075       case STRING: l.u.string=empty; break;
 1076       default: ;
 1077     }
 1078   }
 1079   /*}}}*/
 1080   if (r.type==EMPTY)
 1081   /* try to assign 0 element of l.type */ /*{{{*/
 1082   {
 1083     r.type=l.type;
 1084     switch (l.type)
 1085     {
 1086       case INT: r.u.integer=0; break;
 1087       case FLOAT: r.u.flt=0.0; break;
 1088       case STRING: r.u.string=empty; break;
 1089       default: ;
 1090     }  
 1091   }
 1092   /*}}}*/
 1093   if (l.type==FLOAT && r.type==INT)
 1094   {
 1095     result.type=INT;
 1096     result.u.integer=l.u.flt!=((double)r.u.integer);
 1097   }  
 1098   else if (l.type==INT && r.type==FLOAT)
 1099   {
 1100     result.type=INT;
 1101     result.u.integer=((double)l.u.integer)!=r.u.flt;
 1102   }    
 1103   else if (l.type!=r.type)
 1104   {
 1105     result.type=INT;
 1106     result.u.integer=1;
 1107   }
 1108   else if (l.type==INT)
 1109   {
 1110     result.type=INT;
 1111     result.u.integer=l.u.integer!=r.u.integer;
 1112   }
 1113   else if (l.type==STRING)
 1114   {
 1115     result.type=INT;
 1116     result.u.integer=(strcmp(l.u.string,r.u.string)!=0);
 1117   }
 1118   else if (l.type==FLOAT)
 1119   {
 1120     result.type=INT;
 1121     result.u.integer=l.u.flt!=r.u.flt;
 1122   }
 1123   else if (l.type==EMPTY)
 1124   {
 1125     result.type=INT;
 1126     result.u.integer=0;
 1127   }
 1128   else
 1129   {
 1130     result.type=EEK;
 1131     result.u.err=strcpy(malloc(strlen(_("type mismatch for relational operator"))+1),_("type mismatch for relational operator"));
 1132   }
 1133   return result;
 1134 }
 1135 /*}}}*/
 1136 
 1137