1 /* -*- mode: c; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: t -*-
3 * Conky, a system monitor, based on torsmo
5 * Any original torsmo code is licensed under the BSD license
7 * All code written since the fork of torsmo is licensed under the GPL
9 * Please see COPYING for details
11 * Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen
12 * Copyright (c) 2005-2009 Brenden Matthews, Philip Kovacs, et. al.
14 * All rights reserved.
16 * This program is free software: you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation, either version 3 of the License, or
19 * (at your option) any later version.
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 * You should have received a copy of the GNU General Public License
26 * along with this program. If not, see <http://www.gnu.org/licenses/>.
28 * vim: ts=4 sw=4 noet ai cindent syntax=c
41 /* find the operand in the given expression
42 * returns the index of the first op character or -1 on error
44 int find_match_op(const char *expr)
48 for (idx = 0; idx < strlen(expr); idx++) {
52 if (expr[idx + 1] != '=')
64 int get_match_type(const char *expr)
69 if ((idx = find_match_op(expr)) == -1)
73 if (*str == '=' && *(str + 1) == '=')
75 else if (*str == '!' && *(str + 1) == '=')
77 else if (*str == '>') {
78 if (*(str + 1) == '=')
81 } else if (*str == '<') {
82 if (*(str + 1) == '=')
91 /* generic compare function
93 * v is actually the difference of the compared values. For strings
94 * this is equal to the output of str(n)cmp(). Use a macro here, as
95 * it's type-independent.
97 #define COMPARE(v, t) \
99 case OP_GT: return (v > 0); \
100 case OP_LT: return (v < 0); \
101 case OP_EQ: return (v == 0); \
102 case OP_GEQ: return (v >= 0); \
103 case OP_LEQ: return (v <= 0); \
104 case OP_NEQ: return (v != 0); \
108 int lcompare(long a, enum match_type mtype, long b)
110 DBGP2("comparing longs '%ld' and '%ld'", a, b);
111 COMPARE((a - b), mtype);
113 int dcompare(double a, enum match_type mtype, double b)
115 DBGP2("comparing doubles '%.lf' and '%.lf'", a, b);
116 COMPARE((a - b), mtype);
119 int scompare(const char *a, enum match_type mtype, const char *b)
121 DBGP2("comparing strings '%s' and '%s'", a, b);
122 COMPARE(strcmp(a, b), mtype);
125 enum arg_type get_arg_type(const char *arg)
130 e = arg + strlen(arg);
134 while (*e && *e == ' ')
136 while (p != e && *p == ' ')
139 if (*p == '"' && *e == '"')
142 if (*p == '-') //allow negative values
163 char *arg_to_string(const char *arg)
170 while (*start && *start == ' ')
172 if (!(*(start++) == '"'))
174 while (start[len] != '"')
176 return strndup(start, len);
178 double arg_to_double(const char *arg)
181 if (sscanf(arg, "%lf", &d) != 1) {
182 NORM_ERR("converting '%s' to double failed", arg);
187 long arg_to_long(const char *arg)
190 if (sscanf(arg, "%ld", &l) != 1) {
191 NORM_ERR("converting '%s' to long failed", arg);
196 int compare(const char *expr)
200 enum arg_type type1, type2;
202 idx = find_match_op(expr);
203 mtype = get_match_type(expr);
205 if (!idx || mtype == -1) {
206 NORM_ERR("failed to parse compare string '%s'", expr);
210 expr_dup = strdup(expr);
211 expr_dup[idx] = '\0';
212 if (expr_dup[idx + 1] == '=')
213 expr_dup[++idx] = '\0';
215 type1 = get_arg_type(expr_dup);
216 type2 = get_arg_type(expr_dup + idx + 1);
217 if (type1 == ARG_LONG && type2 == ARG_DOUBLE)
219 if (type1 == ARG_DOUBLE && type2 == ARG_LONG)
221 if (type1 != type2) {
222 NORM_ERR("trying to compare args '%s' and '%s' of different type",
223 expr_dup, (expr_dup + idx + 1));
230 a = arg_to_string(expr_dup);
231 b = arg_to_string(expr_dup + idx + 1);
232 idx = scompare(a, mtype, b);
238 return lcompare(arg_to_long(expr_dup), mtype,
239 arg_to_long(expr_dup + idx + 1));
241 return dcompare(arg_to_double(expr_dup), mtype,
242 arg_to_double(expr_dup + idx + 1));