/[m4]/m4/m4/module.c
ViewVC logotype

Diff of /m4/m4/module.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.26 by gary, Wed Jul 23 16:20:50 2003 UTC revision 1.27 by gary, Tue Aug 12 15:33:57 2003 UTC
# Line 79  Line 79 
79    
80  #define MODULE_SELF_NAME        "!myself!"  #define MODULE_SELF_NAME        "!myself!"
81    
 typedef struct {  
   m4_builtin    *builtin_table;  
   m4_macro      *macro_table;  
 } module_data;  
   
82  static const char*  module_dlerror (void);  static const char*  module_dlerror (void);
83  static int          module_remove  (m4 *context, lt_dlhandle handle,  static int          module_remove  (m4 *context, lt_dlhandle handle,
84                                      m4_obstack *obs);                                      m4_obstack *obs);
85  static void         module_close   (m4 *context, lt_dlhandle handle,  static void         module_close   (m4 *context, lt_dlhandle handle,
86                                      m4_obstack *obs);                                      m4_obstack *obs);
87    
88  static void set_module_macro_table   (m4*, lt_dlhandle, const m4_macro*);  static const m4_builtin * install_builtin_table (m4*, lt_dlhandle);
89  static void set_module_builtin_table (m4*, lt_dlhandle, const m4_builtin*);  static const m4_macro *   install_macro_table   (m4*, lt_dlhandle);
90    
91  static lt_dlcaller_id caller_id = 0;  static lt_dlcaller_id caller_id = 0;
92    
# Line 107  m4_get_module_name (lt_dlhandle handle) Line 102  m4_get_module_name (lt_dlhandle handle)
102    return info ? info->name : 0;    return info ? info->name : 0;
103  }  }
104    
105  m4_builtin *  void *
106  m4_get_module_builtin_table (lt_dlhandle handle)  m4_module_import (m4 *context, const char *module_name,
107                      const char *symbol_name, m4_obstack *obs)
108  {  {
109    module_data *data;    lt_dlhandle   handle          = lt_dlhandle_find (module_name);
110      lt_ptr        symbol_address  = 0;
111    
112    assert (handle);    /* Try to load the module if it is not yet available (errors are
113         diagnosed by m4_module_load).  */
114      if (!handle)
115        handle = m4_module_load (context, module_name, obs);
116    
117    data = lt_dlcaller_get_data (caller_id, handle);    if (handle)
118        {
119          symbol_address = lt_dlsym (handle, symbol_name);
120    
121    return data ? data->builtin_table : 0;        if (!symbol_address)
122            M4ERROR ((m4_get_warning_status_opt (context), 0,
123                      _("Warning: cannot load symbol `%s' from module `%s'"),
124                        symbol_name, module_name));
125        }
126    
127      return (void *) symbol_address;
128  }  }
129    
130  static void  static const m4_builtin *
131  set_module_builtin_table (m4 *context, lt_dlhandle handle,  install_builtin_table (m4 *context, lt_dlhandle handle)
                           const m4_builtin *table)  
