aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--env_universal_common.cpp11
-rw-r--r--highlight.cpp2
-rw-r--r--history.cpp2
-rw-r--r--parse_util.cpp2
-rw-r--r--tokenizer.cpp22
-rw-r--r--tokenizer.h7
-rw-r--r--wutil.cpp45
-rw-r--r--wutil.h3
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;
};
/**
diff --git a/wutil.cpp b/wutil.cpp
index 3621f13d..c3dd80fc 100644
--- a/wutil.cpp
+++ b/wutil.cpp
@@ -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();
diff --git a/wutil.h b/wutil.h
index ddd7248f..d3e241d6 100644
--- a/wutil.h
+++ b/wutil.h
@@ -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