Corrected a long-standing error in which ending text with a literal
[xcircuit.git] / spiceparser / eqn.c
blob3216ff5f04706183675f0677627a1cf31e7f21d3
1 /********************
2 This file is part of the software library CADLIB written by Conrad Ziesler
3 Copyright 2003, Conrad Ziesler, all rights reserved.
5 *************************
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 ******************/
21 /* eqn.c, equation evaluation and parsing
23 Conrad Ziesler
27 #include <ctype.h>
28 #include <math.h>
29 #include <stdio.h>
31 #include "debug.h"
32 #include "eqn.h"
33 extern int __debug_eqn__;
35 /* int __debug_eqn__=1; */
37 #ifndef STRIP_DEBUGGING
38 #define D(level,a) do { if(__debug_eqn__>(level)) a; } while(0)
39 #else
40 #define D(level,a)
41 #endif
44 #define uchar unsigned char
49 #include "memory.h"
50 #define MAX_STACK 1024
52 static memory_t eqn_mem_default=MEMORY_INIT;
53 static memory_t *eqn_mem_stack[MAX_STACK]={ &eqn_mem_default , NULL, NULL };
54 static int eqn_mem_stackp=0;
55 static int eqn_mem_qalloc=0;
57 void eqn_mem_free(void *p)
59 memory_t *mem=p;
60 if(p!=NULL)
62 memory_freeall(mem);
63 free(p);
67 /* make and return a new eqn memory object */
68 void *eqn_mem_new(void)
70 void *p;
71 eqn_mem_qalloc++;
72 p=malloc(sizeof(memory_t));
73 assert(p!=NULL);
74 memory_init(p);
75 return p;
78 void eqn_mem_push(void *p)
80 eqn_mem_stackp++;
81 assert(eqn_mem_stackp<MAX_STACK);
82 eqn_mem_stack[eqn_mem_stackp]=p;
86 /* return and pop stack */
87 void *eqn_mem_pop(void)
89 void *p;
90 assert(eqn_mem_stackp>0);
91 p=eqn_mem_stack[eqn_mem_stackp];
92 eqn_mem_stackp--;
93 return p;
97 #ifdef NO_EQUATIONS
98 void eqn_free(enq_t e)
99 { } /* static equations are not mallocated */
100 #else
102 static void *eqn_malloc(int size)
104 void *p=memory_alloc(eqn_mem_stack[eqn_mem_stackp],size);
105 if(p==((void *)0x81dd014))
107 int i=0;
108 i++;
110 return p;
113 void eqn_free(eqn_t e)
114 { memory_free(eqn_mem_stack[eqn_mem_stackp],e.eqn); }
116 #endif
119 #ifndef NO_EQUATIONS
120 eqntoken_t *eqntoken_next(eqntoken_t *p)
122 eqntoken_t *r;
123 switch(p->op)
125 case OPeolist: case OPeol_const: case OPeol_valp: case OPeol_qty:
126 r=p; break;
127 case OPval: case OPvalm: r= (void *) (((char *)p)+(sizeof(itemop_t)+sizeof(eqntokenval_t) )) ; break;
128 case OPlit: case OPlitm:
129 case OPlitv: case OPlitvm: r= (void *) (((char *)p)+(sizeof(itemop_t)+sizeof(eqntokenlit_t) )) ; break;
130 default: r= (void *) (((char *)p)+(sizeof(itemop_t))) ; break;
132 return r;
135 eqntoken_t *eqntoken_last(eqntoken_t *p)
137 eqntoken_t *r=p;
139 while(!OP_ISEND(p->op))p=eqntoken_next(p);
141 switch(p->op)
143 case OPeol_const:
144 r= (void *) (((char *)p)+(sizeof(itemop_t)+sizeof(eqntokenval_t))) ; break;
145 case OPeol_valp:
146 r= (void *) (((char *)p)+(sizeof(itemop_t)+sizeof(eqntokenpval_t))) ; break;
147 case OPeolist:
148 r= (void *) (((char *)p)+(sizeof(itemop_t))) ; break;
149 case OPeol_qty:
150 assert(0);
151 default:
152 assert(0);
154 return r;
156 #endif
158 static float float_parse(uchar *val, int *count)
160 float v=0.0,sign=1,sig=0,rest=0;
161 int i,offset=0;
162 uchar *ps=NULL,*pa=NULL,*pb=NULL,*tmpc;
163 uchar a;
165 for(ps=val;(isspace(ps[0]))&&(ps[0]!=0);ps++);
166 if(ps[(unsigned)0]=='-') { sign=-1; pa=ps+1; }
167 else if(ps[(unsigned)0]=='+') { sign=1; pa=ps+1; }
168 else pa=ps;
170 if(pa[(unsigned)0]=='.'){ sig=0; pb=pa+1; }
171 else
172 if(isdigit(pa[(unsigned)0]))
174 sig=atoi(pa);
175 for(pb=pa;pb[0]!=0;pb++)
176 if(!isdigit(pb[0])) break;
179 if(pb==NULL){ return -1e99; }
180 if(pb[0]=='.')
181 pb++;
183 i=0;
185 if(isdigit(pb[0]))
187 rest=atoi(pb);
188 for(i=0;pb[i]!=0;i++)
190 if(!isdigit(pb[i]))break;
191 rest=rest*0.1;
195 v=(sig+rest)*sign;
196 offset=pb+i+1-val;
199 switch(pb[i])
201 case 'f': v*=1e-15; break;
202 case 'p': v*=1e-12; break;
203 case 'n': v*=1e-9; break;
204 case 'u': v*=1e-6; break;
205 case 'm': v*=1e-3; break;
206 case 'x': v*=1e6; break;
207 case 'e': v*=pow(10.0,(float)atoi(pb+i+1));
208 for(tmpc=pb+i+1;isdigit(tmpc[0]);tmpc++);
209 offset=tmpc-val;
210 break;
211 case 0: offset--; break;
212 case ' ': offset--; break;
213 default: offset--; break; /* dont eat this char */
216 /* this is for the case of '5fF' where we have some trailing alpha chars for units which
217 must be discarded so the parser doesn't get confused
219 while((a=val[offset])!=0)
221 if(isalpha(a))offset++;
222 else break;
225 D(10,fprintf(stderr,"%s = %e\n",val,v));
226 if(count!=NULL)*count=offset;
227 return v;
230 #ifndef NO_EQUATIONS
231 static int eqntoken_parse(eqntop_t *top)
233 eqntoken_t *node;
234 char *p=top->str;
235 int i=0;
236 int uselast=1;
237 char c;
238 int r=1;
240 if(isspace(top->last)||(top->last==0))uselast=0;
242 if(!uselast)
244 for(p=top->str;(isspace(p[0]))&&(p[0]!=0);p++);
245 c=p[0];
247 else c=top->last;
248 top->last=0;
250 if(top->nodep>=MAXEQNSTACK)return 0;
252 node=top->nodes+top->nodep++;
253 node->z.lit.lit=NULL;
254 switch(c)
256 case EQN_DELIM: if(!uselast)top->str++; /* fall through */
257 case 0: node->op=OPeolist; r=0; break;
258 case '+': node->op=OPadd; if(!uselast)top->str++; top->opc++; break;
259 case '-': node->op=OPsub; if(!uselast)top->str++; top->opc++; break;
260 case '*': node->op=OPmul; if(!uselast)top->str++; top->opc++; break;
261 case '/': node->op=OPdiv; if(!uselast)top->str++; top->opc++; break;
262 case '^': node->op=OPexp; if(!uselast)top->str++; top->opc++; break;
263 case '(': node->op=OPopen; if(!uselast)top->str++; top->opc++; break;
264 case ')': node->op=OPclose; if(!uselast)top->str++; top->opc++; break;
266 default:
267 if(isdigit(p[0]))
269 int count=0;
270 node->z.val.x=float_parse(p,&count);
271 node->op=OPval;
272 top->str=p+count;
274 else
276 for(i=0;p[i]!=0;i++)
277 if(strchr("\'+-/*^\n\r()",p[i])!=NULL)break;
278 top->last=p[i];
279 p[i]=0;
280 if( (top->last==0) || (top->last==EQN_DELIM)) { r=0; top->str=p+i; }
281 else top->str=p+i+1;
283 assert(uselast==0);
284 /* can never have alphanumeral followed by alphanumeral without some delimiter,
285 since it would just become one big identifer
287 node->z.lit.ref=eqn_litref_INIT;
288 node->z.lit.cache=0.0;
289 node->z.lit.lit=p;
290 node->op=OPlit;
293 top->litc++;
295 break;
297 return r;
301 /* this code assumes dependencies have already been cached, see eqnlist.c */
302 static int token_value(eqntoken_t *token, float *v)
304 int r=0;
305 float a=0.0;
306 switch(token->op)
308 case OPeol_valp:
309 if(token->z.pval.xp!=NULL)
310 a=*(token->z.pval.xp);
311 else r++;
312 D(3,fprintf(stderr,"loaded pval=(%p->%g)\n",token->z.pval.xp,a));
313 break;
314 case OPeol_const: a=token->z.val.x; break;
315 case OPlit: a= 0.0; r++; break;
316 case OPlitm: a=-0.0; r++; break;
317 case OPlitv: a= token->z.lit.cache; break;
318 case OPlitvm: a=-(token->z.lit.cache); break;
319 case OPval: a= token->z.val.x; break;
320 case OPvalm: a=-(token->z.val.x); break;
321 default: assert(0);
323 *v=a;
324 return r;
326 #define PUSH(a) do { if(data->stackp<MAXSTACK) data->stack[data->stackp++]=(a); \
327 D(5,fprintf(stderr,"Push(%g) new stackp=%i\n",(a),data->stackp)); } while (0)
328 #define POP(a) do { if(data->stackp>0) (a)=data->stack[--(data->stackp)]; \
329 D(5,fprintf(stderr,"Pop(%g) new stackp=%i\n",(a),data->stackp)); } while (0)
331 static int eqntoken_eval(eqneval_t *data)
333 int loop,toend;
334 int r=0;
335 float a,b;
336 eqntoken_t *token,*lp;
337 int i;
339 static const int precidence[]=OPprecidence;
340 static const int type[]=OPtype;
342 int types[4]={ -10 , -10 , -10 , -10 };
343 int precs[4]={ -10, -10 , -10, -10 };
344 int stack_entry=data->stackp;
346 toend=0;
349 itemop_t ops[4]={OPeolist, OPeolist, OPeolist, OPeolist};
350 eqntoken_t *tokens[4]={ NULL, NULL, NULL, NULL };
352 loop=0;
353 token=data->list;
354 data->list=eqntoken_next(data->list);
355 if(data->list==token)
356 toend++; /* catch endings */
358 for(lp=token,i=0;(i<4);i++,lp=eqntoken_next(lp)) /* lookahead */
360 ops[i]=lp->op;
361 tokens[i]=lp;
362 assert(ops[i]>=0);
363 assert((ops[i]*sizeof(int))<sizeof(precidence));
364 assert((ops[i]*sizeof(int))<sizeof(type));
365 types[i]=type[ops[i]];
366 precs[i]=precidence[ops[i]];
367 if(OP_ISEND(lp->op)) /* we did last token, stop */
368 break;
371 D(8,fprintf(stderr,"Eval: lookahead = "));
372 for(i=0;i<4;i++)
374 char *syms[]=OPsyms;
375 D(8,fprintf(stderr," %s,t%i,p%i" ,syms[ops[i]],types[i],precs[i]));
377 D(8,fprintf(stderr,"\n"));
379 if(OP_ISANYV(token->op))
381 r=token_value(token,&a);
382 D(5,fprintf(stderr,"Value: %g\n",a));
383 PUSH(a);
386 else
388 if(types[0]==2) /* binary op */
390 a=1.0; b=1.0;
391 POP(a);
393 if( /* literal and higher precidence operator after literal not () */
394 (OP_ISV(ops[1]) && (precs[2] > precs[0]) && (types[2]!=4) ) ||
396 /* operator (ie open/close) which has a higher precidence */
397 ((types[1]>=2) && (precs[1] > precs[0]))
400 { /* SHIFT */
401 D(6,fprintf(stderr,"Shift: recursion\n"));
403 eqntoken_eval(data);
406 POP(b);
408 else /* REDUCE */
410 D(6,fprintf(stderr,"Reduce: \n"));
411 if( OP_ISANYV(ops[1]) )
413 data->list=eqntoken_next(data->list);
414 r+=token_value(tokens[1],&b);
417 else { /* error, need literal */ assert(0); }
420 D(6,fprintf(stderr,"Doing Binary Op, %g op %g \n",a,b));
421 switch(token->op)
423 case OPadd: a=a+b; break;
424 case OPsub: a=a-b; break;
425 case OPmul: a=a*b; break;
426 case OPdiv:
427 if(b!=0.0) a=a/b;
428 else a=0.0;
429 break;
431 case OPexp: a=pow(a,b); break;
433 default: assert(0);
435 PUSH(a);
438 else
439 if(types[0]==4) /* open/close */
441 if(token->op==OPopen)
443 D(6,fprintf(stderr,"open { : \n"));
444 loop=1;
446 else if(token->op==OPclose)
448 D(6,fprintf(stderr,"close } : returning \n"));
449 return 0;
453 else if(token->op == OPeolist);
455 if(toend) { D(6,fprintf(stderr,"Ending: \n")); return 0; }
456 else
458 D(6,fprintf(stderr,"Stack: entry=%i now=%i %s \n",stack_entry,data->stackp,
459 ((stack_entry<data->stackp)||loop)?"looping":"returning"));
462 while((stack_entry<data->stackp)||loop);
463 return r;
466 #undef PUSH
467 #undef POP
470 eqntoken_t *eqntok_parse(char *str)
472 eqn_t eq;
473 int i,j,qlit,qval,qvalp;
474 int last_was_op;
475 int type[]=OPtype;
476 eqntoken_t *list,*lp,*lpn;
477 eqntop_t data;
478 eqntoken_t *cp,*np;
479 data.nodep=0;
480 data.litc=0;
481 data.opc=0;
482 data.last=0;
483 data.str=str;
485 D(2,fprintf(stderr,"Parsing [%s]\n",str));
486 while(eqntoken_parse(&data));
488 for(i=0,qval=0,qlit=0,qvalp=0,j=0;i<data.nodep;i++)
490 switch(data.nodes[i].op)
492 case OPlit:
493 case OPlitm:
494 qlit++; break;
495 case OPval:
496 case OPvalm:
497 case OPeol_const:
498 qval++; break;
499 case OPeol_valp:
500 qvalp++; break;
501 default: break;
503 j++;
506 if((qval==1) && (qlit==0) && (qvalp==0) ) /* optimization for single constant, don't store eolist */
508 eq=eqn_const(data.nodes[0].z.val.x);
509 lp=list=eq.eqn;
511 else if((qvalp==1) && (qlit==0) && (qval==0) )
513 eq=eqn_valp(data.nodes[0].z.pval.xp);
514 lp=list=eq.eqn;
516 else if((qvalp==0) && (qlit==0) && (qval==0) )
518 /* it appears we have a parse error, no equation is possible */
519 lp=list=NULL;
520 fprintf(stderr,"Invalid Equation \n");
521 assert(0);
523 else
525 lp=list=eqn_malloc((sizeof(itemop_t)*(j+1)) + (sizeof(eqntokenlit_t)*(qlit)) + (sizeof(eqntokenval_t)*(qval)));
527 for(last_was_op=1,i=j=0;i<data.nodep;i++)
529 cp=data.nodes+i;
530 if((i+1)<data.nodep)
532 np=data.nodes+i+1;
533 if( (last_was_op) && (cp->op==OPsub) && (type[np->op]==1) )
535 np->op++; /* go from OPxxx to OPxxxm */
536 last_was_op=0;
537 continue;
540 if(type[cp->op]>1)
541 last_was_op=1;
542 else last_was_op=0;
544 lp->op=cp->op;
545 lpn=eqntoken_next(lp);
546 memcpy(lp,cp,((char *)lpn)-((char *)lp));
547 lp=lpn;
549 /* list[j++]=cp[0]; */
551 /*memcpy(list,data.nodes,data->nodep*sizeof(eqntok_t));*/
552 lp->op=OPeolist;
553 /* list[j].op=OPeolist; */
556 D(7,
557 do {
558 char *syms[]=OPsyms;
559 fprintf(stderr, "eqnparse: %i tokens %p ", data.nodep,lp);
560 for(lp=list;!OP_ISEND(lp->op);lp=eqntoken_next(lp))
561 fprintf(stderr, "%s ",syms[lp->op]);
562 fprintf(stderr, "%s ",syms[lp->op]);
563 fprintf(stderr,"\n");
564 } while (0)
567 return list;
571 /* returns 0 if equation can be evaluated */
572 int eqntok_depend(eqntoken_t *list, plookup_t *lookup)
574 int q=0;
575 eqn_litref_t vp;
576 eqntoken_t *lp;
578 if(list->op==OPeol_const)return 0; /*optimization */
579 assert(lookup!=NULL);
581 for(lp=list;!OP_ISEND(lp->op);lp=eqntoken_next(lp))
583 if((lp->op==OPlit)||(lp->op==OPlitm))
585 D(3,fprintf(stderr,"eqntok_depend: Looking up %s\n",lp->z.lit.lit));
586 if((vp=lookup->lookup(lookup,lp->z.lit.lit))!=eqn_litref_INIT)
588 lp->z.lit.ref=vp;;
589 lp->op=(lp->op==OPlit)?OPlitv:OPlitvm;
591 else q++;
594 return q;
597 /* only evaluate after eqntok_depend, and
598 call eqntok_eval IN PROPER ORDER
599 returns 0 if eval ok, 1 if broken dependency, 2 on parse error
602 int eqntok_eval(float *res, eqntoken_t *list)
604 eqntoken_t *lp;
605 eqneval_t data;
606 memset(&data,0,sizeof(data));
607 data.stack[(data.stackp=0)]=0.0;
608 data.stackp++;
609 data.list=list;
611 eqn_t v;
612 v.eqn=list;
613 D(3,debug_eqn(stderr,"Evaluating ",&v));
614 D(3,fprintf(stderr,"\n"));
616 for(lp=list;!OP_ISEND(lp->op);lp=eqntoken_next(lp))
618 if(lp->op==OPlit)return 1;
621 eqntoken_eval(&data);
623 if(res!=NULL)
624 *res=data.stack[1];
626 if(data.stackp==2)return 0;
627 else return 2;
632 eqntoken_t *eqntok_copy(eqntoken_t *p)
634 int q;
635 eqntoken_t *np;
636 np=eqntoken_last(p);
637 q=((char *)np)-((char *)p);
638 np=eqn_malloc(q);
639 assert(np!=NULL);
640 memcpy(np,p,q);
641 return np;
645 eqntoken_t *eqntok_copy_m(eqntoken_t *p, float m)
647 int q;
648 eqntoken_t *np,*nnp;
650 if(p->op==OPeol_const) /* common case */
652 np=eqn_malloc(sizeof(itemop_t)+sizeof(eqntokenval_t));
653 np->op=OPeol_const;
654 np->z.val.x=m*p->z.val.x;
656 else /* build np = m*(old_equation)EOL */
658 np=eqntoken_last(p);
659 q=((char *)np)-((char *)p);
661 np=eqn_malloc(q+(sizeof(itemop_t)*4)+sizeof(eqntokenval_t));
662 nnp=np;
663 nnp->op=OPval;
664 nnp->z.val.x=m;
665 nnp=eqntoken_next(nnp);
666 nnp->op=OPmul;
667 nnp=eqntoken_next(nnp);
668 nnp->op=OPopen;
669 nnp=eqntoken_next(nnp);
670 memcpy(nnp,p,q);
671 nnp=(void *) (((char *)nnp)+q-sizeof(itemop_t));
672 nnp->op=OPclose;
673 nnp=eqntoken_next(nnp);
674 nnp->op=OPeolist;
676 return np;
679 #endif
683 void debug_eqn(void *dbg_fp, char *str, eqn_t *eqn)
685 FILE *dbg=dbg_fp;
686 #ifdef NO_EQUATIONS
687 if(eqn==NULL)return;
688 fprintf(dbg,"%g",eqn->val);
689 #else
690 eqntoken_t *eqt;
691 if(eqn==NULL)return;
692 if(0)fprintf(dbg," %s=[%p %p]",str,eqn,eqn->eqn);
693 else fprintf(dbg," %s=",str);
694 if(eqn->eqn!=NULL)
696 char s=' ';
697 for(eqt=eqn->eqn;!OP_ISEND(eqt->op);eqt=eqntoken_next(eqt))
699 switch(eqt->op)
701 case OPlitm:
702 s='-';
703 case OPlit:
704 fprintf(dbg,"(%c%s)",s,eqt->z.lit.lit); break;
705 case OPvalm:
706 s='-';
707 case OPval:
708 fprintf(dbg,"(%c%g)",s,eqt->z.val.x); break;
709 case OPlitvm:
710 s='-';
711 case OPlitv:
712 fprintf(dbg,"(%c%s=%i)",s,eqt->z.lit.lit,eqt->z.lit.ref); break;
714 case OPadd: fprintf(dbg,"+"); break;
715 case OPsub: fprintf(dbg,"-"); break;
716 case OPmul: fprintf(dbg,"*"); break;
717 case OPdiv: fprintf(dbg,"/"); break;
718 case OPexp: fprintf(dbg,"^"); break;
719 case OPopen: fprintf(dbg,"{"); break;
720 case OPclose: fprintf(dbg,"}"); break;
721 default: break;
724 if(eqt->op==OPeol_const)
725 fprintf(dbg,"%g",eqt->z.val.x);
726 if(eqt->op==OPeol_valp)
727 fprintf(dbg,"%p->%g",eqt->z.pval.xp, (eqt->z.pval.xp==NULL)?0.0:*(eqt->z.pval.xp));
729 #endif
740 eqn_t eqn_const(float val)
742 eqn_t eqn;
743 #ifdef NO_EQUATIONS
744 eqn.val=val;
745 #else
746 eqn.eqn=eqn_malloc(sizeof(itemop_t)+sizeof(eqntokenval_t));
747 eqn.eqn->op=OPeol_const;
748 eqn.eqn->z.val.x=val;
749 #endif
750 return eqn;
753 eqn_t eqn_valp(float *valp)
755 eqn_t r;
756 #ifdef NO_EQUATIONS
757 r.val=0.0;
758 #else
759 r.eqn=eqn_malloc(sizeof(itemop_t)+sizeof(eqntokenpval_t));
760 r.eqn->z.pval.xp=valp;
761 r.eqn->op=OPeol_valp;
762 #endif
763 return r;
767 eqn_t eqn_undefined(void)
769 return eqn_valp(NULL);
772 int eqn_is_undefined(eqn_t e)
774 #ifdef NO_EQUATIONS
775 return 0;
776 #else
777 if(e.eqn==NULL)
778 return 1;
779 if(e.eqn->op==OPeol_valp)
780 return 2;
781 return 0;
782 #endif
786 eqn_t eqn_copy(eqn_t e)
788 #ifdef NO_EQUATIONS
789 return e;
790 #else
791 if(e.eqn!=NULL)
792 e.eqn=eqntok_copy(e.eqn);
793 return e;
794 #endif
797 eqn_t eqn_copy_m(eqn_t e, float m)
799 #ifdef NO_EQUATIONS
800 e.val*=m;
801 return e;
802 #else
803 if(e.eqn!=NULL)
805 if(m==1.0) /* multiplication by 1 is a nop */
806 e.eqn=eqntok_copy(e.eqn);
807 else
808 e.eqn=eqntok_copy_m(e.eqn,m);
810 return e;
811 #endif
814 eqn_t eqn_parse(uchar *val)
816 eqn_t eqn;
817 #ifdef NO_EQUATIONS
818 eqn.val=float_parse(val,NULL);
819 #else
820 eqn.eqn=eqntok_parse(val);
821 #endif
822 return eqn;
825 float parse_float(uchar *val)
827 return float_parse(val,NULL);
831 /* this is valid ONLY if we have no literals, ie (6+3*5) */
832 /* use eqnl_eval for equations like (lambda*5+delta) */
834 float eqn_getval_(eqn_t *eqn)
836 #ifdef NO_EQUATIONS
837 assert(eqn!=NULL);
838 return eqn->val;
839 #else
840 float f;
841 assert(eqn!=NULL);
842 assert(eqn->eqn!=NULL);
843 if(eqn->eqn->op==OPeol_const)
844 return eqn->eqn->z.val.x;
845 f=0.0;
846 eqntok_eval(&f,eqn->eqn);
847 return f;
848 #endif
851 eqn_t eqn_empty(void)
853 eqn_t r;
854 #ifdef NO_EQUATIONS
855 r.val=0.0;
856 #else
857 r.eqn=NULL;
858 #endif
859 return r;
862 float eqn_setval(eqn_t *eqn, float val)
864 assert(eqn!=NULL);
865 #ifdef NO_EQUATIONS
866 return (eqn->val=val);
867 #else
868 if(eqn->eqn==NULL)
869 *eqn=eqn_const(val);
870 else
871 if(eqn->eqn->op==OPeol_const)
872 eqn->eqn->z.val.x=val;
873 else
875 D(1,debug_eqn(stderr, "cannot change eqn",eqn));
876 D(1,fprintf(stderr,"\n"));
877 assert(0);
879 return val;
880 #endif
883 float eqn_setvalp(eqn_t *eqn, float *valp)
885 assert(eqn!=NULL);
887 #ifdef NO_EQUATIONS
888 return (eqn->val=*valp);
889 #else
890 if(eqn->eqn==NULL)
891 *eqn=eqn_valp(valp);
892 else
893 if(eqn->eqn->op==OPeol_valp)
894 eqn->eqn->z.pval.xp=valp;
895 else
897 D(1,debug_eqn(stderr, "cannot set valp",eqn));
898 D(1,fprintf(stderr,"\n"));
899 assert(0);
901 return *valp;
902 #endif