2005-09-20 21:26:39 +08:00
/** \file function.c
2006-11-15 22:16:49 +08:00
Prototypes for functions for storing and retrieving function
information . These functions also take care of autoloading
functions in the $ fish_function_path . Actual function evaluation
is taken care of by the parser and to some degree the builtin
handling library .
2005-09-20 21:26:39 +08:00
*/
2006-08-11 09:18:35 +08:00
# include "config.h"
2005-09-20 21:26:39 +08:00
# include <stdlib.h>
# include <stdio.h>
2011-12-27 11:18:46 +08:00
# include <string.h>
2005-09-20 21:26:39 +08:00
# include <wchar.h>
# include <unistd.h>
# include <termios.h>
# include <signal.h>
2011-12-27 11:18:46 +08:00
# include <pthread.h>
# include <errno.h>
2005-09-20 21:26:39 +08:00
2006-01-20 22:27:21 +08:00
# include "wutil.h"
2006-02-28 21:17:16 +08:00
# include "fallback.h"
2005-09-20 21:26:39 +08:00
# include "util.h"
2006-02-28 21:17:16 +08:00
2005-09-20 21:26:39 +08:00
# include "function.h"
# include "proc.h"
# include "parser.h"
# include "common.h"
# include "intern.h"
2005-10-06 06:37:08 +08:00
# include "event.h"
2006-01-26 22:48:10 +08:00
# include "reader.h"
2006-02-05 21:10:35 +08:00
# include "parse_util.h"
2007-04-22 17:50:26 +08:00
# include "parser_keywords.h"
2006-02-08 17:20:05 +08:00
# include "env.h"
2006-02-08 23:29:09 +08:00
# include "expand.h"
2006-11-15 22:16:49 +08:00
# include "halloc.h"
# include "halloc_util.h"
2005-09-20 21:26:39 +08:00
/**
Struct describing a function
*/
typedef struct
{
/** Function definition */
2008-01-14 00:47:47 +08:00
wchar_t * definition ;
2005-09-20 21:26:39 +08:00
/** Function description */
2011-12-27 11:18:46 +08:00
wchar_t * description ;
2006-06-17 21:07:08 +08:00
/**
File where this function was defined
*/
2006-01-26 22:48:10 +08:00
const wchar_t * definition_file ;
2006-06-17 21:07:08 +08:00
/**
Line where definition started
*/
2011-12-27 11:18:46 +08:00
int definition_offset ;
2008-01-14 00:47:47 +08:00
/**
List of all named arguments for this function
*/
2007-04-17 04:06:11 +08:00
array_list_t * named_arguments ;
2011-12-27 11:18:46 +08:00
2006-06-17 21:07:08 +08:00
/**
Flag for specifying that this function was automatically loaded
*/
2006-02-08 17:20:05 +08:00
int is_autoload ;
2007-04-23 06:10:33 +08:00
2008-01-14 00:47:47 +08:00
/**
Set to non - zero if invoking this function shadows the variables
of the underlying function .
*/
2007-04-23 06:10:33 +08:00
int shadows ;
2005-09-20 21:26:39 +08:00
}
2007-04-23 06:10:33 +08:00
function_internal_data_t ;
2005-10-06 06:37:08 +08:00
/**
Table containing all functions
*/
2011-12-27 11:18:46 +08:00
static hash_table_t functions ;
/* Lock for functions */
static pthread_mutex_t functions_lock ;
/* Helper macro for vomiting */
# define VOMIT_ON_FAILURE(a) do { if (0 != (a)) { int err = errno; fprintf(stderr, "%s failed on line %d in file %s: %d (%s)\n", #a, __LINE__, __FILE__, err, strerror(err)); abort(); }} while (0)
static int kLockDepth = 0 ;
static char kLockFunction [ 1024 ] ;
/**
Lock and unlock the functions hash
*/
static void lock_functions ( const char * func ) {
VOMIT_ON_FAILURE ( pthread_mutex_lock ( & functions_lock ) ) ;
if ( ! kLockDepth + + ) {
strcat ( kLockFunction , func ) ;
}
}
static void unlock_functions ( void ) {
if ( ! - - kLockDepth ) {
memset ( kLockFunction , 0 , sizeof kLockFunction ) ;
}
VOMIT_ON_FAILURE ( pthread_mutex_unlock ( & functions_lock ) ) ;
}
# define LOCK_FUNCTIONS() lock_functions(__FUNCTION__)
# define UNLOCK_FUNCTIONS() unlock_functions()
2006-06-17 21:07:08 +08:00
/**
Kludgy flag set by the load function in order to tell function_add
that the function being defined is autoloaded . There should be a
better way to do this . . .
*/
2006-02-08 17:20:05 +08:00
static int is_autoload = 0 ;
2006-02-09 01:37:18 +08:00
/**
Make sure that if the specified function is a dynamically loaded
function , it has been fully loaded .
*/
2006-02-08 17:20:05 +08:00
static int load ( const wchar_t * name )
{
2011-12-27 13:56:23 +08:00
ASSERT_IS_MAIN_THREAD ( ) ;
2006-02-08 17:20:05 +08:00
int was_autoload = is_autoload ;
int res ;
2007-04-23 06:10:33 +08:00
function_internal_data_t * data ;
2011-12-27 11:18:46 +08:00
LOCK_FUNCTIONS ( ) ;
data = ( function_internal_data_t * ) hash_get ( & functions , name ) ;
if ( data & & ! data - > is_autoload ) {
UNLOCK_FUNCTIONS ( ) ;
2006-02-08 17:20:05 +08:00
return 0 ;
2011-12-27 11:18:46 +08:00
}
UNLOCK_FUNCTIONS ( ) ;
is_autoload = 1 ;
2006-02-08 17:20:05 +08:00
res = parse_util_load ( name ,
2006-02-20 01:01:16 +08:00
L " fish_function_path " ,
2006-02-08 17:20:05 +08:00
& function_remove ,
1 ) ;
is_autoload = was_autoload ;
return res ;
}
2006-02-09 01:37:18 +08:00
/**
Insert a list of all dynamically loaded functions into the
specified list .
*/
static void autoload_names ( array_list_t * out , int get_hidden )
{
int i ;
2011-12-27 11:18:46 +08:00
2006-02-09 01:37:18 +08:00
array_list_t path_list ;
const wchar_t * path_var = env_get ( L " fish_function_path " ) ;
2011-12-27 11:18:46 +08:00
2006-02-09 01:37:18 +08:00
if ( ! path_var )
return ;
2011-12-27 11:18:46 +08:00
2006-02-09 01:37:18 +08:00
al_init ( & path_list ) ;
2006-05-29 19:13:42 +08:00
tokenize_variable_array ( path_var , & path_list ) ;
2006-02-09 01:37:18 +08:00
for ( i = 0 ; i < al_get_count ( & path_list ) ; i + + )
{
wchar_t * ndir = ( wchar_t * ) al_get ( & path_list , i ) ;
DIR * dir = wopendir ( ndir ) ;
2006-02-14 05:44:16 +08:00
if ( ! dir )
continue ;
2011-12-27 11:18:46 +08:00
wcstring name ;
while ( wreaddir ( dir , name ) )
2006-02-09 01:37:18 +08:00
{
2011-12-27 11:18:46 +08:00
const wchar_t * fn = name . c_str ( ) ;
2006-02-09 01:37:18 +08:00
wchar_t * suffix ;
if ( ! get_hidden & & fn [ 0 ] = = L ' _ ' )
continue ;
2011-12-27 11:18:46 +08:00
2012-01-06 05:58:48 +08:00
suffix = const_cast < wchar_t * > ( wcsrchr ( fn , L ' . ' ) ) ;
2006-02-09 01:37:18 +08:00
if ( suffix & & ( wcscmp ( suffix , L " .fish " ) = = 0 ) )
{
2006-02-17 18:13:39 +08:00
const wchar_t * dup ;
2006-02-09 01:37:18 +08:00
* suffix = 0 ;
2006-02-14 05:44:16 +08:00
dup = intern ( fn ) ;
2006-02-09 01:37:18 +08:00
if ( ! dup )
2006-07-03 18:39:57 +08:00
DIE_MEM ( ) ;
2006-02-09 01:37:18 +08:00
al_push ( out , dup ) ;
}
2011-12-27 11:18:46 +08:00
}
2006-02-09 01:37:18 +08:00
closedir ( dir ) ;
}
2006-06-13 05:47:42 +08:00
al_foreach ( & path_list , & free ) ;
2006-02-09 01:37:18 +08:00
al_destroy ( & path_list ) ;
2006-02-08 17:20:05 +08:00
}
2005-09-20 21:26:39 +08:00
void function_init ( )
{
2011-12-27 11:18:46 +08:00
hash_init ( & functions ,
2005-09-20 21:26:39 +08:00
& hash_wcs_func ,
& hash_wcs_cmp ) ;
2011-12-27 11:18:46 +08:00
pthread_mutexattr_t a ;
VOMIT_ON_FAILURE ( pthread_mutexattr_init ( & a ) ) ;
VOMIT_ON_FAILURE ( pthread_mutexattr_settype ( & a , PTHREAD_MUTEX_RECURSIVE ) ) ;
VOMIT_ON_FAILURE ( pthread_mutex_init ( & functions_lock , & a ) ) ;
VOMIT_ON_FAILURE ( pthread_mutexattr_destroy ( & a ) ) ;
2005-09-20 21:26:39 +08:00
}
2008-01-14 00:47:47 +08:00
/**
Clear specified value , but not key
*/
2006-11-15 22:16:49 +08:00
static void clear_entry ( void * key , void * value )
{
halloc_free ( value ) ;
}
2005-09-20 21:26:39 +08:00
void function_destroy ( )
{
2011-12-27 11:18:46 +08:00
LOCK_FUNCTIONS ( ) ;
hash_foreach ( & functions , & clear_entry ) ;
hash_destroy ( & functions ) ;
UNLOCK_FUNCTIONS ( ) ;
2005-09-20 21:26:39 +08:00
}
2006-01-26 22:48:10 +08:00
2007-04-23 06:10:33 +08:00
void function_add ( function_data_t * data )
2005-09-20 21:26:39 +08:00
{
2005-10-06 06:37:08 +08:00
int i ;
2006-01-14 09:58:01 +08:00
wchar_t * cmd_end ;
2007-04-23 06:10:33 +08:00
function_internal_data_t * d ;
2011-12-27 11:18:46 +08:00
2007-04-23 06:10:33 +08:00
CHECK ( data - > name , ) ;
CHECK ( data - > definition , ) ;
2011-12-27 11:18:46 +08:00
LOCK_FUNCTIONS ( ) ;
2007-04-23 06:10:33 +08:00
function_remove ( data - > name ) ;
2011-12-27 11:18:46 +08:00
d = ( function_internal_data_t * ) halloc ( 0 , sizeof ( function_internal_data_t ) ) ;
2006-06-08 07:32:06 +08:00
d - > definition_offset = parse_util_lineno ( parser_get_buffer ( ) , current_block - > tok_pos ) - 1 ;
2008-01-14 00:47:47 +08:00
d - > definition = halloc_wcsdup ( d , data - > definition ) ;
2007-04-17 04:06:11 +08:00
2007-04-23 06:10:33 +08:00
if ( data - > named_arguments )
2007-04-17 04:06:11 +08:00
{
d - > named_arguments = al_halloc ( d ) ;
2007-04-23 06:10:33 +08:00
for ( i = 0 ; i < al_get_count ( data - > named_arguments ) ; i + + )
2007-04-17 04:06:11 +08:00
{
2007-04-23 06:10:33 +08:00
al_push ( d - > named_arguments , halloc_wcsdup ( d , ( wchar_t * ) al_get ( data - > named_arguments , i ) ) ) ;
2007-04-17 04:06:11 +08:00
}
}
2011-12-27 11:18:46 +08:00
2008-01-14 00:47:47 +08:00
cmd_end = d - > definition + wcslen ( d - > definition ) - 1 ;
2011-12-27 11:18:46 +08:00
2008-01-14 00:47:47 +08:00
d - > description = data - > description ? halloc_wcsdup ( d , data - > description ) : 0 ;
2006-02-05 21:10:35 +08:00
d - > definition_file = intern ( reader_current_filename ( ) ) ;
2006-02-08 17:20:05 +08:00
d - > is_autoload = is_autoload ;
2007-04-23 06:10:33 +08:00
d - > shadows = data - > shadows ;
2011-12-27 11:18:46 +08:00
hash_put ( & functions , intern ( data - > name ) , d ) ;
2007-04-23 06:10:33 +08:00
for ( i = 0 ; i < al_get_count ( data - > events ) ; i + + )
2005-10-06 06:37:08 +08:00
{
2007-04-23 06:10:33 +08:00
event_add_handler ( ( event_t * ) al_get ( data - > events , i ) ) ;
2005-10-06 06:37:08 +08:00
}
2011-12-27 11:18:46 +08:00
UNLOCK_FUNCTIONS ( ) ;
2005-09-20 21:26:39 +08:00
}
2011-12-27 13:56:23 +08:00
static int function_exists_internal ( const wchar_t * cmd , bool autoload )
2010-09-08 01:31:05 +08:00
{
2011-12-27 11:18:46 +08:00
int res ;
CHECK ( cmd , 0 ) ;
2010-09-08 01:31:05 +08:00
2011-12-27 11:18:46 +08:00
if ( parser_keywords_is_reserved ( cmd ) )
2010-09-08 01:31:05 +08:00
return 0 ;
2011-12-27 11:18:46 +08:00
LOCK_FUNCTIONS ( ) ;
if ( autoload ) load ( cmd ) ;
res = ( hash_get ( & functions , cmd ) ! = 0 ) ;
UNLOCK_FUNCTIONS ( ) ;
return res ;
2010-09-08 01:31:05 +08:00
}
2005-09-20 21:26:39 +08:00
int function_exists ( const wchar_t * cmd )
{
2011-12-27 13:56:23 +08:00
return function_exists_internal ( cmd , true ) ;
2011-12-27 11:18:46 +08:00
}
2010-09-18 09:51:16 +08:00
2011-12-27 11:18:46 +08:00
int function_exists_no_autoload ( const wchar_t * cmd )
{
2011-12-27 13:56:23 +08:00
return function_exists_internal ( cmd , false ) ;
2005-09-20 21:26:39 +08:00
}
void function_remove ( const wchar_t * name )
{
void * key ;
2006-06-13 05:47:42 +08:00
void * dv ;
2007-04-23 06:10:33 +08:00
function_internal_data_t * d ;
2005-10-06 06:37:08 +08:00
event_t ev ;
2011-12-27 11:18:46 +08:00
2006-06-21 08:48:36 +08:00
CHECK ( name , ) ;
2006-07-12 22:22:42 +08:00
2011-12-27 11:18:46 +08:00
LOCK_FUNCTIONS ( ) ;
hash_remove ( & functions ,
2005-09-20 21:26:39 +08:00
name ,
2006-06-13 05:47:42 +08:00
& key ,
2006-03-26 19:23:39 +08:00
& dv ) ;
2005-09-20 21:26:39 +08:00
2007-04-23 06:10:33 +08:00
d = ( function_internal_data_t * ) dv ;
2011-12-27 11:18:46 +08:00
if ( ! key ) {
UNLOCK_FUNCTIONS ( ) ;
2005-09-20 21:26:39 +08:00
return ;
2011-12-27 11:18:46 +08:00
}
2005-09-20 21:26:39 +08:00
2006-02-05 21:10:35 +08:00
ev . type = EVENT_ANY ;
2011-12-27 11:18:46 +08:00
ev . function_name = name ;
2006-02-05 21:10:35 +08:00
event_remove ( & ev ) ;
2006-11-15 22:16:49 +08:00
halloc_free ( d ) ;
2006-07-12 22:22:42 +08:00
/*
Notify the autoloader that the specified function is erased , but
only if this call to fish_remove is not made by the autoloader
itself .
*/
if ( ! is_autoload )
{
parse_util_unload ( name , L " fish_function_path " , 0 ) ;
}
2011-12-27 11:18:46 +08:00
UNLOCK_FUNCTIONS ( ) ;
2005-09-20 21:26:39 +08:00
}
2011-12-27 11:18:46 +08:00
2007-04-17 04:06:11 +08:00
const wchar_t * function_get_definition ( const wchar_t * name )
2005-09-20 21:26:39 +08:00
{
2007-04-23 06:10:33 +08:00
function_internal_data_t * data ;
2011-12-27 11:18:46 +08:00
2007-04-17 04:06:11 +08:00
CHECK ( name , 0 ) ;
2011-12-27 11:18:46 +08:00
LOCK_FUNCTIONS ( ) ;
2007-04-17 04:06:11 +08:00
load ( name ) ;
2011-12-27 11:18:46 +08:00
data = ( function_internal_data_t * ) hash_get ( & functions , name ) ;
UNLOCK_FUNCTIONS ( ) ;
2005-09-20 21:26:39 +08:00
if ( data = = 0 )
return 0 ;
2008-01-14 00:47:47 +08:00
return data - > definition ;
2005-09-20 21:26:39 +08:00
}
2007-04-17 04:06:11 +08:00
array_list_t * function_get_named_arguments ( const wchar_t * name )
{
2007-04-23 06:10:33 +08:00
function_internal_data_t * data ;
2011-12-27 11:18:46 +08:00
2007-04-17 04:06:11 +08:00
CHECK ( name , 0 ) ;
2011-12-27 11:18:46 +08:00
LOCK_FUNCTIONS ( ) ;
2007-04-17 04:06:11 +08:00
load ( name ) ;
2011-12-27 11:18:46 +08:00
data = ( function_internal_data_t * ) hash_get ( & functions , name ) ;
UNLOCK_FUNCTIONS ( ) ;
2007-04-17 04:06:11 +08:00
if ( data = = 0 )
return 0 ;
return data - > named_arguments ;
}
2007-04-23 06:10:33 +08:00
int function_get_shadows ( const wchar_t * name )
{
function_internal_data_t * data ;
2011-12-27 11:18:46 +08:00
2007-04-23 06:10:33 +08:00
CHECK ( name , 0 ) ;
2011-12-27 11:18:46 +08:00
LOCK_FUNCTIONS ( ) ;
2007-04-23 06:10:33 +08:00
load ( name ) ;
2011-12-27 11:18:46 +08:00
data = ( function_internal_data_t * ) hash_get ( & functions , name ) ;
UNLOCK_FUNCTIONS ( ) ;
2007-04-23 06:10:33 +08:00
if ( data = = 0 )
return 0 ;
return data - > shadows ;
}
2011-12-27 11:18:46 +08:00
2007-04-17 04:06:11 +08:00
const wchar_t * function_get_desc ( const wchar_t * name )
2005-09-20 21:26:39 +08:00
{
2007-04-23 06:10:33 +08:00
function_internal_data_t * data ;
2011-12-27 11:18:46 +08:00
2007-04-17 04:06:11 +08:00
CHECK ( name , 0 ) ;
2011-12-27 11:18:46 +08:00
2007-04-17 04:06:11 +08:00
load ( name ) ;
2011-12-27 11:18:46 +08:00
LOCK_FUNCTIONS ( ) ;
data = ( function_internal_data_t * ) hash_get ( & functions , name ) ;
UNLOCK_FUNCTIONS ( ) ;
2005-09-20 21:26:39 +08:00
if ( data = = 0 )
return 0 ;
2011-12-27 11:18:46 +08:00
2008-01-14 00:47:47 +08:00
return _ ( data - > description ) ;
2005-09-20 21:26:39 +08:00
}
void function_set_desc ( const wchar_t * name , const wchar_t * desc )
{
2007-04-23 06:10:33 +08:00
function_internal_data_t * data ;
2011-12-27 11:18:46 +08:00
2006-06-21 08:48:36 +08:00
CHECK ( name , ) ;
CHECK ( desc , ) ;
2011-12-27 11:18:46 +08:00
2006-02-08 17:20:05 +08:00
load ( name ) ;
2011-12-27 11:18:46 +08:00
LOCK_FUNCTIONS ( ) ;
data = ( function_internal_data_t * ) hash_get ( & functions , name ) ;
UNLOCK_FUNCTIONS ( ) ;
2005-09-20 21:26:39 +08:00
if ( data = = 0 )
return ;
2008-01-14 00:47:47 +08:00
data - > description = halloc_wcsdup ( data , desc ) ;
2005-09-20 21:26:39 +08:00
}
2011-12-27 11:18:46 +08:00
int function_copy ( const wchar_t * name , const wchar_t * new_name )
{
int i ;
function_internal_data_t * d , * orig_d ;
CHECK ( name , 0 ) ;
CHECK ( new_name , 0 ) ;
orig_d = ( function_internal_data_t * ) hash_get ( & functions , name ) ;
if ( ! orig_d )
return 0 ;
d = ( function_internal_data_t * ) halloc ( 0 , sizeof ( function_internal_data_t ) ) ;
d - > definition_offset = orig_d - > definition_offset ;
d - > definition = halloc_wcsdup ( d , orig_d - > definition ) ;
if ( orig_d - > named_arguments )
{
d - > named_arguments = al_halloc ( d ) ;
for ( i = 0 ; i < al_get_count ( orig_d - > named_arguments ) ; i + + )
{
al_push ( d - > named_arguments , halloc_wcsdup ( d , ( wchar_t * ) al_get ( orig_d - > named_arguments , i ) ) ) ;
}
d - > description = orig_d - > description ? halloc_wcsdup ( d , orig_d - > description ) : 0 ;
d - > shadows = orig_d - > shadows ;
// This new instance of the function shouldn't be tied to the def
// file of the original.
d - > definition_file = 0 ;
d - > is_autoload = 0 ;
}
hash_put ( & functions , intern ( new_name ) , d ) ;
return 1 ;
}
2006-06-20 08:50:10 +08:00
/**
Search arraylist of strings for specified string
*/
2006-05-14 17:46:35 +08:00
static int al_contains_str ( array_list_t * list , const wchar_t * str )
{
int i ;
2008-01-16 09:05:48 +08:00
CHECK ( list , 0 ) ;
CHECK ( str , 0 ) ;
2011-12-27 11:18:46 +08:00
2006-05-14 17:46:35 +08:00
for ( i = 0 ; i < al_get_count ( list ) ; i + + )
{
2011-12-27 11:18:46 +08:00
if ( wcscmp ( ( const wchar_t * ) al_get ( list , i ) , str ) = = 0 )
2006-11-15 22:16:49 +08:00
{
return 1 ;
}
2006-05-14 17:46:35 +08:00
}
return 0 ;
}
2011-12-27 11:18:46 +08:00
2005-09-20 21:26:39 +08:00
/**
2011-12-27 11:18:46 +08:00
Helper function for removing hidden functions
2005-09-20 21:26:39 +08:00
*/
2006-06-13 05:47:42 +08:00
static void get_names_internal ( void * key ,
void * val ,
2005-09-20 21:26:39 +08:00
void * aux )
{
wchar_t * name = ( wchar_t * ) key ;
2006-10-26 04:28:36 +08:00
if ( name [ 0 ] ! = L ' _ ' & & ! al_contains_str ( ( array_list_t * ) aux , name ) )
2006-05-14 17:46:35 +08:00
{
al_push ( ( array_list_t * ) aux , name ) ;
}
}
/**
2011-12-27 11:18:46 +08:00
Helper function for removing hidden functions
2006-05-14 17:46:35 +08:00
*/
2006-06-13 05:47:42 +08:00
static void get_names_internal_all ( void * key ,
void * val ,
void * aux )
2006-05-14 17:46:35 +08:00
{
wchar_t * name = ( wchar_t * ) key ;
2011-12-27 11:18:46 +08:00
2006-05-14 17:46:35 +08:00
if ( ! al_contains_str ( ( array_list_t * ) aux , name ) )
{
2005-09-20 21:26:39 +08:00
al_push ( ( array_list_t * ) aux , name ) ;
2006-05-14 17:46:35 +08:00
}
2005-09-20 21:26:39 +08:00
}
void function_get_names ( array_list_t * list , int get_hidden )
{
2006-06-21 08:48:36 +08:00
CHECK ( list , ) ;
2011-12-27 11:18:46 +08:00
LOCK_FUNCTIONS ( ) ;
2006-02-09 01:37:18 +08:00
autoload_names ( list , get_hidden ) ;
2011-12-27 11:18:46 +08:00
2005-09-20 21:26:39 +08:00
if ( get_hidden )
2006-05-14 17:46:35 +08:00
{
2011-12-27 11:18:46 +08:00
hash_foreach2 ( & functions , & get_names_internal_all , list ) ;
2006-05-14 17:46:35 +08:00
}
2005-09-20 21:26:39 +08:00
else
2006-05-14 17:46:35 +08:00
{
2011-12-27 11:18:46 +08:00
hash_foreach2 ( & functions , & get_names_internal , list ) ;
2006-05-14 17:46:35 +08:00
}
2011-12-27 11:18:46 +08:00
UNLOCK_FUNCTIONS ( ) ;
2005-09-20 21:26:39 +08:00
}
2005-10-06 06:37:08 +08:00
2007-04-17 04:06:11 +08:00
const wchar_t * function_get_definition_file ( const wchar_t * name )
2006-01-26 22:48:10 +08:00
{
2007-04-23 06:10:33 +08:00
function_internal_data_t * data ;
2006-06-08 08:01:45 +08:00
2007-04-17 04:06:11 +08:00
CHECK ( name , 0 ) ;
2011-12-27 11:18:46 +08:00
LOCK_FUNCTIONS ( ) ;
data = ( function_internal_data_t * ) hash_get ( & functions , name ) ;
UNLOCK_FUNCTIONS ( ) ;
2006-01-26 22:48:10 +08:00
if ( data = = 0 )
return 0 ;
2011-12-27 11:18:46 +08:00
2006-01-26 22:48:10 +08:00
return data - > definition_file ;
}
2007-04-17 04:06:11 +08:00
int function_get_definition_offset ( const wchar_t * name )
2006-01-26 22:48:10 +08:00
{
2007-04-23 06:10:33 +08:00
function_internal_data_t * data ;
2006-06-08 08:01:45 +08:00
2007-04-17 04:06:11 +08:00
CHECK ( name , - 1 ) ;
2011-12-27 11:18:46 +08:00
LOCK_FUNCTIONS ( ) ;
data = ( function_internal_data_t * ) hash_get ( & functions , name ) ;
UNLOCK_FUNCTIONS ( ) ;
2006-01-26 22:48:10 +08:00
if ( data = = 0 )
return - 1 ;
2011-12-27 11:18:46 +08:00
2006-01-26 22:48:10 +08:00
return data - > definition_offset ;
}