| 
									
										
										
										
											2002-08-25 21:19:50 +00:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2006-10-28 20:18:18 +00:00
										 |  |  |  * Copyright (c) 2002-2006 Michael Niedermayer <michaelni@gmx.at> | 
					
						
							| 
									
										
										
										
											2006-10-28 18:30:20 +00:00
										 |  |  |  * Copyright (c) 2006 Oded Shimon <ods15@ods15.dyndns.org> | 
					
						
							| 
									
										
										
										
											2002-08-25 21:19:50 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2011-03-18 17:35:10 +00:00
										 |  |  |  * This file is part of Libav. | 
					
						
							| 
									
										
										
										
											2006-10-07 15:30:46 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2011-03-18 17:35:10 +00:00
										 |  |  |  * Libav is free software; you can redistribute it and/or | 
					
						
							| 
									
										
										
										
											2002-08-25 21:19:50 +00:00
										 |  |  |  * modify it under the terms of the GNU Lesser General Public | 
					
						
							|  |  |  |  * License as published by the Free Software Foundation; either | 
					
						
							| 
									
										
										
										
											2006-10-07 15:30:46 +00:00
										 |  |  |  * version 2.1 of the License, or (at your option) any later version. | 
					
						
							| 
									
										
										
										
											2002-08-25 21:19:50 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2011-03-18 17:35:10 +00:00
										 |  |  |  * Libav is distributed in the hope that it will be useful, | 
					
						
							| 
									
										
										
										
											2002-08-25 21:19:50 +00:00
										 |  |  |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
					
						
							|  |  |  |  * Lesser General Public License for more details. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * You should have received a copy of the GNU Lesser General Public | 
					
						
							| 
									
										
										
										
											2011-03-18 17:35:10 +00:00
										 |  |  |  * License along with Libav; if not, write to the Free Software | 
					
						
							| 
									
										
										
										
											2006-01-12 22:43:26 +00:00
										 |  |  |  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | 
					
						
							| 
									
										
										
										
											2002-08-25 21:19:50 +00:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-03-06 11:32:04 +00:00
										 |  |  | /**
 | 
					
						
							| 
									
										
										
										
											2010-04-20 14:45:34 +00:00
										 |  |  |  * @file | 
					
						
							| 
									
										
										
										
											2003-03-06 11:32:04 +00:00
										 |  |  |  * simple arithmetic expression evaluator. | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2002-08-25 21:19:50 +00:00
										 |  |  |  * see http://joe.hotchkiss.com/programming/eval/eval.html
 | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-12 19:21:08 +00:00
										 |  |  | #include "libavutil/avutil.h"
 | 
					
						
							| 
									
										
										
										
											2009-08-10 01:27:30 +00:00
										 |  |  | #include "eval.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:15 +00:00
										 |  |  | typedef struct Parser { | 
					
						
							| 
									
										
										
										
											2010-05-19 22:55:29 +00:00
										 |  |  |     const AVClass *class; | 
					
						
							| 
									
										
										
										
											2002-08-25 21:19:50 +00:00
										 |  |  |     int stack_index; | 
					
						
							|  |  |  |     char *s; | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:12 +00:00
										 |  |  |     const double *const_values; | 
					
						
							|  |  |  |     const char * const *const_names;          // NULL terminated
 | 
					
						
							|  |  |  |     double (* const *funcs1)(void *, double a);           // NULL terminated
 | 
					
						
							|  |  |  |     const char * const *func1_names;          // NULL terminated
 | 
					
						
							|  |  |  |     double (* const *funcs2)(void *, double a, double b); // NULL terminated
 | 
					
						
							|  |  |  |     const char * const *func2_names;          // NULL terminated
 | 
					
						
							| 
									
										
										
										
											2002-08-25 21:19:50 +00:00
										 |  |  |     void *opaque; | 
					
						
							| 
									
										
										
										
											2010-05-19 22:55:29 +00:00
										 |  |  |     int log_offset; | 
					
						
							|  |  |  |     void *log_ctx; | 
					
						
							| 
									
										
										
										
											2006-10-27 22:16:25 +00:00
										 |  |  | #define VARS 10
 | 
					
						
							|  |  |  |     double var[VARS]; | 
					
						
							| 
									
										
										
										
											2002-08-25 21:19:50 +00:00
										 |  |  | } Parser; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-19 22:55:29 +00:00
										 |  |  | static const AVClass class = { "Eval", av_default_item_name, NULL, LIBAVUTIL_VERSION_INT, offsetof(Parser,log_offset), offsetof(Parser,log_ctx) }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:15 +00:00
										 |  |  | static const int8_t si_prefixes['z' - 'E' + 1] = { | 
					
						
							| 
									
										
										
										
											2006-09-27 20:01:39 +00:00
										 |  |  |     ['y'-'E']= -24, | 
					
						
							|  |  |  |     ['z'-'E']= -21, | 
					
						
							|  |  |  |     ['a'-'E']= -18, | 
					
						
							|  |  |  |     ['f'-'E']= -15, | 
					
						
							|  |  |  |     ['p'-'E']= -12, | 
					
						
							|  |  |  |     ['n'-'E']= - 9, | 
					
						
							|  |  |  |     ['u'-'E']= - 6, | 
					
						
							|  |  |  |     ['m'-'E']= - 3, | 
					
						
							|  |  |  |     ['c'-'E']= - 2, | 
					
						
							|  |  |  |     ['d'-'E']= - 1, | 
					
						
							|  |  |  |     ['h'-'E']=   2, | 
					
						
							|  |  |  |     ['k'-'E']=   3, | 
					
						
							|  |  |  |     ['K'-'E']=   3, | 
					
						
							|  |  |  |     ['M'-'E']=   6, | 
					
						
							|  |  |  |     ['G'-'E']=   9, | 
					
						
							|  |  |  |     ['T'-'E']=  12, | 
					
						
							|  |  |  |     ['P'-'E']=  15, | 
					
						
							|  |  |  |     ['E'-'E']=  18, | 
					
						
							|  |  |  |     ['Z'-'E']=  21, | 
					
						
							|  |  |  |     ['Y'-'E']=  24, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:15 +00:00
										 |  |  | double av_strtod(const char *numstr, char **tail) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2006-09-27 20:01:39 +00:00
										 |  |  |     double d; | 
					
						
							|  |  |  |     char *next; | 
					
						
							| 
									
										
										
										
											2009-06-21 21:37:05 +00:00
										 |  |  |     d = strtod(numstr, &next); | 
					
						
							| 
									
										
										
										
											2006-09-27 20:01:39 +00:00
										 |  |  |     /* if parsing succeeded, check for and interpret postfixes */ | 
					
						
							| 
									
										
										
										
											2009-06-21 21:37:05 +00:00
										 |  |  |     if (next!=numstr) { | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:15 +00:00
										 |  |  |         if (*next >= 'E' && *next <= 'z') { | 
					
						
							| 
									
										
										
										
											2006-09-27 20:01:39 +00:00
										 |  |  |             int e= si_prefixes[*next - 'E']; | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:15 +00:00
										 |  |  |             if (e) { | 
					
						
							|  |  |  |                 if (next[1] == 'i') { | 
					
						
							| 
									
										
										
										
											2006-09-27 20:01:39 +00:00
										 |  |  |                     d*= pow( 2, e/0.3); | 
					
						
							|  |  |  |                     next+=2; | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:15 +00:00
										 |  |  |                 } else { | 
					
						
							| 
									
										
										
										
											2006-09-27 20:01:39 +00:00
										 |  |  |                     d*= pow(10, e); | 
					
						
							|  |  |  |                     next++; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:15 +00:00
										 |  |  |         if (*next=='B') { | 
					
						
							| 
									
										
										
										
											2006-09-27 20:01:39 +00:00
										 |  |  |             d*=8; | 
					
						
							| 
									
										
										
										
											2007-01-16 22:07:49 +00:00
										 |  |  |             next++; | 
					
						
							| 
									
										
										
										
											2006-09-27 20:01:39 +00:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     /* if requested, fill in tail with the position after the last parsed
 | 
					
						
							|  |  |  |        character */ | 
					
						
							|  |  |  |     if (tail) | 
					
						
							|  |  |  |         *tail = next; | 
					
						
							|  |  |  |     return d; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-11-01 09:34:21 +00:00
										 |  |  | #define IS_IDENTIFIER_CHAR(c) ((c) - '0' <= 9U || (c) - 'a' <= 25U || (c) - 'A' <= 25U || (c) == '_')
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:15 +00:00
										 |  |  | static int strmatch(const char *s, const char *prefix) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2002-08-25 21:19:50 +00:00
										 |  |  |     int i; | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:15 +00:00
										 |  |  |     for (i=0; prefix[i]; i++) { | 
					
						
							|  |  |  |         if (prefix[i] != s[i]) return 0; | 
					
						
							| 
									
										
										
										
											2002-08-25 21:19:50 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2010-11-01 09:34:21 +00:00
										 |  |  |     /* return 1 only if the s identifier is terminated */ | 
					
						
							|  |  |  |     return !IS_IDENTIFIER_CHAR(s[i]); | 
					
						
							| 
									
										
										
										
											2002-08-25 21:19:50 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-11 18:44:51 +00:00
										 |  |  | struct AVExpr { | 
					
						
							| 
									
										
										
										
											2006-10-27 16:42:16 +00:00
										 |  |  |     enum { | 
					
						
							|  |  |  |         e_value, e_const, e_func0, e_func1, e_func2, | 
					
						
							| 
									
										
										
										
											2010-11-03 19:44:00 +00:00
										 |  |  |         e_squish, e_gauss, e_ld, e_isnan, | 
					
						
							| 
									
										
										
										
											2006-10-27 16:42:16 +00:00
										 |  |  |         e_mod, e_max, e_min, e_eq, e_gt, e_gte, | 
					
						
							|  |  |  |         e_pow, e_mul, e_div, e_add, | 
					
						
							| 
									
										
										
										
											2011-04-09 13:49:54 +02:00
										 |  |  |         e_last, e_st, e_while, e_floor, e_ceil, e_trunc, | 
					
						
							| 
									
										
										
										
											2006-10-27 16:42:16 +00:00
										 |  |  |     } type; | 
					
						
							|  |  |  |     double value; // is sign in other types
 | 
					
						
							|  |  |  |     union { | 
					
						
							|  |  |  |         int const_index; | 
					
						
							|  |  |  |         double (*func0)(double); | 
					
						
							|  |  |  |         double (*func1)(void *, double); | 
					
						
							|  |  |  |         double (*func2)(void *, double, double); | 
					
						
							|  |  |  |     } a; | 
					
						
							| 
									
										
										
										
											2010-04-11 18:44:51 +00:00
										 |  |  |     struct AVExpr *param[2]; | 
					
						
							| 
									
										
										
										
											2006-10-27 16:42:16 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:15 +00:00
										 |  |  | static double eval_expr(Parser *p, AVExpr *e) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2006-10-27 16:42:16 +00:00
										 |  |  |     switch (e->type) { | 
					
						
							|  |  |  |         case e_value:  return e->value; | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:12 +00:00
										 |  |  |         case e_const:  return e->value * p->const_values[e->a.const_index]; | 
					
						
							| 
									
										
										
										
											2006-10-27 16:42:16 +00:00
										 |  |  |         case e_func0:  return e->value * e->a.func0(eval_expr(p, e->param[0])); | 
					
						
							|  |  |  |         case e_func1:  return e->value * e->a.func1(p->opaque, eval_expr(p, e->param[0])); | 
					
						
							|  |  |  |         case e_func2:  return e->value * e->a.func2(p->opaque, eval_expr(p, e->param[0]), eval_expr(p, e->param[1])); | 
					
						
							|  |  |  |         case e_squish: return 1/(1+exp(4*eval_expr(p, e->param[0]))); | 
					
						
							|  |  |  |         case e_gauss: { double d = eval_expr(p, e->param[0]); return exp(-d*d/2)/sqrt(2*M_PI); } | 
					
						
							| 
									
										
										
										
											2007-02-25 10:27:12 +00:00
										 |  |  |         case e_ld:     return e->value * p->var[av_clip(eval_expr(p, e->param[0]), 0, VARS-1)]; | 
					
						
							| 
									
										
										
										
											2010-11-03 19:44:00 +00:00
										 |  |  |         case e_isnan:  return e->value * !!isnan(eval_expr(p, e->param[0])); | 
					
						
							| 
									
										
										
										
											2011-04-09 13:49:54 +02:00
										 |  |  |         case e_floor:  return e->value * floor(eval_expr(p, e->param[0])); | 
					
						
							|  |  |  |         case e_ceil :  return e->value * ceil (eval_expr(p, e->param[0])); | 
					
						
							|  |  |  |         case e_trunc:  return e->value * trunc(eval_expr(p, e->param[0])); | 
					
						
							| 
									
										
										
										
											2006-10-27 22:35:55 +00:00
										 |  |  |         case e_while: { | 
					
						
							| 
									
										
										
										
											2006-10-28 07:03:24 +00:00
										 |  |  |             double d = NAN; | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:15 +00:00
										 |  |  |             while (eval_expr(p, e->param[0])) | 
					
						
							| 
									
										
										
										
											2006-10-27 22:35:55 +00:00
										 |  |  |                 d=eval_expr(p, e->param[1]); | 
					
						
							|  |  |  |             return d; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2006-10-27 16:42:16 +00:00
										 |  |  |         default: { | 
					
						
							|  |  |  |             double d = eval_expr(p, e->param[0]); | 
					
						
							|  |  |  |             double d2 = eval_expr(p, e->param[1]); | 
					
						
							|  |  |  |             switch (e->type) { | 
					
						
							|  |  |  |                 case e_mod: return e->value * (d - floor(d/d2)*d2); | 
					
						
							|  |  |  |                 case e_max: return e->value * (d >  d2 ?   d : d2); | 
					
						
							|  |  |  |                 case e_min: return e->value * (d <  d2 ?   d : d2); | 
					
						
							|  |  |  |                 case e_eq:  return e->value * (d == d2 ? 1.0 : 0.0); | 
					
						
							|  |  |  |                 case e_gt:  return e->value * (d >  d2 ? 1.0 : 0.0); | 
					
						
							|  |  |  |                 case e_gte: return e->value * (d >= d2 ? 1.0 : 0.0); | 
					
						
							|  |  |  |                 case e_pow: return e->value * pow(d, d2); | 
					
						
							|  |  |  |                 case e_mul: return e->value * (d * d2); | 
					
						
							|  |  |  |                 case e_div: return e->value * (d / d2); | 
					
						
							|  |  |  |                 case e_add: return e->value * (d + d2); | 
					
						
							| 
									
										
										
										
											2006-10-28 08:03:30 +00:00
										 |  |  |                 case e_last:return e->value * d2; | 
					
						
							| 
									
										
										
										
											2007-02-25 10:27:12 +00:00
										 |  |  |                 case e_st : return e->value * (p->var[av_clip(d, 0, VARS-1)]= d2); | 
					
						
							| 
									
										
										
										
											2006-10-27 16:42:16 +00:00
										 |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return NAN; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:07 +00:00
										 |  |  | static int parse_expr(AVExpr **e, Parser *p); | 
					
						
							| 
									
										
										
										
											2006-10-27 16:42:16 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-11-08 14:06:49 +00:00
										 |  |  | void av_expr_free(AVExpr *e) | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:15 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2006-10-27 16:42:16 +00:00
										 |  |  |     if (!e) return; | 
					
						
							| 
									
										
										
										
											2010-11-08 14:06:49 +00:00
										 |  |  |     av_expr_free(e->param[0]); | 
					
						
							|  |  |  |     av_expr_free(e->param[1]); | 
					
						
							| 
									
										
										
										
											2006-10-27 16:42:16 +00:00
										 |  |  |     av_freep(&e); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:07 +00:00
										 |  |  | static int parse_primary(AVExpr **e, Parser *p) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:15 +00:00
										 |  |  |     AVExpr *d = av_mallocz(sizeof(AVExpr)); | 
					
						
							| 
									
										
										
										
											2010-06-16 18:27:46 +00:00
										 |  |  |     char *next = p->s, *s0 = p->s; | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:07 +00:00
										 |  |  |     int ret, i; | 
					
						
							| 
									
										
										
										
											2002-08-25 21:19:50 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-12 17:59:19 +00:00
										 |  |  |     if (!d) | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:07 +00:00
										 |  |  |         return AVERROR(ENOMEM); | 
					
						
							| 
									
										
										
										
											2009-09-12 17:59:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-08-25 21:19:50 +00:00
										 |  |  |     /* number */ | 
					
						
							| 
									
										
										
										
											2006-10-27 16:42:16 +00:00
										 |  |  |     d->value = av_strtod(p->s, &next); | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:15 +00:00
										 |  |  |     if (next != p->s) { | 
					
						
							| 
									
										
										
										
											2006-10-27 16:42:16 +00:00
										 |  |  |         d->type = e_value; | 
					
						
							| 
									
										
										
										
											2002-08-25 21:19:50 +00:00
										 |  |  |         p->s= next; | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:07 +00:00
										 |  |  |         *e = d; | 
					
						
							|  |  |  |         return 0; | 
					
						
							| 
									
										
										
										
											2002-08-25 21:19:50 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2006-10-27 16:42:16 +00:00
										 |  |  |     d->value = 1; | 
					
						
							| 
									
										
										
										
											2005-12-17 18:14:38 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-08-25 21:19:50 +00:00
										 |  |  |     /* named constants */ | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:15 +00:00
										 |  |  |     for (i=0; p->const_names && p->const_names[i]; i++) { | 
					
						
							|  |  |  |         if (strmatch(p->s, p->const_names[i])) { | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:12 +00:00
										 |  |  |             p->s+= strlen(p->const_names[i]); | 
					
						
							| 
									
										
										
										
											2006-10-27 16:42:16 +00:00
										 |  |  |             d->type = e_const; | 
					
						
							|  |  |  |             d->a.const_index = i; | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:07 +00:00
										 |  |  |             *e = d; | 
					
						
							|  |  |  |             return 0; | 
					
						
							| 
									
										
										
										
											2002-08-25 21:19:50 +00:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2005-12-17 18:14:38 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-08-25 21:19:50 +00:00
										 |  |  |     p->s= strchr(p->s, '('); | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:15 +00:00
										 |  |  |     if (p->s==NULL) { | 
					
						
							| 
									
										
										
										
											2010-06-16 18:27:46 +00:00
										 |  |  |         av_log(p, AV_LOG_ERROR, "Undefined constant or missing '(' in '%s'\n", s0); | 
					
						
							| 
									
										
										
										
											2006-09-24 10:38:14 +00:00
										 |  |  |         p->s= next; | 
					
						
							| 
									
										
										
										
											2010-11-08 14:06:49 +00:00
										 |  |  |         av_expr_free(d); | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:07 +00:00
										 |  |  |         return AVERROR(EINVAL); | 
					
						
							| 
									
										
										
										
											2002-08-25 21:19:50 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |     p->s++; // "("
 | 
					
						
							| 
									
										
										
										
											2006-10-27 16:42:16 +00:00
										 |  |  |     if (*next == '(') { // special case do-nothing
 | 
					
						
							|  |  |  |         av_freep(&d); | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:07 +00:00
										 |  |  |         if ((ret = parse_expr(&d, p)) < 0) | 
					
						
							|  |  |  |             return ret; | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:15 +00:00
										 |  |  |         if (p->s[0] != ')') { | 
					
						
							| 
									
										
										
										
											2010-06-16 18:27:46 +00:00
										 |  |  |             av_log(p, AV_LOG_ERROR, "Missing ')' in '%s'\n", s0); | 
					
						
							| 
									
										
										
										
											2010-11-08 14:06:49 +00:00
										 |  |  |             av_expr_free(d); | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:07 +00:00
										 |  |  |             return AVERROR(EINVAL); | 
					
						
							| 
									
										
										
										
											2006-10-27 16:42:16 +00:00
										 |  |  |         } | 
					
						
							|  |  |  |         p->s++; // ")"
 | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:07 +00:00
										 |  |  |         *e = d; | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if ((ret = parse_expr(&(d->param[0]), p)) < 0) { | 
					
						
							| 
									
										
										
										
											2010-11-08 14:06:49 +00:00
										 |  |  |         av_expr_free(d); | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:07 +00:00
										 |  |  |         return ret; | 
					
						
							| 
									
										
										
										
											2006-10-27 16:42:16 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:15 +00:00
										 |  |  |     if (p->s[0]== ',') { | 
					
						
							| 
									
										
										
										
											2004-02-18 12:49:30 +00:00
										 |  |  |         p->s++; // ","
 | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:07 +00:00
										 |  |  |         parse_expr(&d->param[1], p); | 
					
						
							| 
									
										
										
										
											2002-08-25 21:19:50 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:15 +00:00
										 |  |  |     if (p->s[0] != ')') { | 
					
						
							| 
									
										
										
										
											2010-06-16 18:27:46 +00:00
										 |  |  |         av_log(p, AV_LOG_ERROR, "Missing ')' or too many args in '%s'\n", s0); | 
					
						
							| 
									
										
										
										
											2010-11-08 14:06:49 +00:00
										 |  |  |         av_expr_free(d); | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:07 +00:00
										 |  |  |         return AVERROR(EINVAL); | 
					
						
							| 
									
										
										
										
											2004-02-18 12:49:30 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |     p->s++; // ")"
 | 
					
						
							| 
									
										
										
										
											2005-12-17 18:14:38 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-10-27 16:42:16 +00:00
										 |  |  |     d->type = e_func0; | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:15 +00:00
										 |  |  |          if (strmatch(next, "sinh"  )) d->a.func0 = sinh; | 
					
						
							|  |  |  |     else if (strmatch(next, "cosh"  )) d->a.func0 = cosh; | 
					
						
							|  |  |  |     else if (strmatch(next, "tanh"  )) d->a.func0 = tanh; | 
					
						
							|  |  |  |     else if (strmatch(next, "sin"   )) d->a.func0 = sin; | 
					
						
							|  |  |  |     else if (strmatch(next, "cos"   )) d->a.func0 = cos; | 
					
						
							|  |  |  |     else if (strmatch(next, "tan"   )) d->a.func0 = tan; | 
					
						
							|  |  |  |     else if (strmatch(next, "atan"  )) d->a.func0 = atan; | 
					
						
							|  |  |  |     else if (strmatch(next, "asin"  )) d->a.func0 = asin; | 
					
						
							|  |  |  |     else if (strmatch(next, "acos"  )) d->a.func0 = acos; | 
					
						
							|  |  |  |     else if (strmatch(next, "exp"   )) d->a.func0 = exp; | 
					
						
							|  |  |  |     else if (strmatch(next, "log"   )) d->a.func0 = log; | 
					
						
							|  |  |  |     else if (strmatch(next, "abs"   )) d->a.func0 = fabs; | 
					
						
							|  |  |  |     else if (strmatch(next, "squish")) d->type = e_squish; | 
					
						
							|  |  |  |     else if (strmatch(next, "gauss" )) d->type = e_gauss; | 
					
						
							|  |  |  |     else if (strmatch(next, "mod"   )) d->type = e_mod; | 
					
						
							|  |  |  |     else if (strmatch(next, "max"   )) d->type = e_max; | 
					
						
							|  |  |  |     else if (strmatch(next, "min"   )) d->type = e_min; | 
					
						
							|  |  |  |     else if (strmatch(next, "eq"    )) d->type = e_eq; | 
					
						
							|  |  |  |     else if (strmatch(next, "gte"   )) d->type = e_gte; | 
					
						
							|  |  |  |     else if (strmatch(next, "gt"    )) d->type = e_gt; | 
					
						
							|  |  |  |     else if (strmatch(next, "lte"   )) { AVExpr *tmp = d->param[1]; d->param[1] = d->param[0]; d->param[0] = tmp; d->type = e_gt; } | 
					
						
							|  |  |  |     else if (strmatch(next, "lt"    )) { AVExpr *tmp = d->param[1]; d->param[1] = d->param[0]; d->param[0] = tmp; d->type = e_gte; } | 
					
						
							|  |  |  |     else if (strmatch(next, "ld"    )) d->type = e_ld; | 
					
						
							| 
									
										
										
										
											2010-11-03 19:44:00 +00:00
										 |  |  |     else if (strmatch(next, "isnan" )) d->type = e_isnan; | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:15 +00:00
										 |  |  |     else if (strmatch(next, "st"    )) d->type = e_st; | 
					
						
							|  |  |  |     else if (strmatch(next, "while" )) d->type = e_while; | 
					
						
							| 
									
										
										
										
											2011-04-09 13:49:54 +02:00
										 |  |  |     else if (strmatch(next, "floor" )) d->type = e_floor; | 
					
						
							|  |  |  |     else if (strmatch(next, "ceil"  )) d->type = e_ceil; | 
					
						
							|  |  |  |     else if (strmatch(next, "trunc" )) d->type = e_trunc; | 
					
						
							| 
									
										
										
										
											2006-10-27 16:42:16 +00:00
										 |  |  |     else { | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:15 +00:00
										 |  |  |         for (i=0; p->func1_names && p->func1_names[i]; i++) { | 
					
						
							|  |  |  |             if (strmatch(next, p->func1_names[i])) { | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:12 +00:00
										 |  |  |                 d->a.func1 = p->funcs1[i]; | 
					
						
							| 
									
										
										
										
											2006-10-27 16:42:16 +00:00
										 |  |  |                 d->type = e_func1; | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:07 +00:00
										 |  |  |                 *e = d; | 
					
						
							|  |  |  |                 return 0; | 
					
						
							| 
									
										
										
										
											2002-08-25 21:19:50 +00:00
										 |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:15 +00:00
										 |  |  |         for (i=0; p->func2_names && p->func2_names[i]; i++) { | 
					
						
							|  |  |  |             if (strmatch(next, p->func2_names[i])) { | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:12 +00:00
										 |  |  |                 d->a.func2 = p->funcs2[i]; | 
					
						
							| 
									
										
										
										
											2006-10-27 16:42:16 +00:00
										 |  |  |                 d->type = e_func2; | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:07 +00:00
										 |  |  |                 *e = d; | 
					
						
							|  |  |  |                 return 0; | 
					
						
							| 
									
										
										
										
											2002-08-25 21:19:50 +00:00
										 |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-16 18:27:46 +00:00
										 |  |  |         av_log(p, AV_LOG_ERROR, "Unknown function in '%s'\n", s0); | 
					
						
							| 
									
										
										
										
											2010-11-08 14:06:49 +00:00
										 |  |  |         av_expr_free(d); | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:07 +00:00
										 |  |  |         return AVERROR(EINVAL); | 
					
						
							| 
									
										
										
										
											2002-08-25 21:19:50 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2005-01-15 19:05:26 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:07 +00:00
										 |  |  |     *e = d; | 
					
						
							|  |  |  |     return 0; | 
					
						
							| 
									
										
										
										
											2005-12-17 18:14:38 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2005-01-17 18:25:32 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:15 +00:00
										 |  |  | static AVExpr *new_eval_expr(int type, int value, AVExpr *p0, AVExpr *p1) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     AVExpr *e = av_mallocz(sizeof(AVExpr)); | 
					
						
							| 
									
										
										
										
											2009-09-12 17:59:19 +00:00
										 |  |  |     if (!e) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							| 
									
										
										
										
											2006-10-27 20:38:10 +00:00
										 |  |  |     e->type     =type   ; | 
					
						
							|  |  |  |     e->value    =value  ; | 
					
						
							|  |  |  |     e->param[0] =p0     ; | 
					
						
							|  |  |  |     e->param[1] =p1     ; | 
					
						
							|  |  |  |     return e; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:07 +00:00
										 |  |  | static int parse_pow(AVExpr **e, Parser *p, int *sign) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2006-10-16 19:06:56 +00:00
										 |  |  |     *sign= (*p->s == '+') - (*p->s == '-'); | 
					
						
							|  |  |  |     p->s += *sign&1; | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:07 +00:00
										 |  |  |     return parse_primary(e, p); | 
					
						
							| 
									
										
										
										
											2002-08-25 21:19:50 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:07 +00:00
										 |  |  | static int parse_factor(AVExpr **e, Parser *p) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     int sign, sign2, ret; | 
					
						
							|  |  |  |     AVExpr *e0, *e1, *e2; | 
					
						
							|  |  |  |     if ((ret = parse_pow(&e0, p, &sign)) < 0) | 
					
						
							|  |  |  |         return ret; | 
					
						
							| 
									
										
										
										
											2002-08-25 21:19:50 +00:00
										 |  |  |     while(p->s[0]=='^'){ | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:07 +00:00
										 |  |  |         e1 = e0; | 
					
						
							| 
									
										
										
										
											2002-08-25 21:19:50 +00:00
										 |  |  |         p->s++; | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:07 +00:00
										 |  |  |         if ((ret = parse_pow(&e2, p, &sign2)) < 0) { | 
					
						
							| 
									
										
										
										
											2010-11-08 14:06:49 +00:00
										 |  |  |             av_expr_free(e1); | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:07 +00:00
										 |  |  |             return ret; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         e0 = new_eval_expr(e_pow, 1, e1, e2); | 
					
						
							|  |  |  |         if (!e0) { | 
					
						
							| 
									
										
										
										
											2010-11-08 14:06:49 +00:00
										 |  |  |             av_expr_free(e1); | 
					
						
							|  |  |  |             av_expr_free(e2); | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:07 +00:00
										 |  |  |             return AVERROR(ENOMEM); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (e0->param[1]) e0->param[1]->value *= (sign2|1); | 
					
						
							| 
									
										
										
										
											2002-08-25 21:19:50 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:07 +00:00
										 |  |  |     if (e0) e0->value *= (sign|1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     *e = e0; | 
					
						
							|  |  |  |     return 0; | 
					
						
							| 
									
										
										
										
											2002-08-25 21:19:50 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:07 +00:00
										 |  |  | static int parse_term(AVExpr **e, Parser *p) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     int ret; | 
					
						
							|  |  |  |     AVExpr *e0, *e1, *e2; | 
					
						
							|  |  |  |     if ((ret = parse_factor(&e0, p)) < 0) | 
					
						
							|  |  |  |         return ret; | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:15 +00:00
										 |  |  |     while (p->s[0]=='*' || p->s[0]=='/') { | 
					
						
							| 
									
										
										
										
											2006-10-27 20:38:10 +00:00
										 |  |  |         int c= *p->s++; | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:07 +00:00
										 |  |  |         e1 = e0; | 
					
						
							|  |  |  |         if ((ret = parse_factor(&e2, p)) < 0) { | 
					
						
							| 
									
										
										
										
											2010-11-08 14:06:49 +00:00
										 |  |  |             av_expr_free(e1); | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:07 +00:00
										 |  |  |             return ret; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         e0 = new_eval_expr(c == '*' ? e_mul : e_div, 1, e1, e2); | 
					
						
							|  |  |  |         if (!e0) { | 
					
						
							| 
									
										
										
										
											2010-11-08 14:06:49 +00:00
										 |  |  |             av_expr_free(e1); | 
					
						
							|  |  |  |             av_expr_free(e2); | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:07 +00:00
										 |  |  |             return AVERROR(ENOMEM); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2002-08-25 21:19:50 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:07 +00:00
										 |  |  |     *e = e0; | 
					
						
							|  |  |  |     return 0; | 
					
						
							| 
									
										
										
										
											2002-08-25 21:19:50 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:07 +00:00
										 |  |  | static int parse_subexpr(AVExpr **e, Parser *p) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     int ret; | 
					
						
							|  |  |  |     AVExpr *e0, *e1, *e2; | 
					
						
							|  |  |  |     if ((ret = parse_term(&e0, p)) < 0) | 
					
						
							|  |  |  |         return ret; | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:15 +00:00
										 |  |  |     while (*p->s == '+' || *p->s == '-') { | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:07 +00:00
										 |  |  |         e1 = e0; | 
					
						
							|  |  |  |         if ((ret = parse_term(&e2, p)) < 0) { | 
					
						
							| 
									
										
										
										
											2010-11-08 14:06:49 +00:00
										 |  |  |             av_expr_free(e1); | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:07 +00:00
										 |  |  |             return ret; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         e0 = new_eval_expr(e_add, 1, e1, e2); | 
					
						
							|  |  |  |         if (!e0) { | 
					
						
							| 
									
										
										
										
											2010-11-08 14:06:49 +00:00
										 |  |  |             av_expr_free(e1); | 
					
						
							|  |  |  |             av_expr_free(e2); | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:07 +00:00
										 |  |  |             return AVERROR(ENOMEM); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2006-10-27 22:16:25 +00:00
										 |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:07 +00:00
										 |  |  |     *e = e0; | 
					
						
							|  |  |  |     return 0; | 
					
						
							| 
									
										
										
										
											2006-10-27 22:16:25 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:07 +00:00
										 |  |  | static int parse_expr(AVExpr **e, Parser *p) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     int ret; | 
					
						
							|  |  |  |     AVExpr *e0, *e1, *e2; | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:15 +00:00
										 |  |  |     if (p->stack_index <= 0) //protect against stack overflows
 | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:07 +00:00
										 |  |  |         return AVERROR(EINVAL); | 
					
						
							| 
									
										
										
										
											2005-01-15 20:04:41 +00:00
										 |  |  |     p->stack_index--; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:07 +00:00
										 |  |  |     if ((ret = parse_subexpr(&e0, p)) < 0) | 
					
						
							|  |  |  |         return ret; | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:15 +00:00
										 |  |  |     while (*p->s == ';') { | 
					
						
							| 
									
										
										
										
											2010-11-01 09:34:12 +00:00
										 |  |  |         p->s++; | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:07 +00:00
										 |  |  |         e1 = e0; | 
					
						
							|  |  |  |         if ((ret = parse_subexpr(&e2, p)) < 0) { | 
					
						
							| 
									
										
										
										
											2010-11-08 14:06:49 +00:00
										 |  |  |             av_expr_free(e1); | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:07 +00:00
										 |  |  |             return ret; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         e0 = new_eval_expr(e_last, 1, e1, e2); | 
					
						
							|  |  |  |         if (!e0) { | 
					
						
							| 
									
										
										
										
											2010-11-08 14:06:49 +00:00
										 |  |  |             av_expr_free(e1); | 
					
						
							|  |  |  |             av_expr_free(e2); | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:07 +00:00
										 |  |  |             return AVERROR(ENOMEM); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2006-10-27 16:42:16 +00:00
										 |  |  |     }; | 
					
						
							| 
									
										
										
										
											2005-01-15 20:04:41 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     p->stack_index++; | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:07 +00:00
										 |  |  |     *e = e0; | 
					
						
							|  |  |  |     return 0; | 
					
						
							| 
									
										
										
										
											2002-08-25 21:19:50 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:15 +00:00
										 |  |  | static int verify_expr(AVExpr *e) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2006-10-27 16:42:16 +00:00
										 |  |  |     if (!e) return 0; | 
					
						
							|  |  |  |     switch (e->type) { | 
					
						
							|  |  |  |         case e_value: | 
					
						
							|  |  |  |         case e_const: return 1; | 
					
						
							|  |  |  |         case e_func0: | 
					
						
							|  |  |  |         case e_func1: | 
					
						
							|  |  |  |         case e_squish: | 
					
						
							| 
									
										
										
										
											2006-10-27 22:16:25 +00:00
										 |  |  |         case e_ld: | 
					
						
							| 
									
										
										
										
											2010-11-03 19:44:00 +00:00
										 |  |  |         case e_gauss: | 
					
						
							| 
									
										
										
										
											2011-04-09 13:49:54 +02:00
										 |  |  |         case e_isnan: | 
					
						
							|  |  |  |         case e_floor: | 
					
						
							|  |  |  |         case e_ceil: | 
					
						
							|  |  |  |         case e_trunc: | 
					
						
							|  |  |  |             return verify_expr(e->param[0]); | 
					
						
							| 
									
										
										
										
											2006-10-27 16:42:16 +00:00
										 |  |  |         default: return verify_expr(e->param[0]) && verify_expr(e->param[1]); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-11-08 14:06:49 +00:00
										 |  |  | int av_expr_parse(AVExpr **expr, const char *s, | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:12 +00:00
										 |  |  |                   const char * const *const_names, | 
					
						
							|  |  |  |                   const char * const *func1_names, double (* const *funcs1)(void *, double), | 
					
						
							|  |  |  |                   const char * const *func2_names, double (* const *funcs2)(void *, double, double), | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:17 +00:00
										 |  |  |                   int log_offset, void *log_ctx) | 
					
						
							| 
									
										
										
										
											2010-05-19 22:55:29 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2002-08-25 21:19:50 +00:00
										 |  |  |     Parser p; | 
					
						
							| 
									
										
										
										
											2010-04-11 11:47:29 +00:00
										 |  |  |     AVExpr *e = NULL; | 
					
						
							| 
									
										
										
										
											2009-08-19 21:59:40 +00:00
										 |  |  |     char *w = av_malloc(strlen(s) + 1); | 
					
						
							|  |  |  |     char *wp = w; | 
					
						
							| 
									
										
										
										
											2010-06-16 18:27:55 +00:00
										 |  |  |     const char *s0 = s; | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:07 +00:00
										 |  |  |     int ret = 0; | 
					
						
							| 
									
										
										
										
											2009-08-19 21:59:40 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (!w) | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:07 +00:00
										 |  |  |         return AVERROR(ENOMEM); | 
					
						
							| 
									
										
										
										
											2006-10-28 09:49:13 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     while (*s) | 
					
						
							|  |  |  |         if (!isspace(*s++)) *wp++ = s[-1]; | 
					
						
							|  |  |  |     *wp++ = 0; | 
					
						
							| 
									
										
										
										
											2005-12-17 18:14:38 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-19 22:55:29 +00:00
										 |  |  |     p.class      = &class; | 
					
						
							| 
									
										
										
										
											2005-01-15 20:04:41 +00:00
										 |  |  |     p.stack_index=100; | 
					
						
							| 
									
										
										
										
											2006-10-28 09:49:13 +00:00
										 |  |  |     p.s= w; | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:12 +00:00
										 |  |  |     p.const_names = const_names; | 
					
						
							|  |  |  |     p.funcs1      = funcs1; | 
					
						
							|  |  |  |     p.func1_names = func1_names; | 
					
						
							|  |  |  |     p.funcs2      = funcs2; | 
					
						
							|  |  |  |     p.func2_names = func2_names; | 
					
						
							| 
									
										
										
										
											2010-05-19 22:55:29 +00:00
										 |  |  |     p.log_offset = log_offset; | 
					
						
							|  |  |  |     p.log_ctx    = log_ctx; | 
					
						
							| 
									
										
										
										
											2005-12-17 18:14:38 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:07 +00:00
										 |  |  |     if ((ret = parse_expr(&e, &p)) < 0) | 
					
						
							|  |  |  |         goto end; | 
					
						
							| 
									
										
										
										
											2010-06-16 18:27:55 +00:00
										 |  |  |     if (*p.s) { | 
					
						
							|  |  |  |         av_log(&p, AV_LOG_ERROR, "Invalid chars '%s' at the end of expression '%s'\n", p.s, s0); | 
					
						
							|  |  |  |         ret = AVERROR(EINVAL); | 
					
						
							|  |  |  |         goto end; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2006-10-27 16:42:16 +00:00
										 |  |  |     if (!verify_expr(e)) { | 
					
						
							| 
									
										
										
										
											2010-11-08 14:06:49 +00:00
										 |  |  |         av_expr_free(e); | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:07 +00:00
										 |  |  |         ret = AVERROR(EINVAL); | 
					
						
							|  |  |  |         goto end; | 
					
						
							| 
									
										
										
										
											2006-10-27 16:42:16 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:07 +00:00
										 |  |  |     *expr = e; | 
					
						
							| 
									
										
										
										
											2009-08-19 21:59:40 +00:00
										 |  |  | end: | 
					
						
							|  |  |  |     av_free(w); | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:07 +00:00
										 |  |  |     return ret; | 
					
						
							| 
									
										
										
										
											2006-10-27 16:42:16 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-11-08 14:06:49 +00:00
										 |  |  | double av_expr_eval(AVExpr *e, const double *const_values, void *opaque) | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:15 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2006-10-27 16:42:16 +00:00
										 |  |  |     Parser p; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:12 +00:00
										 |  |  |     p.const_values = const_values; | 
					
						
							| 
									
										
										
										
											2006-10-27 16:42:16 +00:00
										 |  |  |     p.opaque     = opaque; | 
					
						
							|  |  |  |     return eval_expr(&p, e); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-11-08 14:06:49 +00:00
										 |  |  | int av_expr_parse_and_eval(double *d, const char *s, | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:12 +00:00
										 |  |  |                            const char * const *const_names, const double *const_values, | 
					
						
							|  |  |  |                            const char * const *func1_names, double (* const *funcs1)(void *, double), | 
					
						
							|  |  |  |                            const char * const *func2_names, double (* const *funcs2)(void *, double, double), | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:17 +00:00
										 |  |  |                            void *opaque, int log_offset, void *log_ctx) | 
					
						
							| 
									
										
										
										
											2010-05-19 22:55:29 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:07 +00:00
										 |  |  |     AVExpr *e = NULL; | 
					
						
							| 
									
										
										
										
											2010-11-08 14:06:49 +00:00
										 |  |  |     int ret = av_expr_parse(&e, s, const_names, func1_names, funcs1, func2_names, funcs2, log_offset, log_ctx); | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:07 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (ret < 0) { | 
					
						
							|  |  |  |         *d = NAN; | 
					
						
							|  |  |  |         return ret; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2010-11-08 14:06:49 +00:00
										 |  |  |     *d = av_expr_eval(e, const_values, opaque); | 
					
						
							|  |  |  |     av_expr_free(e); | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:07 +00:00
										 |  |  |     return isnan(*d) ? AVERROR(EINVAL) : 0; | 
					
						
							| 
									
										
										
										
											2002-08-25 21:19:50 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2005-01-15 19:05:26 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #ifdef TEST
 | 
					
						
							| 
									
										
										
										
											2005-12-17 18:14:38 +00:00
										 |  |  | #undef printf
 | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:15 +00:00
										 |  |  | static double const_values[] = { | 
					
						
							| 
									
										
										
										
											2005-01-15 19:05:26 +00:00
										 |  |  |     M_PI, | 
					
						
							|  |  |  |     M_E, | 
					
						
							|  |  |  |     0 | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:17 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:15 +00:00
										 |  |  | static const char *const_names[] = { | 
					
						
							| 
									
										
										
										
											2005-01-15 19:05:26 +00:00
										 |  |  |     "PI", | 
					
						
							|  |  |  |     "E", | 
					
						
							|  |  |  |     0 | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:17 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:15 +00:00
										 |  |  | int main(void) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2005-01-17 18:25:32 +00:00
										 |  |  |     int i; | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:07 +00:00
										 |  |  |     double d; | 
					
						
							| 
									
										
										
										
											2010-06-16 22:36:52 +00:00
										 |  |  |     const char **expr, *exprs[] = { | 
					
						
							|  |  |  |         "", | 
					
						
							| 
									
										
										
										
											2010-11-01 09:34:12 +00:00
										 |  |  |         "1;2", | 
					
						
							| 
									
										
										
										
											2010-11-01 09:34:15 +00:00
										 |  |  |         "-20", | 
					
						
							|  |  |  |         "-PI", | 
					
						
							|  |  |  |         "+PI", | 
					
						
							| 
									
										
										
										
											2010-06-16 22:36:52 +00:00
										 |  |  |         "1+(5-2)^(3-1)+1/2+sin(PI)-max(-2.2,-3.1)", | 
					
						
							|  |  |  |         "80G/80Gi" | 
					
						
							|  |  |  |         "1k", | 
					
						
							|  |  |  |         "1Gi", | 
					
						
							|  |  |  |         "1gi", | 
					
						
							|  |  |  |         "1GiFoo", | 
					
						
							|  |  |  |         "1k+1k", | 
					
						
							|  |  |  |         "1Gi*3foo", | 
					
						
							|  |  |  |         "foo", | 
					
						
							|  |  |  |         "foo(", | 
					
						
							|  |  |  |         "foo()", | 
					
						
							|  |  |  |         "foo)", | 
					
						
							|  |  |  |         "sin", | 
					
						
							|  |  |  |         "sin(", | 
					
						
							|  |  |  |         "sin()", | 
					
						
							|  |  |  |         "sin)", | 
					
						
							|  |  |  |         "sin 10", | 
					
						
							|  |  |  |         "sin(1,2,3)", | 
					
						
							|  |  |  |         "sin(1 )", | 
					
						
							|  |  |  |         "1", | 
					
						
							|  |  |  |         "1foo", | 
					
						
							|  |  |  |         "bar + PI + E + 100f*2 + foo", | 
					
						
							|  |  |  |         "13k + 12f - foo(1, 2)", | 
					
						
							|  |  |  |         "1gi", | 
					
						
							|  |  |  |         "1Gi", | 
					
						
							| 
									
										
										
										
											2010-11-01 09:34:18 +00:00
										 |  |  |         "st(0, 123)", | 
					
						
							|  |  |  |         "st(1, 123); ld(1)", | 
					
						
							|  |  |  |         /* compute 1+2+...+N */ | 
					
						
							|  |  |  |         "st(0, 1); while(lte(ld(0), 100), st(1, ld(1)+ld(0));st(0, ld(0)+1)); ld(1)", | 
					
						
							|  |  |  |         /* compute Fib(N) */ | 
					
						
							|  |  |  |         "st(1, 1); st(2, 2); st(0, 1); while(lte(ld(0),10), st(3, ld(1)+ld(2)); st(1, ld(2)); st(2, ld(3)); st(0, ld(0)+1)); ld(3)", | 
					
						
							|  |  |  |         "while(0, 10)", | 
					
						
							|  |  |  |         "st(0, 1); while(lte(ld(0),100), st(1, ld(1)+ld(0)); st(0, ld(0)+1))", | 
					
						
							| 
									
										
										
										
											2010-11-03 19:44:00 +00:00
										 |  |  |         "isnan(1)", | 
					
						
							|  |  |  |         "isnan(NAN)", | 
					
						
							| 
									
										
										
										
											2011-04-09 13:49:54 +02:00
										 |  |  |         "floor(NAN)", | 
					
						
							|  |  |  |         "floor(123.123)", | 
					
						
							|  |  |  |         "floor(-123.123)", | 
					
						
							|  |  |  |         "trunc(123.123)", | 
					
						
							|  |  |  |         "trunc(-123.123)", | 
					
						
							|  |  |  |         "ceil(123.123)", | 
					
						
							|  |  |  |         "ceil(-123.123)", | 
					
						
							| 
									
										
										
										
											2010-06-16 22:36:52 +00:00
										 |  |  |         NULL | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (expr = exprs; *expr; expr++) { | 
					
						
							|  |  |  |         printf("Evaluating '%s'\n", *expr); | 
					
						
							| 
									
										
										
										
											2010-11-08 14:06:49 +00:00
										 |  |  |         av_expr_parse_and_eval(&d, *expr, | 
					
						
							| 
									
										
										
										
											2010-06-16 22:36:52 +00:00
										 |  |  |                                const_names, const_values, | 
					
						
							|  |  |  |                                NULL, NULL, NULL, NULL, NULL, 0, NULL); | 
					
						
							|  |  |  |         printf("'%s' -> %f\n\n", *expr, d); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-11-08 14:06:49 +00:00
										 |  |  |     av_expr_parse_and_eval(&d, "1+(5-2)^(3-1)+1/2+sin(PI)-max(-2.2,-3.1)", | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:17 +00:00
										 |  |  |                            const_names, const_values, | 
					
						
							|  |  |  |                            NULL, NULL, NULL, NULL, NULL, 0, NULL); | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:07 +00:00
										 |  |  |     printf("%f == 12.7\n", d); | 
					
						
							| 
									
										
										
										
											2010-11-08 14:06:49 +00:00
										 |  |  |     av_expr_parse_and_eval(&d, "80G/80Gi", | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:17 +00:00
										 |  |  |                            const_names, const_values, | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:21 +00:00
										 |  |  |                            NULL, NULL, NULL, NULL, NULL, 0, NULL); | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:07 +00:00
										 |  |  |     printf("%f == 0.931322575\n", d); | 
					
						
							| 
									
										
										
										
											2005-12-17 18:14:38 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:15 +00:00
										 |  |  |     for (i=0; i<1050; i++) { | 
					
						
							| 
									
										
										
										
											2005-01-17 18:25:32 +00:00
										 |  |  |         START_TIMER | 
					
						
							| 
									
										
										
										
											2010-11-08 14:06:49 +00:00
										 |  |  |             av_expr_parse_and_eval(&d, "1+(5-2)^(3-1)+1/2+sin(PI)-max(-2.2,-3.1)", | 
					
						
							| 
									
										
										
										
											2010-06-01 08:07:17 +00:00
										 |  |  |                                    const_names, const_values, | 
					
						
							|  |  |  |                                    NULL, NULL, NULL, NULL, NULL, 0, NULL); | 
					
						
							| 
									
										
										
										
											2010-11-08 14:06:49 +00:00
										 |  |  |         STOP_TIMER("av_expr_parse_and_eval") | 
					
						
							| 
									
										
										
										
											2005-01-17 18:25:32 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2008-01-22 09:20:25 +00:00
										 |  |  |     return 0; | 
					
						
							| 
									
										
										
										
											2005-01-15 19:05:26 +00:00
										 |  |  | } | 
					
						
							|  |  |  | #endif
 |