1 /* Conky, a system monitor, based on torsmo
3 * Any original torsmo code is licensed under the BSD license
5 * All code written since the fork of torsmo is licensed under the GPL
7 * Please see COPYING for details
9 * Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen
10 * Copyright (c) 2005-2009 Brenden Matthews, Philip Kovacs, et. al.
12 * All rights reserved.
14 * This program is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation, either version 3 of the License, or
17 * (at your option) any later version.
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program. If not, see <http://www.gnu.org/licenses/>.
37 /* find the operand in the given expression
38 * returns the index of the first op character or -1 on error
40 int find_match_op(const char *expr)
44 for (idx = 0; idx < strlen(expr); idx++) {
48 if (expr[idx + 1] != '=')
60 int get_match_type(const char *expr)
65 if ((idx = find_match_op(expr)) == -1)
69 if (*str == '=' && *(str + 1) == '=')
71 else if (*str == '!' && *(str + 1) == '=')
73 else if (*str == '>') {
74 if (*(str + 1) == '=')
77 } else if (*str == '<') {
78 if (*(str + 1) == '=')
87 /* generic compare function
89 * v is actually the difference of the compared values. For strings
90 * this is equal to the output of str(n)cmp(). Use a macro here, as
91 * it's type-independent.
93 #define COMPARE(v, t) \
95 case OP_GT: return (v > 0); \
96 case OP_LT: return (v < 0); \
97 case OP_EQ: return (v == 0); \
98 case OP_GEQ: return (v >= 0); \
99 case OP_LEQ: return (v <= 0); \
100 case OP_NEQ: return (v != 0); \
104 int lcompare(long a, enum match_type mtype, long b)
106 DBGP2("comparing longs '%ld' and '%ld'", a, b);
107 COMPARE((a - b), mtype);
109 int dcompare(double a, enum match_type mtype, double b)
111 DBGP2("comparing doubles '%.lf' and '%.lf'", a, b);
112 COMPARE((a - b), mtype);
115 int scompare(const char *a, enum match_type mtype, const char *b)
117 DBGP2("comparing strings '%s' and '%s'", a, b);
118 COMPARE(strcmp(a, b), mtype);
121 enum arg_type get_arg_type(const char *arg)
126 e = arg + strlen(arg);
130 while (*e && *e == ' ')
132 while (p != e && *p == ' ')
135 if (*p == '"' && *e == '"')
138 if (*p == '-') //allow negative values
159 char *arg_to_string(const char *arg)
166 while (*start && *start == ' ')
168 if (!(*(start++) == '"'))
170 while (start[len] != '"')
172 return strndup(start, len);
174 double arg_to_double(const char *arg)
177 if (sscanf(arg, "%lf", &d) != 1) {
178 ERR("converting '%s' to double failed", arg);
183 long arg_to_long(const char *arg)
186 if (sscanf(arg, "%ld", &l) != 1) {
187 ERR("converting '%s' to long failed", arg);
192 int compare(const char *expr)
196 enum arg_type type1, type2;
198 idx = find_match_op(expr);
199 mtype = get_match_type(expr);
201 if (!idx || mtype == -1) {
202 ERR("failed to parse compare string '%s'", expr);
206 expr_dup = strdup(expr);
207 expr_dup[idx] = '\0';
208 if (expr_dup[idx + 1] == '=')
209 expr_dup[++idx] = '\0';
211 type1 = get_arg_type(expr_dup);
212 type2 = get_arg_type(expr_dup + idx + 1);
213 if (type1 == ARG_LONG && type2 == ARG_DOUBLE)
215 if (type1 == ARG_DOUBLE && type2 == ARG_LONG)
217 if (type1 != type2) {
218 ERR("trying to compare args '%s' and '%s' of different type",
219 expr_dup, (expr_dup + idx + 1));
226 a = arg_to_string(expr_dup);
227 b = arg_to_string(expr_dup + idx + 1);
228 idx = scompare(a, mtype, b);
234 return lcompare(arg_to_long(expr_dup), mtype,
235 arg_to_long(expr_dup + idx + 1));
237 return dcompare(arg_to_double(expr_dup), mtype,
238 arg_to_double(expr_dup + idx + 1));