]> granicus.if.org Git - graphviz/commitdiff
on-demand plugin loading
authorellson <devnull@localhost>
Mon, 4 Apr 2005 21:52:19 +0000 (21:52 +0000)
committerellson <devnull@localhost>
Mon, 4 Apr 2005 21:52:19 +0000 (21:52 +0000)
15 files changed:
Makefile.am
cmd/dot/Makefile.am
cmd/dot/args.c
cmd/tools/plugins.c
configure.ac
lib/common/Makefile.am
lib/common/globals.h
lib/common/types.h
lib/fdpgen/tlayout.c
lib/fdpgen/tlayout.h
lib/gvc/Makefile.am
lib/gvc/gvc.h
lib/gvc/gvconfig.c
lib/gvc/gvplugin.c
lib/gvc/gvplugin.h

index 0e200312fd8204e6f2a300dc0255489048f8daec..d51dabbe6557b2f1c72eb20b891e4d94848e4e41 100644 (file)
@@ -11,8 +11,8 @@ html =
 txt_DATA = $(txt)
 html_DATA = $(html)
 
-#SUBDIRS = libltdl lib plugin cmd tclpkg doc contrib graphs
-SUBDIRS = lib plugin cmd tclpkg doc contrib graphs
+# $(subdirs) contains the list from: AC_CONFIG_SUBDIRS
+SUBDIRS = $(subdirs) lib plugin cmd tclpkg doc contrib graphs
 
 doxygen:
        doxygen
index 2ca9aeb98daf9f124387e0eaf8cc436a0c438e55..e7046dc8d97cfa7d135762e887e94063e1fa7eaa 100644 (file)
@@ -32,10 +32,17 @@ libdotneato_la_LIBADD = \
 
 dot_SOURCES = dot.c args.c
 
+if ENABLE_LTDL
+dot_LDADD = \
+        $(top_builddir)/lib/graph/libgraph.la \
+        $(top_builddir)/lib/common/libcommon.la \
+        $(top_builddir)/lib/gvc/libgvc.la  @LIBGEN_LIBS@
+else
 dot_LDADD = \
         $(top_builddir)/lib/common/libcommon.la \
         $(top_builddir)/lib/gvc/libgvc.la \
-       $(top_builddir)/plugin/libplugins.la @LIBGEN_LIBS@
+       $(top_builddir)/plugin/libplugins.la
+endif
 
 install-data-hook:
        (cd $(DESTDIR)$(man1dir); for i in $(linkedman); do rm -f $$i; $(LN_S) dot.1 $$i; done;)
index ef35b1faeb87395460a909578ef17fbfb4eb037b..476a8a249716f13d769e27492fb2d7d7c0b1747a 100644 (file)
 #include "render.h"
 #include "tlayout.h"
 