132  {  {
133    const m4_builtin *bp;    const m4_builtin *bp;
134    
135    assert (context);    assert (context);
136    assert (handle);    assert (handle);
   assert (table);  
137    
138    for (bp = table; bp->name != NULL; bp++)    bp = (const m4_builtin *) lt_dlsym (handle, BUILTIN_SYMBOL);
139      if (bp)
140      {      {
141        m4_symbol_value *value = m4_symbol_value_create ();        for (; bp->name != NULL; bp++)
       char *    name;  
   
       m4_set_symbol_value_func (value, bp->func);  
       VALUE_HANDLE (value)      = handle;  
       VALUE_MIN_ARGS (value)    = bp->min_args;  
       VALUE_MAX_ARGS (value)    = bp->max_args;  
   
       if (bp->groks_macro_args)  
         BIT_SET (VALUE_FLAGS (value), VALUE_MACRO_ARGS_BIT);  
       if (bp->blind_if_no_args)  
         BIT_SET (VALUE_FLAGS (value), VALUE_BLIND_ARGS_BIT);  
   
       if (m4_get_prefix_builtins_opt (context))  
142          {          {
143            static const char prefix[] = "m4_";            m4_symbol_value *value = m4_symbol_value_create ();
144            size_t len = strlen (prefix) + strlen (bp->name);            char *           name;
145    
146            name = (char *) xmalloc (1+ len);            m4_set_symbol_value_func (value, bp->func);
147            snprintf (name, 1+ len, "%s%s", prefix, bp->name);            VALUE_HANDLE   (value)        = handle;
148          }            VALUE_MIN_ARGS (value)        = bp->min_args;
149        else            VALUE_MAX_ARGS (value)        = bp->max_args;
150          name = (char *) bp->name;  
151              if (bp->groks_macro_args)
152                BIT_SET (VALUE_FLAGS (value), VALUE_MACRO_ARGS_BIT);
153              if (bp->blind_if_no_args)
154                BIT_SET (VALUE_FLAGS (value), VALUE_BLIND_ARGS_BIT);
155    
156              if (m4_get_prefix_builtins_opt (context))
157                {
158                  static const char prefix[] = "m4_";
159                  size_t len = strlen (prefix) + strlen (bp->name);
160    
161        m4_symbol_pushdef (M4SYMTAB, name, value);                name = (char *) xmalloc (1+ len);
162                  snprintf (name, 1+ len, "%s%s", prefix, bp->name);
163                }
164              else
165                name = (char *) bp->name;
166    
167        if (m4_get_prefix_builtins_opt (context))            m4_symbol_pushdef (M4SYMTAB, name, value);
         xfree (name);  
     }  
 }  
168    
169  m4_macro *            if (m4_get_prefix_builtins_opt (context))
170  m4_get_module_macro_table (lt_dlhandle handle)              xfree (name);
171  {          }
   module_data *data;  
   
   assert (handle);  
172    
173    data = lt_dlcaller_get_data (caller_id, handle);  #ifdef DEBUG_MODULES
174          M4_DEBUG_MESSAGE1("module %s: builtins loaded",
175                            m4_get_module_name (handle));
176    #endif /* DEBUG_MODULES */
177        }
178    
179    return data ? data->macro_table : 0;    return bp;
180  }  }
181    
182  static void  static const m4_macro *
183  set_module_macro_table (m4 *context, lt_dlhandle handle,  install_macro_table (m4 *context, lt_dlhandle handle)
                            const m4_macro *table)  
