Subversion Repositories wimsdev

Rev

Rev 12260 | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. /*    Copyright (C) 1998-2003 XIAO, Gang of Universite de Nice - Sophia Antipolis
  2.  *
  3.  *  This program is free software; you can redistribute it and/or modify
  4.  *  it under the terms of the GNU General Public License as published by
  5.  *  the Free Software Foundation; either version 2 of the License, or
  6.  *  (at your option) any later version.
  7.  *
  8.  *  This program is distributed in the hope that it will be useful,
  9.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11.  *  GNU General Public License for more details.
  12.  *
  13.  *  You should have received a copy of the GNU General Public License
  14.  *  along with this program; if not, write to the Free Software
  15.  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16.  */
  17. #include "libwims.h"
  18.  
  19. /* log(-1) does not make sense in real */
  20. #ifndef NAN
  21. #define NAN log(-1)
  22. #endif
  23.  
  24.     /* Only two decimal points, less than 1 million.
  25.      * No check of buffer length which should be at least 12.
  26.      * returns the end of buffer. */
  27. char *moneyprint(char *p, double s)
  28. {
  29.   char *p1, *p2, buf[16];
  30.   int t, t1, t2;
  31.   if(s<0) {*p++='-'; s=-s;}
  32.   if(s>999999) s=999999;
  33.   t=floor(s*100+0.5); if(t>99999999) t=99999999; if(t<0) t=0;
  34.   if(t==0) {*p++='0'; *p=0; return p;}
  35.   t1=t/100; t2=t%100; p1=buf+10;
  36.   for(*p1--=t1%10+'0',t1/=10;t1>0;*p1--=t1%10+'0',t1/=10);
  37.   p2=buf+11;
  38.   if(t2) {
  39.     *p2++='.';
  40.     *p2++=t2/10+'0'; t2%=10;
  41.     if(t2) *p2++=t2+'0';
  42.   }
  43.   p1++; *p2=0; memmove(p,p1,p2-p1+1); p+=p2-p1;
  44.   return p;
  45. }
  46.  
  47. /* #define RAND_BUF_SIZE 4096
  48. static char rand_buf[RAND_BUF_SIZE];
  49. */
  50. /* The trouble here is that httpd does not initialize
  51.      * the variable RANDOM.
  52.      * So I use time (microseconds) to get a quick solution. */
  53. void init_random(void)
  54. {
  55.   int r;
  56.   struct timeval t;
  57. /*    initstate(1,rand_buf,RAND_BUF_SIZE); */
  58.   gettimeofday(&t,NULL);
  59.   r=t.tv_usec+t.tv_sec*1000;
  60.   if(r<0) r=-r;
  61.   if(r==0) r=1;
  62.   srandom(r);
  63. }
  64.  
  65. /* gives a double random number between 0 and m */
  66. double drand(double m)
  67. {
  68.   double r;
  69.   r=((double) random()+(double) random()/(double) RAND_MAX);
  70.   return (r/(double) RAND_MAX)*m;
  71. }
  72.  
  73. /* gives a random integer between 0 and n.
  74.  * n maybe floating, but will be rounded */
  75. double irand(double n)
  76. {
  77.   int  end,r;
  78.   if(n==0) return 0;
  79.   if(n>0) end=n; else end=-n;
  80.   r=(double) random()*end/RAND_MAX;
  81.   if(r==n) r--;
  82.   if(n>0) return r; else return -r;
  83. }
  84.  
  85. /* sign of d */
  86. double sign(double d)
  87. {
  88.   if(d==0) return 0;
  89.   if(d<0) return -1;
  90.   else return 1;
  91. }
  92.  
  93. /* rounding to integer: problem with half-way rounding */
  94. double myround(double d)
  95. {
  96.   long int t;
  97.   if(d<0) t=d-0.5; else t=d+0.5;
  98.   return t;
  99. }
  100.  
  101. /* log of base 2 */
  102. double mylog2(double d)
  103. {
  104.   return log(d)/log(2);
  105. }
  106.  
  107. /* sec */
  108. double sec(double d)
  109. {
  110.   return 1/cos(d);
  111. }
  112.  
  113. /* csc */
  114. double csc(double d)
  115. {
  116.   return 1/sin(d);
  117. }
  118.  
  119. /* cotangent function */
  120. double cotan(double d)
  121. {
  122.   return 1/tan(d);
  123. }
  124.  
  125. /* hyperbolic cotangent */
  126. double cotanh(double d)
  127. {
  128.   return 1/tanh(d);
  129. }
  130.  
  131. /* factorial of an integer */
  132. double factorial(double d)
  133. {
  134.   int i,n; double t;
  135.   n=d;
  136.   if(n<0 || n!=d) return NAN;
  137.   if(n>1000) return HUGE_VAL;
  138.   t=1; for(i=1;i<=n;i++) t=t*i;
  139.   return t;
  140. }
  141.  
  142. /* binomial coefficient */
  143. double binomial(double d1,double d2)
  144. {
  145.   return factorial(d1)/(factorial(d2)*factorial(d1-d2));
  146. }
  147.  
  148. /* max and min */
  149. double max(double d1, double d2)
  150. {
  151.   if(!isfinite(d1) || !isfinite(d2)) return NAN;
  152.   if(d1<d2) return d2; else return d1;
  153. }
  154. double min(double d1, double d2)
  155. {
  156.   if(!isfinite(d1) || !isfinite(d2)) return NAN;
  157.   if(d1<d2) return d1; else return d2;
  158. }
  159.  
  160. /* gcd and lcm, not really checking errors. */
  161. double gcd(double n1, double n2)
  162. {
  163.   unsigned long long int l1, l2, ll;
  164.   n1=fabs(n1); n2=fabs(n2);
  165.   if(!isfinite(n1) || !isfinite(n2) || n1<0 || n2<0 ||
  166.      n1>1E18 || n2>1E18) return NAN;
  167.   l1=n1; l2=n2;
  168.   if(l1<l2) {
  169.     ll=l1;l1=l2;l2=ll;
  170.   }
  171.   if(l1==0) return NAN;
  172.   while(l2>0) {
  173.     ll=l2;l2=l1%l2;l1=ll;
  174.   }
  175.   return l1;
  176. }
  177.  
  178. double lcm(double n1, double n2)
  179. {
  180.   return n1*n2/gcd(n1,n2);
  181. }
  182.  
  183. struct {
  184.   char *name;
  185.   int type;
  186.   double val;
  187.   double (*f1) (double parm);
  188.   double (*f2) (double parm1, double parm2);
  189. } evalname[]={
  190.   {"Argch",     1,      0,      acosh,  NULL},
  191.   {"Argsh",     1,      0,      asinh,  NULL},
  192.   {"Argth",     1,      0,      atanh,  NULL},
  193.   {"E", 0,      M_E,    NULL,   NULL},
  194.   {"EULER",     0,      0.57721566490153286,    NULL,   NULL},
  195.   {EV_S,        0,      0,      NULL,   NULL},
  196.   {EV_T,        0,      0,      NULL,   NULL},
  197.   {EV_X,        0,      0,      NULL,   NULL},
  198.   {EV_Y,        0,      0,      NULL,   NULL},
  199.   {"Euler",     0,      0.57721566490153286,    NULL,   NULL},
  200.   {"Inf",       0,      1,      log,    NULL},
  201.   {"NaN",       0,      0,      log,    NULL},
  202.   {"PI",        0,      M_PI,   NULL,   NULL},
  203.   {"Pi",        0,      M_PI,   NULL,   NULL},
  204.   {"abs",       1,      0,      fabs,   NULL},
  205.   {"acos",      1,      0,      acos,   NULL},
  206.   {"acosh",     1,      0,      acosh,  NULL},
  207.   {"arccos",1,  0,      acos,   NULL},
  208.   {"arcsin",1,  0,      asin,   NULL},
  209.   {"arctan",1,  0,      atan,   NULL},
  210.   {"arctg",     1,      0,      atan,   NULL},
  211.   {"argch",     1,      0,      acosh,  NULL},
  212.   {"argsh",     1,      0,      asinh,  NULL},
  213.   {"argth",     1,      0,      atanh,  NULL},
  214.   {"asin",      1,      0,      asin,   NULL},
  215.   {"asinh",     1,      0,      asinh,  NULL},
  216.   {"atan",      1,      0,      atan,   NULL},
  217.   {"atanh",     1,      0,      atanh,  NULL},
  218.   {"binomial",2,        0,      NULL,   binomial},
  219.   {"ceil",      1,      0,      ceil,   NULL}, /* round-up integer */
  220.   {"ch",        1,      0,      cosh,   NULL},
  221.   {"cos",       1,      0,      cos,    NULL},
  222.   {"cosh",      1,      0,      cosh,   NULL},
  223.   {"cot",       1,      0,      cotan,  NULL},
  224.   {"cotan",     1,      0,      cotan,  NULL},
  225.   {"cotanh",1,  0,      cotanh, NULL},
  226.   {"coth",      1,      0,      cotanh, NULL},
  227.   {"csc",       1,      0,      csc,    NULL},
  228.   {"ctg",       1,      0,      cotan,  NULL},
  229.   {"cth",       1,      0,      cotanh, NULL},
  230.   {"drand",     1,      0,      drand,  NULL},
  231.   {"e", 0,      M_E,    NULL,   NULL},
  232.   {"erf",       1,      0,      erf,    NULL},
  233.   {"erfc",      1,      0,      erfc,   NULL},
  234.   {"euler",     0,      0.57721566490153286,    NULL,   NULL},
  235.   {"exp",       1,      0,      exp,    NULL},
  236.   {"factorial",1,       0,      factorial,      NULL},
  237.   {"floor",     1,      0,      floor,  NULL},
  238.   {"gcd",       2,      0,      NULL,   gcd},
  239.   {"irand",     1,      0,      irand,  NULL},
  240. /*      {"j0",  1,      0,      j0,     NULL}, */ /* Bessel functions */
  241. /*      {"j1",  1,      0,      j1,     NULL}, */
  242.   {"lcm",       2,      0,      NULL,   lcm},
  243.   {"lg",        1,      0,      log10,  NULL},
  244.   {"lgamma",1,  0,      lgamma, NULL}, /* log of Gamma function */
  245.   {"ln",        1,      0,      log,    NULL},
  246.   {"log",       1,      0,      log,    NULL},
  247.   {"log10",     1,      0,      log10,  NULL},
  248.   {"log2",      1,      0,      mylog2, NULL},
  249.   {"max",       2,      0,      NULL,   max},
  250.   {"min",       2,      0,      NULL,   min},
  251.   {"pi",        0,      M_PI,   NULL,   NULL},
  252.   {"pow",       2,      0,      NULL,   pow},
  253.   {"rand",      1,      0,      drand,  NULL},
  254.   {"randdouble",1,      0,      drand,  NULL},
  255.   {"randfloat",1,       0,      drand,  NULL},
  256.   {"randint",1, 0,      irand,  NULL},
  257.   {"random",1,  0,      drand,  NULL},
  258.   {"randreal",1,        0,      drand,  NULL},
  259.   {"rint",      1,      0,      myround,        NULL}, /* closest integer */
  260.   {"round",     1,      0,      myround,        NULL}, /* closest integer */
  261.   {"sec",       1,      0,      sec,    NULL},
  262.   {"sgn",       1,      0,      sign,   NULL}, /* sign of the value */
  263.   {"sh",        1,      0,      sinh,   NULL},
  264.   {"sign",      1,      0,      sign,   NULL}, /* sign of the value */
  265.   {"sin",       1,      0,       sin,   NULL},
  266.   {"sinh",      1,      0,      sinh,   NULL},
  267.   {"sqrt",      1,      0,      sqrt,   NULL},
  268.   {"tan",       1,      0,      tan,    NULL},
  269.   {"tanh",      1,      0,      tanh,   NULL},
  270.   {"tg",        1,      0,      tan,    NULL},
  271.   {"th",        1,      0,      tanh,   NULL},
  272. /*      {"y0",  1,      0,      y0,     NULL}, */
  273. /*      {"y1",  1,      0,      y1,     NULL},  */
  274. };
  275. #define evalname_no (sizeof(evalname)/sizeof(evalname[0]))
  276.  
  277. int get_evalcnt(void) {return evalname_no;}
  278. char *get_evalname(int i) {return evalname[i].name;}
  279. int get_evaltype(int i) {return evalname[i].type;}
  280. int evaltab_verify(void) {return verify_order(evalname,evalname_no,sizeof(evalname[0]));}
  281. int search_evaltab(char *p) {
  282.   return search_list(evalname,evalname_no,sizeof(evalname[0]),p);
  283. }
  284.  
  285. static char *evalue_pt;
  286. int evalue_error;
  287.  
  288. int get_evalue_error(void) { return evalue_error; }
  289. void set_evalue_error(int e) {evalue_error=e; return;}
  290.  
  291. /* prepare pointer for evaluation */
  292. void set_evalue_pointer(char *p)
  293. {
  294.   evalue_pt=p;
  295. }
  296.  
  297. /* get position of name in nametable */
  298. int eval_getpos(char *name)
  299. {
  300.   return search_list(evalname,evalname_no,sizeof(evalname[0]),name);
  301. }
  302.  
  303. /* set value to name */
  304. void eval_setval(int pos, double v)
  305. {
  306.   if(pos>=0 && pos<evalname_no) evalname[pos].val=v;
  307. }
  308.  
  309. /* get string pointer (after evaluation) */
  310. char *get_evalue_pointer(void)
  311. {
  312.   return evalue_pt;
  313. }
  314.  
  315. double _evalue(int ord)
  316. {
  317.   double d,dd;
  318.   int i,k;
  319.   char buf[32];
  320.  
  321.   if(evalue_error) return NAN;
  322.   d=0;
  323.   while(*evalue_pt=='+') evalue_pt++;
  324.   if(*evalue_pt==0) return 0; /* empty string */
  325.   switch(*evalue_pt) {
  326.     case '(':
  327.       evalue_pt++; d=_evalue(')');goto vld;
  328.     case '|':
  329.       if(ord=='|') {
  330.         evalue_pt++; return 0;
  331.       }
  332.       evalue_pt++; d=fabs(_evalue('|'));goto vld;
  333.     case '-':
  334.       evalue_pt++; d=-_evalue(6);goto vld;
  335.   }
  336.   if((128&*evalue_pt)!=0) {/* special character */
  337.     k=(*evalue_pt)&255; evalue_pt++;
  338.     if(k>=130 && k<140) {
  339.       i=(k-130)*200; k=(*evalue_pt)&255; evalue_pt++;
  340.       if(k<33 || k>=233) goto badeval;
  341.       i+=k-33; if(i<0 || i>=evalname_no) goto badeval;
  342.       goto ename;
  343.     }
  344.     if(k>=140 && k<150) {
  345.       i=(k-140)*200; k=(*evalue_pt)&255; evalue_pt++;
  346.       if(k<33 || k>=233) goto badeval;
  347.       if(ev_var==NULL || ev_varcnt==NULL) goto badeval;
  348.       i+=k-33; if(i<0 || i>=*ev_varcnt) goto badeval;
  349.       goto vname;
  350.     }
  351.     evalue_pt++; goto badeval;
  352.   }
  353.   if(*evalue_pt=='.' || myisdigit(*evalue_pt)){
  354.     d=strtod(evalue_pt,&evalue_pt);goto binary;
  355.   }
  356.   for(i=0;myisalnum(*(evalue_pt+i)) && i<16; i++)
  357.     buf[i]=*(evalue_pt+i);
  358.   buf[i]=0; evalue_pt+=i;
  359.   if(i==0) goto badeval;
  360.   if(ev_varcnt!=NULL && ev_var!=NULL && *ev_varcnt>0)
  361.     for(i=0;i<*ev_varcnt;i++) {
  362.       if(strcmp(buf,ev_var[i].name)==0) {
  363.         vname: d=ev_var[i].value; goto vld;
  364.       }
  365.     }
  366.   i=search_list(evalname,evalname_no,sizeof(evalname[0]),buf);
  367.   ename: if(i>=0) switch(evalname[i].type) { /* evaluation of expressions */
  368.     case 0: {
  369.       d=evalname[i].val;
  370.       if(evalname[i].f1!=NULL) {
  371.         if(d==0) d=NAN;
  372.         if(d==1) d=HUGE_VAL;
  373.       }
  374.       break;
  375.     }
  376.     case 1: {
  377.       if(*evalue_pt!='(') return NAN;
  378.       evalue_pt++;
  379.       d=evalname[i].f1(_evalue(')')); break;/* evaluation of function */
  380.     }
  381.     case 2: {
  382.       double parm1,parm2;
  383.       if(*evalue_pt!='(') return NAN;
  384.       evalue_pt++;
  385.       parm1=_evalue(',');parm2=_evalue(')');
  386.       d=evalname[i].f2(parm1,parm2); break;
  387.     }
  388.     default: {      /* This is impossible. */
  389.         return NAN;
  390.     }
  391.   }
  392.   else {
  393.       badeval: evalue_error=-1; return NAN;
  394.   }
  395.   vld:
  396.   if(evalue_error) return NAN;
  397.   binary: /*evaluation des expressions */
  398.   if(*evalue_pt=='!') {
  399.     evalue_pt++; d=factorial(d);
  400.   }
  401.   if(*evalue_pt==ord) {evalue_pt++;goto ok;}/* */
  402.   if(*evalue_pt==0 || /* chaine de caractere finie*/
  403.      (ord<10 && (*evalue_pt==',' || *evalue_pt==';' || *evalue_pt==')'
  404.              || *evalue_pt=='|')))
  405.     goto ok;
  406.   switch(*evalue_pt) {
  407.     case '+':
  408.       if(ord<=8) break;
  409.       evalue_pt++; d+=_evalue(8);goto vld;
  410.     case '-':
  411.       if(ord<=8) break;
  412.       evalue_pt++; d-=_evalue(8);goto vld;
  413.     case '*':
  414.       if(ord<=6) break;
  415.       evalue_pt++; d*=_evalue(6);goto vld;
  416.     case '/':
  417.       if(ord<=6) break;
  418.       evalue_pt++; dd=_evalue(6);
  419.       if(dd==0) {evalue_error=10;return NAN;}
  420.           d/=dd;goto vld;
  421.     case '%': {
  422.       int di, ddi;
  423.       if(ord<=6) break;
  424.       evalue_pt++; dd=_evalue(6);
  425.         if(dd==0) {evalue_error=10;return NAN;}
  426.           di=d; ddi=dd; d=di%ddi;goto vld;
  427.       }
  428.     case '^': {
  429.       if(ord<5) break;
  430.       evalue_pt++; d=pow(d,_evalue(5));goto vld;
  431.     }
  432.     default : {
  433.       return NAN;
  434.     }
  435.   }
  436.   ok: return d;
  437. }
  438.  
  439. /* substitute variable names by their environment strings
  440.  * The buffer pointed to by p must have enough space
  441.  * (defined by MAX_LINELEN). */
  442. char *_substit(char *p)
  443. {
  444.   return p;
  445. }
  446.  
  447. char *(*substitute) (char *p)=_substit;
  448.  
  449. double checked_eval( char* p)
  450. {
  451.   set_evalue_error(0);
  452.   set_evalue_pointer(p);
  453.   return _evalue(10);
  454. }
  455.  
  456. /* evalue a string to double */
  457. double strevalue(char *p)
  458. {
  459.   char buf[MAX_LINELEN+1];
  460.  
  461.   if(p==NULL) return 0;
  462.   mystrncpy(buf,p,sizeof(buf));
  463.   substitute(buf); nospace(buf);
  464.   if(check_parentheses(buf,0)) {return NAN;}
  465.   return checked_eval(buf);
  466. }
  467.  
  468.  
  469. /* compile an expression for faster evaluation
  470.  * returns -1 if cannot be compiled.
  471.  * else returns the number of compilations.
  472.  */
  473. int evalue_compile(char *p)
  474. {
  475.   char *p1, *p2, *pe, name[256], buf[8];
  476.   int i,k;
  477.  
  478.   k=0;
  479.   for(p1=p; *p1; p1++) if((128&*p1)!=0) return -1;
  480.   nospace(p);
  481.   for(p1=find_mathvar_start(p); *p1; p1=find_mathvar_start(pe)) {
  482.     pe=find_mathvar_end(p1);
  483.     if(!myisalpha(*p1)) continue;
  484.     p2=pe; if(p2-p1>16) continue;
  485.     memmove(name,p1,p2-p1); name[p2-p1]=0;
  486. /* replace the variables by a number
  487.  * at most 2000 variables on two characters :
  488.  * variable: 140 <= integer <150,  number between 33 and 233
  489.  * function: 130 <= integer < 140, number between 33 and 233
  490.  */
  491.     if(ev_varcnt!=NULL && ev_var!=NULL && *ev_varcnt>0) {
  492.       for(i=0;i<*ev_varcnt && strcmp(name,ev_var[i].name)!=0;i++);
  493.       if(i<*ev_varcnt && i<2000) {
  494.       buf[0]=i/200+140; buf[1]=i%200+33; buf[2]=0;
  495.       string_modify(p,p1,p2,"%s",buf);
  496.       pe=p1+2; k++; continue;
  497.       }
  498.     }
  499.     i=search_list(evalname,evalname_no,sizeof(evalname[0]),name);
  500.     if(i>=0 && i<2000) {
  501.       buf[0]=i/200+130; buf[1]=i%200+33; buf[2]=0;
  502.       string_modify(p,p1,p2,"%s",buf);
  503.       pe=p1+2; k++; continue;
  504.     }
  505.   }
  506.   return k;
  507. }
  508.  
  509. /* add evaluator (Dominique Bernardi june 2014)
  510. In addition to the general evaluation functions, there is a simple mean
  511. to evaluate standard functions with at most four variables
  512. named "x", "y", "s" and "t". The simplest one is
  513.  
  514. double eval_simple (char *p, double x, double y, double s, double t);
  515.  
  516. which does exactly that. In case of multiple evaluation of the same function
  517. for different values of the variable(s), it is possible to speed up a bit
  518. the evaluation by "precompiling" the string to be evaluated.
  519. This precompilation is done by
  520.  
  521. eval_struct* eval_create (char *p);
  522.  
  523. which returns a newly allocated pointer to something. One can use
  524. this pointer in functions like
  525.  
  526. eval_x, eval_t, eval_x_y
  527.  
  528. When the struct is no longer useful, one can reclaim the memory it used with
  529.  
  530. void eval_destroy (eval_struct *q);
  531.  
  532. */
  533.  
  534. void _aux (char *q, char *varn, char *subst, int *v)
  535. {
  536.   char *pp;
  537.   for(pp=varchr(q,varn); pp; pp=varchr(pp,varn)) {
  538.     string_modify(q,pp,pp+strlen(varn),"%s",subst);
  539.     pp+=strlen(subst);
  540.   }
  541.   *v = eval_getpos(subst);
  542. }
  543.  
  544. eval_struct * eval_create (char *in_p)
  545. {
  546.   eval_struct *p = malloc (sizeof(eval_struct));
  547.   char *q = malloc(MAX_LINELEN+1);
  548.   strncpy (q, in_p, MAX_LINELEN);
  549.   _aux (q, "x", EV_X, &p->x);
  550.   _aux (q, "y", EV_Y, &p->y);
  551.   _aux (q, "s", EV_S, &p->s);
  552.   _aux (q, "t", EV_T, &p->t);
  553.   evalue_compile(q);
  554.   p->texte = q;
  555.   return p;
  556. }
  557.  
  558. double eval_multiple (eval_struct *p, double x, double y, double s, double t)
  559. {
  560.   eval_setval(p->x,x);
  561.   eval_setval(p->y,y);
  562.   eval_setval(p->s,s);
  563.   eval_setval(p->t,t);
  564.   return checked_eval(p->texte);
  565. }
  566. /* non yet useful
  567. double eval_simple (char *p, double x, double y, double s, double t)
  568. {
  569.   eval_struct *q = eval_create (p);
  570.   double r = eval (q, x, y, s, t);
  571.   eval_destroy(q);
  572.   return r;
  573. }
  574.  
  575. */
  576.  
  577. double eval_x (eval_struct *p, double x)
  578. {
  579.   eval_setval(p->x,x);
  580.   return checked_eval(p->texte);
  581. }
  582.  
  583. double eval_t (eval_struct *p, double t)
  584. {
  585.   eval_setval(p->t,t);
  586.   return checked_eval(p->texte);
  587. }
  588.  
  589. double eval_x_y (eval_struct *p, double x, double y)
  590. {
  591.   eval_setval(p->x,x);
  592.   eval_setval(p->y,y);
  593.   return checked_eval(p->texte);
  594. }
  595.  
  596. void eval_destroy(eval_struct *q) {free (q->texte); free (q);}
  597.