+/* Default layout values, possibly set via command line; -1 indicates unset */
+fdpParms_t fdp_parms_default = {
+    1,                          /* useGrid */
+    1,                          /* useNew */
+    -1,                         /* numIters */
+    50,                         /* unscaled */
+    0.0,                        /* C */
+    1.0,                        /* Tfact */
+    -1.0,                       /* K - set in initParams; used in init_edge */
+    -1.0,                       /* T0 */
+};
+
+
 static int
 neato_extra_args(GVC_t *gvc, int argc, char** argv)
 {
@@ -187,6 +200,8 @@ fdp_extra_args (GVC_t *gvc, int argc, char** argv)
   char*  arg;
   int    cnt = 1;
 
+  fdp_parms = fdp_parms_default;
+
   for (i = 1; i < argc; i++) {
     arg = argv[i];
     if (arg && (*arg == '-') && (*(arg+1) == 'L')) {
index b7e1cf6ef16c6ff6dba654dd8dca35445ae9086f..582bd424ef7a1c7ae2fc9ecd1ecd4796b579a818 100644 (file)
@@ -20,7 +20,7 @@
 #include        "types.h"
 #include        "macros.h"
 #include        "gvc.h"
-gvplugin_t *builtins[] = {
+gvplugin_library_t *builtins[] = {
     NULL
 };
 
index 4b2c5ce9eaac26ab693e04cee529d726dc07209b..dc973e9f2539cfa5738bad6db58ba5dd81923f5d 100644 (file)
@@ -3,12 +3,11 @@ AC_INIT(graphviz, 2.3)
 AC_CONFIG_SRCDIR(configure.ac)
 AC_CONFIG_AUX_DIR(config)
 
-#AC_CONFIG_SUBDIRS(libltdl)
-#AC_LIBTOOL_DLOPEN
-#AC_LIBLTDL_CONVENIENCE
-
-HAVE_LTDL=0
+AC_CONFIG_SUBDIRS(libltdl)
+AC_LIBTOOL_DLOPEN
+AC_LIBLTDL_CONVENIENCE
 
+HAVE_LTDL=1
 AC_SUBST(INCLTDL)
 AC_SUBST(LIBLTDL)
 AC_DEFINE_UNQUOTED(HAVE_LTDL,$HAVE_LTDL,Define if to use libltdl dynamic loading of plugins.)
index 72cc4a74c769c3c8c5d37d18c1d44ff6670db22f..5babf714796c86f4d41f7ba989885dd5c6581414 100644 (file)
@@ -5,27 +5,26 @@ AM_CPPFLAGS = \
        -I$(top_srcdir)/lib/gvc \
        -I$(top_srcdir)/lib/pathplan \
        -I$(top_srcdir)/lib/graph \
-       -I$(top_srcdir)/lib/cdt \
-       @GD_INCLUDES@ @EXPAT_INCLUDES@ @CAIRO_CFLAGS@ @Z_INCLUDES@
+       -I$(top_srcdir)/lib/cdt  @GD_INCLUDES@ @EXPAT_INCLUDES@ @Z_INCLUDES@
 
 pkginclude_HEADERS = const.h globals.h htmllex.h htmltable.h macros.h \
        pointset.h render.h renderprocs.h types.h utils.h colortbl.h
 pkglib_LTLIBRARIES = libcommon.la
 
 if !DISABLE_CODEGENS
-CODEGENS = diagen.c figgen.c gdgen.c hpglgen.c mapgen.c mifgen.c mpgen.c \
+CODEGENS = diagen.c figgen.c hpglgen.c gdgen.c mapgen.c mifgen.c mpgen.c \
        picgen.c psgen.c svggen.c vrmlgen.c vtxgen.c ps.txt xdgen.c color_names
 endif
 
 
-libcommon_la_SOURCES = arrows.c colxlate.c fontmetrics.c gdtextsize.c \
-       gdusershape.c globals.c htmllex.c htmlparse.y htmltable.c input.c \
+libcommon_la_SOURCES = arrows.c colxlate.c fontmetrics.c \
+       gdtextsize.c gdusershape.c \
+       globals.c htmllex.c htmlparse.y htmltable.c input.c \
        pointset.c postproc.c psusershape.c routespl.c splines.c \
        svgusershape.c timing.c labels.c ns.c shapes.c utils.c \
        output.c emit.c $(CODEGENS)
 
-libcommon_la_LIBADD = \
-       @GD_LIBS@ @CAIRO_LIBS@ @EXPAT_LIBS@ @Z_LIBS@
+libcommon_la_LIBADD = $(top_builddir)/lib/pathplan/libpathplan.la @GD_LIBS@ @EXPAT_LIBS@ @Z_LIBS@
 
 psgen.o psgen.lo : ps.h
 
index 6e45fe284ba3d959fee2ac260c6317463fae6e48..b36fedcf63f5310f0ff0cd7a35fc9512a5f5bd58 100644 (file)
@@ -118,6 +118,9 @@ extern "C" {
        *E_labelfontsize, *E_labelfontname, *E_labelfontcolor,
        *E_labeldistance, *E_labelangle,
        *E_tailclip, *E_headclip;
+
+    EXTERN fdpParms_t fdp_parms;
+
 #undef external
 
 #ifdef __cplusplus
index 68be02c0a22b1996b49134f33b62049751ab1b31..f522d363aece32cdd22769ef60650c092f3dac86 100644 (file)
@@ -591,6 +591,17 @@ extern "C" {
 #define ED_weight(e) (e)->u.weight
 #define ED_xpenalty(e) (e)->u.xpenalty
 
+    typedef struct {
+        int useGrid;            /* use grid for speed up */
+        int useNew;             /* encode x-K into attractive force */
+        int numIters;           /* actual iterations in layout */
+        int unscaled;           /* % of iterations used in pass 1 */
+        double C;               /* Repulsion factor in xLayout */
+        double Tfact;           /* scale temp from default expression */
+        double K;               /* spring constant; ideal distance */
+        double T0;              /* initial temperature */
+    } fdpParms_t;
+
 #ifdef __cplusplus
 }
 #endif
index 4e509151961fc335ab2f39132f29253d3cf6a934..59378897edf2226ec5fba4c34be2c626cffb1761 100644 (file)
@@ -59,18 +59,6 @@ extern double drand48(void);
 #include "tlayout.h"
 #include "globals.h"
 
-  /* Default layout values, possibly set via command line; -1 indicates unset */
-fdpParms_t fdp_parms = {
-    1,                         /* useGrid */
-    1,                         /* useNew */
-    -1,                                /* numIters */
-    50,                                /* unscaled */
-    0.0,                       /* C */
-    1.0,                       /* Tfact */
-    -1.0,                      /* K - set in initParams; used in init_edge */
-    -1.0,                      /* T0 */
-};
-
 #define D_useGrid   (fdp_parms.useGrid)
 #define D_useNew    (fdp_parms.useNew)
 #define D_numIters  (fdp_parms.numIters)
index aad4dc6ea1bafbae415684408f58922c369eb346..e437250c252b823745dc662bf7be2cc37fa4ee67 100644 (file)
@@ -28,17 +28,6 @@ typedef enum {
   seed_unset, seed_val, seed_time, seed_regular
 } seedMode;
 
-    typedef struct {
-       int useGrid;            /* use grid for speed up */
-       int useNew;             /* encode x-K into attractive force */
-       int numIters;           /* actual iterations in layout */
-       int unscaled;           /* % of iterations used in pass 1 */
-       double C;               /* Repulsion factor in xLayout */
-       double Tfact;           /* scale temp from default expression */
-       double K;               /* spring constant; ideal distance */
-       double T0;              /* initial temperature */
-    } fdpParms_t;
-
     extern fdpParms_t fdp_parms;
 
     extern void fdp_initParams(graph_t *);
index a9168c0f54e917b38a739d9404f8950adf6eaed3..829a3a07601545faccc4911104898b1c8fb4a687 100644 (file)
@@ -5,7 +5,8 @@ AM_CPPFLAGS = \
        -I$(top_srcdir)/lib/common \
        -I$(top_srcdir)/lib/pathplan \
        -I$(top_srcdir)/lib/graph \
-       -I$(top_srcdir)/lib/cdt $(INCLTDL)
+       -I$(top_srcdir)/lib/cdt $(INCLTDL) \
+       -DGVLIBDIR=\"$(pkglibdir)\"
 
 LIBS = $(LIBLTDL)
 
index ccf6b324119a133a476b68ef396d3356e1d3aef6..284e21fafb4737a8f889d80bfde6a7fcde46cd94 100644 (file)
@@ -41,9 +41,11 @@ extern "C" {
                                    char *typestr, int quality, char *path,
                                    gvplugin_type_t * typeptr);
     extern gv_plugin_t *gvplugin_load(GVC_t * gvc, api_t api, char *type);
+    extern gvplugin_library_t *gvplugin_library_load(char *path);
     extern const char *gvplugin_list(GVC_t * gvc, api_t api, char *str);
     extern void gvplugin_builtins(GVC_t * gvc);
     extern api_t gvplugin_api(char *str);
+    extern char * gvplugin_api_name(api_t api);
 
 /* job */
 
index 611e81a872c158775ee2b80ac8cdc058c6f4c8b1..3d99324e5f69c3f9fe1a23bed39b4af85f7d323b 100644 (file)
 #include       <stdio.h>
 #include       <stdlib.h>
 #include       <string.h>
+#include       <sys/types.h>
+#include       <sys/stat.h>
+#include       <unistd.h>
+#include       <glob.h>
 
 #include        "config.h"
 #include        "types.h"
@@ -130,10 +134,17 @@ void gvconfig(GVC_t * gvc)
     api_t gv_api;
     int quality;
     int nest = 0;
-    int sz, rc;
+    int sz, rc, i, j;
+    struct stat config_st, libdir_st;
     FILE *f;
     char *config_path, *home, *config;
-    char *dot_graphviz_config = "/.graphviz/config";
+    glob_t globbuf;
+    gvplugin_library_t *library;
+    gvplugin_api_t *apis;
+    gvplugin_type_t *types;
+
+    char *dot_graphviz = "/.graphviz";
+    char *libdir = GVLIBDIR;
 
 #define SZ_CONFIG 1000
     
@@ -142,14 +153,68 @@ void gvconfig(GVC_t * gvc)
 #endif
     gvplugin_builtins(gvc);
 
+
+    /* see if there are any new plugins */
+
+    rc = stat(libdir, &libdir_st);
+    if (rc == -1) {    /* if we fail to stat it then it probably doesn't exist
+                  so just fail silently, clean up and return */
+       return;
+    }
+
     home = getenv ("HOME");
     if (!home) {
        return;
     }
 
-    config_path = malloc(strlen(home) + strlen(dot_graphviz_config) + 1);
+    config_path = malloc(strlen(home) + strlen(dot_graphviz) + 1);
     strcpy(config_path, home);
-    strcat(config_path, dot_graphviz_config);
+    strcat(config_path, dot_graphviz);
+
+    rc = stat(config_path, &config_st);
+
+    if (rc == -1 || libdir_st.st_mtime > config_st.st_mtime) {
+       f = fopen(config_path,"w");
+       if (!f) {
+            fprintf(stderr,"failed to open %s for write.\n", config_path);
+           free(config_path);
+           return;
+       }
+
+       rc = glob("/home/ellson/FIX/Linux.x86_64/lib/graphviz/libgvplugin*.so",
+               GLOB_NOSORT, NULL, &globbuf);
+
+        if (rc == 0) {
+           for (j = 0; j < globbuf.gl_pathc; j++) {
+               library = gvplugin_library_load(globbuf.gl_pathv[j]);
+               if (library) {
+                   fputs (globbuf.gl_pathv[j], f);
+                   fputs (" {\n", f);
+                   for (apis = library->apis; (types = apis->types); apis++) {
+                       fputs ("\t", f);
+                       fputs (gvplugin_api_name(apis->api), f);
+                       fputs (" {\n", f);
+                       for (i = 0; types[i].type; i++) {
+                           /* might as well install it since its already loaded */
+                           gvplugin_install(gvc, apis->api, types[i].type,
+                                types[i].quality, library->name, &types[i]);
+
+                           fprintf(f, "\t\t%s %d\n",
+                               types[i].type, types[i].quality);
+                       }
+                       fputs ("\t}\n", f);
+                   }
+                   fputs ("}\n", f);
+               }
+           }
+       }
+       globfree(&globbuf);
+
+       fclose(f);
+       return;     /* all plugins have been installed */
+    }
+
+    /* load in the cached plugin library data */
 
     f = fopen(config_path,"r");
     if (!f) {  /* if we fail to open it then it probably doesn't exists
index 7a93ec03b12e9c6fe8aad62d3aac57824c8bb3c8..4e748df7f64ecf23cf12e8bc9bb3f8ad5b4d6f0f 100644 (file)
@@ -33,7 +33,7 @@
  * inititialized here by redefining ELEM and reinvoking APIS.
  */
 #define ELEM(x) #x,
-static char *apis[] = { APIS };        /* "render", "layout", ... */
+static char *api_names[] = { APIS };   /* "render", "layout", ... */
 #undef ELEM
 
 /* translate a string api name to its type, or -1 on error */
@@ -41,13 +41,21 @@ api_t gvplugin_api(char *str)
 {
     int api;
 
-    for (api = 0; api < ARRAY_SIZE(apis); api++) {
-       if (strcmp(str, apis[api]) == 0)
+    for (api = 0; api < ARRAY_SIZE(api_names); api++) {
+       if (strcmp(str, api_names[api]) == 0)
            return (api_t)api;
     }
     return -1;                 /* invalid api */
 }
 
+/* translate api_t into string name, or NULL */
+char *gvplugin_api_name(api_t api)
+{
+    if (api < 0 || api >= ARRAY_SIZE(api_names))
+       return NULL;
+    return api_names[api];
+}
+
 /* install a plugin description into the list of available plugins */
 /* list is alpha sorted by type, the quality sorted within the type,
    then, if qualities are the same, last install wins */
@@ -83,71 +91,125 @@ boolean gvplugin_install(GVC_t * gvc, api_t api,
     return TRUE;
 }
 
+gvplugin_library_t *gvplugin_library_load(char *path)
+{
+#if HAVE_LTDL
+    lt_dlhandle hndl;
+    lt_ptr ptr;
+    char *s, *sym;
+
+    char *suffix = "_LTX_library";
+
+    if (lt_dlinit()) {
+        fprintf(stderr,"failed to init libltdl\n");
+        return NULL;
+    }
+    hndl = lt_dlopen (path);
+    if (!hndl) {
+        fprintf(stderr,"failed to dlopen %s\n", path);
+        return NULL;
+    }
+
+    s = strrchr(path, '/');
+    sym = malloc(strlen(s) + strlen(suffix) + 1);
+    strcpy(sym, s+4);         /* strip leading "/lib" */
+    s = strchr(sym, '.');     /* strip trailing ".so" */
+    strcpy(s,"_LTX_library"); /* append "_LTX_library" */
+
+    ptr = lt_dlsym (hndl, sym);
+    if (!ptr) {
+        fprintf(stderr,"failed to resolve %s in %s\n", sym, path);
+       free(sym);
+        return NULL;
+    }
+    free(sym);
+    return (gvplugin_library_t *)(ptr);
+#else
+    fprintf(stderr,"dynamic loading not available\n");
+    return NULL;
+#endif
+}
+
+
 /* load a plugin of type=str where str can optionally contain a ":path" modifier */
 gv_plugin_t *gvplugin_load(GVC_t * gvc, api_t api, char *str)
 {
-    gv_plugin_t **pnext;
+    gv_plugin_t **pnext, *rv;
+    gvplugin_library_t *library;
+    gvplugin_api_t *apis;
+    gvplugin_type_t *types;
     char *s, *p;
+    int i;
+
 
     /* check for valid apis[] index */
     if (api < 0)
        return NULL;
 
-    /* point to the beginning of the linked list of plugins for this api */
-    pnext = &(gvc->apis[api]);
-
     /* does str have a :path modifier? */
     s = strdup(str);
     p = strchr(s, ':');
     if (p)
        *p++ = '\0';
 
+    /* point to the beginning of the linked list of plugins for this api */
+    pnext = &(gvc->apis[api]);
+
     while (*pnext) {
        if (strcmp(s, (*pnext)->typestr) == 0) {
            if (p) {
                if (strcmp(p, (*pnext)->path) == 0)
                    break;
-           } else
+           }
+           else
                break;
        }
        pnext = &((*pnext)->next);
     }
-    free(s);
-    if ((*pnext) && (*pnext)->typeptr == NULL) {
 
-#if HAVE_LTDL
-        /* dynamically load required plugin library */
-
-       lt_dlhandle hndl;
-       lt_ptr ptr;
-
-       if (lt_dlinit()) {
-           fprintf(stderr,"failed to init libltdl\n");
-           return NULL;
-       }
-       hndl = lt_dlopen ((*pnext)->path);
-       if (!hndl) {
-           fprintf(stderr,"failed to dlopen %s\n", (*pnext)->path);
-           return NULL;
-       }
-       ptr = lt_dlsym (hndl, "gvplugin_cairo_LTX_plugin");
-       if (!ptr) {
-           fprintf(stderr,"failed to resolve %s in %s\n", "gvplugin_cairo_LTX_plugin", (*pnext)->path);
-           return NULL;
-       }
-#if 0
-       /* FIXME */
-       (*pnext)->typeptr = 
-#else
-       fprintf(stderr,"dynamic loading not implemented\n");
-       return NULL;
-#endif
-#else
-       fprintf(stderr,"dynamic loading not available\n");
-       return NULL;
-#endif
+    rv = *pnext;
+    if ((*pnext) && (*pnext)->typeptr == NULL) {
+        rv = NULL;
+       library = gvplugin_library_load((*pnext)->path);
+       if (library) {
+
+           /*
+            * FIXME - would be cleaner to here remove the entries from the
+            * config data for the uninstalled library - i.e. the entries
+            * without type ptrs.   It works without because the real library
+            * data is inserted ahead of, and so supercedes, the config data.
+            */
+
+            /* Now reinsert the library with real type ptrs */
+            for (apis = library->apis; (types = apis->types); apis++) {
+               for (i = 0; types[i].type; i++) {
+                    gvplugin_install(gvc, apis->api, types[i].type,
+                               types[i].quality, library->name, &types[i]);
+               }
+            }
+           
+           /* Now search again for the specific plugin type */
+           pnext = &(gvc->apis[api]);
+           while (*pnext) {
+               if (strcmp(s, (*pnext)->typestr) == 0) {
+                   if (p) {
+                       if (strcmp(p, (*pnext)->path) == 0)
+                           break;
+                   }
+                   else
+                       break;
+               }
+               pnext = &((*pnext)->next);
+           }
+           rv = *pnext;
+        }
     }
-    return (gvc->api[api] = *pnext);
+    /* one last check for succesfull load */
+    if ((*pnext) && (*pnext)->typeptr == NULL)
+       rv = NULL;
+    free(s);
+    gvc->api[api] = rv;
+    return rv;
 }
 
 /* string buffer management - FIXME - must have 20 solutions for this same thing */
@@ -227,22 +289,26 @@ const char *gvplugin_list(GVC_t * gvc, api_t api, char *str)
     return buf;
 }
 
-extern gvplugin_t *builtins[];
+#ifndef HAVE_LTDL
+extern gvplugin_library_t *builtins[];
+#endif
 
 void gvplugin_builtins(GVC_t * gvc)
 {
-    gvplugin_t **plugin;
+#ifndef HAVE_LTDL
+    gvplugin_library_t **library;
     gvplugin_api_t *apis;
     gvplugin_type_t *types;
     int i;
 
-    for (plugin = builtins; *plugin; plugin++) {
-       for (apis = (*plugin)->apis; (types = apis->types); apis++) {
+    for (library = builtins; *library; library++) {
+       for (apis = (*library)->apis; (types = apis->types); apis++) {
            for (i = 0; types[i].type; i++) {
                gvplugin_install(gvc, apis->api,
                                 types[i].type, types[i].quality,
-                                (*plugin)->name, &types[i]);
+                                (*library)->name, &types[i]);
            }
        }
     }
+#endif
 }
index 6dae6f7818d08ee2e3c972bbf856d43f868b27e1..370a4976840803c8a336711de1b174e2f960604a 100644 (file)
@@ -53,9 +53,9 @@ extern "C" {
 
     typedef struct {
        char *name;             /* used instead of a file pathname
-                                       when this plugin is builtin */
+                                       when this plugin is loaded */
        gvplugin_api_t *apis;
-    } gvplugin_t;
+    } gvplugin_library_t;
 
 #ifdef __cplusplus
 }