Commit 460a78ba authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont

New type-safe API for modules listing

module_list_get(): gets the list of modules
module_list_free(): releases the list
parent fd0f3ec3
...@@ -44,6 +44,9 @@ VLC_EXPORT( void, module_Put, ( module_t *module ) ); ...@@ -44,6 +44,9 @@ VLC_EXPORT( void, module_Put, ( module_t *module ) );
VLC_EXPORT( module_config_t *, module_GetConfig, ( const module_t *, unsigned * ) ); VLC_EXPORT( module_config_t *, module_GetConfig, ( const module_t *, unsigned * ) );
VLC_EXPORT( void, module_PutConfig, ( module_config_t * ) ); VLC_EXPORT( void, module_PutConfig, ( module_config_t * ) );
VLC_EXPORT( void, module_list_free, (module_t **) );
VLC_EXPORT( module_t **, module_list_get, (size_t *n) );
/* Return a NULL terminated array with the names of the modules that have a /* Return a NULL terminated array with the names of the modules that have a
* certain capability. * certain capability.
* Free after uses both the string and the table. */ * Free after uses both the string and the table. */
......
...@@ -57,7 +57,6 @@ int __config_LoadCmdLine( vlc_object_t *p_this, int *pi_argc, ...@@ -57,7 +57,6 @@ int __config_LoadCmdLine( vlc_object_t *p_this, int *pi_argc,
{ {
int i_cmd, i_index, i_opts, i_shortopts, flag, i_verbose = 0; int i_cmd, i_index, i_opts, i_shortopts, flag, i_verbose = 0;
module_t *p_parser; module_t *p_parser;
vlc_list_t *p_list;
struct option *p_longopts; struct option *p_longopts;
int i_modules_index; int i_modules_index;
const char **argv_copy = NULL; const char **argv_copy = NULL;
...@@ -85,29 +84,23 @@ int __config_LoadCmdLine( vlc_object_t *p_this, int *pi_argc, ...@@ -85,29 +84,23 @@ int __config_LoadCmdLine( vlc_object_t *p_this, int *pi_argc,
#endif #endif
/* List all modules */ /* List all modules */
p_list = vlc_list_find( p_this, VLC_OBJECT_MODULE, FIND_ANYWHERE ); module_t **list = module_list_get (NULL);
/* /*
* Generate the longopts and shortopts structures used by getopt_long * Generate the longopts and shortopts structures used by getopt_long
*/ */
i_opts = 0; i_opts = 0;
for( i_modules_index = 0; i_modules_index < p_list->i_count; for (size_t i = 0; (p_parser = list[i]) != NULL; i++)
i_modules_index++ )
{
p_parser = (module_t *)p_list->p_values[i_modules_index].p_object ;
/* count the number of exported configuration options (to allocate /* count the number of exported configuration options (to allocate
* longopts). We also need to allocate space for two options when * longopts). We also need to allocate space for two options when
* dealing with boolean to allow for --foo and --no-foo */ * dealing with boolean to allow for --foo and --no-foo */
i_opts += p_parser->i_config_items i_opts += p_parser->i_config_items + 2 * p_parser->i_bool_items;
+ 2 * p_parser->i_bool_items;
}
p_longopts = malloc( sizeof(struct option) * (i_opts + 1) ); p_longopts = malloc( sizeof(struct option) * (i_opts + 1) );
if( p_longopts == NULL ) if( p_longopts == NULL )
{ {
vlc_list_release( p_list ); module_list_free (list);
return -1; return -1;
} }
...@@ -115,7 +108,7 @@ int __config_LoadCmdLine( vlc_object_t *p_this, int *pi_argc, ...@@ -115,7 +108,7 @@ int __config_LoadCmdLine( vlc_object_t *p_this, int *pi_argc,
if( psz_shortopts == NULL ) if( psz_shortopts == NULL )
{ {
free( p_longopts ); free( p_longopts );
vlc_list_release( p_list ); module_list_free (list);
return -1; return -1;
} }
...@@ -129,7 +122,7 @@ int __config_LoadCmdLine( vlc_object_t *p_this, int *pi_argc, ...@@ -129,7 +122,7 @@ int __config_LoadCmdLine( vlc_object_t *p_this, int *pi_argc,
{ {
free( psz_shortopts ); free( psz_shortopts );
free( p_longopts ); free( p_longopts );
vlc_list_release( p_list ); module_list_free (list);
return -1; return -1;
} }
memcpy( argv_copy, ppsz_argv, *pi_argc * sizeof(char *) ); memcpy( argv_copy, ppsz_argv, *pi_argc * sizeof(char *) );
...@@ -144,11 +137,9 @@ int __config_LoadCmdLine( vlc_object_t *p_this, int *pi_argc, ...@@ -144,11 +137,9 @@ int __config_LoadCmdLine( vlc_object_t *p_this, int *pi_argc,
/* Fill the p_longopts and psz_shortopts structures */ /* Fill the p_longopts and psz_shortopts structures */
i_index = 0; i_index = 0;
for( i_modules_index = 0; i_modules_index < p_list->i_count; for (size_t i = 0; (p_parser = list[i]) != NULL; i++)
i_modules_index++ )
{ {
module_config_t *p_item, *p_end; module_config_t *p_item, *p_end;
p_parser = (module_t *)p_list->p_values[i_modules_index].p_object ;
if( !p_parser->i_config_items ) if( !p_parser->i_config_items )
continue; continue;
...@@ -226,7 +217,7 @@ int __config_LoadCmdLine( vlc_object_t *p_this, int *pi_argc, ...@@ -226,7 +217,7 @@ int __config_LoadCmdLine( vlc_object_t *p_this, int *pi_argc,
} }
/* We don't need the module list anymore */ /* We don't need the module list anymore */
vlc_list_release( p_list ); module_list_free( list );
/* Close the longopts and shortopts structures */ /* Close the longopts and shortopts structures */
memset( &p_longopts[i_index], 0, sizeof(struct option) ); memset( &p_longopts[i_index], 0, sizeof(struct option) );
......
...@@ -409,17 +409,17 @@ void __config_PutFloat( vlc_object_t *p_this, ...@@ -409,17 +409,17 @@ void __config_PutFloat( vlc_object_t *p_this,
*****************************************************************************/ *****************************************************************************/
module_config_t *config_FindConfig( vlc_object_t *p_this, const char *psz_name ) module_config_t *config_FindConfig( vlc_object_t *p_this, const char *psz_name )
{ {
vlc_list_t *p_list; module_t *p_parser;
int i_index;
if( !psz_name ) return NULL; if( !psz_name ) return NULL;
p_list = vlc_list_find( p_this, VLC_OBJECT_MODULE, FIND_ANYWHERE ); module_t **list = module_list_get (NULL);
if (list == NULL)
return NULL;
for( i_index = 0; i_index < p_list->i_count; i_index++ ) for (size_t i = 0; (p_parser = list[i]) != NULL; i++)
{ {
module_config_t *p_item, *p_end; module_config_t *p_item, *p_end;
module_t *p_parser = (module_t *)p_list->p_values[i_index].p_object;
if( !p_parser->i_config_items ) if( !p_parser->i_config_items )
continue; continue;
...@@ -435,14 +435,13 @@ module_config_t *config_FindConfig( vlc_object_t *p_this, const char *psz_name ) ...@@ -435,14 +435,13 @@ module_config_t *config_FindConfig( vlc_object_t *p_this, const char *psz_name )
|| ( p_item->psz_oldname || ( p_item->psz_oldname
&& !strcmp( psz_name, p_item->psz_oldname ) ) ) && !strcmp( psz_name, p_item->psz_oldname ) ) )
{ {
vlc_list_release( p_list ); module_list_free (list);
return p_item; return p_item;
} }
} }
} }
vlc_list_release( p_list ); module_list_free (list);
return NULL; return NULL;
} }
...@@ -536,17 +535,15 @@ void __config_ResetAll( vlc_object_t *p_this ) ...@@ -536,17 +535,15 @@ void __config_ResetAll( vlc_object_t *p_this )
{ {
libvlc_priv_t *priv = libvlc_priv (p_this->p_libvlc); libvlc_priv_t *priv = libvlc_priv (p_this->p_libvlc);
int i_index; int i_index;
vlc_list_t *p_list;
module_t *p_module; module_t *p_module;
module_t **list = module_list_get (NULL);
/* Acquire config file lock */ /* Acquire config file lock */
vlc_mutex_lock( &priv->config_lock ); vlc_mutex_lock( &priv->config_lock );
p_list = vlc_list_find( p_this, VLC_OBJECT_MODULE, FIND_ANYWHERE );
for( i_index = 0; i_index < p_list->i_count; i_index++ ) for (size_t j = 0; (p_module = list[j]) != NULL; j++)
{ {
p_module = (module_t *)p_list->p_values[i_index].p_object ;
if( p_module->b_submodule ) continue; if( p_module->b_submodule ) continue;
for (size_t i = 0; i < p_module->confsize; i++ ) for (size_t i = 0; i < p_module->confsize; i++ )
...@@ -566,6 +563,6 @@ void __config_ResetAll( vlc_object_t *p_this ) ...@@ -566,6 +563,6 @@ void __config_ResetAll( vlc_object_t *p_this )
} }
} }
vlc_list_release( p_list ); module_list_free (list);
vlc_mutex_unlock( &priv->config_lock ); vlc_mutex_unlock( &priv->config_lock );
} }
...@@ -158,7 +158,6 @@ static int strtoi (const char *str) ...@@ -158,7 +158,6 @@ static int strtoi (const char *str)
int __config_LoadConfigFile( vlc_object_t *p_this, const char *psz_module_name ) int __config_LoadConfigFile( vlc_object_t *p_this, const char *psz_module_name )
{ {
libvlc_priv_t *priv = libvlc_priv (p_this->p_libvlc); libvlc_priv_t *priv = libvlc_priv (p_this->p_libvlc);
vlc_list_t *p_list;
FILE *file; FILE *file;
file = config_OpenConfigFile (p_this, "rt"); file = config_OpenConfigFile (p_this, "rt");
...@@ -169,7 +168,7 @@ int __config_LoadConfigFile( vlc_object_t *p_this, const char *psz_module_name ) ...@@ -169,7 +168,7 @@ int __config_LoadConfigFile( vlc_object_t *p_this, const char *psz_module_name )
vlc_mutex_lock( &priv->config_lock ); vlc_mutex_lock( &priv->config_lock );
/* Look for the selected module, if NULL then save everything */ /* Look for the selected module, if NULL then save everything */
p_list = vlc_list_find( p_this, VLC_OBJECT_MODULE, FIND_ANYWHERE ); module_t **list = module_list_get (NULL);
/* Look for UTF-8 Byte Order Mark */ /* Look for UTF-8 Byte Order Mark */
char * (*convert) (const char *) = strdupnull; char * (*convert) (const char *) = strdupnull;
...@@ -215,9 +214,9 @@ int __config_LoadConfigFile( vlc_object_t *p_this, const char *psz_module_name ) ...@@ -215,9 +214,9 @@ int __config_LoadConfigFile( vlc_object_t *p_this, const char *psz_module_name )
if ((psz_module_name == NULL) if ((psz_module_name == NULL)
|| (strcmp (psz_module_name, section) == 0)) || (strcmp (psz_module_name, section) == 0))
{ {
for (int i = 0; i < p_list->i_count; i++) for (int i = 0; list[i]; i++)
{ {
module_t *m = (module_t *)p_list->p_values[i].p_object; module_t *m = list[i];
if ((strcmp (section, m->psz_object_name) == 0) if ((strcmp (section, m->psz_object_name) == 0)
&& (m->i_config_items > 0)) /* ignore config-less modules */ && (m->i_config_items > 0)) /* ignore config-less modules */
...@@ -317,7 +316,7 @@ int __config_LoadConfigFile( vlc_object_t *p_this, const char *psz_module_name ) ...@@ -317,7 +316,7 @@ int __config_LoadConfigFile( vlc_object_t *p_this, const char *psz_module_name )
} }
fclose (file); fclose (file);
vlc_list_release( p_list ); module_list_free (list);
if (loc != (locale_t)0) if (loc != (locale_t)0)
{ {
uselocale (baseloc); uselocale (baseloc);
...@@ -416,7 +415,6 @@ static int SaveConfigFile( vlc_object_t *p_this, const char *psz_module_name, ...@@ -416,7 +415,6 @@ static int SaveConfigFile( vlc_object_t *p_this, const char *psz_module_name,
{ {
libvlc_priv_t *priv = libvlc_priv (p_this->p_libvlc); libvlc_priv_t *priv = libvlc_priv (p_this->p_libvlc);
module_t *p_parser; module_t *p_parser;
vlc_list_t *p_list;
FILE *file; FILE *file;
char p_line[1024], *p_index2; char p_line[1024], *p_index2;
int i_sizebuf = 0; int i_sizebuf = 0;
...@@ -460,7 +458,7 @@ static int SaveConfigFile( vlc_object_t *p_this, const char *psz_module_name, ...@@ -460,7 +458,7 @@ static int SaveConfigFile( vlc_object_t *p_this, const char *psz_module_name,
p_bigbuffer[0] = 0; p_bigbuffer[0] = 0;
/* List all available modules */ /* List all available modules */
p_list = vlc_list_find( p_this, VLC_OBJECT_MODULE, FIND_ANYWHERE ); module_t **list = module_list_get (NULL);
/* backup file into memory, we only need to backup the sections we won't /* backup file into memory, we only need to backup the sections we won't
* save later on */ * save later on */
...@@ -471,10 +469,8 @@ static int SaveConfigFile( vlc_object_t *p_this, const char *psz_module_name, ...@@ -471,10 +469,8 @@ static int SaveConfigFile( vlc_object_t *p_this, const char *psz_module_name,
{ {
/* we found a section, check if we need to do a backup */ /* we found a section, check if we need to do a backup */
for( i_index = 0; i_index < p_list->i_count; i_index++ ) for( i_index = 0; (p_parser = list[i_index]) != NULL; i_index++ )
{ {
p_parser = (module_t *)p_list->p_values[i_index].p_object ;
if( ((p_index2 - &p_line[1]) if( ((p_index2 - &p_line[1])
== (int)strlen(p_parser->psz_object_name) ) == (int)strlen(p_parser->psz_object_name) )
&& !memcmp( &p_line[1], p_parser->psz_object_name, && !memcmp( &p_line[1], p_parser->psz_object_name,
...@@ -488,7 +484,7 @@ static int SaveConfigFile( vlc_object_t *p_this, const char *psz_module_name, ...@@ -488,7 +484,7 @@ static int SaveConfigFile( vlc_object_t *p_this, const char *psz_module_name,
} }
} }
if( i_index == p_list->i_count ) if( list[i_index] == NULL )
{ {
/* we don't have this section in our list so we need to back /* we don't have this section in our list so we need to back
* it up */ * it up */
...@@ -526,7 +522,7 @@ static int SaveConfigFile( vlc_object_t *p_this, const char *psz_module_name, ...@@ -526,7 +522,7 @@ static int SaveConfigFile( vlc_object_t *p_this, const char *psz_module_name,
file = config_OpenConfigFile (p_this, "wt"); file = config_OpenConfigFile (p_this, "wt");
if( !file ) if( !file )
{ {
vlc_list_release( p_list ); module_list_free (list);
free( p_bigbuffer ); free( p_bigbuffer );
vlc_mutex_unlock( &priv->config_lock ); vlc_mutex_unlock( &priv->config_lock );
return -1; return -1;
...@@ -540,10 +536,9 @@ static int SaveConfigFile( vlc_object_t *p_this, const char *psz_module_name, ...@@ -540,10 +536,9 @@ static int SaveConfigFile( vlc_object_t *p_this, const char *psz_module_name,
locale_t baseloc = uselocale (loc); locale_t baseloc = uselocale (loc);
/* Look for the selected module, if NULL then save everything */ /* Look for the selected module, if NULL then save everything */
for( i_index = 0; i_index < p_list->i_count; i_index++ ) for( i_index = 0; (p_parser = list[i_index]) != NULL; i_index++ )
{ {
module_config_t *p_item, *p_end; module_config_t *p_item, *p_end;
p_parser = (module_t *)p_list->p_values[i_index].p_object ;
if( psz_module_name && strcmp( psz_module_name, if( psz_module_name && strcmp( psz_module_name,
p_parser->psz_object_name ) ) p_parser->psz_object_name ) )
...@@ -644,7 +639,7 @@ static int SaveConfigFile( vlc_object_t *p_this, const char *psz_module_name, ...@@ -644,7 +639,7 @@ static int SaveConfigFile( vlc_object_t *p_this, const char *psz_module_name,
} }
} }
vlc_list_release( p_list ); module_list_free (list);
if (loc != (locale_t)0) if (loc != (locale_t)0)
{ {
uselocale (baseloc); uselocale (baseloc);
...@@ -666,18 +661,17 @@ static int SaveConfigFile( vlc_object_t *p_this, const char *psz_module_name, ...@@ -666,18 +661,17 @@ static int SaveConfigFile( vlc_object_t *p_this, const char *psz_module_name,
int config_AutoSaveConfigFile( vlc_object_t *p_this ) int config_AutoSaveConfigFile( vlc_object_t *p_this )
{ {
libvlc_priv_t *priv = libvlc_priv (p_this->p_libvlc); libvlc_priv_t *priv = libvlc_priv (p_this->p_libvlc);
vlc_list_t *p_list; size_t i_index;
int i_index, i_count; bool done;
assert( p_this ); assert( p_this );
/* Check if there's anything to save */ /* Check if there's anything to save */
vlc_mutex_lock( &priv->config_lock ); vlc_mutex_lock( &priv->config_lock );
p_list = vlc_list_find( p_this, VLC_OBJECT_MODULE, FIND_ANYWHERE ); module_t **list = module_list_get (NULL);
i_count = p_list->i_count; for( i_index = 0; list[i_index]; i_index++ )
for( i_index = 0; i_index < i_count; i_index++ )
{ {
module_t *p_parser = (module_t *)p_list->p_values[i_index].p_object ; module_t *p_parser = list[i_index];
module_config_t *p_item, *p_end; module_config_t *p_item, *p_end;
if( !p_parser->i_config_items ) continue; if( !p_parser->i_config_items ) continue;
...@@ -690,11 +684,11 @@ int config_AutoSaveConfigFile( vlc_object_t *p_this ) ...@@ -690,11 +684,11 @@ int config_AutoSaveConfigFile( vlc_object_t *p_this )
} }
if( p_item < p_end ) break; if( p_item < p_end ) break;
} }
vlc_list_release( p_list ); done = list[i_index] == NULL;
module_list_free (list);
vlc_mutex_unlock( &priv->config_lock ); vlc_mutex_unlock( &priv->config_lock );
if( i_index == i_count ) return VLC_SUCCESS; return done ? VLC_SUCCESS : SaveConfigFile( p_this, NULL, true );
return SaveConfigFile( p_this, NULL, true );
} }
int __config_SaveConfigFile( vlc_object_t *p_this, const char *psz_module_name ) int __config_SaveConfigFile( vlc_object_t *p_this, const char *psz_module_name )
......
...@@ -1424,14 +1424,12 @@ static void Usage( libvlc_int_t *p_this, char const *psz_search ) ...@@ -1424,14 +1424,12 @@ static void Usage( libvlc_int_t *p_this, char const *psz_search )
#else #else
# define OPTION_VALUE_SEP " " # define OPTION_VALUE_SEP " "
#endif #endif
vlc_list_t *p_list = NULL;
char psz_spaces_text[PADDING_SPACES+LINE_START+1]; char psz_spaces_text[PADDING_SPACES+LINE_START+1];
char psz_spaces_longtext[LINE_START+3]; char psz_spaces_longtext[LINE_START+3];
char psz_format[sizeof(COLOR_FORMAT_STRING)]; char psz_format[sizeof(COLOR_FORMAT_STRING)];
char psz_format_bool[sizeof(COLOR_FORMAT_STRING_BOOL)]; char psz_format_bool[sizeof(COLOR_FORMAT_STRING_BOOL)];
char psz_buffer[10000]; char psz_buffer[10000];
char psz_short[4]; char psz_short[4];
int i_index;
int i_width = ConsoleWidth() - (PADDING_SPACES+LINE_START+1); int i_width = ConsoleWidth() - (PADDING_SPACES+LINE_START+1);
int i_width_description = i_width + PADDING_SPACES - 1; int i_width_description = i_width + PADDING_SPACES - 1;
bool b_advanced = config_GetInt( p_this, "advanced" ) > 0; bool b_advanced = config_GetInt( p_this, "advanced" ) > 0;
...@@ -1466,7 +1464,9 @@ static void Usage( libvlc_int_t *p_this, char const *psz_search ) ...@@ -1466,7 +1464,9 @@ static void Usage( libvlc_int_t *p_this, char const *psz_search )
} }
/* List all modules */ /* List all modules */
p_list = vlc_list_find( p_this, VLC_OBJECT_MODULE, FIND_ANYWHERE ); module_t **list = module_list_get (NULL);
if (!list)
return;
/* Ugly hack to make sure that the help options always come first /* Ugly hack to make sure that the help options always come first
* (part 1) */ * (part 1) */
...@@ -1474,10 +1474,10 @@ static void Usage( libvlc_int_t *p_this, char const *psz_search ) ...@@ -1474,10 +1474,10 @@ static void Usage( libvlc_int_t *p_this, char const *psz_search )
Usage( p_this, "help" ); Usage( p_this, "help" );
/* Enumerate the config for each module */ /* Enumerate the config for each module */
for( i_index = 0; i_index < p_list->i_count; i_index++ ) for (size_t i = 0; list[i]; i++)
{ {
bool b_help_module; bool b_help_module;
module_t *p_parser = (module_t *)p_list->p_values[i_index].p_object; module_t *p_parser = list[i];
module_config_t *p_item = NULL; module_config_t *p_item = NULL;
module_config_t *p_section = NULL; module_config_t *p_section = NULL;
module_config_t *p_end = p_parser->p_config + p_parser->confsize; module_config_t *p_end = p_parser->p_config + p_parser->confsize;
...@@ -1870,7 +1870,7 @@ static void Usage( libvlc_int_t *p_this, char const *psz_search ) ...@@ -1870,7 +1870,7 @@ static void Usage( libvlc_int_t *p_this, char const *psz_search )
} }
/* Release the module list */ /* Release the module list */
vlc_list_release( p_list ); module_list_free (list);
} }
/***************************************************************************** /*****************************************************************************
...@@ -1881,10 +1881,8 @@ static void Usage( libvlc_int_t *p_this, char const *psz_search ) ...@@ -1881,10 +1881,8 @@ static void Usage( libvlc_int_t *p_this, char const *psz_search )
*****************************************************************************/ *****************************************************************************/
static void ListModules( libvlc_int_t *p_this, bool b_verbose ) static void ListModules( libvlc_int_t *p_this, bool b_verbose )
{ {
vlc_list_t *p_list = NULL; module_t *p_parser;
module_t *p_parser = NULL;
char psz_spaces[22]; char psz_spaces[22];
int i_index;
bool b_color = config_GetInt( p_this, "color" ) > 0; bool b_color = config_GetInt( p_this, "color" ) > 0;
...@@ -1895,15 +1893,13 @@ static void ListModules( libvlc_int_t *p_this, bool b_verbose ) ...@@ -1895,15 +1893,13 @@ static void ListModules( libvlc_int_t *p_this, bool b_verbose )
#endif #endif
/* List all modules */ /* List all modules */
p_list = vlc_list_find( p_this, VLC_OBJECT_MODULE, FIND_ANYWHERE ); module_t **list = module_list_get (NULL);
/* Enumerate each module */ /* Enumerate each module */
for( i_index = 0; i_index < p_list->i_count; i_index++ ) for (size_t j = 0; (p_parser = list[j]) != NULL; j++)
{ {
int i; int i;
p_parser = (module_t *)p_list->p_values[i_index].p_object ;
/* Nasty hack, but right now I'm too tired to think about a nice /* Nasty hack, but right now I'm too tired to think about a nice
* solution */ * solution */
i = 22 - strlen( p_parser->psz_object_name ) - 1; i = 22 - strlen( p_parser->psz_object_name ) - 1;
...@@ -1951,8 +1947,7 @@ static void ListModules( libvlc_int_t *p_this, bool b_verbose ) ...@@ -1951,8 +1947,7 @@ static void ListModules( libvlc_int_t *p_this, bool b_verbose )
psz_spaces[i] = ' '; psz_spaces[i] = ' ';
} }
module_list_free (list);
vlc_list_release( p_list );
#ifdef WIN32 /* Pause the console because it's destroyed when we exit */ #ifdef WIN32 /* Pause the console because it's destroyed when we exit */
PauseConsole(); PauseConsole();
......
...@@ -212,6 +212,8 @@ __module_GetModulesNamesForCapability ...@@ -212,6 +212,8 @@ __module_GetModulesNamesForCapability
module_GetName module_GetName
module_GetObjName module_GetObjName
module_IsCapable module_IsCapable
module_list_free
module_list_get
__module_Need __module_Need
module_Put module_Put
module_PutConfig module_PutConfig
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment