root/lm-sensors/branches/lm-sensors-3.0.0/lib/data.c @ 4677

Revision 4677, 6.4 KB (checked in by khali, 7 years ago)

Chip types can no longer contain dashes. This makes it possible to
rewrite sensors_parse_chip_name() with a simpler algorithm. The new
code is smaller by about one third, and twice as fast on average
(5 times as fast in the most frequent case "foo-*".)

This closes ticket #2221.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/*
2    data.c - Part of libsensors, a Linux library for reading sensor data.
3    Copyright (c) 1998, 1999  Frodo Looijaard <frodol@dds.nl>
4    Copyright (C) 2007        Jean Delvare <khali@linux-fr.org>
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2 of the License, or
9    (at your option) any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19*/
20
21/* this define needed for strndup() */
22#define _GNU_SOURCE
23
24#include <stdlib.h>
25#include <string.h>
26
27#include "access.h"
28#include "error.h"
29#include "data.h"
30#include "sensors.h"
31#include "../version.h"
32
33const char *libsensors_version = LM_VERSION;
34
35sensors_chip *sensors_config_chips = NULL;
36int sensors_config_chips_count = 0;
37int sensors_config_chips_max = 0;
38
39sensors_bus *sensors_config_busses = NULL;
40int sensors_config_busses_count = 0;
41int sensors_config_busses_max = 0;
42
43sensors_chip_features *sensors_proc_chips = NULL;
44int sensors_proc_chips_count = 0;
45int sensors_proc_chips_max = 0;
46
47sensors_bus *sensors_proc_bus = NULL;
48int sensors_proc_bus_count = 0;
49int sensors_proc_bus_max = 0;
50
51static int sensors_substitute_chip(sensors_chip_name *name,int lineno);
52
53/*
54   Parse a chip name to the internal representation. These are valid names:
55
56     lm78-i2c-10-5e             *-i2c-10-5e
57     lm78-i2c-10-*              *-i2c-10-*
58     lm78-i2c-*-5e              *-i2c-*-5e
59     lm78-i2c-*-*               *-i2c-*-*
60     lm78-isa-10dd              *-isa-10dd
61     lm78-isa-*                 *-isa-*
62     lm78-*                     *-*
63
64   Here 'lm78' can be any prefix. 'i2c' and 'isa' are
65   literal strings, just like all dashes '-' and wildcards '*'. '10' can
66   be any decimal i2c bus number. '5e' can be any hexadecimal i2c device
67   address, and '10dd' any hexadecimal isa address.
68
69   The 'prefix' part in the result is freshly allocated. All old contents
70   of res is overwritten. res itself is not allocated. In case of an error
71   return (ie. != 0), res is undefined, but all allocations are undone.
72*/
73
74int sensors_parse_chip_name(const char *name, sensors_chip_name *res)
75{
76        char *dash;
77
78        /* First, the prefix. It's either "*" or a real chip name. */
79        if (!strncmp(name, "*-", 2)) {
80                res->prefix = SENSORS_CHIP_NAME_PREFIX_ANY;
81                name += 2;
82        } else {
83                if (!(dash = strchr(name, '-')))
84                        return -SENSORS_ERR_CHIP_NAME;
85                res->prefix = strndup(name, dash - name);
86                if (!res->prefix)
87                        sensors_fatal_error("sensors_parse_chip_name",
88                                            "Allocating name prefix");
89                name = dash + 1;
90        }
91
92        /* Then we have either a sole "*" (all chips with this name) or a bus
93           type and an address. */
94        if (!strcmp(name, "*")) {
95                res->bus = SENSORS_CHIP_NAME_BUS_ANY;
96                res->addr = SENSORS_CHIP_NAME_ADDR_ANY;
97                return 0;
98        }
99
100        if (!(dash = strchr(name, '-')))
101                goto ERROR;
102        if (!strncmp(name, "i2c", dash - name))
103                res->bus = SENSORS_CHIP_NAME_BUS_ANY_I2C;
104        else if (!strncmp(name, "isa", dash - name))
105                res->bus = SENSORS_CHIP_NAME_BUS_ISA;
106        else if (!strncmp(name, "pci", dash - name))
107                res->bus = SENSORS_CHIP_NAME_BUS_PCI;
108        else
109                goto ERROR;
110        name = dash + 1;
111
112        /* Some bus types (i2c) have an additional bus number. For these, the
113           next part is either a "*" (any bus of that type) or a decimal
114           number. */
115        switch (res->bus) {
116        case SENSORS_CHIP_NAME_BUS_ANY_I2C:
117                if (!strncmp(name, "*-", 2)) {
118                        name += 2;
119                        break;
120                }
121
122                res->bus = strtoul(name, &dash, 10);
123                if (*name == '\0' || *dash != '-' || res->bus < 0)
124                        goto ERROR;
125                name = dash + 1;
126        }
127
128        /* Last part is the chip address, or "*" for any address. */
129        if (!strcmp(name, "*")) {
130                res->addr = SENSORS_CHIP_NAME_ADDR_ANY;
131        } else {
132                res->addr = strtoul(name, &dash, 16);
133                if (*name == '\0' || *dash != '\0' || res->addr < 0)
134                        goto ERROR;
135        }
136
137        return 0;
138
139ERROR:
140        free(res->prefix);
141        return -SENSORS_ERR_CHIP_NAME;
142}
143
144int sensors_snprintf_chip_name(char *str, size_t size,
145                               const sensors_chip_name *chip)
146{
147        if (sensors_chip_name_has_wildcards(chip))
148                return -SENSORS_ERR_WILDCARDS;
149
150        switch (chip->bus) {
151        case SENSORS_CHIP_NAME_BUS_ISA:
152                return snprintf(str, size, "%s-isa-%04x", chip->prefix,
153                                chip->addr);
154        case SENSORS_CHIP_NAME_BUS_PCI:
155                return snprintf(str, size, "%s-pci-%04x", chip->prefix,
156                                chip->addr);
157        default:
158                return snprintf(str, size, "%s-i2c-%d-%02x", chip->prefix,
159                                chip->bus, chip->addr);
160        }
161}
162
163int sensors_parse_i2cbus_name(const char *name, int *res)
164{
165  char *endptr;
166
167  if (strncmp(name,"i2c-",4)) {
168    return -SENSORS_ERR_BUS_NAME;
169  }
170  name += 4;
171  *res = strtoul(name, &endptr, 10);
172  if (*name == '\0' || *endptr != '\0' || *res < 0)
173    return -SENSORS_ERR_BUS_NAME;
174  return 0;
175}
176
177
178int sensors_substitute_chip(sensors_chip_name *name,int lineno)
179{
180  int i,j;
181  for (i = 0; i < sensors_config_busses_count; i++)
182    if (sensors_config_busses[i].number == name->bus)
183      break;
184
185  if (i == sensors_config_busses_count) {
186    sensors_parse_error("Undeclared i2c bus referenced",lineno);
187    name->bus = sensors_proc_bus_count;
188    return -SENSORS_ERR_BUS_NAME;
189  }
190
191  /* Compare the adapter names */
192  for (j = 0; j < sensors_proc_bus_count; j++) {
193    if (!strcmp(sensors_config_busses[i].adapter,
194                sensors_proc_bus[j].adapter)) {
195      name->bus = sensors_proc_bus[j].number;
196      return 0;
197    }
198  }
199
200  /* We did not find anything. sensors_proc_bus_count is not a valid
201     bus number, so it will never be matched. Good. */
202  name->bus = sensors_proc_bus_count;
203  return 0;
204}
205
206     
207int sensors_substitute_busses(void)
208{
209  int err,i,j,lineno;
210  sensors_chip_name_list *chips;
211  int res=0;
212 
213  for(i = 0; i < sensors_config_chips_count; i++) {
214    lineno = sensors_config_chips[i].lineno;
215    chips = &sensors_config_chips[i].chips;
216    for(j = 0; j < chips->fits_count; j++)
217      if ((chips->fits[j].bus != SENSORS_CHIP_NAME_BUS_ISA) &&
218          (chips->fits[j].bus != SENSORS_CHIP_NAME_BUS_PCI) &&
219          (chips->fits[j].bus != SENSORS_CHIP_NAME_BUS_ANY) &&
220          (chips->fits[j].bus != SENSORS_CHIP_NAME_BUS_ANY_I2C))
221        if ((err = sensors_substitute_chip(chips->fits+j, lineno)))
222          res = err;
223  }
224  return res;
225}
Note: See TracBrowser for help on using the browser.