Import version 1.8.3
[s390-tools.git] / cpuplugd / terms.c
blob0d08e9e000c67bd8c668ceaf3f006e6062251ca8
1 /*
2 * Copyright IBM Corp 2007
3 * Author: Hans-Joachim Picht <hans@linux.vnet.ibm.com>
5 * The original parser contained in this file was written by
6 * Martin Schwidefsky <schwidefsky@de.ibm.com>
8 * Linux for System Hotplug Daemon
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the Free
12 * Software Foundation; either version 2 of the License, or (at your option)
13 * any later version.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include <unistd.h>
22 #include "cpuplugd.h"
24 static enum op_prio op_prio_table[] =
26 [OP_NEG] = OP_PRIO_ADD,
27 [OP_GREATER] = OP_PRIO_CMP,
28 [OP_LESSER] = OP_PRIO_CMP,
29 [OP_PLUS] = OP_PRIO_ADD,
30 [OP_MINUS] = OP_PRIO_ADD,
31 [OP_MULT] = OP_PRIO_MULT,
32 [OP_DIV] = OP_PRIO_MULT,
33 [OP_AND] = OP_PRIO_AND,
34 [OP_OR] = OP_PRIO_OR,
37 void free_term(struct term *fn)
39 if (!fn)
40 return;
41 switch (fn->op) {
42 case OP_SYMBOL_LOADAVG:
43 case OP_SYMBOL_RUNABLE:
44 case OP_SYMBOL_CPUS:
45 case OP_SYMBOL_IDLE:
46 case OP_CONST:
47 free(fn);
48 break;
49 case OP_NEG:
50 case OP_NOT:
51 free_term(fn->left);
52 free(fn);
53 break;
54 case OP_GREATER:
55 case OP_LESSER:
56 case OP_PLUS:
57 case OP_MINUS:
58 case OP_MULT:
59 case OP_DIV:
60 case OP_AND:
61 free_term(fn->left);
62 free_term(fn->right);
63 free(fn);
64 break;
65 case OP_OR:
66 free_term(fn->left);
67 free_term(fn->right);
68 free(fn);
69 break;
70 default:
71 break;
75 void print_term(struct term *fn)
77 switch (fn->op) {
78 case OP_SYMBOL_LOADAVG:
79 printf("loadavg");
80 break;
81 case OP_SYMBOL_RUNABLE:
82 printf("runable_proc");
83 break;
84 case OP_SYMBOL_CPUS:
85 printf("onumcpus");
86 break;
87 case OP_SYMBOL_IDLE:
88 printf("idle");
89 break;
90 case OP_SYMBOL_SWAPRATE:
91 printf("swaprate");
92 break;
93 case OP_SYMBOL_FREEMEM:
94 printf("freemem");
95 break;
96 case OP_SYMBOL_APCR:
97 printf("apcr");
98 break;
99 case OP_CONST:
100 printf("%f", fn->value);
101 break;
102 case OP_NEG:
103 printf("-(");
104 print_term(fn->left);
105 printf(")");
106 break;
107 case OP_NOT:
108 printf("!(");
109 print_term(fn->left);
110 printf(")");
111 break;
112 case OP_PLUS:
113 case OP_MINUS:
114 case OP_MULT:
115 case OP_DIV:
116 case OP_AND:
117 case OP_OR:
118 case OP_GREATER:
119 case OP_LESSER:
120 printf("(");
121 print_term(fn->left);
122 switch (fn->op) {
123 case OP_AND:
124 printf(") & (");
125 break;
126 case OP_OR:
127 printf(") | (");
128 break;
129 case OP_GREATER:
130 printf(") > (");
131 break;
132 case OP_LESSER:
133 printf(") < (");
134 break;
135 case OP_PLUS:
136 printf(") + (");
137 break;
138 case OP_MINUS:
139 printf(") - (");
140 break;
141 case OP_MULT:
142 printf(") * (");
143 break;
144 case OP_DIV:
145 printf(") / (");
146 break;
147 case OP_CONST:
148 printf("%f", fn->value);
149 break;
150 case OP_SYMBOL_LOADAVG:
151 case OP_SYMBOL_RUNABLE:
152 case OP_SYMBOL_CPUS:
153 case OP_SYMBOL_IDLE:
154 case OP_SYMBOL_APCR:
155 case OP_SYMBOL_SWAPRATE:
156 case OP_SYMBOL_FREEMEM:
157 case OP_NEG:
158 case OP_NOT:
159 case VAR_LOAD:
160 case VAR_RUN:
161 case VAR_ONLINE:
162 break;
164 print_term(fn->right);
165 printf(")");
166 break;
167 case VAR_LOAD:
168 case VAR_RUN:
169 case VAR_ONLINE:
170 break;
174 struct term *parse_term(char **p, enum op_prio prio)
176 static struct {
177 char *name;
178 enum operation symop;
179 } sym_names [] = {
180 { "loadavg", OP_SYMBOL_LOADAVG },
181 { "runable_proc", OP_SYMBOL_RUNABLE },
182 { "onumcpus", OP_SYMBOL_CPUS },
183 { "idle", OP_SYMBOL_IDLE },
184 { "swaprate", OP_SYMBOL_SWAPRATE },
185 { "apcr", OP_SYMBOL_APCR },
186 { "freemem", OP_SYMBOL_FREEMEM },
188 struct term *fn, *new;
189 enum operation op;
190 char *s;
191 double value;
192 unsigned int i, length;
194 s = *p;
195 fn = NULL;
196 if (*s == '-') {
197 s++;
198 fn = malloc(sizeof(struct term));
199 if (fn == NULL)
200 goto out_error;
201 if (isdigit(*s)) {
202 value = 0;
203 length = 0;
204 sscanf(s, "%lf %n", &value, &length);
205 fn->op = OP_CONST;
206 fn->value = -value;
207 s += length;
208 } else {
209 fn->op = OP_NEG;
210 fn->left = parse_term(&s, prio);
211 if (fn->left == NULL)
212 goto out_error;
214 } else if (*s == '!') {
215 s++;
216 fn = malloc(sizeof(struct term));
217 if (fn == NULL)
218 goto out_error;
219 fn->op = OP_NOT;
220 fn->left = parse_term(&s, prio);
221 if (fn->left == NULL)
222 goto out_error;
223 } else if (isdigit(*s)) {
224 value = 0;
225 length = 0;
226 sscanf(s, "%lf %n", &value, &length);
227 for (i = 0; i < length; i++)
228 s++;
229 fn = malloc(sizeof(struct term));
230 if (fn == NULL)
231 goto out_error;
232 fn->op = OP_CONST;
233 fn->value = value;
234 } else if (*s == '(') {
235 s++;
236 fn = parse_term(&s, OP_PRIO_NONE);
237 if (fn == NULL || *s != ')')
238 goto out_error;
239 s++;
240 } else {
241 for (i = 0; i < sizeof(sym_names)/sizeof(sym_names[0]); i++)
242 if (strncmp(s, sym_names[i].name,
243 strlen(sym_names[i].name)) == 0)
244 break;
245 if (i >= sizeof(sym_names)/sizeof(sym_names[0]))
246 /* Term doesn't make sense. */
247 goto out_error;
248 fn = malloc(sizeof(struct term));
249 if (fn == NULL)
250 goto out_error;
251 fn->op = sym_names[i].symop;
252 s += strlen(sym_names[i].name);
254 while (1) {
255 switch (*s) {
256 case '>':
257 op = OP_GREATER;
258 break;
259 case '<':
260 op = OP_LESSER;
261 break;
262 case '+':
263 op = OP_PLUS;
264 break;
265 case '-':
266 op = OP_MINUS;
267 break;
268 case '*':
269 op = OP_MULT;
270 break;
271 case '/':
272 op = OP_DIV;
273 break;
274 case '|':
275 op = OP_OR;
276 break;
277 case '&':
278 op = OP_AND;
279 break;
280 default:
281 goto out;
283 if (prio >= op_prio_table[op])
284 break;
285 s++;
286 new = malloc(sizeof(struct term));
287 new->op = op;
288 new->left = fn;
289 if (new == NULL)
290 goto out_error;
291 new->right = parse_term(&s, op_prio_table[op]);
292 if (new->right == NULL) {
293 free(new);
294 goto out_error;
296 fn = new;
298 out:
299 *p = s;
300 return fn;
301 out_error:
302 if (fn)
303 free_term(fn);
304 return NULL;
307 static double eval_double(struct term *fn, struct symbols *symbols)
310 double a;
311 double b;
312 double sum;
313 switch (fn->op) {
314 case OP_SYMBOL_LOADAVG:
315 return symbols->loadavg;
316 case OP_SYMBOL_RUNABLE:
317 return symbols->runable_proc;
318 case OP_SYMBOL_CPUS:
319 return symbols->onumcpus;
320 case OP_SYMBOL_IDLE:
321 return symbols->idle;
322 case OP_SYMBOL_FREEMEM:
323 return symbols->freemem;
324 case OP_SYMBOL_APCR:
325 return symbols->apcr;
326 case OP_SYMBOL_SWAPRATE:
327 return symbols->swaprate;
328 case OP_CONST:
329 return fn->value;
330 case OP_NEG:
331 return -eval_double(fn->left, symbols);
332 case OP_PLUS:
333 return eval_double(fn->left, symbols) +
334 eval_double(fn->right, symbols);
335 case OP_MINUS:
336 return eval_double(fn->left, symbols) -
337 eval_double(fn->right, symbols);
338 case OP_MULT:
339 a = eval_double(fn->left, symbols);
340 b = eval_double(fn->right, symbols);
341 sum = a*b;
342 /*return eval_double(fn->left, symbols) *
343 eval_double(fn->right, symbols);*/
344 case OP_DIV:
345 a = eval_double(fn->left, symbols);
346 b = eval_double(fn->right, symbols);
347 sum = a/b;
348 return sum;
349 /*return eval_double(fn->left, symbols) /
350 eval_double(fn->right, symbols); */
351 case OP_NOT:
352 case OP_AND:
353 case OP_OR:
354 case OP_GREATER:
355 case OP_LESSER:
356 case VAR_LOAD:
357 case VAR_RUN:
358 case VAR_ONLINE:
359 fprintf(stderr, "Invalid term specified: %i\n", fn->op);
360 clean_up();
362 return 0;
365 int eval_term(struct term *fn, struct symbols *symbols)
367 if (fn == NULL || symbols == NULL)
368 return 0.0;
369 switch (fn->op) {
370 case OP_NOT:
371 return !eval_term(fn->left, symbols);
372 case OP_OR:
373 return eval_term(fn->left, symbols) == 1 ||
374 eval_term(fn->right, symbols) == 1;
375 case OP_AND:
376 return eval_term(fn->left, symbols) == 1 &&
377 eval_term(fn->right, symbols) == 1;
378 case OP_GREATER:
379 return eval_double(fn->left, symbols) >
380 eval_double(fn->right, symbols);
381 case OP_LESSER:
382 return eval_double(fn->left, symbols) <
383 eval_double(fn->right, symbols);
384 default:
385 return eval_double(fn, symbols) != 0.0;