Subversion Repositories wimsdev

Rev

Rev 11126 | Rev 12260 | Go to most recent revision | 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. {    return 1/cos(d);}
  110.  
  111. /* csc */
  112. double csc(double d)
  113. {    return 1/sin(d);}
  114.  
  115. /* cotangent function */
  116. double cotan(double d)
  117. {
  118.     return 1/tan(d);
  119. }
  120.  
  121. /* hyperbolic cotangent */
  122. double cotanh(double d)
  123. {
  124.     return 1/tanh(d);
  125. }
  126.  
  127. /* factorial of an integer */
  128. double factorial(double d)
  129. {
  130.     int i,n; double t;
  131.     n=d;
  132.     if(n<0 || n!=d) return NAN;
  133.     if(n>1000) return HUGE_VAL;
  134.     t=1; for(i=1;i<=n;i++) t=t*i;
  135.     return t;
  136. }
  137.  
  138. /* binomial coefficient */
  139. double binomial(double d1,double d2)
  140. {
  141.     return factorial(d1)/(factorial(d2)*factorial(d1-d2));
  142. }
  143.  
  144. /* max and min */
  145. double max(double d1, double d2)
  146. {
  147.     if(!isfinite(d1) || !isfinite(d2)) return NAN;
  148.     if(d1<d2) return d2; else return d1;
  149. }
  150. double min(double d1, double d2)
  151. {
  152.     if(!isfinite(d1) || !isfinite(d2)) return NAN;
  153.     if(d1<d2) return d1; else return d2;
  154. }
  155.  
  156. /* gcd and lcm, not really checking errors. */
  157. double gcd(double n1, double n2)
  158. {
  159.     unsigned long long int l1, l2, ll;
  160.     n1=fabs(n1); n2=fabs(n2);
  161.     if(!isfinite(n1) || !isfinite(n2) || n1<0 || n2<0 ||
  162.        n1>1E18 || n2>1E18) return NAN;
  163.     l1=n1; l2=n2;
  164.     if(l1<l2) {
  165.       ll=l1;l1=l2;l2=ll;
  166.     }
  167.     if(l1==0) return NAN;
  168.     while(l2>0) {
  169.       ll=l2;l2=l1%l2;l1=ll;
  170.     }
  171.     return l1;
  172. }
  173.  
  174. double lcm(double n1, double n2)
  175. {
  176.     return n1*n2/gcd(n1,n2);
  177. }
  178.  
  179. struct {
  180.     char *name;
  181.     int type;
  182.     double val;
  183.     double (*f1) (double parm);
  184.     double (*f2) (double parm1, double parm2);
  185. } evalname[]={
  186.       {"Argch", 1,      0,      acosh,  NULL},
  187.       {"Argsh", 1,      0,      asinh,  NULL},
  188.       {"Argth", 1,      0,      atanh,  NULL},
  189.       {"E",     0,      M_E,    NULL,   NULL},
  190.       {"EULER", 0,      0.57721566490153286,    NULL,   NULL},
  191.       {EV_S,    0,      0,      NULL,   NULL},
  192.       {EV_T,    0,      0,      NULL,   NULL},
  193.       {EV_X,    0,      0,      NULL,   NULL},
  194.       {EV_Y,    0,      0,      NULL,   NULL},
  195.       {"Euler", 0,      0.57721566490153286,    NULL,   NULL},
  196.       {"Inf",   0,      1,      log,    NULL},
  197.       {"NaN",   0,      0,      log,    NULL},
  198.       {"PI",    0,      M_PI,   NULL,   NULL},
  199.       {"Pi",    0,      M_PI,   NULL,   NULL},
  200.       {"abs",   1,      0,      fabs,   NULL},
  201.       {"acos",  1,      0,      acos,   NULL},
  202.       {"acosh", 1,      0,      acosh,  NULL},
  203.       {"arccos",1,      0,      acos,   NULL},
  204.       {"arcsin",1,      0,      asin,   NULL},
  205.       {"arctan",1,      0,      atan,   NULL},
  206.       {"arctg", 1,      0,      atan,   NULL},
  207.       {"argch", 1,      0,      acosh,  NULL},
  208.       {"argsh", 1,      0,      asinh,  NULL},
  209.       {"argth", 1,      0,      atanh,  NULL},
  210.       {"asin",  1,      0,      asin,   NULL},
  211.       {"asinh", 1,      0,      asinh,  NULL},
  212.       {"atan",  1,      0,      atan,   NULL},
  213.       {"atanh", 1,      0,      atanh,  NULL},
  214.       {"binomial",2,    0,      NULL,   binomial},
  215.       {"ceil",  1,      0,      ceil,   NULL}, /* round-up integer */
  216.       {"ch",    1,      0,      cosh,   NULL},
  217.       {"cos",   1,      0,      cos,    NULL},
  218.       {"cosh",  1,      0,      cosh,   NULL},
  219.       {"cot",   1,      0,      cotan,  NULL},
  220.       {"cotan", 1,      0,      cotan,  NULL},
  221.       {"cotanh",1,      0,      cotanh, NULL},
  222.       {"coth",  1,      0,      cotanh, NULL},
  223.       {"csc",   1,      0,      csc,    NULL},
  224.       {"ctg",   1,      0,      cotan,  NULL},
  225.       {"cth",   1,      0,      cotanh, NULL},
  226.       {"drand", 1,      0,      drand,  NULL},
  227.       {"e",     0,      M_E,    NULL,   NULL},
  228.       {"erf",   1,      0,      erf,    NULL},
  229.       {"erfc",  1,      0,      erfc,   NULL},
  230.       {"euler", 0,      0.57721566490153286,    NULL,   NULL},
  231.       {"exp",   1,      0,      exp,    NULL},
  232.       {"factorial",1,   0,      factorial,      NULL},
  233.       {"floor", 1,      0,      floor,  NULL},
  234.       {"gcd",   2,      0,      NULL,   gcd},
  235.       {"irand", 1,      0,      irand,  NULL},
  236. /*      {"j0",  1,      0,      j0,     NULL}, */ /* Bessel functions */
  237. /*      {"j1",  1,      0,      j1,     NULL}, */
  238.       {"lcm",   2,      0,      NULL,   lcm},
  239.       {"lg",    1,      0,      log10,  NULL},
  240.       {"lgamma",1,      0,      lgamma, NULL}, /* log of Gamma function */
  241.       {"ln",    1,      0,      log,    NULL},
  242.       {"log",   1,      0,      log,    NULL},
  243.       {"log10", 1,      0,      log10,  NULL},
  244.       {"log2",  1,      0,      mylog2, NULL},
  245.       {"max",   2,      0,      NULL,   max},
  246.       {"min",   2,      0,      NULL,   min},
  247.       {"pi",    0,      M_PI,   NULL,   NULL},
  248.       {"pow",   2,      0,      NULL,   pow},
  249.       {"rand",  1,      0,      drand,  NULL},
  250.       {"randdouble",1,  0,      drand,  NULL},
  251.       {"randfloat",1,   0,      drand,  NULL},
  252.       {"randint",1,     0,      irand,  NULL},
  253.       {"random",1,      0,      drand,  NULL},
  254.       {"randreal",1,    0,      drand,  NULL},
  255.       {"rint",  1,      0,      myround,        NULL}, /* closest integer */
  256.       {"round", 1,      0,      myround,        NULL}, /* closest integer */
  257.       {"sec",   1,      0,      sec,    NULL},
  258.       {"sgn",   1,      0,      sign,   NULL}, /* sign of the value */
  259.       {"sh",    1,      0,      sinh,   NULL},
  260.       {"sign",  1,      0,      sign,   NULL}, /* sign of the value */
  261.       {"sin",   1,      0,       sin,   NULL},
  262.       {"sinh",  1,      0,      sinh,   NULL},
  263.       {"sqrt",  1,      0,      sqrt,   NULL},
  264.       {"tan",   1,      0,      tan,    NULL},
  265.       {"tanh",  1,      0,      tanh,   NULL},
  266.       {"tg",    1,      0,      tan,    NULL},
  267.       {"th",    1,      0,      tanh,   NULL},
  268. /*      {"y0",  1,      0,      y0,     NULL}, */
  269. /*      {"y1",  1,      0,      y1,     NULL},  */
  270. };
  271. #define evalname_no (sizeof(evalname)/sizeof(evalname[0]))
  272.  
  273. int get_evalcnt(void) {return evalname_no;}
  274. char *get_evalname(int i) {return evalname[i].name;}
  275. int get_evaltype(int i) {return evalname[i].type;}
  276. int evaltab_verify(void) {return verify_order(evalname,evalname_no,sizeof(evalname[0]));}
  277. int search_evaltab(char *p) {
  278.     return search_list(evalname,evalname_no,sizeof(evalname[0]),p);
  279. }
  280.  
  281. static char *evalue_pt;
  282. int evalue_error;
  283.  
  284. int get_evalue_error(void) { return evalue_error; }
  285. void set_evalue_error(int e) {evalue_error=e; return;}
  286.  
  287. /* prepare pointer for evaluation */
  288. void set_evalue_pointer(char *p)
  289. {
  290.     evalue_pt=p;
  291. }
  292.  
  293. /* get position of name in nametable */
  294. int eval_getpos(char *name)
  295. {
  296.     return search_list(evalname,evalname_no,sizeof(evalname[0]),name);
  297. }
  298.  
  299. /* set value to name */
  300. void eval_setval(int pos, double v)
  301. {
  302.     if(pos>=0 && pos<evalname_no) evalname[pos].val=v;
  303. }
  304.  
  305. /* get string pointer (after evaluation) */
  306. char *get_evalue_pointer(void)
  307. {
  308.     return evalue_pt;
  309. }
  310.  
  311. double _evalue(int ord)
  312. {
  313.     double d,dd;
  314.     int i,k;
  315.     char buf[32];
  316.  
  317.  
  318.     if(evalue_error) return NAN;
  319.     d=0;
  320.     while(*evalue_pt=='+') evalue_pt++;
  321.     if(*evalue_pt==0) return 0; /* empty string */
  322.     switch(*evalue_pt) {
  323.       case '(':
  324.        evalue_pt++; d=_evalue(')');goto vld;
  325.       case '|':
  326.        if(ord=='|') {
  327.         evalue_pt++; return 0;
  328.        }
  329.        evalue_pt++; d=fabs(_evalue('|'));goto vld;
  330.       case '-':
  331.        evalue_pt++; d=-_evalue(6);goto vld;
  332.     }
  333.     if((128&*evalue_pt)!=0) {/* special character */
  334.       k=(*evalue_pt)&255; evalue_pt++;
  335.       if(k>=130 && k<140) {
  336.           i=(k-130)*200; k=(*evalue_pt)&255; evalue_pt++;
  337.           if(k<33 || k>=233) goto badeval;
  338.           i+=k-33; if(i<0 || i>=evalname_no) goto badeval;
  339.           goto ename;
  340.       }
  341.       if(k>=140 && k<150) {
  342.           i=(k-140)*200; k=(*evalue_pt)&255; evalue_pt++;
  343.           if(k<33 || k>=233) goto badeval;
  344.           if(ev_var==NULL || ev_varcnt==NULL) goto badeval;
  345.           i+=k-33; if(i<0 || i>=*ev_varcnt) goto badeval;
  346.           goto vname;
  347.       }
  348.       evalue_pt++; goto badeval;
  349.     }
  350.     if(*evalue_pt=='.' || myisdigit(*evalue_pt))
  351.       {d=strtod(evalue_pt,&evalue_pt);goto binary;}
  352.     for(i=0;myisalnum(*(evalue_pt+i)) && i<16; i++)
  353.       buf[i]=*(evalue_pt+i);
  354.     buf[i]=0; evalue_pt+=i;
  355.     if(i==0) goto badeval;
  356.     if(ev_varcnt!=NULL && ev_var!=NULL && *ev_varcnt>0)
  357.       for(i=0;i<*ev_varcnt;i++) {
  358.         if(strcmp(buf,ev_var[i].name)==0) {
  359.             vname: d=ev_var[i].value; goto vld;
  360.         }
  361.       }
  362.     i=search_list(evalname,evalname_no,sizeof(evalname[0]),buf);
  363.     ename: if(i>=0) switch(evalname[i].type) { /* evaluation of expressions */
  364.       case 0: {
  365.           d=evalname[i].val;
  366.           if(evalname[i].f1!=NULL) {
  367.             if(d==0) d=NAN;
  368.             if(d==1) d=HUGE_VAL;
  369.           }
  370.           break;
  371.       }
  372.       case 1: {
  373.           if(*evalue_pt!='(') return NAN;
  374.           evalue_pt++;
  375.           d=evalname[i].f1(_evalue(')')); break;/* evaluation of function */
  376.       }
  377.       case 2: {
  378.           double parm1,parm2;
  379.           if(*evalue_pt!='(') return NAN;
  380.           evalue_pt++;
  381.           parm1=_evalue(',');parm2=_evalue(')');
  382.           d=evalname[i].f2(parm1,parm2); break;
  383.       }
  384.       default: {      /* This is impossible. */
  385.           return NAN;
  386.       }
  387.     }
  388.     else {
  389.       badeval: evalue_error=-1; return NAN;
  390.     }
  391.   vld:
  392.     if(evalue_error) return NAN;
  393.   binary: /*evaluation des expressions */
  394.     if(*evalue_pt=='!') {
  395.       evalue_pt++; d=factorial(d);
  396.     }
  397.     if(*evalue_pt==ord) {evalue_pt++;goto ok;}/* */
  398.     if(*evalue_pt==0 || /* chaine de caractere finie*/
  399.        (ord<10 && (*evalue_pt==',' || *evalue_pt==';' || *evalue_pt==')'
  400.                || *evalue_pt=='|')))
  401.        goto ok;
  402.     switch(*evalue_pt) {
  403.       case '+':
  404.         if(ord<=8) break;
  405.         evalue_pt++; d+=_evalue(8);goto vld;
  406.       case '-':
  407.         if(ord<=8) break;
  408.         evalue_pt++; d-=_evalue(8);goto vld;
  409.       case '*':
  410.         if(ord<=6) break;
  411.         evalue_pt++; d*=_evalue(6);goto vld;
  412.       case '/':
  413.         if(ord<=6) break;
  414.         evalue_pt++; dd=_evalue(6);
  415.         if(dd==0) {evalue_error=10;return NAN;}
  416.             d/=dd;goto vld;
  417.       case '%': {
  418.         int di, ddi;
  419.         if(ord<=6) break;
  420.         evalue_pt++; dd=_evalue(6);
  421.         if(dd==0) {evalue_error=10;return NAN;}
  422.           di=d; ddi=dd; d=di%ddi;goto vld;
  423.       }
  424.       case '^': {
  425.        if(ord<5) break;
  426.        evalue_pt++; d=pow(d,_evalue(5));goto vld;
  427.       }
  428.       default : {
  429.           return NAN;
  430.       }
  431.     }
  432.     ok: return d;
  433. }
  434.  
  435. /* substitute variable names by their environment strings
  436.  * The buffer pointed to by p must have enough space
  437.  * (defined by MAX_LINELEN). */
  438. char *_substit(char *p)
  439. {
  440.     return p;
  441. }
  442.  
  443. char *(*substitute) (char *p)=_substit;
  444.  
  445. double checked_eval( char* p)
  446. {
  447.     set_evalue_error(0);
  448.     set_evalue_pointer(p);
  449.     return _evalue(10);
  450. }
  451.  
  452. /* evalue a string to double */
  453. double strevalue(char *p)
  454. {
  455.     char buf[MAX_LINELEN+1];
  456.  
  457.     if(p==NULL) return 0;
  458.     mystrncpy(buf,p,sizeof(buf));
  459.     substitute(buf); nospace(buf);
  460.     if(check_parentheses(buf,0)) {return NAN;}
  461.     return checked_eval(buf);
  462. }
  463.  
  464.  
  465. /* compile an expression for faster evaluation
  466.  * returns -1 if cannot be compiled.
  467.  * else returns the number of compilations.
  468.  */
  469. int evalue_compile(char *p)
  470. {
  471.     char *p1, *p2, *pe, name[256], buf[8];
  472.     int i,k;
  473.  
  474.     k=0;
  475.     for(p1=p; *p1; p1++) if((128&*p1)!=0) return -1;
  476.     nospace(p);
  477.     for(p1=find_mathvar_start(p); *p1; p1=find_mathvar_start(pe)) {
  478.       pe=find_mathvar_end(p1);
  479.       if(!myisalpha(*p1)) continue;
  480.       p2=pe; if(p2-p1>16) continue;
  481.       memmove(name,p1,p2-p1); name[p2-p1]=0;
  482. /* replace the variables by a number
  483.  * at most 2000 variables on two characters :
  484.  * variable: 140 <= integer <150,  number between 33 and 233
  485.  * function: 130 <= integer < 140, number between 33 and 233
  486.  */
  487.     if(ev_varcnt!=NULL && ev_var!=NULL && *ev_varcnt>0) {
  488.         for(i=0;i<*ev_varcnt && strcmp(name,ev_var[i].name)!=0;i++);
  489.         if(i<*ev_varcnt && i<2000) {
  490.         buf[0]=i/200+140; buf[1]=i%200+33; buf[2]=0;
  491.         string_modify(p,p1,p2,"%s",buf);
  492.         pe=p1+2; k++; continue;
  493.         }
  494.     }
  495.     i=search_list(evalname,evalname_no,sizeof(evalname[0]),name);
  496.     if(i>=0 && i<2000) {
  497.         buf[0]=i/200+130; buf[1]=i%200+33; buf[2]=0;
  498.         string_modify(p,p1,p2,"%s",buf);
  499.         pe=p1+2; k++; continue;
  500.     }
  501.   }
  502.   return k;
  503. }
  504.  
  505. /* add evaluator (Dominique Bernardi june 2014)
  506. In addition to the general evaluation functions, there is a simple mean
  507. to evaluate standard functions with at most four variables
  508. named "x", "y", "s" and "t". The simplest one is
  509.  
  510. double eval_simple (char *p, double x, double y, double s, double t);
  511.  
  512. which does exactly that. In case of multiple evaluation of the same function
  513. for different values of the variable(s), it is possible to speed up a bit
  514. the evaluation by "precompiling" the string to be evaluated.
  515. This precompilation is done by
  516.  
  517. eval_struct* eval_create (char *p);
  518.  
  519. which returns a newly allocated pointer to something. One can use
  520. this pointer in functions like
  521.  
  522. eval_x, eval_t, eval_x_y
  523.  
  524. When the struct is no longer useful, one can reclaim the memory it used with
  525.  
  526. void eval_destroy (eval_struct *q);
  527.  
  528. */
  529.  
  530. void _aux (char *q, char *varn, char *subst, int *v)
  531. {
  532.   char *pp;
  533.   for(pp=varchr(q,varn); pp; pp=varchr(pp,varn))
  534.     {
  535.       string_modify(q,pp,pp+strlen(varn),"%s",subst);
  536.       pp+=strlen(subst);
  537.     }
  538.   *v = eval_getpos(subst);
  539. }
  540.  
  541. eval_struct * eval_create (char *in_p)
  542. {
  543.   eval_struct *p = malloc (sizeof(eval_struct));
  544.   char *q = malloc(MAX_LINELEN+1);
  545.   strncpy (q, in_p, MAX_LINELEN);
  546.   _aux (q, "x", EV_X, &p->x);
  547.   _aux (q, "y", EV_Y, &p->y);
  548.   _aux (q, "s", EV_S, &p->s);
  549.   _aux (q, "t", EV_T, &p->t);
  550.   evalue_compile(q);
  551.   p->texte = q;
  552.   return p;
  553. }
  554.  
  555. double eval_multiple (eval_struct *p, double x, double y, double s, double t)
  556. {
  557.   eval_setval(p->x,x);
  558.   eval_setval(p->y,y);
  559.   eval_setval(p->s,s);
  560.   eval_setval(p->t,t);
  561.   return checked_eval(p->texte);
  562. }
  563. /* non yet useful
  564. double eval_simple (char *p, double x, double y, double s, double t)
  565. {
  566.   eval_struct *q = eval_create (p);
  567.   double r = eval (q, x, y, s, t);
  568.   eval_destroy(q);
  569.   return r;
  570. }
  571.  
  572. */
  573.  
  574. double eval_x (eval_struct *p, double x)
  575. {
  576.   eval_setval(p->x,x);
  577.   return checked_eval(p->texte);
  578. }
  579.  
  580. double eval_t (eval_struct *p, double t)
  581. {
  582.   eval_setval(p->t,t);
  583.   return checked_eval(p->texte);
  584. }
  585.  
  586. double eval_x_y (eval_struct *p, double x, double y)
  587. {
  588.   eval_setval(p->x,x);
  589.   eval_setval(p->y,y);
  590.   return checked_eval(p->texte);
  591. }
  592.  
  593. void eval_destroy(eval_struct *q) {free (q->texte); free (q);}
  594.