]> arthur.barton.de Git - netdata.git/blob - src/eval.c
added RRDCALC management; preparation for expression evaluation
[netdata.git] / src / eval.c
1 #include "common.h"
2
3 // ----------------------------------------------------------------------------
4 // operators that work on 2 operands
5
6 static inline int isoperatorterm_word(const char s) {
7     if(isspace(s) || s == '(' || s == '$' || s == '!' || s == '-' || s == '+' || isdigit(s)) return 1;
8     return 0;
9 }
10
11 static inline int isoperatorterm_symbol(const char s) {
12     if(isoperatorterm_word(s) || isalpha(s)) return 1;
13     return 0;
14 }
15
16 static inline int parse_and(const char **string) {
17     const char *s = *string;
18
19     // AND
20     if((s[0] == 'A' || s[0] == 'a') && (s[1] == 'N' || s[1] == 'n') && (s[2] == 'D' || s[2] == 'd') && isoperatorterm_word(s[3])) {
21         *string = &s[4];
22         return 1;
23     }
24
25     // &&
26     if(s[0] == '&' && s[1] == '&' && isoperatorterm_symbol(s[2])) {
27         *string = &s[2];
28         return 1;
29     }
30
31     return 0;
32 }
33
34 static inline int parse_or(const char **string) {
35     const char *s = *string;
36
37     // OR
38     if((s[0] == 'O' || s[0] == '0') && (s[1] == 'R' || s[1] == 'r') && isoperatorterm_word(s[2])) {
39         *string = &s[3];
40         return 1;
41     }
42
43     // ||
44     if(s[0] == '|' && s[1] == '|' && isoperatorterm_symbol(s[2])) {
45         *string = &s[2];
46         return 1;
47     }
48
49     return 0;
50 }
51
52 static inline int parse_greater_than_or_equal(const char **string) {
53     const char *s = *string;
54
55     // >=
56     if(s[0] == '>' && s[1] == '=' && isoperatorterm_symbol(s[2])) {
57         *string = &s[2];
58         return 1;
59     }
60
61     return 0;
62 }
63
64 static inline int parse_less_than_or_equal(const char **string) {
65     const char *s = *string;
66
67     // <=
68     if (s[0] == '<' && s[1] == '=' && isoperatorterm_symbol(s[2])) {
69         *string = &s[2];
70         return 1;
71     }
72
73     return 0;
74 }
75
76 static inline int parse_greater(const char **string) {
77     const char *s = *string;
78
79     // >
80     if(s[0] == '>' && isoperatorterm_symbol(s[1])) {
81         *string = &s[1];
82         return 1;
83     }
84
85     return 0;
86 }
87
88 static inline int parse_less(const char **string) {
89     const char *s = *string;
90
91     // <
92     if(s[0] == '<' && isoperatorterm_symbol(s[1])) {
93         *string = &s[1];
94         return 1;
95     }
96
97     return 0;
98 }
99
100 static inline int parse_equal(const char **string) {
101     const char *s = *string;
102
103     // ==
104     if(s[0] == '=' && s[1] == '=' && isoperatorterm_symbol(s[2])) {
105         *string = &s[2];
106         return 1;
107     }
108
109     // =
110     if(s[0] == '=' && isoperatorterm_symbol(s[1])) {
111         *string = &s[1];
112         return 1;
113     }
114
115     return 0;
116 }
117
118 static inline int parse_not_equal(const char **string) {
119     const char *s = *string;
120
121     // !=
122     if(s[0] == '!' && s[1] == '=' && isoperatorterm_symbol(s[2])) {
123         *string = &s[2];
124         return 1;
125     }
126
127     // <>
128     if(s[0] == '<' && s[1] == '>' && isoperatorterm_symbol(s[2])) {
129         *string = &s[2];
130     }
131
132     return 0;
133 }
134
135 static inline int parse_multiply(const char **string) {
136     const char *s = *string;
137
138     // *
139     if(s[0] == '*' && isoperatorterm_symbol(s[1])) {
140         *string = &s[1];
141         return 1;
142     }
143
144     return 0;
145 }
146
147 static inline int parse_divide(const char **string) {
148     const char *s = *string;
149
150     // /
151     if(s[0] == '/' && isoperatorterm_symbol(s[1])) {
152         *string = &s[1];
153         return 1;
154     }
155
156     return 0;
157 }
158
159 static inline int parse_minus(const char **string) {
160     const char *s = *string;
161
162     // -
163     if(s[0] == '-' && isoperatorterm_symbol(s[1])) {
164         *string = &s[1];
165         return 1;
166     }
167
168     return 0;
169 }
170
171 static inline int parse_plus(const char **string) {
172     const char *s = *string;
173
174     // +
175     if(s[0] == '+' && isoperatorterm_symbol(s[1])) {
176         *string = &s[1];
177         return 1;
178     }
179
180     return 0;
181 }
182
183 // ----------------------------------------------------------------------------
184 // operators that affect a single operand
185
186 static inline int parse_not(const char **string) {
187     const char *s = *string;
188
189     // NOT
190     if((s[0] == 'N' || s[0] == 'n') && (s[1] == 'O' || s[1] == 'o') && (s[2] == 'T' || s[2] == 't') && isoperatorterm_word(s[3])) {
191         *string = &s[4];
192         return 1;
193     }
194
195     if(s[0] == EVAL_OPERATOR_NOT) {
196         *string = &s[1];
197         return 1;
198     }
199
200     return 0;
201 }
202
203 static struct operator {
204     const char *printas;
205     int precedence;
206     char id;
207     int (*parse)(const char **);
208 } operators[] = {
209         { "&&", 2, '&', parse_and },
210         { "||", 2, '|', parse_or },
211         { ">=", 3, '}', parse_greater_than_or_equal },
212         { "<=", 3, '{', parse_less_than_or_equal },
213         { "<>", 3, '~', parse_not_equal },
214         { "==", 3, '=', parse_equal },
215         { "<",  3, '<', parse_less },
216         { ">",  3, '>', parse_greater },
217         { "+",  4, EVAL_OPERATOR_PLUS, parse_plus },
218         { "-",  4, EVAL_OPERATOR_MINUS, parse_minus },
219         { "*",  5, '*', parse_multiply },
220         { "/",  5, '/', parse_divide },
221
222         // we should not put NOT in this list
223
224         { NULL, 0, EVAL_OPERATOR_NOP, NULL }
225 };
226
227 static inline char parse_operator(const char **s, int *precedence) {
228     int i;
229
230     for(i = 0 ; operators[i].parse != NULL ; i++)
231         if(operators[i].parse(s)) {
232             if(precedence) *precedence = operators[i].precedence;
233             return operators[i].id;
234         }
235
236     return EVAL_OPERATOR_NOP;
237 }
238
239 static inline EVAL_OPERAND *operand_alloc(int count) {
240     EVAL_OPERAND *op = calloc(1, sizeof(EVAL_OPERAND) + (sizeof(EVAL_VALUE) * count));
241     if(!op) fatal("Cannot allocate memory for OPERAND");
242
243     op->count = count;
244     return op;
245 }
246
247 static inline void operand_set_value_operand(EVAL_OPERAND *op, int pos, EVAL_OPERAND *value) {
248     if(pos >= op->count)
249         fatal("Invalid request to set position %d of OPERAND that has only %d values", pos + 1, op->count + 1);
250
251     op->ops[pos].type = EVAL_OPERAND_EXPRESSION;
252     op->ops[pos].expression = value;
253 }
254
255 // forward definitions
256 static inline EVAL_OPERAND *parse_operand(const char **string);
257
258 static inline EVAL_OPERAND *operand_alloc_single(const char **string, char type) {
259     EVAL_OPERAND *sub = parse_operand(string);
260     if(!sub) return NULL;
261
262     EVAL_OPERAND *op = operand_alloc(1);
263     if(!op) fatal("Cannot allocate memory for OPERAND");
264
265     op->operator = type;
266     operand_set_value_operand(op, 0, sub);
267     return op;
268 }
269
270 static inline EVAL_OPERAND *parse_operand(const char **string) {
271     const char *s = *string;
272     while(isspace(*s)) s++;
273
274     if(!*s) return NULL;
275     *string = s;
276
277     if(parse_not(string))
278         return operand_alloc_single(string, EVAL_OPERATOR_NOT);
279
280     if(parse_plus(string))
281         return operand_alloc_single(string, EVAL_OPERATOR_PLUS);
282
283     if(parse_minus(string))
284         return operand_alloc_single(string, EVAL_OPERATOR_MINUS);
285
286
287
288     return NULL;
289 }