X-Git-Url: https://git.octo.it/?p=rrdtool.git;a=blobdiff_plain;f=src%2Frrd_rpncalc.c;h=5bb5e4056ac21c5beb203c973d29962479ba5725;hp=717ad42f5fc5ef8b96ff2e9c7c80ddcc9bf8cc9b;hb=22129bb15a8ad204cf8a5e88e8834ec0b51908c0;hpb=5b16d46cb37b99d50005603382c7b0fa11ff4347 diff --git a/src/rrd_rpncalc.c b/src/rrd_rpncalc.c index 717ad42..5bb5e40 100644 --- a/src/rrd_rpncalc.c +++ b/src/rrd_rpncalc.c @@ -1,13 +1,14 @@ /**************************************************************************** - * RRDtool 1.2.23 Copyright by Tobi Oetiker, 1997-2007 + * RRDtool 1.3.2 Copyright by Tobi Oetiker, 1997-2008 **************************************************************************** * rrd_rpncalc.c RPN calculator functions ****************************************************************************/ #include "rrd_tool.h" #include "rrd_rpncalc.h" -#include "rrd_graph.h" +// #include "rrd_graph.h" #include +#include short addop2str( enum op_en op, @@ -177,6 +178,7 @@ void rpn_compact2str( add_op(OP_DEG2RAD, DEG2RAD) add_op(OP_AVG, AVG) add_op(OP_ABS, ABS) + add_op(OP_ADDNAN, ADDNAN) #undef add_op } (*str)[offset] = '\0'; @@ -287,6 +289,9 @@ rpnp_t *rpn_parse( long steps = -1; rpnp_t *rpnp; char vname[MAX_VNAME_LEN + 10]; + char *old_locale; + + old_locale = setlocale(LC_NUMERIC, "C"); rpnp = NULL; expr = (char *) expr_const; @@ -294,6 +299,7 @@ rpnp_t *rpn_parse( while (*expr) { if ((rpnp = (rpnp_t *) rrd_realloc(rpnp, (++steps + 2) * sizeof(rpnp_t))) == NULL) { + setlocale(LC_NUMERIC, old_locale); return NULL; } @@ -306,8 +312,7 @@ rpnp_t *rpn_parse( else if (strncmp(expr, #VVV, strlen(#VVV))==0 && ( expr[strlen(#VVV)] == ',' || expr[strlen(#VVV)] == '\0' )){ \ rpnp[steps].op = VV; \ expr+=strlen(#VVV); \ - } - + } #define match_op_param(VV,VVV) \ else if (sscanf(expr, #VVV "(" DEF_NAM_FMT ")",vname) == 1) { \ @@ -370,6 +375,7 @@ rpnp_t *rpn_parse( match_op(OP_DEG2RAD, DEG2RAD) match_op(OP_AVG, AVG) match_op(OP_ABS, ABS) + match_op(OP_ADDNAN, ADDNAN) #undef match_op else if ((sscanf(expr, DEF_NAM_FMT "%n", vname, &pos) == 1) && ((rpnp[steps].ptr = (*lookup) (key_hash, vname)) != @@ -379,19 +385,23 @@ rpnp_t *rpn_parse( } else { + setlocale(LC_NUMERIC, old_locale); free(rpnp); return NULL; } + if (*expr == 0) break; if (*expr == ',') expr++; else { + setlocale(LC_NUMERIC, old_locale); free(rpnp); return NULL; } } rpnp[steps + 1].op = OP_END; + setlocale(LC_NUMERIC, old_locale); return rpnp; } @@ -535,6 +545,20 @@ short rpn_calc( + rpnstack->s[stptr]; stptr--; break; + case OP_ADDNAN: + stackunderflow(1); + if (isnan(rpnstack->s[stptr - 1])) { + rpnstack->s[stptr - 1] = rpnstack->s[stptr]; + } else if (isnan(rpnstack->s[stptr])) { + /* NOOP */ + /* rpnstack->s[stptr - 1] = rpnstack->s[stptr - 1]; */ + } else { + rpnstack->s[stptr - 1] = rpnstack->s[stptr - 1] + + rpnstack->s[stptr]; + } + + stptr--; + break; case OP_SUB: stackunderflow(1); rpnstack->s[stptr - 1] = rpnstack->s[stptr - 1] @@ -682,8 +706,10 @@ short rpn_calc( break; case OP_IF: stackunderflow(2); - rpnstack->s[stptr - 2] = rpnstack->s[stptr - 2] != 0.0 ? - rpnstack->s[stptr - 1] : rpnstack->s[stptr]; + rpnstack->s[stptr - 2] = (isnan(rpnstack->s[stptr - 2]) + || rpnstack->s[stptr - 2] == + 0.0) ? rpnstack->s[stptr] : rpnstack-> + s[stptr - 1]; stptr--; stptr--; break; @@ -759,7 +785,7 @@ short rpn_calc( } break; case OP_TREND: - case OP_TRENDNAN: + case OP_TRENDNAN: stackunderflow(1); if ((rpi < 2) || (rpnp[rpi - 2].op != OP_VARIABLE)) { rrd_set_error("malformed trend arguments"); @@ -769,23 +795,24 @@ short rpn_calc( time_t step = (time_t) rpnp[rpi - 2].step; if (output_idx > (int) ceil((float) dur / (float) step)) { - int ignorenan = (rpnp[rpi].op == OP_TREND); - double accum = 0.0; - int i = 0; - int count = 0; - - do { - double val = - rpnp[rpi - 2].data[rpnp[rpi - 2].ds_cnt * i--]; - if (ignorenan || !isnan(val)) { - accum += val; - ++count; - } - - dur -= step; - } while (dur > 0); - - rpnstack -> s[--stptr] = (count == 0) ? DNAN : (accum / count); + int ignorenan = (rpnp[rpi].op == OP_TREND); + double accum = 0.0; + int i = 0; + int count = 0; + + do { + double val = + rpnp[rpi - 2].data[rpnp[rpi - 2].ds_cnt * i--]; + if (ignorenan || !isnan(val)) { + accum += val; + ++count; + } + + dur -= step; + } while (dur > 0); + + rpnstack->s[--stptr] = + (count == 0) ? DNAN : (accum / count); } else rpnstack->s[--stptr] = DNAN; }