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