@cryptotaxi247 / netdata-1 / commits / 3aefe0787

infix notation parser almost done; preparing the evaluator and variables lookup

Costa Tsaousis committed Aug 10, 2016 at 20:12 UTC 3aefe07876179e73131a7659e758bb13a2480006
7 files changed +563 -65
profile/benchmark-dictionary.c
-7
@@ -7,13 +7,6 @@
7 *
8 */
9
10 -#include <stdio.h>
11 -#include <stdlib.h>
12 -#include <inttypes.h>
13 -
14 -#include "dictionary.h"
15 -#include "main.h"
16 -#include "log.h"
10 #include "common.h"
11
12 struct myvalue {
profile/benchmark-registry.c
+3 -1
@@ -1,13 +1,15 @@
1
2 /*
3 * compile with
4 - * gcc -O1 -ggdb -Wall -Wextra -I ../src/ -I ../ -o benchmark-registry benchmark-registry.c ../src/dictionary.o ../src/log.o ../src/avl.o ../src/common.o ../src/appconfig.o ../src/web_buffer.o ../src/storage_number.o ../src/rrd.o -pthread -luuid -lm -DHAVE_CONFIG_H -DVARLIB_DIR="\"/tmp\""
4 + * gcc -O1 -ggdb -Wall -Wextra -I ../src/ -I ../ -o benchmark-registry benchmark-registry.c ../src/dictionary.o ../src/log.o ../src/avl.o ../src/common.o ../src/appconfig.o ../src/web_buffer.o ../src/storage_number.o ../src/rrd.o ../src/health.o -pthread -luuid -lm -DHAVE_CONFIG_H -DVARLIB_DIR="\"/tmp\""
5 */
6
7 char *hostname = "me";
8
9 #include "../src/registry.c"
10
11 +void netdata_cleanup_and_exit(int ret) { exit(ret); }
12 +
13 // ----------------------------------------------------------------------------
14 // TESTS
15
profile/test-eval.c new
+165
@@ -0,0 +1,165 @@
1 +
2 +/*
3 + * 1. build netdata (as normally)
4 + * 2. cd profile/
5 + * 3. compile with:
6 + * gcc -O1 -ggdb -Wall -Wextra -I ../src/ -I ../ -o test-eval test-eval.c ../src/log.o ../src/eval.o ../src/common.o -pthread
7 + *
8 + */
9 +
10 +#include "common.h"
11 +
12 +void netdata_cleanup_and_exit(int ret) { exit(ret); }
13 +
14 +void indent(int level, int show) {
15 + int i = level;
16 + while(i--) printf(" | ");
17 + if(show) printf(" \\_ ");
18 + else printf(" \\_ ");
19 +}
20 +
21 +void print_operand(EVAL_OPERAND *op, int level);
22 +
23 +void print_value(EVAL_VALUE *v, int level) {
24 + indent(level, 0);
25 +
26 + switch(v->type) {
27 + case EVAL_VALUE_INVALID:
28 + printf("VALUE (NOP)\n");
29 + break;
30 +
31 + case EVAL_VALUE_NUMBER:
32 + printf("VALUE %Lf (NUMBER)\n", v->number);
33 + break;
34 +
35 + case EVAL_VALUE_EXPRESSION:
36 + printf("VALUE (SUB-EXPRESSION)\n");
37 + print_operand(v->expression, level+1);
38 + break;
39 +
40 + default:
41 + printf("VALUE (INVALID type %d)\n", v->type);
42 + break;
43 +
44 + }
45 +}
46 +
47 +void print_operand(EVAL_OPERAND *op, int level) {
48 +
49 +// if(op->operator != EVAL_OPERATOR_NOP) {
50 + indent(level, 1);
51 + if(op->operator) printf("%c (OPERATOR %d, prec: %d)\n", op->operator, op->id, op->precedence);
52 + else printf("NOP (OPERATOR %d, prec: %d)\n", op->id, op->precedence);
53 +// }
54 +
55 + int i = op->count;
56 + while(i--) print_value(&op->ops[i], level + 1);
57 +}
58 +
59 +calculated_number evaluate(EVAL_OPERAND *op);
60 +
61 +calculated_number evaluate_value(EVAL_VALUE *v) {
62 + switch(v->type) {
63 + case EVAL_VALUE_NUMBER:
64 + return v->number;
65 +
66 + case EVAL_VALUE_EXPRESSION:
67 + return evaluate(v->expression);
68 +
69 + default:
70 + fatal("I don't know how to handle EVAL_VALUE type %d", v->type);
71 + }
72 +}
73 +
74 +calculated_number evaluate(EVAL_OPERAND *op) {
75 + calculated_number n1, n2, r;
76 +
77 + switch(op->operator) {
78 + case EVAL_OPERATOR_SIGN_PLUS:
79 + r = evaluate_value(&op->ops[0]);
80 + break;
81 +
82 + case EVAL_OPERATOR_SIGN_MINUS:
83 + r = -evaluate_value(&op->ops[0]);
84 + break;
85 +
86 + case EVAL_OPERATOR_PLUS:
87 + if(op->count != 2)
88 + fatal("Operator '%c' requires 2 values, but we have %d", op->operator, op->count);
89 + n1 = evaluate_value(&op->ops[0]);
90 + n2 = evaluate_value(&op->ops[1]);
91 + r = n1 + n2;
92 + printf("%Lf = %Lf %c %Lf\n", r, n1, op->operator, n2);
93 + break;
94 +
95 + case EVAL_OPERATOR_MINUS:
96 + if(op->count != 2)
97 + fatal("Operator '%c' requires 2 values, but we have %d", op->operator, op->count);
98 + n1 = evaluate_value(&op->ops[0]);
99 + n2 = evaluate_value(&op->ops[1]);
100 + r = n1 - n2;
101 + printf("%Lf = %Lf %c %Lf\n", r, n1, op->operator, n2);
102 + break;
103 +
104 + case EVAL_OPERATOR_MULTIPLY:
105 + if(op->count != 2)
106 + fatal("Operator '%c' requires 2 values, but we have %d", op->operator, op->count);
107 + n1 = evaluate_value(&op->ops[0]);
108 + n2 = evaluate_value(&op->ops[1]);
109 + r = n1 * n2;
110 + printf("%Lf = %Lf %c %Lf\n", r, n1, op->operator, n2);
111 + break;
112 +
113 + case EVAL_OPERATOR_DIVIDE:
114 + if(op->count != 2)
115 + fatal("Operator '%c' requires 2 values, but we have %d", op->operator, op->count);
116 + n1 = evaluate_value(&op->ops[0]);
117 + n2 = evaluate_value(&op->ops[1]);
118 + r = n1 / n2;
119 + printf("%Lf = %Lf %c %Lf\n", r, n1, op->operator, n2);
120 + break;
121 +
122 + case EVAL_OPERATOR_EXPRESSION_OPEN:
123 + printf("BEGIN SUB-EXPRESSION\n");
124 + r = evaluate_value(&op->ops[0]);
125 + printf("END SUB-EXPRESSION\n");
126 + break;
127 +
128 + case EVAL_OPERATOR_NOP:
129 + case EVAL_OPERATOR_VALUE:
130 + r = evaluate_value(&op->ops[0]);
131 + break;
132 +
133 + default:
134 + fatal("I don't know how to handle operator '%c'", op->operator);
135 + break;
136 + }
137 +
138 + return r;
139 +}
140 +
141 +void print_expression(EVAL_OPERAND *op, const char *failed_at, int error) {
142 + if(op) {
143 + printf("<expression root>\n");
144 + print_operand(op, 0);
145 + evaluate(op);
146 + free_expression(op);
147 + }
148 + else {
149 + printf("error: %d, failed_at: '%s'\n", error, (failed_at)?failed_at:"<NONE>");
150 + }
151 +}
152 +
153 +
154 +int main(int argc, char **argv) {
155 + if(argc != 2) {
156 + fprintf(stderr, "I need an epxression\n");
157 + exit(1);
158 + }
159 +
160 + const char *failed_at = NULL;
161 + int error;
162 + EVAL_OPERAND *op = parse_expression(argv[1], &failed_at, &error);
163 + print_expression(op, failed_at, error);
164 + return 0;
165 +}
src/common.c
+2
@@ -3,6 +3,8 @@
3 char *global_host_prefix = "";
4 int enable_ksm = 1;
5
6 +volatile sig_atomic_t netdata_exit = 0;
7 +
8 // time(NULL) in milliseconds
9 unsigned long long timems(void) {
10 struct timeval now;
src/eval.c
+359 -47
@@ -1,5 +1,11 @@
1 #include "common.h"
2
3 +static inline void skip_spaces(const char **string) {
4 + const char *s = *string;
5 + while(isspace(*s)) s++;
6 + *string = s;
7 +}
8 +
9 // ----------------------------------------------------------------------------
10 // operators that work on 2 operands
11
@@ -35,7 +41,7 @@ static inline int parse_or(const char **string) {
41 const char *s = *string;
42
43 // OR
38 - if((s[0] == 'O' || s[0] == '0') && (s[1] == 'R' || s[1] == 'r') && isoperatorterm_word(s[2])) {
44 + if((s[0] == 'O' || s[0] == 'o') && (s[1] == 'R' || s[1] == 'r') && isoperatorterm_word(s[2])) {
45 *string = &s[3];
46 return 1;
47 }
@@ -180,6 +186,39 @@ static inline int parse_plus(const char **string) {
186 return 0;
187 }
188
189 +static inline int parse_open_subexpression(const char **string) {
190 + const char *s = *string;
191 +
192 + // (
193 + if(s[0] == '(') {
194 + *string = &s[1];
195 + return 1;
196 + }
197 +
198 + return 0;
199 +}
200 +
201 +static inline int parse_close_subexpression(const char **string) {
202 + const char *s = *string;
203 +
204 + // (
205 + if(s[0] == ')') {
206 + *string = &s[1];
207 + return 1;
208 + }
209 +
210 + return 0;
211 +}
212 +
213 +static inline int parse_literal(const char **string, calculated_number *number) {
214 + char *end = NULL;
215 + *number = strtold(*string, &end);
216 + if(!end || *string == end) return 0;
217 +
218 + *string = end;
219 + return 1;
220 +}
221 +
222 // ----------------------------------------------------------------------------
223 // operators that affect a single operand
224
@@ -188,7 +227,7 @@ static inline int parse_not(const char **string) {
227
228 // NOT
229 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];
230 + *string = &s[3];
231 return 1;
232 }
233
@@ -200,46 +239,150 @@ static inline int parse_not(const char **string) {
239 return 0;
240 }
241
203 -static struct operator {
204 - const char *printas;
205 - int precedence;
242 +static struct operator_parser {
243 char id;
244 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 }
245 +} operator_parsers[] = {
246 + // the order in this list is important!
247 + // the first matching will be used
248 + // so place the longer of overlapping ones
249 + // at the top
250 +
251 + { EVAL_OPERATOR_AND, parse_and },
252 + { EVAL_OPERATOR_OR, parse_or },
253 + { EVAL_OPERATOR_GREATER_THAN_OR_EQUAL, parse_greater_than_or_equal },
254 + { EVAL_OPERATOR_LESS_THAN_OR_EQUAL, parse_less_than_or_equal },
255 + { EVAL_OPERATOR_NOT_EQUAL, parse_not_equal },
256 + { EVAL_OPERATOR_EQUAL, parse_equal },
257 + { EVAL_OPERATOR_LESS, parse_less },
258 + { EVAL_OPERATOR_GREATER, parse_greater },
259 + { EVAL_OPERATOR_PLUS, parse_plus },
260 + { EVAL_OPERATOR_MINUS, parse_minus },
261 + { EVAL_OPERATOR_MULTIPLY, parse_multiply },
262 + { EVAL_OPERATOR_DIVIDE, parse_divide },
263 +
264 + /* we should not put
265 + *
266 + * - NOT
267 + * - (
268 + * - )
269 + *
270 + * in this list
271 + */
272 +
273 + { EVAL_OPERATOR_NOP, NULL }
274 };
275
227 -static inline char parse_operator(const char **s, int *precedence) {
228 - int i;
276 +// ----------------------------------------------------------------------------
277 +// evaluation of operations
278 +
279 +calculated_number eval_and(EVAL_OPERAND *op) {
280 + return 0;
281 +}
282 +calculated_number eval_or(EVAL_OPERAND *op) {
283 + return 0;
284 +}
285 +calculated_number eval_greater_than_or_equal(EVAL_OPERAND *op) {
286 + return 0;
287 +}
288 +calculated_number eval_less_than_or_equal(EVAL_OPERAND *op) {
289 + return 0;
290 +}
291 +calculated_number eval_not_equal(EVAL_OPERAND *op) {
292 + return 0;
293 +}
294 +calculated_number eval_equal(EVAL_OPERAND *op) {
295 + return 0;
296 +}
297 +calculated_number eval_less(EVAL_OPERAND *op) {
298 + return 0;
299 +}
300 +calculated_number eval_greater(EVAL_OPERAND *op) {
301 + return 0;
302 +}
303 +calculated_number eval_plus(EVAL_OPERAND *op) {
304 + return 0;
305 +}
306 +calculated_number eval_minus(EVAL_OPERAND *op) {
307 + return 0;
308 +}
309 +calculated_number eval_multiply(EVAL_OPERAND *op) {
310 + return 0;
311 +}
312 +calculated_number eval_divide(EVAL_OPERAND *op) {
313 + return 0;
314 +}
315 +calculated_number eval_nop(EVAL_OPERAND *op) {
316 + return 0;
317 +}
318 +calculated_number eval_not(EVAL_OPERAND *op) {
319 + return 0;
320 +}
321 +calculated_number eval_sign_plus(EVAL_OPERAND *op) {
322 + return 0;
323 +}
324 +calculated_number eval_sign_minus(EVAL_OPERAND *op) {
325 + return 0;
326 +}
327 +
328 +static struct operator {
329 + const char *print_as;
330 + char precedence;
331 + calculated_number (*eval)(EVAL_OPERAND *op);
332 +} operators[256] = {
333 + // this is a random access array
334 + // we always access it with a known EVAL_OPERATOR_X
335 +
336 + [EVAL_OPERATOR_AND] = { "&&", 2, eval_and },
337 + [EVAL_OPERATOR_OR] = { "||", 2, eval_or },
338 + [EVAL_OPERATOR_GREATER_THAN_OR_EQUAL] = { ">=", 3, eval_greater_than_or_equal },
339 + [EVAL_OPERATOR_LESS_THAN_OR_EQUAL] = { "<=", 3, eval_less_than_or_equal },
340 + [EVAL_OPERATOR_NOT_EQUAL] = { "!=", 3, eval_not_equal },
341 + [EVAL_OPERATOR_EQUAL] = { "==", 3, eval_equal },
342 + [EVAL_OPERATOR_LESS] = { "<", 3, eval_less },
343 + [EVAL_OPERATOR_GREATER] = { ">", 3, eval_greater },
344 + [EVAL_OPERATOR_PLUS] = { "+", 4, eval_plus },
345 + [EVAL_OPERATOR_MINUS] = { "-", 4, eval_minus },
346 + [EVAL_OPERATOR_MULTIPLY] = { "*", 5, eval_multiply },
347 + [EVAL_OPERATOR_DIVIDE] = { "/", 5, eval_divide },
348 + [EVAL_OPERATOR_NOT] = { "!", 6, eval_not },
349 + [EVAL_OPERATOR_SIGN_PLUS] = { "+", 6, eval_sign_plus },
350 + [EVAL_OPERATOR_SIGN_MINUS] = { "-", 6, eval_sign_minus },
351 + [EVAL_OPERATOR_NOP] = { NULL, 7, eval_nop },
352 + [EVAL_OPERATOR_VALUE] = { NULL, 7, eval_nop },
353 + [EVAL_OPERATOR_EXPRESSION_OPEN] = { "(", 7, eval_nop },
354 +
355 + // this should exist in our evaluation list
356 + [EVAL_OPERATOR_EXPRESSION_CLOSE] = { ")", 7, eval_nop }
357 +};
358 +
359 +#define eval_precedence(operator) (operators[(unsigned char)(operator)].precedence)
360
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;
361 +// ----------------------------------------------------------------------------
362 +
363 +static inline char parse_operator(const char **string, int *precedence) {
364 + skip_spaces(string);
365 +
366 + int i;
367 + for(i = 0 ; operator_parsers[i].parse != NULL ; i++)
368 + if(operator_parsers[i].parse(string)) {
369 + if(precedence) *precedence = eval_precedence(operator_parsers[i].id);
370 + return operator_parsers[i].id;
371 }
372
373 return EVAL_OPERATOR_NOP;
374 }
375
376 +
377 static inline EVAL_OPERAND *operand_alloc(int count) {
378 + static int id = 1;
379 +
380 EVAL_OPERAND *op = calloc(1, sizeof(EVAL_OPERAND) + (sizeof(EVAL_VALUE) * count));
241 - if(!op) fatal("Cannot allocate memory for OPERAND");
381 + if(!op) fatal("Cannot allocate memory for OPERAND with %d slots", count);
382
383 + op->id = id++;
384 + op->operator = EVAL_OPERATOR_NOP;
385 + op->precedence = eval_precedence(EVAL_OPERATOR_NOP);
386 op->count = count;
387 return op;
388 }
@@ -248,42 +391,211 @@ static inline void operand_set_value_operand(EVAL_OPERAND *op, int pos, EVAL_OPE
391 if(pos >= op->count)
392 fatal("Invalid request to set position %d of OPERAND that has only %d values", pos + 1, op->count + 1);
393
251 - op->ops[pos].type = EVAL_OPERAND_EXPRESSION;
394 + op->ops[pos].type = EVAL_VALUE_EXPRESSION;
395 op->ops[pos].expression = value;
396 }
397
398 +static inline void operand_set_value_literal(EVAL_OPERAND *op, int pos, calculated_number value) {
399 + if(pos >= op->count)
400 + fatal("Invalid request to set position %d of OPERAND that has only %d values", pos + 1, op->count + 1);
401 +
402 + op->ops[pos].type = EVAL_VALUE_NUMBER;
403 + op->ops[pos].number = value;
404 +}
405 +
406 // forward definitions
256 -static inline EVAL_OPERAND *parse_operand(const char **string);
407 +static inline void operand_free(EVAL_OPERAND *op);
408 +static inline EVAL_OPERAND *parse_operand(const char **string, int *error);
409 +static inline EVAL_OPERAND *parse_operand1(const char **string, int *error);
410 +
411 +static inline void variable_free(VARIABLE *v) {
412 + free(v);
413 +}
414 +
415 +static inline void value_free(EVAL_VALUE *v) {
416 + switch(v->type) {
417 + case EVAL_VALUE_EXPRESSION:
418 + operand_free(v->expression);
419 + break;
420 +
421 + case EVAL_VALUE_VARIABLE:
422 + variable_free(v->variable);
423 + break;
424 +
425 + default:
426 + break;
427 + }
428 +}
429 +
430 +static inline void operand_free(EVAL_OPERAND *op) {
431 + if(op->count) {
432 + int i;
433 + for(i = op->count - 1; i >= 0 ;i--)
434 + value_free(&op->ops[i]);
435 + }
436 +
437 + free(op);
438 +}
439
258 -static inline EVAL_OPERAND *operand_alloc_single(const char **string, char type) {
259 - EVAL_OPERAND *sub = parse_operand(string);
440 +static inline EVAL_OPERAND *parse_operand_with_operator(const char **string, char type, int *error) {
441 + EVAL_OPERAND *sub = parse_operand1(string, error);
442 if(!sub) return NULL;
443
444 EVAL_OPERAND *op = operand_alloc(1);
263 - if(!op) fatal("Cannot allocate memory for OPERAND");
264 -
445 op->operator = type;
446 operand_set_value_operand(op, 0, sub);
447 return op;
448 }
449
270 -static inline EVAL_OPERAND *parse_operand(const char **string) {
271 - const char *s = *string;
272 - while(isspace(*s)) s++;
450 +static inline EVAL_OPERAND *parse_operand1(const char **string, int *error) {
451 + EVAL_OPERAND *op1 = NULL;
452 + calculated_number number;
453
274 - if(!*s) return NULL;
275 - *string = s;
454 + *error = EVAL_ERROR_OK;
455 +
456 + skip_spaces(string);
457 + if(!(**string)) {
458 + *error = EVAL_ERROR_MISSING_OPERAND;
459 + return NULL;
460 + }
461 +
462 + if(parse_not(string)) {
463 + op1 = parse_operand_with_operator(string, EVAL_OPERATOR_NOT, error);
464 + op1->precedence = eval_precedence(EVAL_OPERATOR_NOT);
465 + }
466 + else if(parse_plus(string)) {
467 + op1 = parse_operand_with_operator(string, EVAL_OPERATOR_SIGN_PLUS, error);
468 + op1->precedence = eval_precedence(EVAL_OPERATOR_SIGN_PLUS);
469 + }
470 + else if(parse_minus(string)) {
471 + op1 = parse_operand_with_operator(string, EVAL_OPERATOR_SIGN_MINUS, error);
472 + op1->precedence = eval_precedence(EVAL_OPERATOR_SIGN_MINUS);
473 + }
474 + else if(parse_open_subexpression(string)) {
475 + EVAL_OPERAND *sub = parse_operand(string, error);
476 + if(sub) {
477 + op1 = operand_alloc(1);
478 + op1->operator = EVAL_OPERATOR_EXPRESSION_OPEN;
479 + op1->precedence = eval_precedence(EVAL_OPERATOR_EXPRESSION_OPEN);
480 + operand_set_value_operand(op1, 0, sub);
481 + if(!parse_close_subexpression(string)) {
482 + *error = EVAL_ERROR_MISSING_CLOSE_SUBEXPRESSION;
483 + operand_free(op1);
484 + return NULL;
485 + }
486 + }
487 + }
488 +// else if(parse_variable(string)) {
489 +//
490 +// }
491 + else if(parse_literal(string, &number)) {
492 + op1 = operand_alloc(1);
493 + op1->operator = EVAL_OPERATOR_VALUE;
494 + operand_set_value_literal(op1, 0, number);
495 + }
496 + else if(*string)
497 + *error = EVAL_ERROR_UNKNOWN_OPERAND;
498 + else
499 + *error = EVAL_ERROR_MISSING_OPERAND;
500 +
501 + return op1;
502 +}
503 +
504 +static inline EVAL_OPERAND *parse_operand_rest(const char **string, int *error, EVAL_OPERAND *op1) {
505 + EVAL_OPERAND *op2 = NULL;
506 + char operator;
507 + int precedence;
508 +
509 + operator = parse_operator(string, &precedence);
510 + skip_spaces(string);
511 +
512 + if(operator != EVAL_OPERATOR_NOP) {
513 + op2 = parse_operand1(string, error);
514 + if(!op2) {
515 + operand_free(op1);
516 + return NULL;
517 + }
518 +
519 + EVAL_OPERAND *op = operand_alloc(2);
520 + op->operator = operator;
521 + op->precedence = precedence;
522 +
523 + operand_set_value_operand(op, 0, op1);
524 + operand_set_value_operand(op, 1, op2);
525 +
526 + if(op->precedence > op1->precedence && op1->count == 2 && op1->operator != '(' && op1->ops[1].type == EVAL_VALUE_EXPRESSION) {
527 + operand_set_value_operand(op, 0, op1->ops[1].expression);
528 + op1->ops[1].expression = op;
529 + op = op1;
530 + }
531 +
532 + return parse_operand_rest(string, error, op);
533 + }
534 + else if(**string == EVAL_OPERATOR_EXPRESSION_CLOSE) {
535 + ;
536 + }
537 + else if(**string) {
538 + if(op1) operand_free(op1);
539 + op1 = NULL;
540 + *error = EVAL_ERROR_MISSING_OPERATOR;
541 + }
542 +
543 + return op1;
544 +}
545 +
546 +static inline EVAL_OPERAND *parse_operand(const char **string, int *error) {
547 + EVAL_OPERAND *op1 = NULL;
548
277 - if(parse_not(string))
278 - return operand_alloc_single(string, EVAL_OPERATOR_NOT);
549 + op1 = parse_operand1(string, error);
550 + if(!op1) {
551 + *error = EVAL_ERROR_MISSING_OPERAND;
552 + return NULL;
553 + }
554 +
555 + return parse_operand_rest(string, error, op1);
556 +}
557
280 - if(parse_plus(string))
281 - return operand_alloc_single(string, EVAL_OPERATOR_PLUS);
558 +const char *eval_error(int error) {
559 + switch(error) {
560 + case EVAL_ERROR_OK:
561 + return "success";
562
283 - if(parse_minus(string))
284 - return operand_alloc_single(string, EVAL_OPERATOR_MINUS);
563 + case EVAL_ERROR_MISSING_CLOSE_SUBEXPRESSION:
564 + return "missing closing parenthesis";
565
566 + case EVAL_ERROR_UNKNOWN_OPERAND:
567 + return "unknown operand";
568
569 + case EVAL_ERROR_MISSING_OPERAND:
570 + return "expected operand";
571 +
572 + case EVAL_ERROR_MISSING_OPERATOR:
573 + return "expected operator";
574 +
575 + default:
576 + return "unknown error";
577 + }
578 +}
579 +
580 +EVAL_OPERAND *parse_expression(const char *string, const char **failed_at, int *error) {
581 + const char *s;
582 + int err = EVAL_ERROR_OK;
583 + unsigned long pos = 0;
584 +
585 + s = string;
586 + EVAL_OPERAND *op = parse_operand(&s, &err);
587 +
588 + if (failed_at) *failed_at = s;
589 + if (error) *error = err;
590 +
591 + if(!op) {
592 + pos = s - string + 1;
593 + error("failed to parse expression '%s': %s at character %lu (i.e.: '%s').", string, eval_error(err), pos, s);
594 + }
595 +
596 + return op;
597 +}
598
288 - return NULL;
599 +void free_expression(EVAL_OPERAND *op) {
600 + if(op) operand_free(op);
601 }
src/eval.h
+34 -8
@@ -7,16 +7,37 @@ typedef struct variable {
7 struct variable *next;
8 } VARIABLE;
9
10 -#define EVAL_OPERAND_INVALID 0
11 -#define EVAL_OPERAND_NUMBER 1
12 -#define EVAL_OPERAND_VARIABLE 2
13 -#define EVAL_OPERAND_EXPRESSION 3
10 +#define EVAL_VALUE_INVALID 0
11 +#define EVAL_VALUE_NUMBER 1
12 +#define EVAL_VALUE_VARIABLE 2
13 +#define EVAL_VALUE_EXPRESSION 3
14
15 // these are used for EVAL_OPERAND.operator
16 -#define EVAL_OPERATOR_NOP '\0'
17 -#define EVAL_OPERATOR_NOT '!'
18 -#define EVAL_OPERATOR_PLUS '+'
19 -#define EVAL_OPERATOR_MINUS '-'
16 +#define EVAL_OPERATOR_NOP '\0'
17 +#define EVAL_OPERATOR_VALUE ':'
18 +#define EVAL_OPERATOR_EXPRESSION_OPEN '('
19 +#define EVAL_OPERATOR_EXPRESSION_CLOSE ')'
20 +#define EVAL_OPERATOR_NOT '!'
21 +#define EVAL_OPERATOR_PLUS '+'
22 +#define EVAL_OPERATOR_MINUS '-'
23 +#define EVAL_OPERATOR_AND '&'
24 +#define EVAL_OPERATOR_OR '|'
25 +#define EVAL_OPERATOR_GREATER_THAN_OR_EQUAL 'G'
26 +#define EVAL_OPERATOR_LESS_THAN_OR_EQUAL 'L'
27 +#define EVAL_OPERATOR_NOT_EQUAL '~'
28 +#define EVAL_OPERATOR_EQUAL '='
29 +#define EVAL_OPERATOR_LESS '<'
30 +#define EVAL_OPERATOR_GREATER '>'
31 +#define EVAL_OPERATOR_MULTIPLY '*'
32 +#define EVAL_OPERATOR_DIVIDE '/'
33 +#define EVAL_OPERATOR_SIGN_PLUS 'P'
34 +#define EVAL_OPERATOR_SIGN_MINUS 'M'
35 +
36 +#define EVAL_ERROR_OK 0
37 +#define EVAL_ERROR_MISSING_CLOSE_SUBEXPRESSION 1
38 +#define EVAL_ERROR_UNKNOWN_OPERAND 2
39 +#define EVAL_ERROR_MISSING_OPERAND 3
40 +#define EVAL_ERROR_MISSING_OPERATOR 4
41
42 typedef struct eval_value {
43 int type;
@@ -29,10 +50,15 @@ typedef struct eval_value {
50 } EVAL_VALUE;
51
52 typedef struct eval_operand {
53 + int id;
54 char operator;
55 + int precedence;
56
57 int count;
58 EVAL_VALUE ops[];
59 } EVAL_OPERAND;
60
61 +extern EVAL_OPERAND *parse_expression(const char *string, const char **failed_at, int *error);
62 +extern void free_expression(EVAL_OPERAND *op);
63 +
64 #endif //NETDATA_EVAL_H
src/main.c
-2
@@ -2,8 +2,6 @@
2
3 extern void *cgroups_main(void *ptr);
4
5 -volatile sig_atomic_t netdata_exit = 0;
6 -
5 void netdata_cleanup_and_exit(int ret) {
6 netdata_exit = 1;
7