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-2008 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/>.
36 /* find the operand in the given expression
37 * returns the index of the first op character or -1 on error
39 int find_match_op(const char *expr)
43 for (idx = 0; idx < strlen(expr); idx++) {
47 if (expr[idx + 1] != '=')
59 int get_match_type(const char *expr)
64 if ((idx = find_match_op(expr)) == -1)
68 if (*str == '=' && *(str + 1) == '=')
70 else if (*str == '!' && *(str + 1) == '=')
72 else if (*str == '>') {
73 if (*(str + 1) == '=')
76 } else if (*str == '<') {
77 if (*(str + 1) == '=')
86 /* generic compare function
88 * v is actually the difference of the compared values. For strings
89 * this is equal to the output of str(n)cmp(). Use a macro here, as
90 * it's type-independent.
92 #define COMPARE(v, t) \
94 case OP_GT: return (v > 0); \
95 case OP_LT: return (v < 0); \
96 case OP_EQ: return (v == 0); \
97 case OP_GEQ: return (v >= 0); \
98 case OP_LEQ: return (v <= 0); \
99 case OP_NEQ: return (v != 0); \
103 int lcompare(long a, enum match_type mtype, long b)
105 DBGP2("comparing longs '%ld' and '%ld'", a, b);
106 COMPARE((a - b), mtype);
108 int dcompare(double a, enum match_type mtype, double b)
110 DBGP2("comparing doubles '%.lf' and '%.lf'", a, b);
111 COMPARE((a - b), mtype);
114 int scompare(const char *a, enum match_type mtype, const char *b)
116 DBGP2("comparing strings '%s' and '%s'", a, b);
117 COMPARE(strcmp(a, b), mtype);
120 enum arg_type get_arg_type(const char *arg)
125 e = arg + strlen(arg);
129 while (*e && *e == ' ')
131 while (p != e && *p == ' ')
134 if (*p == '"' && *e == '"')
137 if (*p == '-') //allow negative values
158 char *arg_to_string(const char *arg)
165 while (*start && *start == ' ')
167 if (!(*(start++) == '"'))
169 while (start[len] != '"')
171 return strndup(start, len);
173 double arg_to_double(const char *arg)
176 if (sscanf(arg, "%lf", &d) != 1) {
177 ERR("converting '%s' to double failed", arg);
182 long arg_to_long(const char *arg)
185 if (sscanf(arg, "%ld", &l) != 1) {
186 ERR("converting '%s' to long failed", arg);
191 int compare(const char *expr)
195 enum arg_type type1, type2;
197 idx = find_match_op(expr);
198 mtype = get_match_type(expr);
200 if (!idx || mtype == -1) {
201 ERR("failed to parse compare string '%s'", expr);
205 expr_dup = strdup(expr);
206 expr_dup[idx] = '\0';
207 if (expr_dup[idx + 1] == '=')
208 expr_dup[++idx] = '\0';
210 type1 = get_arg_type(expr_dup);
211 type2 = get_arg_type(expr_dup + idx + 1);
212 if (type1 == ARG_LONG && type2 == ARG_DOUBLE)
214 if (type1 == ARG_DOUBLE && type2 == ARG_LONG)
216 if (type1 != type2) {
217 ERR("trying to compare args '%s' and '%s' of different type",
218 expr_dup, (expr_dup + idx + 1));
225 a = arg_to_string(expr_dup);
226 b = arg_to_string(expr_dup + idx + 1);
227 idx = scompare(a, mtype, b);
233 return lcompare(arg_to_long(expr_dup), mtype,
234 arg_to_long(expr_dup + idx + 1));
236 return dcompare(arg_to_double(expr_dup), mtype,
237 arg_to_double(expr_dup + idx + 1));