Expression.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1996-2017 The Squid Software Foundation and contributors
3  *
4  * Squid software is distributed under GPLv2+ license and includes
5  * contributions from numerous individuals and organizations.
6  * Please see the COPYING and CONTRIBUTORS files for details.
7  */
8 
9 /* DEBUG: section 86 ESI processing */
10 
11 #include "squid.h"
12 #include "Debug.h"
13 #include "esi/Expression.h"
14 #include "profiler/Profiler.h"
15 
16 #include <cerrno>
17 #include <cmath>
18 
19 /* stack precedence rules:
20  * before pushing an operator onto the stack, the
21  * top 2 elements are checked. if either has a higher
22  * or equal precedence than the current operator, they
23  * are evaluated.
24  * Start of expression has 5 precedence,
25  * end of expression has 0 precedence
26  * literal has 1 as does expression results
27  * | has 2
28  * & has 3
29  * ! has 4
30  * == != < > <= >= has 5
31  * ( has 5
32  * ) has 0
33  */
34 
35 typedef struct _stackmember stackmember;
36 
37 typedef int evaluate(stackmember * stack, int *depth, int whereAmI,
38  stackmember * candidate);
39 
40 typedef enum {
54  ESI_EXPR_EXPR /* the result of an expr PRI 1 */
55 } evaltype;
56 
57 typedef enum {
63 } literalhint;
64 
65 struct _stackmember {
67  union {
68  char *string;
69  double floating;
70  int integral;
71  } value;
75 };
76 
77 static void cleanmember(stackmember *);
78 static void stackpop(stackmember * s, int *depth);
79 
80 void
82 {
83  if (s->valuetype == ESI_EXPR_LITERAL
86  s->value.string = NULL;
87  }
88 
89 }
90 
91 void
92 stackpop(stackmember * s, int *depth)
93 {
94  if (!(*depth)--)
95  return;
96 
97  cleanmember(&s[*depth]);
98 }
99 
113 static void dumpstack(stackmember * stack, int depth);
114 static int addmember(stackmember * stack, int *stackdepth,
115  stackmember * candidate);
116 static int membercompare(stackmember a, stackmember b);
117 static char const *trim(char const *s);
118 static stackmember getsymbol(const char *s, char const **endptr);
119 
120 /* -2 = failed to compate
121  * -1 = a less than b
122  * 0 = a equal b
123  * 2 - a more than b
124  */
125 int
127 {
128  /* we can compare: sub expressions to sub expressions ,
129  * literals to literals
130  */
131 
135  return -2;
136 
137  if (a.valuetype == ESI_EXPR_EXPR) {
138  if (a.value.integral == b.value.integral)
139  return 0;
140  else
141  return 1;
142  } else if (a.valuestored == ESI_LITERAL_STRING) {
143  if (b.valuestored == ESI_LITERAL_STRING) {
144  int i =strcmp(a.value.string, b.value.string);
145 
146  if (i < 0)
147  return -1;
148 
149  if (i > 0)
150  return 1;
151 
152  return 0;
153  } else {
154  /* TODO: numeric to string conversion ? */
155  debugs(86, DBG_IMPORTANT, "strcmp with non-string");
156  return -2;
157  }
158  } else if (a.valuestored == ESI_LITERAL_FLOAT) {
159  if (b.valuestored == ESI_LITERAL_INT) {
160  if (fabs(a.value.floating - b.value.integral) < 0.00001)
161  return 0;
162  else if (a.value.floating < b.value.integral)
163  return -1;
164  else
165  return 1;
166  } else if (b.valuestored == ESI_LITERAL_FLOAT) {
167  if (a.value.floating == b.value.floating)
168  return 0;
169  else if (a.value.floating < b.value.floating)
170  return -1;
171  else
172  return 1;
173  } else {
174  /* TODO: attempt numeric converson again? */
175  debugs(86, DBG_IMPORTANT, "floatcomp with non float or int");
176  return -2;
177  }
178  } else if (a.valuestored == ESI_LITERAL_INT) {
179  if (b.valuestored == ESI_LITERAL_INT) {
180  if (a.value.integral == b.value.integral)
181  return 0;
182  else if (a.value.integral < b.value.integral)
183  return -1;
184  else
185  return 1;
186  } else if (b.valuestored == ESI_LITERAL_FLOAT) {
187  if (fabs(a.value.integral - b.value.floating) < 0.00001)
188  return 0;
189  else if (a.value.integral < b.value.floating)
190  return -1;
191  else
192  return 1;
193  } else {
194  /* TODO: attempt numeric converson again? */
195  debugs(86, DBG_IMPORTANT, "intcomp vs non float non int");
196  return -2;
197  }
198  }
199 
200  return -2;
201 }
202 
203 /* return 0 on success, 1 on failure */
204 int
205 evalnegate(stackmember * stack, int *depth, int whereAmI, stackmember * candidate)
206 {
207  if (whereAmI != *depth - 2)
208  /* invalid stack */
209  return 1;
210 
211  if (stack[whereAmI + 1].valuetype != ESI_EXPR_EXPR)
212  /* invalid operand */
213  return 1;
214 
215  /* copy down */
216  --(*depth);
217 
218  stack[whereAmI] = stack[(*depth)];
219 
220  cleanmember(candidate);
221 
222  if (stack[whereAmI].value.integral == 1)
223  stack[whereAmI].value.integral = 0;
224  else
225  stack[whereAmI].value.integral = 1;
226 
227  return 0;
228 }
229 
230 int
231 evalliteral(stackmember * stack, int *depth, int whereAmI, stackmember * candidate)
232 {
233  debugs(86, DBG_IMPORTANT, "attempt to evaluate a literal");
234  /* literals can't be evaluated */
235  return 1;
236 }
237 
238 int
239 evalexpr(stackmember * stack, int *depth, int whereAmI, stackmember * candidate)
240 {
241  debugs(86, DBG_IMPORTANT, "attempt to evaluate a sub-expression result");
242  /* sub-scpr's can't be evaluated */
243  return 1;
244 }
245 
246 int
247 evalor(stackmember * stack, int *depth, int whereAmI, stackmember * candidate)
248 {
249  int rv;
250  stackmember srv;
251 
252  if (*depth < 3)
253  /* Not enough operands */
254  return 1;
255 
256  if (whereAmI != *depth - 2)
257  /* invalid stack */
258  return 1;
259 
260  if (stack[whereAmI + 1].valuetype != ESI_EXPR_EXPR ||
261  stack[whereAmI - 1].valuetype != ESI_EXPR_EXPR)
262  /* invalid operand */
263  return 1;
264 
265  rv = stack[whereAmI - 1].value.integral || stack[whereAmI + 1].value.integral;
266 
267  stackpop(stack, depth); /* arg rhs */
268 
269  stackpop(stack, depth); /* me */
270 
271  stackpop(stack, depth); /* arg lhs */
272 
273  srv.valuetype = ESI_EXPR_EXPR;
274 
275  srv.eval = evalliteral;
276 
278 
279  srv.value.integral = rv ? 1 : 0;
280 
281  srv.precedence = 1;
282 
283  stack[(*depth)++] = srv;
284 
285  /* we're out of way, try adding now */
286  if (!addmember(stack, depth, candidate))
287  /* Something wrong upstream */
288  return 1;
289 
290  return 0;
291 }
292 
293 int
294 evaland(stackmember * stack, int *depth, int whereAmI, stackmember * candidate)
295 {
296  int rv;
297  stackmember srv;
298 
299  if (*depth < 3)
300  /* Not enough operands */
301  return 1;
302 
303  if (whereAmI != *depth - 2)
304  /* invalid stack */
305  return 1;
306 
307  if (stack[whereAmI + 1].valuetype != ESI_EXPR_EXPR ||
308  stack[whereAmI - 1].valuetype != ESI_EXPR_EXPR)
309  /* invalid operand */
310  return 1;
311 
312  rv = stack[whereAmI - 1].value.integral && stack[whereAmI + 1].value.integral;
313 
314  stackpop(stack, depth); /* arg rhs */
315 
316  stackpop(stack, depth); /* me */
317 
318  stackpop(stack, depth); /* arg lhs */
319 
320  srv.valuetype = ESI_EXPR_EXPR;
321 
322  srv.eval = evalexpr;
323 
325 
326  srv.value.integral = rv ? 1 : 0;
327 
328  srv.precedence = 1;
329 
330  stack[(*depth)++] = srv;
331 
332  /* we're out of way, try adding now */
333  if (!addmember(stack, depth, candidate))
334  /* Something wrong upstream */
335  return 1;
336 
337  return 0;
338 }
339 
340 int
341 evallesseq(stackmember * stack, int *depth, int whereAmI, stackmember * candidate)
342 {
343  int rv;
344  stackmember srv;
345 
346  if (*depth < 3)
347  /* Not enough operands */
348  return 1;
349 
350  if (whereAmI != *depth - 2)
351  /* invalid stack */
352  return 1;
353 
354  rv = membercompare(stack[whereAmI - 1], stack[whereAmI + 1]);
355 
356  if (rv == -2)
357  /* invalid comparison */
358  return 1;
359 
360  stackpop(stack, depth); /* arg rhs */
361 
362  stackpop(stack, depth); /* me */
363 
364  stackpop(stack, depth); /* arg lhs */
365 
366  srv.valuetype = ESI_EXPR_EXPR;
367 
368  srv.eval = evalexpr;
369 
371 
372  srv.value.integral = rv <= 0 ? 1 : 0;
373 
374  srv.precedence = 1;
375 
376  stack[(*depth)++] = srv;
377 
378  /* we're out of way, try adding now */
379  if (!addmember(stack, depth, candidate))
380  /* Something wrong upstream */
381  return 1;
382 
383  /* debugs(86, DBG_IMPORTANT, "?= " << srv.value.integral << " "); */
384  return 0;
385 
386 }
387 
388 int
389 evallessthan(stackmember * stack, int *depth, int whereAmI, stackmember * candidate)
390 {
391  int rv;
392  stackmember srv;
393 
394  if (*depth < 3)
395  /* Not enough operands */
396  return 1;
397 
398  if (whereAmI != *depth - 2)
399  /* invalid stack */
400  return 1;
401 
402  rv = membercompare(stack[whereAmI - 1], stack[whereAmI + 1]);
403 
404  if (rv == -2)
405  /* invalid comparison */
406  return 1;
407 
408  stackpop(stack, depth); /* arg rhs */
409 
410  stackpop(stack, depth); /* me */
411 
412  stackpop(stack, depth); /* arg lhs */
413 
414  srv.valuetype = ESI_EXPR_EXPR;
415 
416  srv.eval = evalexpr;
417 
419 
420  srv.value.integral = rv < 0 ? 1 : 0;
421 
422  srv.precedence = 1;
423 
424  stack[(*depth)++] = srv;
425 
426  /* we're out of way, try adding now */
427  if (!addmember(stack, depth, candidate))
428  /* Something wrong upstream */
429  return 1;
430 
431  /* debugs(86, DBG_IMPORTANT, "?= " << srv.value.integral << " "); */
432  return 0;
433 
434 }
435 
436 int
437 evalmoreeq(stackmember * stack, int *depth, int whereAmI, stackmember * candidate)
438 {
439  int rv;
440  stackmember srv;
441 
442  if (*depth < 3)
443  /* Not enough operands */
444  return 1;
445 
446  if (whereAmI != *depth - 2)
447  /* invalid stack */
448  return 1;
449 
450  rv = membercompare(stack[whereAmI - 1], stack[whereAmI + 1]);
451 
452  if (rv == -2)
453  /* invalid comparison */
454  return 1;
455 
456  stackpop(stack, depth); /* arg rhs */
457 
458  stackpop(stack, depth); /* me */
459 
460  stackpop(stack, depth); /* arg lhs */
461 
462  srv.valuetype = ESI_EXPR_EXPR;
463 
464  srv.eval = evalexpr;
465 
467 
468  srv.value.integral = rv >= 0 ? 1 : 0;
469 
470  srv.precedence = 1;
471 
472  stack[(*depth)++] = srv;
473 
474  /* we're out of way, try adding now */
475  if (!addmember(stack, depth, candidate))
476  /* Something wrong upstream */
477  return 1;
478 
479  /* debugs(86, DBG_IMPORTANT, "?= " << srv.value.integral << " "); */
480  return 0;
481 
482 }
483 
484 int
485 evalmorethan(stackmember * stack, int *depth, int whereAmI, stackmember * candidate)
486 {
487  int rv;
488  stackmember srv;
489 
490  if (*depth < 3)
491  /* Not enough operands */
492  return 1;
493 
494  if (whereAmI != *depth - 2)
495  /* invalid stack */
496  return 1;
497 
498  rv = membercompare(stack[whereAmI - 1], stack[whereAmI + 1]);
499 
500  if (rv == -2)
501  /* invalid comparison */
502  return 1;
503 
504  stackpop(stack, depth); /* arg rhs */
505 
506  stackpop(stack, depth); /* me */
507 
508  stackpop(stack, depth); /* arg lhs */
509 
510  srv.valuetype = ESI_EXPR_EXPR;
511 
512  srv.eval = evalexpr;
513 
515 
516  srv.value.integral = rv > 0 ? 1 : 0;
517 
518  srv.precedence = 1;
519 
520  stack[(*depth)++] = srv;
521 
522  /* we're out of way, try adding now */
523  if (!addmember(stack, depth, candidate))
524  /* Something wrong upstream */
525  return 1;
526 
527  /* debugs(86, DBG_IMPORTANT, "?= " << srv.value.integral << " "); */
528  return 0;
529 
530 }
531 
532 int
533 evalequals(stackmember * stack, int *depth, int whereAmI,
534  stackmember * candidate)
535 {
536  int rv;
537  stackmember srv;
538 
539  if (*depth < 3)
540  /* Not enough operands */
541  return 1;
542 
543  if (whereAmI != *depth - 2)
544  /* invalid stack */
545  return 1;
546 
547  rv = membercompare(stack[whereAmI - 1], stack[whereAmI + 1]);
548 
549  if (rv == -2)
550  /* invalid comparison */
551  return 1;
552 
553  stackpop(stack, depth); /* arg rhs */
554 
555  stackpop(stack, depth); /* me */
556 
557  stackpop(stack, depth); /* arg lhs */
558 
559  srv.valuetype = ESI_EXPR_EXPR;
560 
561  srv.eval = evalexpr;
562 
564 
565  srv.value.integral = rv ? 0 : 1;
566 
567  srv.precedence = 1;
568 
569  stack[(*depth)++] = srv;
570 
571  /* we're out of way, try adding now */
572  if (!addmember(stack, depth, candidate))
573  /* Something wrong upstream */
574  return 1;
575 
576  /* debugs(86, DBG_IMPORTANT, "?= " << srv.value.integral << " "); */
577  return 0;
578 }
579 
580 int
581 evalnotequals(stackmember * stack, int *depth, int whereAmI, stackmember * candidate)
582 {
583  int rv;
584  stackmember srv;
585 
586  if (*depth < 3)
587  /* Not enough operands */
588  return 1;
589 
590  if (whereAmI != *depth - 2)
591  /* invalid stack */
592  return 1;
593 
594  rv = membercompare(stack[whereAmI - 1], stack[whereAmI + 1]);
595 
596  if (rv == -2)
597  /* invalid comparison */
598  return 1;
599 
600  stackpop(stack, depth); /* arg rhs */
601 
602  stackpop(stack, depth); /* me */
603 
604  stackpop(stack, depth); /* arg lhs */
605 
606  srv.valuetype = ESI_EXPR_EXPR;
607 
608  srv.eval = evalexpr;
609 
611 
612  srv.value.integral = rv ? 1 : 0;
613 
614  srv.precedence = 1;
615 
616  stack[(*depth)++] = srv;
617 
618  /* we're out of way, try adding now */
619  if (!addmember(stack, depth, candidate))
620  /* Something wrong upstream */
621  return 1;
622 
623  /* debugs(86, DBG_IMPORTANT, "?= " << srv.value.integral << " "); */
624  return 0;
625 }
626 
627 int
628 evalstartexpr(stackmember * stack, int *depth, int whereAmI, stackmember * candidate)
629 {
630  /* debugs(86, DBG_IMPORTANT, "?("); */
631 
632  if (whereAmI != *depth - 2)
633  /* invalid stack */
634  return 1;
635 
636  /* Only valid when RHS is an end bracket */
637  if (candidate->valuetype != ESI_EXPR_END)
638  return 1;
639 
640  --(*depth);
641 
642  stack[whereAmI] = stack[(*depth)];
643 
644  cleanmember(candidate);
645 
646  return 0;
647 }
648 
649 int
650 evalendexpr(stackmember * stack, int *depth, int whereAmI, stackmember * candidate)
651 {
652  /* Can't evaluate ) brackets */
653  return 1;
654 }
655 
656 char const *
657 trim(char const *s)
658 {
659  while (*s == ' ')
660  ++s;
661 
662  return s;
663 }
664 
666 getsymbol(const char *s, char const **endptr)
667 {
668  stackmember rv;
669  char *end;
670  char const *origs = s;
671  /* trim whitespace */
672  s = trim(s);
673  rv.eval = NULL; /* A literal */
676  rv.precedence = 1; /* A literal */
677 
678  if (('0' <= *s && *s <= '9') || *s == '-') {
679  size_t length = strspn(s, "0123456789.");
680  char const *point;
681 
682  if ((point = strchr(s, '.')) && point - s < (ssize_t)length) {
683  /* floating point */
684  errno=0; /* reset errno */
685  rv.value.floating = strtod(s, &end);
686 
687  if (s == end || errno) {
688  /* Couldn't convert to float */
689  debugs(86, DBG_IMPORTANT, "failed to convert '" << s << "' to float ");
690  *endptr = origs;
691  } else {
692  debugs(86,6, "found " << rv.value.floating << " of length " << end - s);
693  *endptr = end;
694  rv.eval = evalliteral;
697  rv.precedence = 1;
698  }
699  } else {
700  /* INT */
701  errno=0; /* reset errno */
702  rv.value.integral = strtol(s, &end, 0);
703 
704  if (s == end || errno) {
705  /* Couldn't convert to int */
706  debugs(86, DBG_IMPORTANT, "failed to convert '" << s << "' to int ");
707  *endptr = origs;
708  } else {
709  debugs(86,6, "found " << rv.value.integral << " of length " << end - s);
710  *endptr = end;
711  rv.eval = evalliteral;
714  rv.precedence = 1;
715  }
716  }
717  } else if ('!' == *s) {
718  if ('=' == *(s + 1)) {
719  debugs(86, 6, "found !=");
720  *endptr = s + 2;
721  rv.eval = evalnotequals;
723  rv.precedence = 5;
724  } else {
725  debugs(86, 6, "found !");
726  *endptr = s + 1;
727  rv.valuetype = ESI_EXPR_NOT;
728  rv.precedence = 4;
729  rv.eval = evalnegate;
730  }
731  } else if ('\'' == *s) {
732  char const *t = s + 1;
733  debugs(86, 6, "found \'");
734 
735  while (*t != '\'' && *t)
736  ++t;
737 
738  if (!*t) {
739  debugs(86, DBG_IMPORTANT, "missing end \' in '" << s << "'");
740  *endptr = origs;
741  } else {
742  *endptr = t + 1;
743  /* Special case for zero length strings */
744 
745  if (t - s - 1)
746  rv.value.string = xstrndup(s + 1, t - (s + 1) + 1);
747  else
748  rv.value.string = static_cast<char *>(xcalloc(1,1));
749 
750  rv.eval = evalliteral;
751 
753 
755 
756  rv.precedence = 1;
757 
758  debugs(86, 6, "found string '" << rv.value.string << "'");
759  }
760  } else if ('(' == *s) {
761  debugs(86, 6, "found subexpr start");
762  *endptr = s + 1;
764  rv.precedence = 5;
765  rv.eval = evalstartexpr;
766  } else if (')' == *s) {
767  debugs(86, 6, "found subexpr end");
768  *endptr = s + 1;
769  rv.valuetype = ESI_EXPR_END;
770  rv.precedence = 0;
771  rv.eval = evalendexpr;
772  } else if ('&' == *s) {
773  debugs(86, 6, "found AND");
774  *endptr = s + 1;
775  rv.valuetype = ESI_EXPR_AND;
776  rv.precedence = 3;
777  rv.eval = evaland;
778  } else if ('|' == *s) {
779  debugs(86, 6, "found OR");
780  *endptr = s + 1;
781  rv.valuetype = ESI_EXPR_OR;
782  rv.precedence = 2;
783  rv.eval = evalor;
784  } else if ('=' == *s) {
785  if ('=' == *(s + 1)) {
786  debugs(86, 6, "found equals");
787  *endptr = s + 2;
788  rv.valuetype = ESI_EXPR_EQ;
789  rv.precedence = 5;
790  rv.eval = evalequals;
791  } else {
792  debugs(86, DBG_IMPORTANT, "invalid expr '" << s << "'");
793  *endptr = origs;
794  }
795  } else if ('<' == *s) {
796  if ('=' == *(s + 1)) {
797  debugs(86, 6, "found less-equals");
798  *endptr = s + 2;
800  rv.precedence = 5;
801  rv.eval = evallesseq;
802  } else {
803  debugs(86, 6, "found less than");
804  *endptr = s + 1;
806  rv.precedence = 5;
807  rv.eval = evallessthan;
808  }
809  } else if ('>' == *s) {
810  if ('=' == *(s + 1)) {
811  debugs(86, 6, "found more-equals");
812  *endptr = s + 2;
814  rv.precedence = 5;
815  rv.eval = evalmoreeq;
816  } else {
817  debugs(86, 6, "found more than");
818  *endptr = s + 1;
820  rv.precedence = 5;
821  rv.eval = evalmorethan;
822  }
823  } else if (!strncmp(s, "false", 5)) {
824  debugs(86, 5, "getsymbol: found variable result 'false'");
825  *endptr = s + 5;
828  rv.value.integral = 0;
829  rv.precedence = 1;
830  rv.eval = evalexpr;
831  } else if (!strncmp(s, "true", 4)) {
832  debugs(86, 5, "getsymbol: found variable result 'true'");
833  *endptr = s + 4;
836  rv.value.integral = 1;
837  rv.precedence = 1;
838  rv.eval = evalexpr;
839  } else {
840  debugs(86, DBG_IMPORTANT, "invalid expr '" << s << "'");
841  *endptr = origs;
842  }
843 
844  return rv;
845 }
846 
847 static void
848 printLiteral(std::ostream &os, const stackmember &s)
849 {
850  switch (s.valuestored) {
851 
852  case ESI_LITERAL_INVALID:
853  os << " Invalid ";
854  break;
855 
856  case ESI_LITERAL_FLOAT:
857  os << s.value.floating;
858  break;
859 
860  case ESI_LITERAL_STRING:
861  os << '\'' << s.value.string << '\'';
862  break;
863 
864  case ESI_LITERAL_INT:
865  os << s.value.integral;
866  break;
867 
868  case ESI_LITERAL_BOOL:
869  os << (s.value.integral ? "true" : "false");
870  }
871 }
872 
873 static std::ostream &
874 operator <<(std::ostream &os, const stackmember &s)
875 {
876  switch (s.valuetype) {
877 
878  case ESI_EXPR_INVALID:
879  os << " Invalid ";
880  break;
881 
882  case ESI_EXPR_LITERAL:
883  printLiteral(os, s);
884  break;
885 
886  case ESI_EXPR_EXPR:
887  os << (s.value.integral ? "true" : "false");
888  break;
889 
890  case ESI_EXPR_OR:
891  os << "|";
892  break;
893 
894  case ESI_EXPR_AND:
895  os << "&";
896  break;
897 
898  case ESI_EXPR_NOT:
899  os << "!";
900  break;
901 
902  case ESI_EXPR_START:
903  os << "(";
904  break;
905 
906  case ESI_EXPR_END:
907  os << ")";
908  break;
909 
910  case ESI_EXPR_EQ:
911  os << "==";
912  break;
913 
914  case ESI_EXPR_NOTEQ:
915  os << "!=";
916  break;
917 
918  case ESI_EXPR_LESS:
919  os << "<";
920  break;
921 
922  case ESI_EXPR_LESSEQ:
923  os << "<=";
924  break;
925 
926  case ESI_EXPR_MORE:
927  os << ">";
928  break;
929 
930  case ESI_EXPR_MOREEQ:
931  os << ">=";
932  break;
933  }
934 
935  return os;
936 }
937 
938 void
939 dumpstack(stackmember * stack, int depth)
940 {
941  if (depth) {
942  std::ostringstream buf;
943  for (int i = 0; i < depth; ++i)
944  buf << stack[i];
945  debugs(86,1, buf.str());
946  }
947 }
948 
949 int
950 addmember(stackmember * stack, int *stackdepth, stackmember * candidate)
951 {
952  if (candidate->valuetype != ESI_EXPR_LITERAL && *stackdepth > 1) {
953  /* !(!(a==b))) is why thats safe */
954  /* strictly less than until we unwind */
955 
956  if (candidate->precedence < stack[*stackdepth - 1].precedence ||
957  candidate->precedence < stack[*stackdepth - 2].precedence) {
958  /* must be an operator */
959 
960  if (stack[*stackdepth - 2].valuetype == ESI_EXPR_LITERAL ||
961  stack[*stackdepth - 2].valuetype == ESI_EXPR_INVALID ||
962  stack[*stackdepth - 2].eval(stack, stackdepth,
963  *stackdepth - 2, candidate)) {
964  /* cleanup candidate and stack */
965  dumpstack(stack, *stackdepth);
966  cleanmember(candidate);
967  debugs(86, DBG_IMPORTANT, "invalid expression");
968  return 0;
969  }
970  } else {
971  stack[(*stackdepth)++] = *candidate;
972  }
973  } else if (candidate->valuetype != ESI_EXPR_INVALID)
974  stack[(*stackdepth)++] = *candidate;
975 
976  return 1;
977 }
978 
979 int
981 {
982  stackmember stack[20];
983  int stackdepth = 0;
984  char const *end;
985  PROF_start(esiExpressionEval);
986 
987  while (*s) {
988  stackmember candidate = getsymbol(s, &end);
989 
990  if (candidate.valuetype != ESI_EXPR_INVALID) {
991  assert(s != end);
992 
993  if (!addmember(stack, &stackdepth, &candidate)) {
994  PROF_stop(esiExpressionEval);
995  return 0;
996  }
997 
998  s = end;
999  } else {
1000  assert (s == end);
1001  debugs(86, DBG_IMPORTANT, "failed parsing expression");
1002  PROF_stop(esiExpressionEval);
1003  return 0;
1004  }
1005  }
1006 
1007  if (stackdepth > 1) {
1008  stackmember rv;
1010  rv.precedence = 0;
1011 
1012  if (stack[stackdepth - 2].
1013  eval(stack, &stackdepth, stackdepth - 2, &rv)) {
1014  /* special case - leading operator failed */
1015  debugs(86, DBG_IMPORTANT, "invalid expression");
1016  PROF_stop(esiExpressionEval);
1017  return 0;
1018  }
1019  }
1020 
1021  if (stackdepth == 0) {
1022  /* Empty expression - evaluate to false */
1023  PROF_stop(esiExpressionEval);
1024  return 0;
1025  }
1026 
1027  /* if we hit here, we think we have a valid result */
1028  assert(stackdepth == 1);
1029 
1030  assert(stack[0].valuetype == ESI_EXPR_EXPR);
1031 
1032  PROF_stop(esiExpressionEval);
1033 
1034  return stack[0].value.integral ? 1 : 0;
1035 }
1036 
static void stackpop(stackmember *s, int *depth)
Definition: Expression.cc:92
static char const * trim(char const *s)
Definition: Expression.cc:657
#define assert(EX)
Definition: assert.h:17
static evaluate evalexpr
Definition: Expression.cc:112
#define xcalloc
Definition: membanger.c:57
int i
Definition: membanger.c:49
union _stackmember::@63 value
char * xstrndup(const char *s, size_t n)
Definition: xstring.cc:56
#define safe_free(x)
Definition: xalloc.h:73
static evaluate evalmorethan
Definition: Expression.cc:107
static evaluate evalequals
Definition: Expression.cc:108
static evaluate evalstartexpr
Definition: Expression.cc:110
evaltype valuetype
Definition: Expression.cc:73
evaluate * eval
Definition: Expression.cc:66
double floating
Definition: Expression.cc:69
static evaluate evaland
Definition: Expression.cc:103
#define debugs(SECTION, LEVEL, CONTENT)
Definition: Debug.h:123
#define DBG_IMPORTANT
Definition: Debug.h:45
static evaluate evalnotequals
Definition: Expression.cc:109
literalhint valuestored
Definition: Expression.cc:72
static evaluate evalliteral
Definition: Expression.cc:101
evaltype
Definition: Expression.cc:40
static evaluate evallesseq
Definition: Expression.cc:104
static int addmember(stackmember *stack, int *stackdepth, stackmember *candidate)
Definition: Expression.cc:950
static evaluate evalendexpr
Definition: Expression.cc:111
static void dumpstack(stackmember *stack, int depth)
Definition: Expression.cc:939
void const char * buf
Definition: stub_helper.cc:16
static void printLiteral(std::ostream &os, const stackmember &s)
Definition: Expression.cc:848
static evaluate evalmoreeq
Definition: Expression.cc:106
static int Evaluate(char const *)
Definition: Expression.cc:980
static stackmember getsymbol(const char *s, char const **endptr)
Definition: Expression.cc:666
#define PROF_start(probename)
Definition: Profiler.h:62
int evaluate(stackmember *stack, int *depth, int whereAmI, stackmember *candidate)
Definition: Expression.cc:37
int a
Definition: membanger.c:50
static void cleanmember(stackmember *)
Definition: Expression.cc:81
#define PROF_stop(probename)
Definition: Profiler.h:63
static evaluate evallessthan
Definition: Expression.cc:105
static int membercompare(stackmember a, stackmember b)
Definition: Expression.cc:126
char * string
Definition: Expression.cc:68
static evaluate evalnegate
Definition: Expression.cc:100
static std::ostream & operator<<(std::ostream &os, const stackmember &s)
Definition: Expression.cc:874
static evaluate evalor
Definition: Expression.cc:102
#define NULL
Definition: types.h:166
literalhint
Definition: Expression.cc:57

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors