- long stptr=-1;
- /* process each op from the rpn in turn */
- for (rpi=0;im->gdes[gdi].rpnp[rpi].op != OP_END;rpi++){
- if (stptr +5 > dc_stacksize){
- dc_stacksize += dc_stackblock;
- stack = rrd_realloc(stack,dc_stacksize*sizeof(*stack));
- if (stack==NULL){
- rrd_set_error("RPN stack overflow");
- return -1;
- }
- }
- switch (im->gdes[gdi].rpnp[rpi].op){
- case OP_NUMBER:
- stack[++stptr] = im->gdes[gdi].rpnp[rpi].val;
- break;
- case OP_VARIABLE:
- /* make sure we pull the correct value from the *.data array */
- /* adjust the pointer into the array acordingly. */
- if(now > im->gdes[gdi].start &&
- now % im->gdes[gdi].rpnp[rpi].step == 0){
- im->gdes[gdi].rpnp[rpi].data +=
- im->gdes[gdi].rpnp[rpi].ds_cnt;
- }
- stack[++stptr] = *im->gdes[gdi].rpnp[rpi].data;
- break;
- case OP_PREV:
- if (dataidx <= 0) {
- stack[++stptr] = DNAN;
- } else {
- stack[++stptr] = im->gdes[gdi].data[dataidx];
- }
- break;
- case OP_UNKN:
- stack[++stptr] = DNAN;
- break;
- case OP_INF:
- stack[++stptr] = DINF;
- break;
- case OP_NEGINF:
- stack[++stptr] = -DINF;
- break;
- case OP_NOW:
- stack[++stptr] = (double)time(NULL);
- break;
- case OP_TIME:
- stack[++stptr] = (double)now;
- break;
- case OP_LTIME:
- stack[++stptr] = (double)tzoffset(now)+(double)now;
- break;
- case OP_ADD:
- if(stptr<1){
- rrd_set_error("RPN stack underflow");
- free(stack);
- return -1;
- }
- stack[stptr-1] = stack[stptr-1] + stack[stptr];
- stptr--;
- break;
- case OP_SUB:
- if(stptr<1){
- rrd_set_error("RPN stack underflow");
- free(stack);
- return -1;
- }
- stack[stptr-1] = stack[stptr-1] - stack[stptr];
- stptr--;
- break;
- case OP_MUL:
- if(stptr<1){
- rrd_set_error("RPN stack underflow");
- free(stack);
- return -1;
- }
- stack[stptr-1] = stack[stptr-1] * stack[stptr];
- stptr--;
- break;
- case OP_DIV:
- if(stptr<1){
- rrd_set_error("RPN stack underflow");
- free(stack);
- return -1;
- }
- stack[stptr-1] = stack[stptr-1] / stack[stptr];
- stptr--;
- break;
- case OP_MOD:
- if(stptr<1){
- rrd_set_error("RPN stack underflow");
- free(stack);
- return -1;
- }
- stack[stptr-1] = fmod(stack[stptr-1],stack[stptr]);
- stptr--;
- break;
- case OP_SIN:
- if(stptr<0){
- rrd_set_error("RPN stack underflow");
- free(stack);
- return -1;
- }
- stack[stptr] = sin(stack[stptr]);
- break;
- case OP_COS:
- if(stptr<0){
- rrd_set_error("RPN stack underflow");
- free(stack);
- return -1;
- }
- stack[stptr] = cos(stack[stptr]);
- break;
- case OP_CEIL:
- if(stptr<0){
- rrd_set_error("RPN stack underflow");
- free(stack);
- return -1;
- }
- stack[stptr] = ceil(stack[stptr]);
- break;
- case OP_FLOOR:
- if(stptr<0){
- rrd_set_error("RPN stack underflow");
- free(stack);
- return -1;
- }
- stack[stptr] = floor(stack[stptr]);
- break;
- case OP_LOG:
- if(stptr<0){
- rrd_set_error("RPN stack underflow");
- free(stack);
- return -1;
- }
- stack[stptr] = log(stack[stptr]);
- break;
- case OP_DUP:
- if(stptr<0){
- rrd_set_error("RPN stack underflow");
- free(stack);
- return -1;
- }
- stack[stptr+1] = stack[stptr];
- stptr++;
- break;
- case OP_POP:
- if(stptr<0){
- rrd_set_error("RPN stack underflow");
- free(stack);
- return -1;
- }
- stptr--;
- break;
- case OP_EXC:
- if(stptr<1){
- rrd_set_error("RPN stack underflow");
- free(stack);
- return -1;
- } else {
- double dummy;
- dummy = stack[stptr] ;
- stack[stptr] = stack[stptr-1];
- stack[stptr-1] = dummy;
- }
- break;
- case OP_EXP:
- if(stptr<0){
- rrd_set_error("RPN stack underflow");
- free(stack);
- return -1;
- }
- stack[stptr] = exp(stack[stptr]);
- break;
- case OP_LT:
- if(stptr<1){
- rrd_set_error("RPN stack underflow");
- free(stack);
- return -1;
- }
- if (isnan(stack[stptr-1]) || isnan(stack[stptr]))
- stack[stptr-1] = 0.0;
- else
- stack[stptr-1] = stack[stptr-1] < stack[stptr] ? 1.0 : 0.0;
- stptr--;
- break;
- case OP_LE:
- if(stptr<1){
- rrd_set_error("RPN stack underflow");
- free(stack);
- return -1;
- }
- if (isnan(stack[stptr-1]) || isnan(stack[stptr]))
- stack[stptr-1] = 0.0;
- else
- stack[stptr-1] = stack[stptr-1] <= stack[stptr] ? 1.0 : 0.0;
- stptr--;
- break;
- case OP_GT:
- if(stptr<1){
- rrd_set_error("RPN stack underflow");
- free(stack);
- return -1;
- }
- if (isnan(stack[stptr-1]) || isnan(stack[stptr]))
- stack[stptr-1] = 0.0;
- else
- stack[stptr-1] = stack[stptr-1] > stack[stptr] ? 1.0 : 0.0;
- stptr--;
- break;
- case OP_GE:
- if(stptr<1){
- rrd_set_error("RPN stack underflow");
- free(stack);
- return -1;
- }
- if (isnan(stack[stptr-1]) || isnan(stack[stptr]))
- stack[stptr-1] = 0.0;
- else
- stack[stptr-1] = stack[stptr-1] >= stack[stptr] ? 1.0 : 0.0;
- stptr--;
- break;
- case OP_EQ:
- if(stptr<1){
- rrd_set_error("RPN stack underflow");
- free(stack);
- return -1;
- }
- if (isnan(stack[stptr-1]) || isnan(stack[stptr]))
- stack[stptr-1] = 0.0;
- else
- stack[stptr-1] = stack[stptr-1] == stack[stptr] ? 1.0 : 0.0;
- stptr--;
- break;
- case OP_IF:
- if(stptr<2){
- rrd_set_error("RPN stack underflow");
- free(stack);
- return -1;
- }
- stack[stptr-2] = stack[stptr-2] != 0.0 ? stack[stptr-1] : stack[stptr];
- stptr--;
- stptr--;
- break;
- case OP_MIN:
- if(stptr<1){
- rrd_set_error("RPN stack underflow");
- free(stack);
- return -1;
- }
- if (isnan(stack[stptr-1]))
- ;
- else if (isnan(stack[stptr]))
- stack[stptr-1] = stack[stptr];
- else if (stack[stptr-1] > stack[stptr])
- stack[stptr-1] = stack[stptr];
- stptr--;
- break;
- case OP_MAX:
- if(stptr<1){
- rrd_set_error("RPN stack underflow");
- free(stack);
- return -1;
- }
- if (isnan(stack[stptr-1]))
- ;
- else if (isnan(stack[stptr]))
- stack[stptr-1] = stack[stptr];
- else if (stack[stptr-1] < stack[stptr])
- stack[stptr-1] = stack[stptr];
- stptr--;
- break;
- case OP_LIMIT:
- if(stptr<2){
- rrd_set_error("RPN stack underflow");
- free(stack);
- return -1;
- }
- if (isnan(stack[stptr-2]))
- ;
- else if (isnan(stack[stptr-1]))
- stack[stptr-2] = stack[stptr-1];
- else if (isnan(stack[stptr]))
- stack[stptr-2] = stack[stptr];
- else if (stack[stptr-2] < stack[stptr-1])
- stack[stptr-2] = DNAN;
- else if (stack[stptr-2] > stack[stptr])
- stack[stptr-2] = DNAN;
- stptr-=2;
- break;
- case OP_UN:
- if(stptr<0){
- rrd_set_error("RPN stack underflow");
- free(stack);
- return -1;
- }
- stack[stptr] = isnan(stack[stptr]) ? 1.0 : 0.0;
- break;
- case OP_END:
- break;
- }
- }
- if(stptr!=0){
- rrd_set_error("RPN final stack size != 1");
- free(stack);
- return -1;
- }
- im->gdes[gdi].data[++dataidx] = stack[0];
- }
- }
- free(stack);