/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */ /* $Id$ */ /* Copyright (C) 1998-99 Martin Baulig This file is part of LibGTop 1.0. Contributed by Martin Baulig , April 1998. LibGTop is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. LibGTop is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with LibGTop; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include static GHashTable *_glibtop_backend_list = NULL; static long _glibtop_backend_nr = 0; #define LIBGTOP_XML_NAMESPACE "http://www.home-of-linux.org/libgtop/1.1" #include #include static void _glibtop_init_gmodule_backends (const char *); void glibtop_init_backends (void) { static int backends_initialized = 0; if (backends_initialized) return; backends_initialized = 1; LIBXML_TEST_VERSION; _glibtop_init_gmodule_backends (LIBGTOP_BACKEND_DIR); } static gchar * _get_library_filename (xmlDocPtr doc, xmlNodePtr cur, const char *directory) { char *filename = xmlNodeListGetString (doc, cur->xmlChildrenNode, 1); gchar *retval; if (!filename) return NULL; /* already absolute */ if (filename [0] == '/') retval = g_strdup (filename); else retval = g_strdup_printf ("%s/%s", directory, filename); return retval; } static GSList * _parse_extra_libs (xmlDocPtr doc, xmlNsPtr ns, xmlNodePtr cur, const char *dir) { GSList *list = NULL; /* We don't care what the top level element name is */ cur = cur->xmlChildrenNode; while (cur != NULL) { if ((!strcmp (cur->name, "ExtraLib")) && (cur->ns == ns)) { xmlNodePtr sub = cur->xmlChildrenNode; while (sub != NULL) { if ((!strcmp (sub->name, "ShlibName")) && (sub->ns == ns)) list = g_slist_append (list, _get_library_filename (doc, sub, dir)); sub = sub->next; } } cur = cur->next; } return list; } static glibtop_backend_entry * _parseBackend (xmlDocPtr doc, xmlNsPtr ns, xmlNodePtr cur, const char *dir) { glibtop_backend_entry *ret = NULL; /* * allocate the struct */ ret = g_new0 (glibtop_backend_entry, 1); /* We don't care what the top level element name is */ cur = cur->xmlChildrenNode; while (cur != NULL) { if ((!strcmp (cur->name, "Name")) && (cur->ns == ns)) ret->name = xmlNodeListGetString (doc, cur->xmlChildrenNode, 1); if ((!strcmp (cur->name, "Location")) && (cur->ns == ns)) { xmlNodePtr sub = cur->xmlChildrenNode; while (sub != NULL) { if ((!strcmp (sub->name, "LibtoolName")) && (sub->ns == ns)) ret->libtool_name = _get_library_filename (doc, sub, dir); if ((!strcmp (sub->name, "ShlibName")) && (sub->ns == ns)) ret->shlib_name = _get_library_filename (doc, sub, dir); if ((!strcmp (sub->name, "ExtraLibs")) && (sub->ns == ns)) ret->extra_libs = _parse_extra_libs (doc, ns, sub, dir); sub = sub->next; } } cur = cur->next; } return ret; } static void _glibtop_init_gmodule_backends (const char *directory) { DIR *dir; struct dirent *entry; dir = opendir (directory); if (!dir) return; while ((entry = readdir (dir)) != NULL) { size_t len = strlen (entry->d_name); gchar *filename; xmlDocPtr doc; xmlNsPtr ns; xmlNodePtr cur; if (len < 8) continue; if (strcmp (entry->d_name+len-8, ".backend")) continue; filename = g_strdup_printf ("%s/%s", directory, entry->d_name); doc = xmlParseFile (filename); if (!doc) { g_warning ("Cannot parse %s", filename); g_free (filename); continue; } /* Make sure the document is of the right kind */ cur = xmlDocGetRootElement (doc); if (!cur) { xmlFreeDoc (doc); g_free (filename); continue; } ns = xmlSearchNsByHref (doc, cur, LIBGTOP_XML_NAMESPACE); if (!ns) { g_warning ("File %s of wrong type; LibGTop Namespace not found", filename); g_free (filename); xmlFreeDoc (doc); continue; } if (strcmp (cur->name, "Backends")) { g_warning ("File %s of the wrong type, root node != 'Backends'", filename); g_free (filename); xmlFreeDoc (doc); continue; } cur = cur->xmlChildrenNode; while (cur != NULL) { glibtop_backend_entry *backend; if ((!strcmp(cur->name, "Backend")) && (cur->ns == ns)) { backend = _parseBackend (doc, ns, cur, directory); if (!backend) { g_warning ("File %s of wrong type; cannot parse", filename); continue; } glibtop_register_backend (backend); } cur = cur->next; } g_free (filename); xmlFreeDoc (doc); } closedir (dir); } long glibtop_register_backend (glibtop_backend_entry *entry) { long id; if (!_glibtop_backend_list) _glibtop_backend_list = g_hash_table_new (NULL, NULL); id = ++_glibtop_backend_nr; g_hash_table_insert (_glibtop_backend_list, GINT_TO_POINTER (id), entry); return id; } void glibtop_unregister_backend (long id) { g_hash_table_remove (_glibtop_backend_list, GINT_TO_POINTER (id)); } glibtop_backend_entry * glibtop_backend_by_id (long id) { return g_hash_table_lookup (_glibtop_backend_list, GINT_TO_POINTER (id)); } typedef struct { const char *backend_name; glibtop_backend_entry *entry; } _find_by_name_param_t; static void find_by_name (gpointer key, gpointer value, gpointer user_data) { _find_by_name_param_t *param = (_find_by_name_param_t *) user_data; glibtop_backend_entry *entry = (glibtop_backend_entry *) value; if (!entry || !entry->name || param->entry) return; if (!strcmp (entry->name, param->backend_name)) param->entry = entry; } glibtop_backend_entry * glibtop_backend_by_name (const char *backend_name) { _find_by_name_param_t param = { backend_name, NULL }; g_hash_table_foreach (_glibtop_backend_list, find_by_name, ¶m); return param.entry; }