load dynamic-library during rc-file parsing
- From: matsu arch comp kyutech ac jp (Takashi Matsuda)
- To: gtk-list redhat com
- Subject: load dynamic-library during rc-file parsing
- Date: Sun, 12 Jul 1998 22:34:24 +0900 (JST)
I post the idea to this mailing list at several days ago.
That is loading dynamic-library during rc-file parsing.
I was very excited by the potential of this mechanism, and expected
affirmative replays. But there was no replays. ( why? :-( )
So, I implement the idea.
In rc-file, following directive become available.
library <tag> = <filename>
or
library <tag> [ = <filename> ]
{
[file = <filename>]
[init = <initialize function name>]
}
During rc-file parsing, if parser met above directive, it loads specified
library and call initialize function.
Default intialize function is named <tag>_init. but if user specifies the
name, it is called instead of the default.
Current implementation allows just loading any library at run-time.
But, if signal connection or key-binding becomes controlable by rc-file and
these are combined with this mechanism, almost all gtk application has
infinite configurability.
bind "<Control><Shift>n" {
<library tag> "any_function_you_want" ()
}
(IMHO, there is few scriptable application, but almost all gtk apps use
gtk_rc_parse)
For example, vi key-binding requires special functions which implement
the current state, regular expression searching, etc.
But, people who satisfied current key-binding would not agree to add these
vi specific functions to gtk.
With presented feature, anyone who want to use vi binding just add following
directive to rc-file.
include "<somewhere>/vi-binding"
( somebody would implement vi-binding ;-> )
May this mechanism be allowed to use some space in libgtk ?
Thanks.
-Takashi Matsuda
matsu@arch.comp.kyutech.ac.jp
Index: gtk/gtkrc.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkrc.c,v
retrieving revision 1.19
diff -r1.19 gtkrc.c
25a26
> #include <dlfcn.h>
30,33c31,35
< typedef struct _GtkRcStyle GtkRcStyle;
< typedef struct _GtkRcSet GtkRcSet;
< typedef struct _GtkRcNode GtkRcNode;
< typedef struct _GtkRcFile GtkRcFile;
---
> typedef struct _GtkRcStyle GtkRcStyle;
> typedef struct _GtkRcSet GtkRcSet;
> typedef struct _GtkRcNode GtkRcNode;
> typedef struct _GtkRcFile GtkRcFile;
> typedef struct _GtkRcLibrary GtkRcLibrary;
64a67,74
> struct _GtkRcLibrary
> {
> void *handle;
> gchar *name;
> gchar *file;
> gchar *init_func;
> };
>
108a119
> static guint gtk_rc_parse_library (GScanner *scanner);
175a187,190
> TOKEN_LIBRARY,
> TOKEN_FILE,
> TOKEN_INIT,
> TOKEN_CONNECT,
202a218,221
> { "library", TOKEN_LIBRARY },
> { "file", TOKEN_FILE },
> { "init", TOKEN_INIT },
> { "connect", TOKEN_CONNECT },
206a226
> static GHashTable *rc_library_ht = NULL;
223a244,245
> rc_library_ht = g_hash_table_new ((GHashFunc) gtk_rc_style_hash,
> (GCompareFunc) gtk_rc_style_compare);
805a828,830
> case TOKEN_LIBRARY:
> return gtk_rc_parse_library (scanner);
>
1485a1511,1696
> }
>
> static void
> gtk_rc_close_library (GtkRcLibrary *lib)
> {
> if (lib->handle)
> {
> dlclose (lib->handle);
> lib->handle = NULL;
> }
> }
>
> static guint
> gtk_rc_parse_library (GScanner *scanner)
> {
> GtkRcLibrary *rc_lib;
> guint token;
> guint retval;
> gchar *funcname;
> gint insert = FALSE;
> gint namelen;
> gint (*init_func)(void) = NULL;
>
> token = g_scanner_get_next_token (scanner);
> if (token != TOKEN_LIBRARY)
> return TOKEN_LIBRARY;
>
> token = g_scanner_get_next_token (scanner);
> if (token != G_TOKEN_STRING)
> return G_TOKEN_STRING;
>
> rc_lib = g_hash_table_lookup (rc_library_ht, scanner->value.v_string);
>
> if (!rc_lib)
> {
> rc_lib = g_new (GtkRcLibrary, 1);
> rc_lib->name = g_strdup (scanner->value.v_string);
> rc_lib->file = NULL;
> rc_lib->init_func = NULL;
> rc_lib->handle = NULL;
>
> insert = TRUE;
> }
>
> token = g_scanner_peek_next_token (scanner);
> if (token == G_TOKEN_EQUAL_SIGN)
> {
> token = g_scanner_get_next_token (scanner);
>
> token = g_scanner_get_next_token (scanner);
> if (token != G_TOKEN_STRING)
> {
> retval = G_TOKEN_STRING;
> goto ERROR;
> }
> if (rc_lib->file)
> {
> g_free (rc_lib->file);
> gtk_rc_close_library (rc_lib);
> }
> rc_lib->file = g_strdup (scanner->value.v_string);
>
> token = g_scanner_peek_next_token (scanner);
> }
>
> if (token != G_TOKEN_LEFT_CURLY && !rc_lib->file)
> {
> retval = G_TOKEN_LEFT_CURLY;
> goto ERROR;
> }
>
> if (token == G_TOKEN_LEFT_CURLY)
> {
> token = g_scanner_get_next_token (scanner);
>
> token = g_scanner_get_next_token (scanner);
> while (token != G_TOKEN_RIGHT_CURLY)
> {
> switch (token)
> {
> case TOKEN_FILE:
> token = g_scanner_get_next_token (scanner);
> if (token != G_TOKEN_EQUAL_SIGN)
> {
> retval = G_TOKEN_EQUAL_SIGN;
> goto ERROR;
> }
> token = g_scanner_get_next_token (scanner);
> if (token != G_TOKEN_STRING)
> {
> retval = G_TOKEN_STRING;
> goto ERROR;
> }
> if (rc_lib->file)
> g_free (rc_lib->file);
> if (rc_lib->handle)
> gtk_rc_close_library (rc_lib);
> rc_lib->file = g_strdup (scanner->value.v_string);
>
> break;
>
> case TOKEN_INIT:
> token = g_scanner_get_next_token (scanner);
> if (token != G_TOKEN_EQUAL_SIGN)
> {
> retval = G_TOKEN_EQUAL_SIGN;
> goto ERROR;
> }
> token = g_scanner_get_next_token (scanner);
> if (token != G_TOKEN_STRING)
> {
> retval = G_TOKEN_STRING;
> goto ERROR;
> }
> if (rc_lib->init_func)
> g_free (rc_lib->init_func);
> rc_lib->init_func = g_strdup (scanner->value.v_string);
>
> break;
> default:
> retval = G_TOKEN_RIGHT_CURLY;
> goto ERROR;
> }
>
> token = g_scanner_get_next_token (scanner);
> }
> }
>
> if (!rc_lib->file)
> {
> g_warning ("library file for library tag \"%s\" is not specified.",
> rc_lib->name);
> retval = G_TOKEN_NONE;
> goto ERROR;
> }
>
> if (!rc_lib->handle)
> {
> rc_lib->handle = dlopen (rc_lib->file, RTLD_LAZY);
> if (!rc_lib->handle)
> {
> g_warning ("can not load library \"%s\".", rc_lib->file);
> retval = G_TOKEN_NONE;
> goto ERROR;
> }
>
> if (rc_lib->init_func)
> init_func = dlsym (rc_lib->handle, rc_lib->init_func);
> if (!init_func)
> {
> namelen = strlen (rc_lib->name);
> funcname = g_new (gchar, namelen + 6);
> strcpy (funcname, rc_lib->name);
> strcpy (funcname+namelen, "_init");
> init_func = dlsym (rc_lib->handle, funcname);
> g_free (funcname);
> }
> if (init_func)
> {
> gint ret = (*init_func)();
> if (ret)
> {
> g_warning ("library \"%s\" initialization failed.", rc_lib->name);
> retval = G_TOKEN_NONE;
> goto ERROR;
> }
> }
> }
>
> if (insert)
> g_hash_table_insert (rc_library_ht, rc_lib->name, rc_lib);
>
> return G_TOKEN_NONE;
>
> ERROR:
> if (rc_lib)
> {
> if (rc_lib->name)
> g_free (rc_lib->name);
> if (rc_lib->file)
> g_free (rc_lib->file);
>
> g_free (rc_lib);
> }
>
> return retval;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]