184  {  {
185    const m4_macro *mp;    const m4_macro *mp;
186    
187    assert (context);    assert (context);
188    assert (handle);    assert (handle);
   assert (table);  
189    
190    for (mp = table; mp->name != NULL; mp++)    mp = (const m4_macro *) lt_dlsym (handle, MACRO_SYMBOL);
191    
192      if (mp)
193      {      {
194        m4_symbol_value *value = m4_symbol_value_create ();        for (; mp->name != NULL; mp++)
195            {
196              m4_symbol_value *value = m4_symbol_value_create ();
197    
198              m4_set_symbol_value_text (value, xstrdup (mp->value));
199              VALUE_HANDLE (value) = handle;
200    
201        m4_set_symbol_value_text (value, xstrdup (mp->value));            m4_symbol_pushdef (M4SYMTAB, mp->name, value);
202        VALUE_HANDLE (value) = handle;          }
203    
204        m4_symbol_pushdef (M4SYMTAB, mp->name, value);  #ifdef DEBUG_MODULES
205          M4_DEBUG_MESSAGE1("module %s: macros loaded",
206                            m4_get_module_name (handle));
207    #endif /* DEBUG_MODULES */
208      }      }
209    
210      return mp;
211  }  }
212    
213  lt_dlhandle  lt_dlhandle
# Line 201  m4_module_load (m4 *context, const char Line 215  m4_module_load (m4 *context, const char
215  {  {
216    const lt_dlhandle handle = m4__module_open (context, name, obs);    const lt_dlhandle handle = m4__module_open (context, name, obs);
217    
   /* If name is not set we are getting a reflective handle, but we  
      might need to display an error message later so we set an appropriate  
      value here.  */  
   if (!name)  
     name = MODULE_SELF_NAME;  
   
218    if (handle)    if (handle)
219      {      {
220        const lt_dlinfo  *info    = lt_dlgetinfo (handle);        const lt_dlinfo  *info    = lt_dlgetinfo (handle);
221    
222        if (!info)        if (!info)
223          {          {
224              /* If name is not set we are getting a reflective handle, but we
225                 need to display an error message so we set an appropriate
226                 value here.  */
227              if (!name)
228                name = MODULE_SELF_NAME;
229    
230            M4ERROR ((m4_get_warning_status_opt (context), 0,            M4ERROR ((m4_get_warning_status_opt (context), 0,
231                      _("Warning: cannot load module `%s': %s"),                      _("Warning: cannot load module `%s': %s"),
232                      name, module_dlerror ()));                      name, module_dlerror ()));
233          }          }
234        else if (info->ref_count == 1)        else if (info->ref_count == 1)
235          {          {
236            const m4_builtin *builtin_table            install_builtin_table (context, handle);
237              = m4_get_module_builtin_table (handle);            install_macro_table (context, handle);
           const m4_macro   *macro_table  
             = m4_get_module_macro_table (handle);  
   
           /* Install the macro functions.  */  
           if (builtin_table)  
             {  
               set_module_builtin_table (context, handle, builtin_table);  
 #ifdef DEBUG_MODULES  
               M4_DEBUG_MESSAGE1("module %s: builtins loaded", name);  
 #endif /* DEBUG_MODULES */  
             }  
   
           /* Install the user macros. */  
           if (macro_table)  
             {  
               set_module_macro_table (context, handle, macro_table);  
 #ifdef DEBUG_MODULES  
               M4_DEBUG_MESSAGE1("module %s: macros loaded", name);  
 #endif /* DEBUG_MODULES */  
             }  
238          }          }
239      }      }
240    
# Line 254  m4_module_unload (m4 *context, const cha Line 248  m4_module_unload (m4 *context, const cha
248    lt_dlhandle   handle  = 0;    lt_dlhandle   handle  = 0;
249    int           errors  = 0;    int           errors  = 0;
250    
251    /* Scan the list for the first module with a matching name.  */    assert (context);
252    while ((handle = lt_dlhandle_next (handle)))  
253      {    if (name)
254        if (name && (strcmp (name, m4_get_module_name (handle)) == 0))      handle = lt_dlhandle_find (name);
         break;  
     }  
255    
256    if (!handle)    if (!handle)
257      {      {
# Line 358  lt_dlhandle Line 350  lt_dlhandle
350  m4__module_open (m4 *context, const char *name, m4_obstack *obs)  m4__module_open (m4 *context, const char *name, m4_obstack *obs)
351  {  {
352    lt_dlhandle           handle          = lt_dlopenext (name);    lt_dlhandle           handle          = lt_dlopenext (name);
353    m4_module_init_func  *init_func       = 0;    m4_module_init_func * init_func       = 0;
354    m4_builtin           *builtin_table           = 0;  
355    m4_macro             *macro_table             = 0;    assert (context);
356      assert (caller_id);
357    
358    if (handle)    if (handle)
359      {      {
 #ifdef DEBUG_MODULES  
360        const lt_dlinfo *info = lt_dlgetinfo (handle);        const lt_dlinfo *info = lt_dlgetinfo (handle);
       M4_DEBUG_MESSAGE2("module %s: opening at %s", name, info->filename);  
 #endif  
361    
362        /* Find the builtin table in the opened module. */        /* If we have a handle, there must be handle info.  */
363        builtin_table = (m4_builtin *) lt_dlsym (handle, BUILTIN_SYMBOL);        assert (info);
364    
365        /* Find the macro table in the opened module. */  #ifdef DEBUG_MODULES
366        macro_table = (m4_macro *) lt_dlsym (handle, MACRO_SYMBOL);        M4_DEBUG_MESSAGE2("module %s: opening at %s",
367                            name ? name : MODULE_SELF_NAME, info->filename);
368    #endif
369    
370        /* Find and run any initialising function in the opened module,        /* Find and run any initialising function in the opened module,
371           each time the module is opened.  */           each time the module is opened.  */
# Line 386  m4__module_open (m4 *context, const char Line 378  m4__module_open (m4 *context, const char
378            M4_DEBUG_MESSAGE1("module %s: init hook called", name);            M4_DEBUG_MESSAGE1("module %s: init hook called", name);
379  #endif /* DEBUG_MODULES */  #endif /* DEBUG_MODULES */
380          }          }
381    
382          if (!init_func
383              && !lt_dlsym (handle, FINISH_SYMBOL)
384              && !lt_dlsym (handle, BUILTIN_SYMBOL)
385              && !lt_dlsym (handle, MACRO_SYMBOL))
386            {
387                M4ERROR ((EXIT_FAILURE, 0,
388                          _("module `%s' has no entry points"),
389                          name));
390            }
391    
392    #ifdef DEBUG_MODULES
393          M4_DEBUG_MESSAGE1("module %s: opened", name);
394    #endif /* DEBUG_MODULES */
395      }      }
396    else    else
397      {      {
# Line 395  m4__module_open (m4 *context, const char Line 401  m4__module_open (m4 *context, const char
401                  name, module_dlerror ()));                  name, module_dlerror ()));
402      }      }
403    
   if (!builtin_table && !macro_table && !init_func)  
     {  
       /* Since we don't use it here, only check for the finish hook  
          if we were about to diagnose a module with no entry points.  */  
       if (!lt_dlsym (handle, FINISH_SYMBOL))  
         M4ERROR ((EXIT_FAILURE, 0,  
                   _("module `%s' has no entry points"),  
                   name));  
     }  
   
   /* If the module was correctly opened and has the necessary  
      symbols, then store some client data for the new module  
      on the first open only.  */  
   if (handle)  
     {  
       const lt_dlinfo  *info    = lt_dlgetinfo (handle);  
   
       if (info && (info->ref_count == 1))  
         {  
           module_data *data     = XMALLOC (module_data, 1);  
           module_data *stale    = 0;  
   
           data->builtin_table   = builtin_table;  
           data->macro_table     = macro_table;  
   
           stale = lt_dlcaller_set_data (caller_id, handle, data);  
   
           if (stale)  
             {  
               xfree (stale);  
   
               M4ERROR ((m4_get_warning_status_opt (context), 0,  
                         _("Warning: overiding stale caller data in module `%s'"),  
                         name));  
             }  
   
 #ifdef DEBUG_MODULES  
           M4_DEBUG_MESSAGE1("module %s: opened", name);  
 #endif /* DEBUG_MODULES */  
         }  
     }  
   
