X-Git-Url: https://git.verplant.org/?a=blobdiff_plain;f=src%2Frrd_rpncalc.c;h=2fc6ca77ee2cdd6598a914f888e34a1849ab48f3;hb=f33dd0fcc721e4efb1ce3be0d672e00e587d7491;hp=d1ab0dea2a95b2942659055a76239dd92f8a61be;hpb=2a6a270edfda89b04722b42b57992907f871c671;p=rrdtool.git diff --git a/src/rrd_rpncalc.c b/src/rrd_rpncalc.c index d1ab0de..2fc6ca7 100644 --- a/src/rrd_rpncalc.c +++ b/src/rrd_rpncalc.c @@ -8,6 +8,7 @@ #include "rrd_rpncalc.h" #include "rrd_graph.h" #include +#include short addop2str( enum op_en op, @@ -19,8 +20,8 @@ int tzoffset( time_t); /* used to implement LTIME */ short rpn_compact( - rpnp_t * rpnp, - rpn_cdefds_t ** rpnc, + rpnp_t *rpnp, + rpn_cdefds_t **rpnc, short *count) { short i; @@ -61,7 +62,7 @@ short rpn_compact( } rpnp_t *rpn_expand( - rpn_cdefds_t * rpnc) + rpn_cdefds_t *rpnc) { short i; rpnp_t *rpnp; @@ -93,8 +94,8 @@ rpnp_t *rpn_expand( * str: out string, memory is allocated by the function, must be freed by the * the caller */ void rpn_compact2str( - rpn_cdefds_t * rpnc, - ds_def_t * ds_def, + rpn_cdefds_t *rpnc, + ds_def_t *ds_def, char **str) { unsigned short i, offset = 0; @@ -172,6 +173,7 @@ void rpn_compact2str( add_op(OP_SORT, SORT) add_op(OP_REV, REV) add_op(OP_TREND, TREND) + add_op(OP_TRENDNAN, TRENDNAN) add_op(OP_RAD2DEG, RAD2DEG) add_op(OP_DEG2RAD, DEG2RAD) add_op(OP_AVG, AVG) @@ -278,14 +280,16 @@ long lookup_DS( rpnp_t *rpn_parse( void *key_hash, const char *const expr_const, - long (*lookup) (void *, - char *)) + long (*lookup) (void *, + char *)) { int pos = 0; char *expr; 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; @@ -293,9 +297,10 @@ 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; } - + else if ((sscanf(expr, "%lf%n", &rpnp[steps].val, &pos) == 1) && (expr[pos] == ',')) { rpnp[steps].op = OP_NUMBER; @@ -305,8 +310,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) { \ @@ -364,6 +368,7 @@ rpnp_t *rpn_parse( match_op(OP_SORT, SORT) match_op(OP_REV, REV) match_op(OP_TREND, TREND) + match_op(OP_TRENDNAN, TRENDNAN) match_op(OP_RAD2DEG, RAD2DEG) match_op(OP_DEG2RAD, DEG2RAD) match_op(OP_AVG, AVG) @@ -377,24 +382,28 @@ 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; } void rpnstack_init( - rpnstack_t * rpnstack) + rpnstack_t *rpnstack) { rpnstack->s = NULL; rpnstack->dc_stacksize = 0; @@ -402,7 +411,7 @@ void rpnstack_init( } void rpnstack_free( - rpnstack_t * rpnstack) + rpnstack_t *rpnstack) { if (rpnstack->s != NULL) free(rpnstack->s); @@ -434,10 +443,10 @@ static int rpn_compare_double( * 0 on success */ short rpn_calc( - rpnp_t * rpnp, - rpnstack_t * rpnstack, + rpnp_t *rpnp, + rpnstack_t *rpnstack, long data_idx, - rrd_value_t * output, + rrd_value_t *output, int output_idx) { int rpi; @@ -757,6 +766,7 @@ short rpn_calc( } break; case OP_TREND: + case OP_TRENDNAN: stackunderflow(1); if ((rpi < 2) || (rpnp[rpi - 2].op != OP_VARIABLE)) { rrd_set_error("malformed trend arguments"); @@ -766,16 +776,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 { - accum += + 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] = (accum / -i); + rpnstack->s[--stptr] = + (count == 0) ? DNAN : (accum / count); } else rpnstack->s[--stptr] = DNAN; }