2005-09-20 23:26:39 +10:00
/** \file function.c
Functions for storing and retrieving function information .
*/
# include <stdlib.h>
# include <stdio.h>
# include <wchar.h>
# include <unistd.h>
# include <termios.h>
# include <signal.h>
# include "config.h"
2006-01-21 00:27:21 +10:00
# include "wutil.h"
2005-09-20 23:26:39 +10:00
# include "util.h"
# include "function.h"
# include "proc.h"
# include "parser.h"
# include "common.h"
# include "intern.h"
2005-10-06 08:37:08 +10:00
# include "event.h"
2006-01-27 00:48:10 +10:00
# include "reader.h"
2005-09-20 23:26:39 +10:00
/**
Struct describing a function
*/
typedef struct
{
/** Function definition */
wchar_t * cmd ;
/** Function description */
wchar_t * desc ;
2006-01-27 00:48:10 +10:00
const wchar_t * definition_file ;
int definition_offset ;
2005-09-21 09:42:00 +10:00
int is_binding ;
2005-09-20 23:26:39 +10:00
}
2005-10-06 08:37:08 +10:00
function_data_t ;
/**
Table containing all functions
*/
static hash_table_t function ;
2005-09-20 23:26:39 +10:00
/**
Free all contents of an entry to the function hash table
*/
static void clear_function_entry ( const void * key ,
const void * data )
{
function_data_t * d = ( function_data_t * ) data ;
free ( ( void * ) d - > cmd ) ;
free ( ( void * ) d - > desc ) ;
free ( ( void * ) d ) ;
}
void function_init ( )
{
hash_init ( & function ,
& hash_wcs_func ,
& hash_wcs_cmp ) ;
}
void function_destroy ( )
{
hash_foreach ( & function , & clear_function_entry ) ;
hash_destroy ( & function ) ;
}
2006-01-27 00:48:10 +10:00
static int count_lineno ( const wchar_t * str , int len )
{
int res = 0 ;
int i ;
for ( i = 0 ; i < len ; i + + )
{
if ( str [ i ] = = L ' \n ' )
res + + ;
}
return res ;
}
2005-09-20 23:26:39 +10:00
void function_add ( const wchar_t * name ,
const wchar_t * val ,
2005-09-21 09:42:00 +10:00
const wchar_t * desc ,
2005-10-06 08:37:08 +10:00
array_list_t * events ,
int is_binding )
2005-09-20 23:26:39 +10:00
{
2005-10-06 08:37:08 +10:00
int i ;
2006-01-14 11:58:01 +10:00
wchar_t * cmd_end ;
2006-01-31 02:51:50 +10:00
function_data_t * d ;
2005-10-06 08:37:08 +10:00
2005-09-20 23:26:39 +10:00
if ( function_exists ( name ) )
function_remove ( name ) ;
2006-01-31 02:51:50 +10:00
d = malloc ( sizeof ( function_data_t ) ) ;
2006-01-27 00:48:10 +10:00
d - > definition_offset = count_lineno ( parser_get_buffer ( ) , current_block - > tok_pos ) ;
2005-09-20 23:26:39 +10:00
d - > cmd = wcsdup ( val ) ;
2006-01-31 02:51:50 +10:00
2006-01-14 11:58:01 +10:00
cmd_end = d - > cmd + wcslen ( d - > cmd ) - 1 ;
while ( ( cmd_end > d - > cmd ) & & wcschr ( L " \n \r \t " , * cmd_end ) )
{
2006-01-27 00:48:10 +10:00
* cmd_end - - = 0 ;
2006-01-14 11:58:01 +10:00
}
2005-09-20 23:26:39 +10:00
d - > desc = desc ? wcsdup ( desc ) : 0 ;
2005-09-21 09:42:00 +10:00
d - > is_binding = is_binding ;
2006-01-27 00:48:10 +10:00
d - > definition_file = reader_current_filename ( ) ? intern ( reader_current_filename ( ) ) : 0 ;
2006-01-31 02:51:50 +10:00
2005-09-20 23:26:39 +10:00
hash_put ( & function , intern ( name ) , d ) ;
2006-01-27 00:48:10 +10:00
2005-10-06 08:37:08 +10:00
for ( i = 0 ; i < al_get_count ( events ) ; i + + )
{
event_add_handler ( ( event_t * ) al_get ( events , i ) ) ;
}
2005-09-20 23:26:39 +10:00
}
int function_exists ( const wchar_t * cmd )
{
return ( hash_get ( & function , cmd ) ! = 0 ) ;
}
void function_remove ( const wchar_t * name )
{
void * key ;
function_data_t * d ;
2005-10-06 08:37:08 +10:00
event_t ev ;
2006-01-31 02:51:50 +10:00
2005-10-06 08:37:08 +10:00
ev . type = EVENT_ANY ;
ev . function_name = name ;
event_remove ( & ev ) ;
2005-09-20 23:26:39 +10:00
hash_remove ( & function ,
name ,
( const void * * ) & key ,
( const void * * ) & d ) ;
if ( ! d )
return ;
clear_function_entry ( key , d ) ;
}
const wchar_t * function_get_definition ( const wchar_t * argv )
{
function_data_t * data =
( function_data_t * ) hash_get ( & function , argv ) ;
if ( data = = 0 )
return 0 ;
return data - > cmd ;
}
const wchar_t * function_get_desc ( const wchar_t * argv )
{
function_data_t * data =
( function_data_t * ) hash_get ( & function , argv ) ;
if ( data = = 0 )
return 0 ;
2006-01-24 09:32:13 +10:00
return data - > desc ;
2005-09-20 23:26:39 +10:00
}
void function_set_desc ( const wchar_t * name , const wchar_t * desc )
{
function_data_t * data =
( function_data_t * ) hash_get ( & function , name ) ;
if ( data = = 0 )
return ;
data - > desc = wcsdup ( desc ) ;
}
/**
Helper function for removing hidden functions
*/
static void get_names_internal ( const void * key ,
const void * val ,
void * aux )
{
wchar_t * name = ( wchar_t * ) key ;
2005-09-21 09:42:00 +10:00
function_data_t * f = ( function_data_t * ) val ;
if ( name [ 0 ] ! = L ' _ ' & & ! f - > is_binding )
2005-09-20 23:26:39 +10:00
al_push ( ( array_list_t * ) aux , name ) ;
}
void function_get_names ( array_list_t * list , int get_hidden )
{
if ( get_hidden )
hash_get_keys ( & function , list ) ;
else
hash_foreach2 ( & function , & get_names_internal , list ) ;
}
2005-10-06 08:37:08 +10:00
2006-01-27 00:48:10 +10:00
const wchar_t * function_get_definition_file ( const wchar_t * argv )
{
function_data_t * data =
( function_data_t * ) hash_get ( & function , argv ) ;
if ( data = = 0 )
return 0 ;
return data - > definition_file ;
}
int function_get_definition_offset ( const wchar_t * argv )
{
function_data_t * data =
( function_data_t * ) hash_get ( & function , argv ) ;
if ( data = = 0 )
return - 1 ;
return data - > definition_offset ;
}