Switched to std::map instead of hash_table_t in env.cpp and env_universal_common.cpp.

This commit is contained in:
Siteshwar Vashisht 2012-02-18 00:22:30 +05:30
parent a08450bcb6
commit 6e58c9f7c8
7 changed files with 342 additions and 378 deletions

View File

@ -431,6 +431,8 @@ static int builtin_complete( parser_t &parser, wchar_t **argv )
path.push_back(a); path.push_back(a);
else else
cmd.push_back(a); cmd.push_back(a);
free(a);
} }
else else
{ {

518
env.cpp
View File

@ -17,6 +17,7 @@
#include <pwd.h> #include <pwd.h>
#include <set> #include <set>
#include <map> #include <map>
#include <algorithm>
#if HAVE_NCURSES_H #if HAVE_NCURSES_H
#include <ncurses.h> #include <ncurses.h>
@ -79,6 +80,22 @@ extern char **environ;
*/ */
extern char **__environ; extern char **__environ;
/**
A variable entry. Stores the value of a variable and whether it
should be exported. Obviously, it needs to be allocated large
enough to fit the value string.
*/
typedef struct var_entry
{
int exportv; /**< Whether the variable should be exported */
size_t size; /**< The maximum length (excluding the NULL) that will fit into this var_entry_t */
wcstring val; /**< The value of the variable */
var_entry():exportv(0), size(0){ }
}
var_entry_t;
/** /**
Struct representing one level in the function variable stack Struct representing one level in the function variable stack
@ -88,7 +105,7 @@ typedef struct env_node
/** /**
Variable table Variable table
*/ */
hash_table_t env; std::map<wcstring, var_entry_t*> env;
/** /**
Does this node imply a new variable scope? If yes, all Does this node imply a new variable scope? If yes, all
non-global variables below this one in the stack are non-global variables below this one in the stack are
@ -105,27 +122,12 @@ typedef struct env_node
Pointer to next level Pointer to next level
*/ */
struct env_node *next; struct env_node *next;
env_node() : new_scope(0), exportv(0), next(NULL) { }
} }
env_node_t; env_node_t;
/**
A variable entry. Stores the value of a variable and whether it
should be exported. Obviously, it needs to be allocated large
enough to fit the value string.
*/
typedef struct var_entry
{
int exportv; /**< Whether the variable should be exported */
size_t size; /**< The maximum length (excluding the NULL) that will fit into this var_entry_t */
#if __STDC_VERSION__ < 199901L
wchar_t val[1]; /**< The value of the variable */
#else
wchar_t val[]; /**< The value of the variable */
#endif
}
var_entry_t;
class variable_entry_t { class variable_entry_t {
bool exportv; /**< Whether the variable should be exported */ bool exportv; /**< Whether the variable should be exported */
wcstring value; /**< Value of the variable */ wcstring value; /**< Value of the variable */
@ -147,7 +149,7 @@ static env_node_t *global_env = 0;
/** /**
Table for global variables Table for global variables
*/ */
static hash_table_t *global; static std::map<wcstring, var_entry_t *> *global;
/** /**
Table of variables that may not be set using the set command. Table of variables that may not be set using the set command.
@ -221,20 +223,6 @@ static const wchar_t *locale_variable[] =
} }
; ;
/**
Free hash key and hash value
*/
static void clear_hash_entry( void *key, void *data )
{
var_entry_t *entry = (var_entry_t *)data;
if( entry->exportv )
{
has_changed = 1;
}
free( (void *)key );
free( (void *)data );
}
/** /**
When fishd isn't started, this function is provided to When fishd isn't started, this function is provided to
@ -257,7 +245,7 @@ static void start_fishd()
wcstring cmd = format_string(FISHD_CMD, pw->pw_name); wcstring cmd = format_string(FISHD_CMD, pw->pw_name);
parser_t &parser = parser_t::principal_parser(); parser_t &parser = parser_t::principal_parser();
parser.eval( cmd.c_str(), 0, TOP ); parser.eval( cmd, 0, TOP );
} }
/** /**
@ -560,11 +548,7 @@ void env_init()
env_electric.insert(L"status"); env_electric.insert(L"status");
env_electric.insert(L"umask"); env_electric.insert(L"umask");
top = (env_node_t *)malloc( sizeof(env_node_t) ); top = new env_node_t;
top->next = 0;
top->new_scope = 0;
top->exportv=0;
hash_init( &top->env, &hash_wcs_func, &hash_wcs_cmp );
global_env = top; global_env = top;
global = &top->env; global = &top->env;
@ -702,30 +686,38 @@ void env_destroy()
env_electric.clear(); env_electric.clear();
hash_foreach( global, &clear_hash_entry ); std::map<wcstring, var_entry_t*>::iterator iter;
hash_destroy( global ); for (iter = global->begin(); iter != global->end(); ++iter) {
free( top ); var_entry_t *entry = iter->second;
if( entry->exportv )
free( export_arr ); {
has_changed = 1;
}
delete entry;
}
delete top;
free( export_arr );
} }
/** /**
Search all visible scopes in order for the specified key. Return Search all visible scopes in order for the specified key. Return
the first scope in which it was found. the first scope in which it was found.
*/ */
static env_node_t *env_get_node( const wchar_t *key ) static env_node_t *env_get_node( const wcstring &key )
{ {
var_entry_t* res; var_entry_t* res = NULL;
env_node_t *env = top; env_node_t *env = top;
while( env != 0 ) while( env != 0 )
{ {
res = (var_entry_t *) hash_get( &env->env, std::map<wcstring, var_entry_t*>::const_iterator result = env->env.find( key );
key );
if( res != 0 ) if ( result != env->env.end() )
{ {
res = result->second;
return env; return env;
} }
@ -747,8 +739,8 @@ int env_set( const wchar_t *key,
int var_mode ) int var_mode )
{ {
int free_val = 0; int free_val = 0;
var_entry_t *entry; var_entry_t *entry = NULL;
env_node_t *node; env_node_t *node = NULL;
int has_changed_old = has_changed; int has_changed_old = has_changed;
int has_changed_new = 0; int has_changed_new = 0;
var_entry_t *e=0; var_entry_t *e=0;
@ -829,10 +821,16 @@ int env_set( const wchar_t *key,
{ {
node = env_get_node( key ); node = env_get_node( key );
if( node && &node->env != 0 ) if( node )
{ {
e = (var_entry_t *) hash_get( &node->env,
key ); std::map<wcstring, var_entry_t*>::iterator result = node->env.find(key);
if ( result != node->env.end() ) {
e = result->second;
}
else {
e = NULL;
}
if( e->exportv ) if( e->exportv )
{ {
@ -901,98 +899,85 @@ int env_set( const wchar_t *key,
} }
if( !done ) if( !done )
{ {
void *k, *v; var_entry_t *old_entry = NULL;
var_entry_t *old_entry; size_t val_len = wcslen(val);
size_t val_len = wcslen(val); std::map<wcstring, var_entry_t*>::iterator result = node->env.find(key);
if ( result != node->env.end() )
{
old_entry = result->second;
node->env.erase(result);
}
hash_remove( &node->env, key, &k, &v );
/*
Try to reuse previous key string
*/
if( !k )
{
k = wcsdup(key);
}
old_entry = (var_entry_t *)v;
if( old_entry && old_entry->size >= val_len ) if( old_entry && old_entry->size >= val_len )
{ {
entry = old_entry; entry = old_entry;
if( !!(var_mode & ENV_EXPORT) || entry->exportv ) if( !!(var_mode & ENV_EXPORT) || entry->exportv )
{ {
entry->exportv = !!(var_mode & ENV_EXPORT); entry->exportv = !!(var_mode & ENV_EXPORT);
has_changed_new = 1; has_changed_new = 1;
} }
} }
else else
{ {
free( v ); delete old_entry;
entry = new var_entry_t;
entry = (var_entry_t *)malloc( sizeof( var_entry_t ) + if( !entry )
sizeof(wchar_t )*(val_len+1)); {
DIE_MEM();
if( !entry ) }
{
DIE_MEM();
}
entry->size = val_len; entry->size = val_len;
if( var_mode & ENV_EXPORT) if( var_mode & ENV_EXPORT)
{ {
entry->exportv = 1; entry->exportv = 1;
has_changed_new = 1; has_changed_new = 1;
} }
else else
{ {
entry->exportv = 0; entry->exportv = 0;
} }
} }
wcscpy( entry->val, val ); entry->val = val;
hash_put( &node->env, k, entry ); node->env.insert(std::pair<wcstring, var_entry_t*>(key, entry));
if( entry->exportv ) if( entry->exportv )
{ {
node->exportv=1; node->exportv=1;
} }
if( free_val )
{
free((void *)val);
}
has_changed = has_changed_old || has_changed_new; has_changed = has_changed_old || has_changed_new;
} }
} }
if( !is_universal ) if( !is_universal )
{ {
event_t ev = event_t::variable_event(key); event_t ev = event_t::variable_event(key);
ev.arguments.reset(new wcstring_list_t); ev.arguments.reset(new wcstring_list_t);
ev.arguments->push_back(L"VARIABLE"); ev.arguments->push_back(L"VARIABLE");
ev.arguments->push_back(L"SET"); ev.arguments->push_back(L"SET");
ev.arguments->push_back(key); ev.arguments->push_back(key);
// debug( 1, L"env_set: fire events on variable %ls", key ); // debug( 1, L"env_set: fire events on variable %ls", key );
event_fire( &ev ); event_fire( &ev );
// debug( 1, L"env_set: return from event firing" ); // debug( 1, L"env_set: return from event firing" );
ev.arguments.reset(NULL); ev.arguments.reset(NULL);
} }
if( is_locale( key ) ) if( is_locale( key ) )
{ {
handle_locale(); handle_locale();
} }
return 0; return 0;
} }
/** /**
@ -1005,32 +990,22 @@ static int try_remove( env_node_t *n,
const wchar_t *key, const wchar_t *key,
int var_mode ) int var_mode )
{ {
void *old_key_void, *old_val_void;
wchar_t *old_key, *old_val;
if( n == 0 ) if( n == 0 )
{ {
return 0; return 0;
} }
hash_remove( &n->env,
key,
&old_key_void,
&old_val_void );
old_key = (wchar_t *)old_key_void; std::map<wcstring, var_entry_t*>::iterator result = n->env.find( key );
old_val = (wchar_t *)old_val_void; if ( result != n->env.end() )
if( old_key != 0 )
{ {
var_entry_t * v = (var_entry_t *)old_val; var_entry_t *v = result->second;
if( v->exportv ) if( v->exportv )
{ {
has_changed = 1; has_changed = 1;
} }
free(old_key); delete v;
free(old_val);
return 1; return 1;
} }
@ -1174,30 +1149,39 @@ env_var_t env_get_string( const wchar_t *key )
wcstring result; wcstring result;
while( env != 0 ) while( env != 0 )
{ {
res = (var_entry_t *) hash_get( &env->env, std::map<wcstring, var_entry_t*>::iterator result = env->env.find(key);
key ); if ( result != env->env.end() )
if( res != 0 ) {
{ res = result->second;
if( wcscmp( res->val, ENV_NULL )==0) }
{ else
return wcstring(L""); {
} res = 0;
else }
{
return res->val;
} if( res != 0 )
} {
if( res->val == ENV_NULL )
{
return wcstring(L"");
}
else
{
return res->val;
}
}
if( env->new_scope ) if( env->new_scope )
{ {
env = global_env; env = global_env;
} }
else else
{ {
env = env->next; env = env->next;
} }
} }
if( !proc_had_barrier) if( !proc_had_barrier)
{ {
proc_had_barrier=1; proc_had_barrier=1;
@ -1251,7 +1235,7 @@ const wchar_t *env_get( const wchar_t *key )
} }
/* We always have a trailing ARRAY_SEP_STR; get rid of it */ /* We always have a trailing ARRAY_SEP_STR; get rid of it */
if (dyn_var.size() >= wcslen(ARRAY_SEP_STR)) { if (dyn_var.size() >= wcslen(ARRAY_SEP_STR)) {
dyn_var.resize(dyn_var.size() - wcslen(ARRAY_SEP_STR)); dyn_var.resize(dyn_var.size() - wcslen(ARRAY_SEP_STR));
} }
@ -1280,17 +1264,26 @@ const wchar_t *env_get( const wchar_t *key )
while( env != 0 ) while( env != 0 )
{ {
res = (var_entry_t *) hash_get( &env->env, std::map<wcstring, var_entry_t*>::iterator result = env->env.find(key);
key ); if ( result != env->env.end() )
{
res = result->second;
}
else
{
res = 0;
}
if( res != 0 ) if( res != 0 )
{ {
if( wcscmp( res->val, ENV_NULL )==0) if( res->val == ENV_NULL )
{ {
return 0; return 0;
} }
else else
{ {
return res->val; return wcsdup(res->val.c_str());
} }
} }
@ -1347,8 +1340,16 @@ int env_exist( const wchar_t *key, int mode )
while( env != 0 ) while( env != 0 )
{ {
res = (var_entry_t *) hash_get( &env->env, std::map<wcstring, var_entry_t*>::iterator result = env->env.find( key );
key ); if ( result != env->env.end() )
{
res = result->second;
}
else
{
res = 0;
}
if( res != 0 ) if( res != 0 )
{ {
return 1; return 1;
@ -1405,11 +1406,10 @@ static int local_scope_exports( env_node_t *n )
void env_push( int new_scope ) void env_push( int new_scope )
{ {
env_node_t *node = (env_node_t *)malloc( sizeof(env_node_t) ); env_node_t *node = new env_node_t;
node->next = top; node->next = top;
node->exportv=0;
hash_init( &node->env, &hash_wcs_func, &hash_wcs_cmp );
node->new_scope=new_scope; node->new_scope=new_scope;
if( new_scope ) if( new_scope )
{ {
has_changed |= local_scope_exports(top); has_changed |= local_scope_exports(top);
@ -1430,7 +1430,8 @@ void env_pop()
for( i=0; locale_variable[i]; i++ ) for( i=0; locale_variable[i]; i++ )
{ {
if( hash_get( &killme->env, locale_variable[i] ) ) std::map<wcstring, var_entry_t*>::iterator result = killme->env.find( locale_variable[i] );
if ( result != killme->env.end() )
{ {
locale_changed = 1; locale_changed = 1;
break; break;
@ -1443,9 +1444,20 @@ void env_pop()
} }
top = top->next; top = top->next;
hash_foreach( &killme->env, &clear_hash_entry );
hash_destroy( &killme->env ); std::map<wcstring, var_entry_t*>::iterator iter;
free( killme ); for (iter = killme->env.begin(); iter != killme->env.end(); ++iter)
{
var_entry_t *entry = iter->second;
if( entry->exportv )
{
has_changed = 1;
}
delete entry;
}
delete killme;
if( locale_changed ) if( locale_changed )
handle_locale(); handle_locale();
@ -1478,6 +1490,23 @@ static void add_key_to_string_set( void *key,
} }
} }
static void add_key_to_string_set(const std::map<wcstring, var_entry_t*> &envs, std::set<wcstring> &strSet)
{
std::map<wcstring, var_entry_t*>::const_iterator iter;
for (iter = envs.begin(); iter != envs.end(); ++iter)
{
var_entry_t *e = iter->second;
if( ( e->exportv && get_names_show_exported) ||
( !e->exportv && get_names_show_unexported) )
{
/*Insert Key*/
strSet.insert(iter->first);
}
}
}
wcstring_list_t env_get_names( int flags ) wcstring_list_t env_get_names( int flags )
{ {
wcstring_list_t result; wcstring_list_t result;
@ -1506,10 +1535,7 @@ wcstring_list_t env_get_names( int flags )
if( n == global_env ) if( n == global_env )
break; break;
hash_foreach2( &n->env, add_key_to_string_set(n->env, names);
add_key_to_string_set,
&names );
if( n->new_scope ) if( n->new_scope )
break; break;
else else
@ -1520,10 +1546,7 @@ wcstring_list_t env_get_names( int flags )
if( show_global ) if( show_global )
{ {
hash_foreach2( &global_env->env, add_key_to_string_set(global_env->env, names);
add_key_to_string_set,
&names );
if( get_names_show_unexported ) { if( get_names_show_unexported ) {
result.insert(result.end(), env_electric.begin(), env_electric.end()); result.insert(result.end(), env_electric.begin(), env_electric.end());
} }
@ -1551,77 +1574,58 @@ wcstring_list_t env_get_names( int flags )
} }
/** /**
Function used by env_export_arr to iterate over hashtable of variables Get list of all exported variables
*/ */
static void export_func1( void *k, void *v, void *aux )
{
var_entry_t *val_entry = (var_entry_t *)v;
hash_table_t *h = (hash_table_t *)aux;
hash_remove( h, k, 0, 0 ); static void get_exported2( const env_node_t *n, std::map<wcstring, wcstring> &h )
if( val_entry->exportv && wcscmp( val_entry->val, ENV_NULL ) )
{
hash_put( h, k, val_entry->val );
}
}
/**
Get list of all exported variables
*/
static void get_exported( env_node_t *n, hash_table_t *h )
{ {
if( !n ) if( !n )
return; return;
if( n->new_scope ) if( n->new_scope )
get_exported( global_env, h ); get_exported2( global_env, h );
else else
get_exported( n->next, h ); get_exported2( n->next, h );
hash_foreach2( &n->env, &export_func1, h );
}
std::map<wcstring, var_entry_t*>::const_iterator iter;
for (iter = n->env.begin(); iter != n->env.end(); ++iter)
{
wcstring key = iter->first;
var_entry_t *val_entry = iter->second;
if( val_entry->exportv && (val_entry->val != ENV_NULL ) )
{
h.insert(std::pair<wcstring, wcstring>(key, val_entry->val));
}
}
}
/** /**
Function used by env_export_arr to iterate over hashtable of variables Function used by env_export_arr to iterate over map of variables
*/ */
static void export_func2( void *k, void *v, void *aux ) static void export_func2(std::map<wcstring, wcstring> &envs, buffer_t* out)
{ {
wchar_t *key = (wchar_t *)k; std::map<wcstring, wcstring>::const_iterator iter;
wchar_t *val = (wchar_t *)v; for (iter = envs.begin(); iter != envs.end(); ++iter)
char *ks = wcs2str( key );
char *vs = wcs2str( val );
char *pos = vs;
buffer_t *out = (buffer_t *)aux;
if( !ks || !vs )
{ {
DIE_MEM(); char* ks = wcs2str(iter->first.c_str());
} char* vs = wcs2str(iter->second.c_str());
char *pos = vs;
/* while( *pos )
Make arrays into colon-separated lists {
*/ if( *pos == ARRAY_SEP )
while( *pos ) *pos = ':';
{ pos++;
if( *pos == ARRAY_SEP ) }
*pos = ':'; int nil = 0;
pos++;
}
int nil = 0;
b_append( out, ks, strlen(ks) );
b_append( out, "=", 1 );
b_append( out, vs, strlen(vs) );
b_append( out, &nil, 1 );
free( ks ); b_append( out, ks, strlen(ks) );
free( vs ); b_append( out, "=", 1 );
b_append( out, vs, strlen(vs) );
b_append( out, &nil, 1 );
free(ks);
free(vs);
}
} }
char **env_export_arr( int recalc ) char **env_export_arr( int recalc )
@ -1634,34 +1638,36 @@ char **env_export_arr( int recalc )
if( has_changed ) if( has_changed )
{ {
hash_table_t vals; std::map<wcstring, wcstring> vals;
int prev_was_null=1; int prev_was_null=1;
int pos=0; int pos=0;
size_t i; size_t i;
debug( 4, L"env_export_arr() recalc" ); debug( 4, L"env_export_arr() recalc" );
hash_init( &vals, &hash_wcs_func, &hash_wcs_cmp ); get_exported2( top, vals );
get_exported( top, &vals );
wcstring_list_t uni; wcstring_list_t uni;
env_universal_get_names2( uni, 1, 0 ); env_universal_get_names2( uni, 1, 0 );
for( i=0; i<uni.size(); i++ ) for( i=0; i<uni.size(); i++ )
{ {
const wchar_t *key = uni.at(i).c_str(); const wcstring &key = uni.at(i);
const wchar_t *val = env_universal_get( key ); const wchar_t *val = env_universal_get( key.c_str() );
if( wcscmp( val, ENV_NULL) && !hash_get( &vals, key ) )
hash_put( &vals, key, val ); std::map<wcstring, wcstring>::iterator result = vals.find( key );
if( wcscmp( val, ENV_NULL) && ( result == vals.end() ) )
{
vals.insert(std::pair<wcstring, wcstring>(key, val));
}
} }
export_buffer.used=0; export_buffer.used=0;
hash_foreach2( &vals, &export_func2, &export_buffer ); export_func2(vals, &export_buffer );
hash_destroy( &vals );
export_arr = (char **)realloc( export_arr, export_arr = (char **)realloc( export_arr,
sizeof(char *)*(hash_get_count( &vals) + 1) ); sizeof(char *)*(vals.size()) + 4) ; //REVIEW I replaced 1 with 4 because I was getting an invalid write of 4 bytes for export[arr] = 0 below
for( i=0; i<export_buffer.used; i++ ) for( i=0; i<export_buffer.used; i++ )
{ {
@ -1672,7 +1678,7 @@ char **env_export_arr( int recalc )
} }
prev_was_null = (export_buffer.buff[i]==0); prev_was_null = (export_buffer.buff[i]==0);
} }
export_arr[pos]=0; export_arr[pos]=0; // REVIEW <- This is why I have changed 1 with 4
has_changed=0; has_changed=0;
} }

View File

@ -217,7 +217,7 @@ static void env_universal_remove_all()
for( i=0; i<lst.size(); i++ ) for( i=0; i<lst.size(); i++ )
{ {
const wcstring &key = lst.at(i); const wcstring &key = lst.at(i);
env_universal_common_remove( key.c_str() ); env_universal_common_remove( key );
} }
} }
@ -450,7 +450,7 @@ int env_universal_remove( const wchar_t *name )
if( is_dead() ) if( is_dead() )
{ {
env_universal_common_remove( name ); env_universal_common_remove( wcstring(name) );
} }
else else
{ {
@ -463,21 +463,6 @@ int env_universal_remove( const wchar_t *name )
return res; return res;
} }
void env_universal_get_names( array_list_t *l,
int show_exported,
int show_unexported )
{
if( !init )
return;
CHECK( l, );
env_universal_common_get_names( l,
show_exported,
show_unexported );
}
void env_universal_get_names2( wcstring_list_t &lst, void env_universal_get_names2( wcstring_list_t &lst,
int show_exported, int show_exported,
int show_unexported ) int show_unexported )

View File

@ -28,6 +28,7 @@
#include <dirent.h> #include <dirent.h>
#include <signal.h> #include <signal.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <map>
#ifdef HAVE_SYS_SELECT_H #ifdef HAVE_SYS_SELECT_H
#include <sys/select.h> #include <sys/select.h>
@ -93,7 +94,8 @@
typedef struct var_uni_entry typedef struct var_uni_entry
{ {
int exportv; /**< Whether the variable should be exported */ int exportv; /**< Whether the variable should be exported */
wchar_t val[1]; /**< The value of the variable */ wcstring val; /**< The value of the variable */
var_uni_entry():exportv(0) { }
} }
var_uni_entry_t; var_uni_entry_t;
@ -104,7 +106,7 @@ static void parse_message( wchar_t *msg,
/** /**
The table of all universal variables The table of all universal variables
*/ */
hash_table_t env_universal_var; std::map<wcstring, var_uni_entry_t*> env_universal_var;
/** /**
Callback function, should be called on all events Callback function, should be called on all events
@ -113,17 +115,6 @@ void (*callback)( int type,
const wchar_t *key, const wchar_t *key,
const wchar_t *val ); const wchar_t *val );
/**
Variable used by env_get_names to communicate auxiliary information
to add_key_to_hash
*/
static int get_names_show_exported;
/**
Variable used by env_get_names to communicate auxiliary information
to add_key_to_hash
*/
static int get_names_show_unexported;
/** /**
List of names for the UTF-8 character set. List of names for the UTF-8 character set.
*/ */
@ -389,7 +380,6 @@ static char *wcs2utf( const wchar_t *in )
void env_universal_common_init( void (*cb)(int type, const wchar_t *key, const wchar_t *val ) ) void env_universal_common_init( void (*cb)(int type, const wchar_t *key, const wchar_t *val ) )
{ {
callback = cb; callback = cb;
hash_init( &env_universal_var, &hash_wcs_func, &hash_wcs_cmp );
} }
/** /**
@ -399,14 +389,20 @@ static void erase( void *key,
void *data ) void *data )
{ {
free( (void *)key ); free( (void *)key );
free( (void *)data ); // free( (void *)data );//data is allocated through new
delete data;
} }
void env_universal_common_destroy() void env_universal_common_destroy()
{ {
hash_foreach( &env_universal_var, &erase ); std::map<wcstring, var_uni_entry_t*>::iterator iter;
hash_destroy( &env_universal_var );
for(iter = env_universal_var.begin(); iter != env_universal_var.end(); ++iter)
{
var_uni_entry_t* value = iter->second;
delete value;
}
} }
/** /**
@ -531,15 +527,14 @@ void read_message( connection_t *src )
/** /**
Remove variable with specified name Remove variable with specified name
*/ */
void env_universal_common_remove( const wchar_t *name ) void env_universal_common_remove( const wcstring &name )
{ {
void *k, *v; std::map<wcstring, var_uni_entry_t*>::iterator result = env_universal_var.find(name);
hash_remove( &env_universal_var, if (result != env_universal_var.end())
name, {
&k, var_uni_entry_t* v = result->second;
&v ); delete v;
free( k ); }
free( v );
} }
/** /**
@ -565,23 +560,23 @@ void env_universal_common_set( const wchar_t *key, const wchar_t *val, int expor
CHECK( key, ); CHECK( key, );
CHECK( val, ); CHECK( val, );
entry = (var_uni_entry_t *)malloc( sizeof(var_uni_entry_t) + sizeof(wchar_t)*(wcslen(val)+1) ); entry = new var_uni_entry_t;
name = wcsdup(key); name = wcsdup(key);
if( !entry || !name ) if( !entry || !name )
DIE_MEM(); DIE_MEM();
entry->exportv=exportv; entry->exportv=exportv;
entry->val = val;
wcscpy( entry->val, val );
env_universal_common_remove( name ); env_universal_common_remove( name );
hash_put( &env_universal_var, name, entry ); env_universal_var.insert( std::pair<wcstring, var_uni_entry_t*>(key, entry));
if( callback ) if( callback )
{ {
callback( exportv?SET_EXPORT:SET, name, val ); callback( exportv?SET_EXPORT:SET, name, val );
} }
free(name);
} }
@ -894,99 +889,71 @@ message_t *create_message( int type,
} }
/** /**
Function used with hash_foreach to insert keys of one table into Put exported or unexported variables in a string list
another */
*/
static void add_key_to_hash( void *key,
void *data,
void *aux )
{
var_uni_entry_t *e = (var_uni_entry_t *)data;
if( ( e->exportv && get_names_show_exported) ||
( !e->exportv && get_names_show_unexported) )
al_push( (array_list_t *)aux, key );
}
static void add_key_to_hash2( void *key,
void *data,
void *aux )
{
wcstring_list_t &lst = *(wcstring_list_t *)aux;
var_uni_entry_t *e = (var_uni_entry_t *)data;
if( ( e->exportv && get_names_show_exported) ||
( !e->exportv && get_names_show_unexported) )
lst.push_back((wchar_t *)key);
}
void env_universal_common_get_names( array_list_t *l,
int show_exported,
int show_unexported )
{
get_names_show_exported = show_exported;
get_names_show_unexported = show_unexported;
hash_foreach2( &env_universal_var,
add_key_to_hash,
l );
}
void env_universal_common_get_names2( wcstring_list_t &lst, void env_universal_common_get_names2( wcstring_list_t &lst,
int show_exported, int show_exported,
int show_unexported ) int show_unexported )
{ {
get_names_show_exported = show_exported; std::map<wcstring, var_uni_entry_t*>::const_iterator iter;
get_names_show_unexported = show_unexported; for (iter = env_universal_var.begin(); iter != env_universal_var.end(); ++iter)
{
const wcstring& key = iter->first;
const var_uni_entry_t *e = iter->second;
if( ( e->exportv && show_exported) ||
( !e->exportv && show_unexported) )
{
lst.push_back(key);
}
hash_foreach2( &env_universal_var, }
add_key_to_hash2,
&lst );
} }
wchar_t *env_universal_common_get( const wchar_t *name ) wchar_t *env_universal_common_get( const wchar_t *name )
{ {
var_uni_entry_t *e = (var_uni_entry_t *)hash_get( &env_universal_var, name ); std::map<wcstring, var_uni_entry_t*>::const_iterator result = env_universal_var.find(name);
if( e )
return e->val; if (result != env_universal_var.end() )
{
const var_uni_entry_t *e = result->second;
if( e )
return const_cast<wchar_t*>(e->val.c_str());
}
return 0; return 0;
} }
int env_universal_common_get_export( const wchar_t *name ) int env_universal_common_get_export( const wchar_t *name )
{ {
var_uni_entry_t *e = (var_uni_entry_t *)hash_get( &env_universal_var, name ); std::map<wcstring, var_uni_entry_t*>::const_iterator result = env_universal_var.find(name);
if( e )
return e->exportv; if (result != env_universal_var.end() )
{
const var_uni_entry_t *e = result->second;
if( e )
return e->exportv;
}
return 0; return 0;
} }
/**
Adds a variable creation message about the specified variable to
the specified queue. The function signature is non-obvious since
this function is used together with hash_foreach2, which requires
the specified function signature.
\param k the variable name
\param v the variable value
\param q the queue to add the message to
*/
static void enqueue( void *k,
void *v,
void *q)
{
const wchar_t *key = (const wchar_t *)k;
const var_uni_entry_t *val = (const var_uni_entry_t *)v;
message_queue_t *queue = (message_queue_t *)q;
message_t *msg = create_message( val->exportv?SET_EXPORT:SET, key, val->val );
msg->count=1;
queue->push(msg);
}
void enqueue_all( connection_t *c ) void enqueue_all( connection_t *c )
{ {
hash_foreach2( &env_universal_var, std::map<wcstring, var_uni_entry_t*>::const_iterator iter;
&enqueue,
(void *)c->unsent ); for (iter = env_universal_var.begin(); iter != env_universal_var.end(); ++iter)
{
const wcstring &key = iter->first;
const var_uni_entry_t *val = iter->second;
message_t *msg = create_message( val->exportv?SET_EXPORT:SET, key.c_str(), val->val.c_str() );
msg->count=1;
c->unsent->push(msg);
}
try_send_all( c ); try_send_all( c );
} }

View File

@ -176,7 +176,7 @@ void env_universal_common_set( const wchar_t *key, const wchar_t *val, int expor
Do not call this function. Create a message to do it. This function Do not call this function. Create a message to do it. This function
is only to be used when fishd is dead. is only to be used when fishd is dead.
*/ */
void env_universal_common_remove( const wchar_t *key ); void env_universal_common_remove( const wcstring &key );
/** /**
Get the value of the variable with the specified name Get the value of the variable with the specified name

View File

@ -1742,6 +1742,8 @@ static int exec_subshell_internal( const wcstring &cmd, wcstring_list_t *lst )
if( el ) if( el )
{ {
lst->push_back(el); lst->push_back(el);
free(el);
} }
else else
{ {
@ -1760,6 +1762,8 @@ static int exec_subshell_internal( const wcstring &cmd, wcstring_list_t *lst )
if( el ) if( el )
{ {
lst->push_back(el); lst->push_back(el);
free(el);
} }
else else
{ {

View File

@ -728,7 +728,7 @@ static char *get_action( const char *mimetype )
} }
// fprintf( stderr, "WOOT %s\n", launcher_str ); // fprintf( stderr, "WOOT %s\n", launcher_str );
launcher = strchr( launcher_str, '=' ); launcher = const_cast<char*>(strchr( launcher_str, '=' ));
if( !launcher ) if( !launcher )
{ {