[Nut-upsdev] upsdrv_print_ups_list and afferant reflections

Jonathan Dion dion.jonathan at gmail.com
Thu Aug 10 06:12:46 UTC 2006


On 8/9/06, Peter Selinger <selinger at mathstat.dal.ca> wrote:
> Hi Jonathan,
>
> I had a brief look at the parser. Here are some cases where I think
> the parser will malfunction:
>
> Name: APC Back-UPS 800         # the parser will set value="APC"

The program print-ups-list don't use other tag than VendorID and
Product ID for the moment. I would of course manage this case when I'd
need it

> VendorID:0x0001                # the parser will not see the ":"

You are right

> ProductID: 0002                # missing "0x"

The parser should add the 0x. It is a good idea

> ====                           # the parser will not recognize this line

You are right. Didn't think of this case

> Name: XYZ UPS 1000
> VendorID: 0x0003
> ProductID: 0x0004
> ===
> Name: XYZ UPS 1001
> VendorID: 0x0005               # since productID != 0 (line 152), the
>                                # parser will call print_ups(0005,0004), a bug

For once you are wrong here ^^. The "===" line set up productID and
vendorID to 0, so it won't call print_ups. I used this mechanism to be
able to have VendorID and ProductID in any order.

> ProductID: 0x0006              # since vendorID != 0 (line 165), the
>                                # parser will call print_ups(0005,0006)
>
> Is it really appropriate to use the PCONF_CTX macros for parsing a
> key-value file format? Perhaps it would be better to have a function
> strip() (destructively remove white space, i.e., ' \t\n', from front
> and end of a string), and a function key_value, perhaps as follows:
>
> /* if line represents a key-value pair, return 1 and let key and value
>    point to key and value. "line" is updated destructively, and key
>    and value may point inside line. If not a key-value-pair, return 0
>    and leave line unchanged. */
> int key_value(char *line, char **key, char **value) {
>     char *p;
>
>     p = strchr(line, ':');
>     if (!p) {
>        return 0;
>     }
>     *p = 0;
>     *key = strip(line);
>     *value = strip(value);
>     return 1;
> }
>
> Then the parse() function could be something simple and reliable, like:
>
> void parse(FILE *pipe) {
>      char line[100];
>      char *p, *key, *value;
>      int l = 0;
>      int productid = 0, vendorid = 0, ...;
>      int have_record = 0;
>
>      while (getline(line, 100, pipe) >= 0) {
>          l++;
>          p = strip(line);
>          if (*p == 0 || *p == '#') { /* comment, blank line */
>             continue;
>          } else if (key_value(p, &key, &value)) {
>             if (strcasecmp(key, "ProductID") == 0) {
>                productid = parse_hex(value);
>             } else if (strcasecmp(key, "VendorID") == 0) {
>                vendorid = parse_hex(value);
>             } else if (...) {
>                ...
>             } else {
>                upsdebugx("Warning: unknown key %s in line %d\n", key, l);
>             }
>             have_record = 1;
>             continue;
>          } else if (*p == '=') {  /* any line starting with '=' */
>             if (have_record) {
>                 print_record(vendorid, productid, ...);
>             }
>          }
>      }
>      if (have_record) {
>          print_record(vendorid, productid, ...);
>      }
> }
>
> This would treat multi-word values, and all the other special cases,
> correctly, and would also extend easily to new key-value pairs.
>

You are totally right ! I like your solution, simple and elegant !

> -- Peter
>

Thank for your comments. I'll do the modifications

Jonathan



More information about the Nut-upsdev mailing list