diff options
-rw-r--r-- | env_universal_common.cpp | 11 | ||||
-rw-r--r-- | highlight.cpp | 2 | ||||
-rw-r--r-- | history.cpp | 2 | ||||
-rw-r--r-- | parse_util.cpp | 2 | ||||
-rw-r--r-- | tokenizer.cpp | 22 | ||||
-rw-r--r-- | tokenizer.h | 7 | ||||
-rw-r--r-- | wutil.cpp | 45 | ||||
-rw-r--r-- | wutil.h | 3 |
8 files changed, 52 insertions, 42 deletions
diff --git a/env_universal_common.cpp b/env_universal_common.cpp index 80fd1b1f..9628b630 100644 --- a/env_universal_common.cpp +++ b/env_universal_common.cpp @@ -382,17 +382,6 @@ void env_universal_common_init( void (*cb)(int type, const wchar_t *key, const w callback = cb; } -/** - Free both key and data -*/ -static void erase( void *key, - void *data ) -{ - free( (void *)key ); -// free( (void *)data );//data is allocated through new - delete data; -} - void env_universal_common_destroy() { diff --git a/highlight.cpp b/highlight.cpp index 2d447478..059ccbfe 100644 --- a/highlight.cpp +++ b/highlight.cpp @@ -557,7 +557,7 @@ static void tokenize( const wchar_t * const buff, int * const color, const int p color[i] = -1; tokenizer tok; - for( tok_init( &tok, buff, TOK_SHOW_COMMENTS ); + for( tok_init( &tok, buff, TOK_SHOW_COMMENTS | TOK_SQUASH_ERRORS ); tok_has_next( &tok ); tok_next( &tok ) ) { diff --git a/history.cpp b/history.cpp index 7d7f9196..ad9abca2 100644 --- a/history.cpp +++ b/history.cpp @@ -776,7 +776,7 @@ void history_t::add_with_file_detection(const wcstring &str) path_list_t potential_paths; tokenizer tokenizer; - for( tok_init( &tokenizer, str.c_str(), 0 ); + for( tok_init( &tokenizer, str.c_str(), TOK_SQUASH_ERRORS ); tok_has_next( &tokenizer ); tok_next( &tokenizer ) ) { diff --git a/parse_util.cpp b/parse_util.cpp index 7b3781d5..e2fc9fcb 100644 --- a/parse_util.cpp +++ b/parse_util.cpp @@ -523,7 +523,7 @@ void parse_util_token_extent( const wchar_t *buff, DIE_MEM(); } - for( tok_init( &tok, buffcpy, TOK_ACCEPT_UNFINISHED ); + for( tok_init( &tok, buffcpy, TOK_ACCEPT_UNFINISHED | TOK_SQUASH_ERRORS ); tok_has_next( &tok ); tok_next( &tok ) ) { diff --git a/tokenizer.cpp b/tokenizer.cpp index 0d2c9015..9ac83298 100644 --- a/tokenizer.cpp +++ b/tokenizer.cpp @@ -23,6 +23,8 @@ segments. #include "tokenizer.h" #include "common.h" +/* Wow what a hack */ +#define TOK_CALL_ERROR(t, e, x) do { tok_call_error((t), (e), (t)->squash_errors ? L"" : (x)); } while (0) /** Error string for unexpected end of string @@ -101,7 +103,7 @@ static int check_size( tokenizer *tok, size_t len ) /** Set the latest tokens string to be the specified error message */ -static void tok_error( tokenizer *tok, int error_type, const wchar_t *error_message ) +static void tok_call_error( tokenizer *tok, int error_type, const wchar_t *error_message ) { tok->last_type = TOK_ERROR; tok->error = error_type; @@ -124,6 +126,11 @@ int tok_get_error( tokenizer *tok ) void tok_init( tokenizer *tok, const wchar_t *b, int flags ) { + /* We can only generate error messages on the main thread due to wgettext() thread safety issues. */ + if (! (flags & TOK_SQUASH_ERRORS)) { + ASSERT_IS_MAIN_THREAD(); + } + CHECK( tok, ); memset( tok, 0, sizeof( tokenizer) ); @@ -133,6 +140,7 @@ void tok_init( tokenizer *tok, const wchar_t *b, int flags ) tok->accept_unfinished = !! (flags & TOK_ACCEPT_UNFINISHED); tok->show_comments = !! (flags & TOK_SHOW_COMMENTS); + tok->squash_errors = !! (flags & TOK_SQUASH_ERRORS); tok->has_next=1; tok->has_next = (*b != L'\0'); @@ -224,7 +232,7 @@ static void read_string( tokenizer *tok ) { if( (!tok->accept_unfinished) ) { - tok_error( tok, TOK_UNTERMINATED_ESCAPE, QUOTE_ERROR ); + TOK_CALL_ERROR( tok, TOK_UNTERMINATED_ESCAPE, QUOTE_ERROR ); return; } else @@ -290,7 +298,7 @@ static void read_string( tokenizer *tok ) if( (!tok->accept_unfinished) ) { - tok_error( tok, TOK_UNTERMINATED_QUOTE, QUOTE_ERROR ); + TOK_CALL_ERROR( tok, TOK_UNTERMINATED_QUOTE, QUOTE_ERROR ); return; } do_loop = 0; @@ -327,7 +335,7 @@ static void read_string( tokenizer *tok ) tok->buff += wcslen( tok->buff ); if( (!tok->accept_unfinished) ) { - tok_error( tok, TOK_UNTERMINATED_QUOTE, QUOTE_ERROR ); + TOK_CALL_ERROR( tok, TOK_UNTERMINATED_QUOTE, QUOTE_ERROR ); return; } do_loop = 0; @@ -381,7 +389,7 @@ static void read_string( tokenizer *tok ) if( (!tok->accept_unfinished) && (mode!=0) ) { - tok_error( tok, TOK_UNTERMINATED_SUBSHELL, PARAN_ERROR ); + TOK_CALL_ERROR( tok, TOK_UNTERMINATED_SUBSHELL, PARAN_ERROR ); return; } @@ -442,7 +450,7 @@ static void read_redirect( tokenizer *tok, int fd ) { if( fd == 0 ) { - tok_error( tok, TOK_OTHER, PIPE_ERROR ); + TOK_CALL_ERROR( tok, TOK_OTHER, PIPE_ERROR ); return; } check_size( tok, FD_STR_MAX_LEN ); @@ -459,7 +467,7 @@ static void read_redirect( tokenizer *tok, int fd ) } else { - tok_error( tok, TOK_OTHER, REDIRECT_ERROR); + TOK_CALL_ERROR( tok, TOK_OTHER, REDIRECT_ERROR); } if( !check_size( tok, 2 )) diff --git a/tokenizer.h b/tokenizer.h index c0c4034d..731f49bf 100644 --- a/tokenizer.h +++ b/tokenizer.h @@ -57,6 +57,10 @@ enum tokenizer_error */ #define TOK_SHOW_COMMENTS 2 +/** Flag telling the tokenizer to not generate error messages, which we need to do when tokenizing off of the main thread (since wgettext is not thread safe). +*/ +#define TOK_SQUASH_ERRORS 4 + /** The tokenizer struct. @@ -88,6 +92,9 @@ struct tokenizer wchar_t last_quote; /** Last error */ int error; + + /* Whether we are squashing errors */ + bool squash_errors; }; /** @@ -18,8 +18,10 @@ #include <stdarg.h> #include <limits.h> #include <libgen.h> +#include <pthread.h> #include <string> + #if HAVE_LIBINTL_H #include <libintl.h> #endif @@ -71,13 +73,6 @@ static char *wcs2str_buff=0; */ static size_t wcs2str_buff_count=0; -/** - For wgettext: Flag to tell whether the translation library has been initialized -*/ -static int wgettext_is_init = 0; - - - void wutil_init() { @@ -282,24 +277,25 @@ wcstring wbasename( const wcstring &path ) return result; } -/** - For wgettext: Internal init function. Automatically called when a translation is first requested. -*/ -static void wgettext_init() -{ - int i; - - wgettext_is_init = 1; - - for( i=0; i<BUFF_COUNT; i++ ) +/* Really init wgettext */ +static void wgettext_really_init() { + for( size_t i=0; i<BUFF_COUNT; i++ ) { sb_init( &buff[i] ); } - bindtextdomain( PACKAGE_NAME, LOCALEDIR ); textdomain( PACKAGE_NAME ); } +/** + For wgettext: Internal init function. Automatically called when a translation is first requested. +*/ +static void wgettext_init_if_necessary() +{ + static pthread_once_t once = PTHREAD_ONCE_INIT; + pthread_once(&once, wgettext_really_init); +} + /** For wgettext: Wide to narrow character conversion. Internal implementation that @@ -322,11 +318,12 @@ static char *wgettext_wcs2str( const wchar_t *in ) const wchar_t *wgettext( const wchar_t *in ) { + ASSERT_IS_MAIN_THREAD(); + if( !in ) return in; - if( !wgettext_is_init ) - wgettext_init(); + wgettext_init_if_necessary(); char *mbs_in = wgettext_wcs2str( in ); char *out = gettext( mbs_in ); @@ -341,6 +338,14 @@ const wchar_t *wgettext( const wchar_t *in ) return wres; } +wcstring wgettext2(const wcstring &in) { + wgettext_init_if_necessary(); + std::string mbs_in = wcs2string(in); + char *out = gettext( mbs_in.c_str() ); + wcstring result = format_string(L"%s", out); + return result; +} + const wchar_t *wgetenv( const wchar_t *name ) { ASSERT_IS_MAIN_THREAD(); @@ -15,7 +15,7 @@ #include <sys/types.h> #include <stdarg.h> #include <string> - +#include "common.h" /** @@ -134,6 +134,7 @@ std::wstring wbasename( const std::wstring &path); around gettext, like all other functions in this file. */ const wchar_t *wgettext( const wchar_t *in ); +wcstring wgettext2(const wcstring &in); /** Wide character version of getenv |