[PATCH 6/6] libsensors4: Rewrite sensors_parse_chip_name

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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-*".)

---
 lib/data.c         |  152 +++++++++++++++++++++++-----------------------------
 lib/sensors.conf.5 |   16 +----
 2 files changed, 74 insertions(+), 94 deletions(-)

--- lm-sensors-3.orig/lib/data.c	2007-08-15 16:21:16.000000000 +0200
+++ lm-sensors-3/lib/data.c	2007-08-15 16:22:03.000000000 +0200
@@ -1,6 +1,7 @@
 /*
     data.c - Part of libsensors, a Linux library for reading sensor data.
     Copyright (c) 1998, 1999  Frodo Looijaard <frodol at dds.nl>
+    Copyright (C) 2007        Jean Delvare <khali at linux-fr.org>
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
@@ -17,6 +18,9 @@
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
+/* this define needed for strndup() */
+#define _GNU_SOURCE
+
 #include <stdlib.h>
 #include <string.h>
 
@@ -46,8 +50,8 @@ int sensors_proc_bus_max = 0;
 
 static int sensors_substitute_chip(sensors_chip_name *name,int lineno);
 
-/* Wow, this must be one of the ugliest functions I have ever written.
-   The idea is that it parses a chip name. These are valid names:
+/*
+   Parse a chip name to the internal representation. These are valid names:
 
      lm78-i2c-10-5e		*-i2c-10-5e
      lm78-i2c-10-*		*-i2c-10-*
@@ -56,103 +60,85 @@ static int sensors_substitute_chip(senso
      lm78-isa-10dd		*-isa-10dd
      lm78-isa-*			*-isa-*
      lm78-*			*-*
-     				*
-   Here 'lm78' can be any prefix. To complicate matters, such a prefix
-   can also contain dashes (like lm78-j, for example!). 'i2c' and 'isa' are
+
+   Here 'lm78' can be any prefix. 'i2c' and 'isa' are
    literal strings, just like all dashes '-' and wildcards '*'. '10' can
    be any decimal i2c bus number. '5e' can be any hexadecimal i2c device
    address, and '10dd' any hexadecimal isa address.
 
-   If '*' is used in prefixes, together with dashes, ambigious parses are
-   introduced. In that case, the prefix is kept as small as possible.
-
    The 'prefix' part in the result is freshly allocated. All old contents
    of res is overwritten. res itself is not allocated. In case of an error
    return (ie. != 0), res is undefined, but all allocations are undone.
-
-   Don't tell me there are bugs in here, because I'll start screaming :-)
 */
 