404    return handle;    return handle;
405  }  }
406    
# Line 451  m4__module_exit (m4 *context) Line 415  m4__module_exit (m4 *context)
415        lt_dlhandle      pending  = handle;        lt_dlhandle      pending  = handle;
416        const lt_dlinfo *info     = lt_dlgetinfo (pending);        const lt_dlinfo *info     = lt_dlgetinfo (pending);
417    
       /* We are *really* shutting down here, so freeing the module  
          data is required.  */  
       if (info)  
         {  
           module_data *stale  
             = lt_dlcaller_set_data (caller_id, handle, 0);  
           XFREE (stale);  
         }  
   
418        /* If we are about to unload the final reference, move on to the        /* If we are about to unload the final reference, move on to the
419           next handle before we unload the current one.  */           next handle before we unload the current one.  */
420        if (info->ref_count <= 1)        if (info->ref_count <= 1)
# Line 519  module_close (m4 *context, lt_dlhandle h Line 474  module_close (m4 *context, lt_dlhandle h
474    
475    if (!lt_dlisresident (handle))    if (!lt_dlisresident (handle))
476      {      {
       const lt_dlinfo  *info    = lt_dlgetinfo (handle);  
   
       /* When we are about to unload the module for the final  
          time, be sure to release any client data memory.  */  
       if (info && (info->ref_count == 1))  
         {  
           module_data *stale  
             = lt_dlcaller_set_data (caller_id, handle, 0);  
           XFREE (stale);  
         }  
   
477        errors = lt_dlclose (handle);        errors = lt_dlclose (handle);
478        if (!errors)        if (!errors)
479          {          {

Legend:
Removed from v.1.26  
changed lines
  Added in v.1.27

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26