1 /* -*- mode: c; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: t -*-
2 * vim: ts=4 sw=4 noet ai cindent syntax=c
4 * Conky, a system monitor, based on torsmo
6 * Any original torsmo code is licensed under the BSD license
8 * All code written since the fork of torsmo is licensed under the GPL
10 * Please see COPYING for details
12 * Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen
13 * Copyright (c) 2005-2010 Brenden Matthews, Philip Kovacs, et. al.
15 * All rights reserved.
17 * This program is free software: you can redistribute it and/or modify
18 * it under the terms of the GNU General Public License as published by
19 * the Free Software Foundation, either version 3 of the License, or
20 * (at your option) any later version.
22 * This program is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
26 * You should have received a copy of the GNU General Public License
27 * along with this program. If not, see <http://www.gnu.org/licenses/>.
40 /* find the operand in the given expression
41 * returns the index of the first op character or -1 on error
43 int find_match_op(const char *expr)
47 for (idx = 0; idx < strlen(expr); idx++) {
51 if (expr[idx + 1] != '=')
63 int get_match_type(const char *expr)
68 if ((idx = find_match_op(expr)) == -1)
72 if (*str == '=' && *(str + 1) == '=')
74 else if (*str == '!' && *(str + 1) == '=')
76 else if (*str == '>') {
77 if (*(str + 1) == '=')
80 } else if (*str == '<') {
81 if (*(str + 1) == '=')
90 /* generic compare function
92 * v is actually the difference of the compared values. For strings
93 * this is equal to the output of str(n)cmp(). Use a macro here, as
94 * it's type-independent.
96 #define COMPARE(v, t) \
98 case OP_GT: return (v > 0); \
99 case OP_LT: return (v < 0); \
100 case OP_EQ: return (v == 0); \
101 case OP_GEQ: return (v >= 0); \
102 case OP_LEQ: return (v <= 0); \
103 case OP_NEQ: return (v != 0); \
107 int lcompare(long a, enum match_type mtype, long b)
109 DBGP2("comparing longs '%ld' and '%ld'", a, b);
110 COMPARE((a - b), mtype);
112 int dcompare(double a, enum match_type mtype, double b)
114 DBGP2("comparing doubles '%.lf' and '%.lf'", a, b);
115 COMPARE((a - b), mtype);
118 int scompare(const char *a, enum match_type mtype, const char *b)
120 DBGP2("comparing strings '%s' and '%s'", a, b);
121 COMPARE(strcmp(a, b), mtype);
124 enum arg_type get_arg_type(const char *arg)
129 e = arg + strlen(arg)-1;
131 while (p != e && *e && *e == ' ')
133 while (p != e && *p == ' ')
136 if (*p == '"' && *e == '"')
139 if (*p == '-') //allow negative values
160 char *arg_to_string(const char *arg)
167 while (*start && *start == ' ')
169 if (!(*(start++) == '"'))
171 while (start[len] != '"')
173 return strndup(start, len);
175 double arg_to_double(const char *arg)
178 if (sscanf(arg, "%lf", &d) != 1) {
179 NORM_ERR("converting '%s' to double failed", arg);
184 long arg_to_long(const char *arg)
187 if (sscanf(arg, "%ld", &l) != 1) {
188 NORM_ERR("converting '%s' to long failed", arg);
193 int compare(const char *expr)
197 enum arg_type type1, type2;
201 idx = find_match_op(expr);
202 mtype = get_match_type(expr);
204 if (!idx || mtype == -1) {
205 NORM_ERR("failed to parse compare string '%s'", expr);
209 expr_dup = strdup(expr);
210 expr_dup[idx] = '\0';
211 if (expr_dup[idx + 1] == '=')
212 expr_dup[++idx] = '\0';
214 type1 = get_arg_type(expr_dup);
215 type2 = get_arg_type(expr_dup + idx + 1);
216 if (type1 == ARG_BAD || type2 == ARG_BAD) {
217 NORM_ERR("Bad arguments: '%s' and '%s'", expr_dup, (expr_dup + idx + 1));
221 if (type1 == ARG_LONG && type2 == ARG_DOUBLE)
223 if (type1 == ARG_DOUBLE && type2 == ARG_LONG)
225 if (type1 != type2) {
226 NORM_ERR("trying to compare args '%s' and '%s' of different type",
227 expr_dup, (expr_dup + idx + 1));
235 a = arg_to_string(expr_dup);
236 b = arg_to_string(expr_dup + idx + 1);
237 idx = scompare(a, mtype, b);
244 lng_a = arg_to_long(expr_dup);
245 lng_b = arg_to_long(expr_dup + idx + 1);
247 return lcompare(lng_a, mtype, lng_b);
249 dbl_a = arg_to_double(expr_dup);
250 dbl_b = arg_to_double(expr_dup + idx + 1);
252 return lcompare(dbl_a, mtype, dbl_b);
253 case ARG_BAD: /* make_gcc_happy() */;