-int sensors_parse_chip_name(const char *orig_name, sensors_chip_name *res)
+int sensors_parse_chip_name(const char *name, sensors_chip_name *res)
 {
-  char *part2, *part3, *part4;
-  char *name = strdup(orig_name);
-  char *endptr;
+	char *dash;
 
-  if (! name)
-    sensors_fatal_error("sensors_parse_chip_name","Allocating new name");
-  /* First split name in upto four pieces. */
-  if ((part4 = strrchr(name,'-')))
-    *part4++ = '\0';
-  if ((part3 = strrchr(name,'-')))
-    *part3++ = '\0';
-  if ((part2 = strrchr(name,'-'))) 
-    *part2++ = '\0';
-
-  /* No dashes found? */
-  if (! part4) {
-    if (!strcmp(name,"*")) {
-      res->prefix = SENSORS_CHIP_NAME_PREFIX_ANY;
-      res->bus = SENSORS_CHIP_NAME_BUS_ANY;
-      res->addr = SENSORS_CHIP_NAME_ADDR_ANY;
-      goto SUCCES;
-    } else 
-      goto ERROR;
-  }
+	/* First, the prefix. It's either "*" or a real chip name. */
+	if (!strncmp(name, "*-", 2)) {
+		res->prefix = SENSORS_CHIP_NAME_PREFIX_ANY;
+		name += 2;
+	} else {
+		if (!(dash = strchr(name, '-')))
+			return -SENSORS_ERR_CHIP_NAME;
+		res->prefix = strndup(name, dash - name);
+		if (!res->prefix)
+			sensors_fatal_error("sensors_parse_chip_name",
+					    "Allocating name prefix");
+		name = dash + 1;
+	}
 
-  /* At least one dash found. Now part4 is either '*', or an address */
-  if (!strcmp(part4,"*"))
-    res->addr = SENSORS_CHIP_NAME_ADDR_ANY;
-  else {
-    res->addr = strtoul(part4, &endptr, 16);
-    if (*part4 == '\0' || *endptr != '\0' || res->addr < 0)
-      goto ERROR;
-  }
+	/* Then we have either a sole "*" (all chips with this name) or a bus
+	   type and an address. */
+	if (!strcmp(name, "*")) {
+		res->bus = SENSORS_CHIP_NAME_BUS_ANY;
+		res->addr = SENSORS_CHIP_NAME_ADDR_ANY;
+		return 0;
+	}
 
-  /* OK. So let's look at part3. It must either be the number of the
-     i2c bus (and then part2 *must* be "i2c"), or it must be "isa",
-     or, if part4 was "*", it belongs to 'prefix'. Or no second dash
-     was found at all, of course. */
-  if (! part3) {
-    if (res->addr == SENSORS_CHIP_NAME_ADDR_ANY) {
-      res->bus = SENSORS_CHIP_NAME_BUS_ANY;
-    } else
-      goto ERROR;
-  } else if (!strcmp(part3,"isa")) {
-    res->bus = SENSORS_CHIP_NAME_BUS_ISA;
-    if (part2)
-      *(part2-1) = '-';
-  } else if (!strcmp(part3,"pci")) {
-    res->bus = SENSORS_CHIP_NAME_BUS_PCI;
-    if (part2)
-      *(part2-1) = '-';
-  } else if (part2 && !strcmp(part2,"i2c") && !strcmp(part3,"*"))
-    res->bus = SENSORS_CHIP_NAME_BUS_ANY_I2C;
-  else if (part2 && !strcmp(part2,"i2c")) {
-    res->bus = strtoul(part3, &endptr, 10);
-    if (*part3 == '\0' || *endptr != '\0' || res->bus < 0)
-      goto ERROR;
-  } else if (res->addr == SENSORS_CHIP_NAME_ADDR_ANY) {
-    res->bus = SENSORS_CHIP_NAME_BUS_ANY;
-    if (part2)
-      *(part2-1) = '-';
-    *(part3-1) = '-';
-  } else
-    goto ERROR;
-    
-  if (!strcmp(name,"*"))
-    res->prefix = SENSORS_CHIP_NAME_PREFIX_ANY;
-  else if (! (res->prefix = strdup(name)))
-    sensors_fatal_error("sensors_parse_chip_name","Allocating new name");
-  goto SUCCES;
+	if (!(dash = strchr(name, '-')))
+		goto ERROR;
+	if (!strncmp(name, "i2c", dash - name))
+		res->bus = SENSORS_CHIP_NAME_BUS_ANY_I2C;
+	else if (!strncmp(name, "isa", dash - name))
+		res->bus = SENSORS_CHIP_NAME_BUS_ISA;
+	else if (!strncmp(name, "pci", dash - name))
+		res->bus = SENSORS_CHIP_NAME_BUS_PCI;
+	else
+		goto ERROR;
+	name = dash + 1;
+
+	/* Some bus types (i2c) have an additional bus number. For these, the
+	   next part is either a "*" (any bus of that type) or a decimal
+	   number. */
+	switch (res->bus) {
+	case SENSORS_CHIP_NAME_BUS_ANY_I2C:
+		if (!strncmp(name, "*-", 2)) {
+			name += 2;
+			break;
+		}
+
+		res->bus = strtoul(name, &dash, 10);
+		if (*name == '\0' || *dash != '-' || res->bus < 0)
+			goto ERROR;
+		name = dash + 1;
+	}
 
-SUCCES:
-  free(name);
-  return 0;
+	/* Last part is the chip address, or "*" for any address. */
+	if (!strcmp(name, "*")) {
+		res->addr = SENSORS_CHIP_NAME_ADDR_ANY;
+	} else {
+		res->addr = strtoul(name, &dash, 16);
+		if (*name == '\0' || *dash != '\0' || res->addr < 0)
+			goto ERROR;
+	}
+
+	return 0;
 
 ERROR:
-  free(name);
-  return -SENSORS_ERR_CHIP_NAME;
+	free(res->prefix);
+	return -SENSORS_ERR_CHIP_NAME;
 }
 
 int sensors_snprintf_chip_name(char *str, size_t size,
--- lm-sensors-3.orig/lib/sensors.conf.5	2007-06-25 16:12:05.000000000 +0200
+++ lm-sensors-3/lib/sensors.conf.5	2007-08-15 16:52:05.000000000 +0200
@@ -186,9 +186,7 @@ statement is ignored upto the next
 statement.
 
 A chip description is built from a couple of elements, separated by
-dashes. To complicate matters, sometimes an element can also contain
-dashes. This complicates the parsing algorithm, but is not too confusing
-for humans (we hope!).
+dashes.
 
 The first element is the name of the chip type. Sometimes a single driver
 implements several chip types, with several names. The driver documentation
@@ -216,10 +214,10 @@ the wildcard operator
 .I *
 for this element. 
 
-There are some folding rules for wildcards to make things easier for humans
-to read. Also, you can't specify the address if you wildcard the complete
-second element. The following are all valid chip type specification based
-on 
+Note that it wouldn't make any sense to specify the address without the
+bus type. For this reason, the address part is plain omitted when the bus
+type isn't specified.
+The following are all valid chip type specification based on
 .I lm78\-i2c\-1\-2d
 or
 .IR lm78\-isa\-0290 :
@@ -250,10 +248,6 @@ lm78\-*       
 *\-isa\-0290
 .sp 0
 *\-isa\-*
-.sp 0
-*\-*
-.sp 0
-*
 .RE
 
 .SS COMPUTE STATEMENT


-- 
Jean Delvare




[Index of Archives]     [Linux Kernel]     [Linux Hardware Monitoring]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]

  Powered by Linux