# vendor-xml.c

Go to the documentation of this file.

    00001
    00011 /* $Progeny$
    00012  *
    00013  * AUTHOR: John R. Daily <jdaily@progeny.com>
    00014  *
    00015  * Copyright 2002 Progeny Linux Systems, Inc.
    00016  * Copyright 2002 Hewlett-Packard Company
    00017  *
    00018  * Permission is hereby granted, free of charge, to any person obtaining a
    00019  * copy of this software and associated documentation files (the "Software"),
    00020  * to deal in the Software without restriction, including without limitation
    00021  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
    00022  * and/or sell copies of the Software, and to permit persons to whom the
    00023  * Software is furnished to do so, subject to the following conditions:
    00024  *
    00025  * The above copyright notice and this permission notice shall be included in
    00026  * all copies or substantial portions of the Software.
    00027  *
    00028  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    00029  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    00030  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
    00031  * THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    00032  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
    00033  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
    00034  * DEALINGS IN THE SOFTWARE.
    00035  */
    00036
    00037 #include "config.h"
    00038
    00039 #include <sys/types.h>
    00040
    00041 #include <assert.h>
    00042 #include <limits.h>
    00043 #include <stdio.h>
    00044 #include <string.h>
    00045
    00046 #include <expat.h>
    00047
    00048 #include <discover/discover.h>
    00049 #include <discover/discover-xml.h>
    00050
    00051 #include <discover/load-url.h>
    00052 #include <discover/utils.h>
    00053
    00055 struct discover_xml_vendor {
    00056     char *id;
    00057     char *name;
    00058     discover_xml_vendor_t *next;
    00059 };
    00060
    00061 static discover_xml_vendor_t *vendors[BUS_COUNT];
    00062
    00064 struct context {
    00065     discover_xml_vendor_t **vlist;
    00066
    00067     int unknown_level; /* How deep are we into unknown XML tags? */
    00068 };
    00069
    00070 static char *known_vendor_elements[] = {
    00071     "vendor",
    00072     "vendor_list",
    00073     NULL
    00074 };
    00075
    00076
    00077 static bool
    00078 unknown_vendor_element(const XML_Char * const tag)
    00079 {
    00080     int i;
    00081     for (i = 0; known_vendor_elements[i] != NULL; i++) {
    00082         if (strcmp(tag, known_vendor_elements[i]) == 0)
    00083             return false;
    00084     }
    00085     return true;
    00086 }
    00087
    00088 static void
    00089 start_element(void *ctx, const XML_Char *name, const XML_Char *attrs[])
    00090 {
    00091     struct context *context = ctx;
    00092     int i;
    00093     char *vid, *vname;
    00094     discover_xml_vendor_t *next, **vlist;
    00095
    00096     assert(context != NULL);
    00097     assert(name != NULL);
    00098     assert(attrs != NULL);
    00099
    00100     if (unknown_vendor_element(name)) {
    00101         context->unknown_level++;
    00102         return;
    00103     }
    00104
    00105     if (context->unknown_level > 0) {
    00106         return;
    00107     }
    00108
    00109     if (strcmp(name, "vendor") == 0) {
    00110         vid = vname = NULL;
    00111         for (i = 0; attrs[i]; i += 2) {
    00112             if (strcmp(attrs[i], "id") == 0) {
    00113                 vid = (char *) attrs[i + 1];
    00114             } else if (strcmp(attrs[i], "name") == 0) {
    00115                 vname = (char *) attrs[i + 1];
    00116             }
    00117         }
    00118
    00119         assert(vid != NULL);
    00120         assert(vname != NULL);
    00121
    00122         vlist = context->vlist;
    00123         next = *vlist;
    00124         *vlist = discover_xml_vendor_new();
    00125         (*vlist)->id = _discover_xstrdup(vid);
    00126         (*vlist)->name = _discover_xstrdup(vname);
    00127         (*vlist)->next = next;
    00128     }
    00129 }
    00130
    00131 static void
    00132 end_element(void *ctx, const XML_Char *name)
    00133 {
    00134     struct context *context = ctx;
    00135
    00136     assert(context != NULL);
    00137     assert(name != NULL);
    00138
    00139     if (unknown_vendor_element(name)) {
    00140         context->unknown_level--;
    00141         return;
    00142     }
    00143
    00144     if (context->unknown_level > 0) {
    00145         return;
    00146     }
    00147
    00148     /*
    00149      * We don't have any end tags to worry about, but if we did, they
    00150      * would be handled here.
    00151      */
    00152 }
    00153
    00166 /* Sshh!  Don't tell, but this doesn't actually do any merging at all.
    00167  * Instead, it simply inserts newer entries at the front of the list,
    00168  * meaning that vendor info found later supersedes info found earlier.
    00169  * This gives the illusion of merging, but potentially wastes memory
    00170  * with duplicates.
    00171  */
    00172 void
    00173 discover_xml_merge_vendor_url(discover_xml_vendor_t **vlist,
    00174                               char *url, discover_error_t *status)
    00175 {
    00176     XML_Parser parser;
    00177     struct context context;
    00178
    00179     assert(url != NULL);
    00180     assert(status != NULL);
    00181
    00182     status->code = 0;
    00183
    00184     context.vlist = vlist;
    00185     context.unknown_level = 0;
    00186
    00187     parser = XML_ParserCreate(NULL);
    00188     XML_SetElementHandler(parser, start_element, end_element);
    00189     XML_SetUserData(parser, &context);
    00190
    00191     if (!_discover_load_url(url, parser)) {
    00192         XML_ParserFree(parser);
    00193         status->code = DISCOVER_EIO;
    00194         return;
    00195     }
    00196
    00197     if (!XML_Parse(parser, "", 0, 1)) {
    00198         XML_ParserFree(parser);
    00199         status->code = DISCOVER_EXML;
    00200         return;
    00201     }
    00202
    00203     XML_ParserFree(parser);
    00204
    00205     return;
    00206 }
    00207
    00214 discover_xml_vendor_t *
    00215 discover_xml_get_vendors(discover_bus_t bus, discover_error_t *status)
    00216 {
    00217     discover_xml_url_t *urls, *i;
    00218     char *url;
    00219
    00220     assert(status != NULL);
    00221
    00222     status->code = 0;
    00223
    00224     if (!vendors[bus]) {
    00225         urls = discover_xml_get_data_urls(bus, VENDOR_TYPE, status);
    00226         if (status->code != 0) {
    00227             return NULL;
    00228         }
    00229
    00230         for (i = urls;
    00231              i;
    00232              i = discover_xml_url_get_next(i)) {
    00233             url = discover_xml_url_get_url(i);
    00234             discover_xml_merge_vendor_url(&(vendors[bus]), url, status);
    00235             if (status->code != 0) {
    00236                 return NULL;
    00237             }
    00238         }
    00239     }
    00240
    00241     return vendors[bus];
    00242 }
    00243
    00247 void
    00248 discover_xml_free_vendors(void)
    00249 {
    00250     int i;
    00251     for (i = 0; i < BUS_COUNT; i++) {
    00252         discover_xml_vendor_free(vendors[i]);
    00253         vendors[i] = NULL;
    00254     }
    00255 }
    00256
    00263 char *
    00264 discover_xml_vendor_id2name(discover_xml_vendor_t *vendors, char *id)
    00265 {
    00266     discover_xml_vendor_t *vendor;
    00267     char *name;
    00268
    00269     assert(vendors != NULL);
    00270     assert(id != NULL);
    00271
    00272     name = NULL;
    00273
    00274     for (vendor = vendors;
    00275          vendor;
    00276          vendor = vendor->next) {
    00277         if (strcmp(id, vendor->id) == 0) {
    00278             name = vendor->name;
    00279             break;
    00280         }
    00281     }
    00282
    00283     return name;
    00284 }
    00285
    00289 char *
    00290 discover_xml_vendor_get_id(discover_xml_vendor_t *vendor)
    00291 {
    00292     assert(vendor != NULL);
    00293
    00294     return vendor->id;
    00295 }
    00296
    00300 char *
    00301 discover_xml_vendor_get_name(discover_xml_vendor_t *vendor)
    00302 {
    00303     assert(vendor != NULL);
    00304
    00305     return vendor->name;
    00306 }
    00307
    00311 discover_xml_vendor_t *
    00312 discover_xml_vendor_get_next(discover_xml_vendor_t *vendor)
    00313 {
    00314     assert(vendor != NULL);
    00315
    00316     return vendor->next;
    00317 }
    00318
    00322 discover_xml_vendor_t *
    00323 discover_xml_vendor_new(void)
    00324 {
    00325     discover_xml_vendor_t *new;
    00326
    00327     new = _discover_xmalloc(sizeof(discover_xml_vendor_t));
    00328
    00329     new->id = NULL;
    00330     new->name = NULL;
    00331     new->next = NULL;
    00332
    00333     return new;
    00334 }
    00335
    00341 void
    00342 discover_xml_vendor_free(discover_xml_vendor_t *vendors)
    00343 {
    00344     discover_xml_vendor_t *vendor, *last;
    00345
    00346     last = NULL;
    00347
    00348     for (vendor = vendors;
    00349          vendor;
    00350          vendor = vendor->next) {
    00351         if (vendor->id) {
    00352             free(vendor->id);
    00353         }
    00354
    00355         if (vendor->name) {
    00356             free(vendor->name);
    00357         }
    00358
    00359         if (last) {
    00360             free(last);
    00361         }
    00362         last = vendor;
    00363     }
    00364
    00365     if (last) {
    00366         free(last);
    00367     }
    00368 }
    00369
    00372 /*
    00373  * Local variables:
    00374  * c-file-style: "progeny"
    00375  * indent-tabs-mode: nil
    00376  * End:
    00377  */
    00378 /* vim: set cin fo=tcroq sw=4 et sts=4 tw=75: */