[Nut-upsdev] upsdrv_print_ups_list and afferant reflections
Peter Selinger
selinger at mathstat.dal.ca
Thu Aug 10 14:54:51 UTC 2006
Jonathan Dion wrote:
>
...
> > 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.
No, the parser will set productID and vendorID to 0 *if* new_entry == 1.
(line 134). In the particular sequence that I gave, new_entry would
have been 0, so this bug would have happened.
> > 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 !
Oops, my solution also contains a bug similar to the new_entry bug:
should have been:
} else if (*p == '=') { /* any line starting with '=' */
if (have_record) {
print_record(vendorid, productid, ...);
}
have_record = 0;
product_id = 0;
vendor_id = 0;
...;
}
-- Peter
More information about the Nut-upsdev
mailing list