Eliminate str2wcs

This commit is contained in:
ridiculousfish 2012-12-19 13:31:06 -08:00
parent b0a9a5a756
commit 644607c29f
16 changed files with 161 additions and 210 deletions

View file

@ -188,12 +188,11 @@ static void builtin_wperror(const wchar_t *s)
stderr_buffer.append(L": ");
}
char *err = strerror(errno);
wchar_t *werr = str2wcs(err);
if (werr)
if (err)
{
const wcstring werr = str2wcstring(err);
stderr_buffer.append(werr);
stderr_buffer.push_back(L'\n');
free(werr);
}
}
@ -3065,7 +3064,7 @@ static int builtin_source(parser_t &parser, wchar_t ** argv)
return STATUS_BUILTIN_ERROR;
}
fn = wrealpath(argv[1], 0);
fn = wrealpath(argv[1], NULL);
if (!fn)
{

View file

@ -81,6 +81,7 @@ parts of fish.
#include "fallback.cpp"
static wchar_t *str2wcs_internal(const char *in, const size_t in_len, wchar_t *out);
struct termios shell_modes;
@ -163,23 +164,31 @@ int fgetws2(wcstring *s, FILE *f)
}
}
wchar_t *str2wcs(const char *in)
static wchar_t *str2wcs(const char *in)
{
wchar_t *out;
size_t len = strlen(in);
out = (wchar_t *)malloc(sizeof(wchar_t)*(len+1));
wchar_t *out = (wchar_t *)malloc(sizeof(wchar_t)*(len+1));
if (!out)
{
DIE_MEM();
}
return str2wcs_internal(in, out);
return str2wcs_internal(in, strlen(in), out);
}
wcstring str2wcstring(const char *in, size_t len)
{
assert(in != NULL);
std::string tmp_str(in, len);
wchar_t *tmp = str2wcs(tmp_str.c_str());
wcstring result = tmp;
free(tmp);
return result;
}
wcstring str2wcstring(const char *in)
{
assert(in != NULL);
wchar_t *tmp = str2wcs(in);
wcstring result = tmp;
free(tmp);
@ -194,24 +203,31 @@ wcstring str2wcstring(const std::string &in)
return result;
}
wchar_t *str2wcs_internal(const char *in, wchar_t *out)
/**
Converts the narrow character string \c in into it's wide
equivalent, stored in \c out. \c out must have enough space to fit
the entire string.
The string may contain embedded nulls.
This function encodes illegal character sequences in a reversible
way using the private use area.
*/
static wchar_t *str2wcs_internal(const char *in, const size_t in_len, wchar_t *out)
{
size_t res=0;
size_t in_pos=0;
size_t out_pos = 0;
mbstate_t state;
size_t len;
CHECK(in, 0);
CHECK(out, 0);
len = strlen(in);
memset(&state, 0, sizeof(state));
while (in[in_pos])
{
res = mbrtowc(&out[out_pos], &in[in_pos], len-in_pos, &state);
res = mbrtowc(&out[out_pos], &in[in_pos], in_len-in_pos, &state);
if (((out[out_pos] >= ENCODE_DIRECT_BASE) &&
(out[out_pos] < ENCODE_DIRECT_BASE+256)) ||
@ -298,12 +314,12 @@ std::string wcs2string(const wcstring &input)
{
std::string result;
result.reserve(input.size());
mbstate_t state;
memset(&state, 0, sizeof(state));
char converted[MB_LEN_MAX + 1];
for (size_t i=0; i < input.size(); i++)
{
wchar_t wc = input[i];
@ -330,7 +346,7 @@ std::string wcs2string(const wcstring &input)
}
}
}
return result;
}

View file

@ -206,35 +206,18 @@ void show_stackframe();
*/
int fgetws2(wcstring *s, FILE *f);
/**
Returns a newly allocated wide character string equivalent of the
specified multibyte character string
This function encodes illegal character sequences in a reversible
way using the private use area.
*/
wchar_t *str2wcs(const char *in);
/**
Returns a newly allocated wide character string equivalent of the
Returns a wide character string equivalent of the
specified multibyte character string
This function encodes illegal character sequences in a reversible
way using the private use area.
*/
wcstring str2wcstring(const char *in);
wcstring str2wcstring(const char *in, size_t len);
wcstring str2wcstring(const std::string &in);
/**
Converts the narrow character string \c in into it's wide
equivalent, stored in \c out. \c out must have enough space to fit
the entire string.
This function encodes illegal character sequences in a reversible
way using the private use area.
*/
wchar_t *str2wcs_internal(const char *in, wchar_t *out);
/**
Returns a newly allocated multibyte character string equivalent of
the specified wide character string

View file

@ -1719,17 +1719,16 @@ bool completer_t::try_complete_user(const wcstring &str)
while ((pw=getpwent()) != 0)
{
double current_time = timef();
wchar_t *pw_name;
if (current_time - start_time > 0.2)
{
return 1;
}
pw_name = str2wcs(pw->pw_name);
if (pw_name)
if (pw->pw_name)
{
const wcstring pw_name_str = str2wcstring(pw->pw_name);
const wchar_t *pw_name = pw_name_str.c_str();
if (wcsncmp(user_name, pw_name, name_len)==0)
{
wcstring desc = format_string(COMPLETE_USER_DESC, pw_name);
@ -1751,7 +1750,6 @@ bool completer_t::try_complete_user(const wcstring &str)
COMPLETE_NO_CASE | COMPLETE_DONT_ESCAPE | COMPLETE_NO_SPACE);
res=1;
}
free(pw_name);
}
}
endpwent();

74
env.cpp
View file

@ -518,9 +518,11 @@ static void env_set_defaults()
if (env_get_string(L"USER").missing())
{
struct passwd *pw = getpwuid(getuid());
wchar_t *unam = str2wcs(pw->pw_name);
env_set(L"USER", unam, ENV_GLOBAL);
free(unam);
if (pw->pw_name != NULL)
{
const wcstring wide_name = str2wcstring(pw->pw_name);
env_set(L"USER", NULL, ENV_GLOBAL);
}
}
if (env_get_string(L"HOME").missing())
@ -528,9 +530,11 @@ static void env_set_defaults()
const env_var_t unam = env_get_string(L"USER");
char *unam_narrow = wcs2str(unam.c_str());
struct passwd *pw = getpwnam(unam_narrow);
wchar_t *dir = str2wcs(pw->pw_dir);
env_set(L"HOME", dir, ENV_GLOBAL);
free(dir);
if (pw->pw_dir != NULL)
{
const wcstring dir = str2wcstring(pw->pw_dir);
env_set(L"HOME", dir.c_str(), ENV_GLOBAL);
}
free(unam_narrow);
}
@ -539,9 +543,9 @@ static void env_set_defaults()
}
// Some variables should not be arrays. This used to be handled by a startup script, but we'd like to get down to 0 forks for startup, so handle it here.
static bool variable_can_be_array(const wchar_t *key)
static bool variable_can_be_array(const wcstring &key)
{
if (! wcscmp(key, L"DISPLAY"))
if (key == L"DISPLAY")
{
return false;
}
@ -554,9 +558,6 @@ static bool variable_can_be_array(const wchar_t *key)
void env_init(const struct config_paths_t *paths /* or NULL */)
{
char **p;
struct passwd *pw;
wchar_t *uname;
wchar_t *version;
/*
env_read_only variables can not be altered directly by the user
@ -610,41 +611,24 @@ void env_init(const struct config_paths_t *paths /* or NULL */)
*/
for (p=environ?environ:__environ; p && *p; p++)
{
wchar_t *key, *val;
key = str2wcs(*p);
if (!key)
const wcstring key_and_val = str2wcstring(*p); //like foo=bar
size_t eql = key_and_val.find(L'=');
if (eql == wcstring::npos)
{
continue;
}
val = wcschr(key, L'=');
if (val == 0)
{
env_set(key, L"", ENV_EXPORT);
// no equals found
env_set(key_and_val, L"", ENV_EXPORT);
}
else
{
*val = L'\0';
val++;
//fwprintf( stderr, L"Set $%ls to %ls\n", key, val );
wcstring key = key_and_val.substr(0, eql);
wcstring val = key_and_val.substr(eql + 1);
if (variable_can_be_array(val))
{
for (size_t i=0; val[i] != L'\0'; i++)
{
if (val[i] == L':')
{
val[i] = ARRAY_SEP;
}
}
std::replace(val.begin(), val.end(), L':', ARRAY_SEP);
}
env_set(key, val, ENV_EXPORT | ENV_GLOBAL);
env_set(key, val.c_str(), ENV_EXPORT | ENV_GLOBAL);
}
free(key);
}
/* Set the given paths in the environment, if we have any */
@ -664,21 +648,19 @@ void env_init(const struct config_paths_t *paths /* or NULL */)
/*
Set up the USER variable
*/
pw = getpwuid(getuid());
if (pw)
const struct passwd *pw = getpwuid(getuid());
if (pw && pw->pw_name)
{
uname = str2wcs(pw->pw_name);
env_set(L"USER", uname, ENV_GLOBAL | ENV_EXPORT);
free(uname);
const wcstring uname = str2wcstring(pw->pw_name);
env_set(L"USER", uname.c_str(), ENV_GLOBAL | ENV_EXPORT);
}
/*
Set up the version variables
*/
version = str2wcs(PACKAGE_VERSION);
env_set(L"version", version, ENV_GLOBAL);
env_set(L"FISH_VERSION", version, ENV_GLOBAL);
free(version);
wcstring version = str2wcstring(PACKAGE_VERSION);
env_set(L"version", version.c_str(), ENV_GLOBAL);
env_set(L"FISH_VERSION", version.c_str(), ENV_GLOBAL);
const env_var_t fishd_dir_wstr = env_get_string(L"FISHD_SOCKET_DIR");
const env_var_t user_dir_wstr = env_get_string(L"USER");

View file

@ -1211,12 +1211,12 @@ void exec(parser_t &parser, job_t *j)
/* Get the strings we'll write before we fork (since they call malloc) */
const wcstring &out = get_stdout_buffer(), &err = get_stderr_buffer();
/* These strings may contain embedded nulls, so don't treat them as C strings */
const std::string outbuff_str = wcs2string(out);
const char *outbuff = outbuff_str.data();
size_t outbuff_len = outbuff_str.size();
const std::string errbuff_str = wcs2string(err);
const char *errbuff = errbuff_str.data();
size_t errbuff_len = errbuff_str.size();
@ -1466,25 +1466,19 @@ static int exec_subshell_internal(const wcstring &cmd, wcstring_list_t *lst)
begin=end=io_buffer->out_buffer_ptr();
//REWRITEME
if (lst)
{
while (1)
{
if (*end == 0)
{
assert(begin != NULL);
if (begin != end)
{
wchar_t *el = str2wcs(begin);
if (el)
{
lst->push_back(el);
free(el);
}
else
{
debug(2, L"Got null string on line %d of file %s", __LINE__, __FILE__);
}
const wcstring el = str2wcstring(begin);
lst->push_back(el);
}
io_buffer_destroy(io_buffer);
@ -1492,19 +1486,9 @@ static int exec_subshell_internal(const wcstring &cmd, wcstring_list_t *lst)
}
else if (*end == sep)
{
wchar_t *el;
*end=0;
el = str2wcs(begin);
if (el)
{
lst->push_back(el);
free(el);
}
else
{
debug(2, L"Got null string on line %d of file %s", __LINE__, __FILE__);
}
const wcstring el = str2wcstring(begin);
lst->push_back(el);
begin = end+1;
}
end++;

View file

@ -115,7 +115,7 @@ enum
};
/** Character for separating two array elements. We use 30, i.e. the ascii record separator since that seems logical. */
#define ARRAY_SEP 0x1e
#define ARRAY_SEP ((wchar_t)(0x1e))
/** String containing the character for separating two array elements */
#define ARRAY_SEP_STR L"\x1e"

View file

@ -483,11 +483,10 @@ int main(int argc, char **argv)
const io_chain_t empty_ios;
if (read_init(paths))
{
if (cmd != 0)
if (cmd != NULL)
{
wchar_t *cmd_wcs = str2wcs(cmd);
const wcstring cmd_wcs = str2wcstring(cmd);
res = parser.eval(cmd_wcs, empty_ios, TOP);
free(cmd_wcs);
reader_exit(0, 0);
}
else
@ -502,7 +501,6 @@ int main(int argc, char **argv)
char *file = *(argv+(my_optind++));
int i;
int fd;
wchar_t *rel_filename, *abs_filename;
if ((fd = open(file, O_RDONLY)) == -1)
@ -527,17 +525,16 @@ int main(int argc, char **argv)
env_set(L"argv", sb.c_str(), 0);
}
rel_filename = str2wcs(file);
abs_filename = wrealpath(rel_filename, 0);
const wcstring rel_filename = str2wcstring(file);
const wchar_t *abs_filename = wrealpath(rel_filename, NULL);
if (!abs_filename)
{
abs_filename = wcsdup(rel_filename);
abs_filename = wcsdup(rel_filename.c_str());
}
reader_push_current_filename(intern(abs_filename));
free(rel_filename);
free(abs_filename);
free((void *)abs_filename);
res = reader_read(fd, empty_ios);

View file

@ -479,7 +479,7 @@ static void completion_print(int cols,
int *width,
int row_start,
int row_stop,
wchar_t *prefix,
const wchar_t *prefix,
int is_quoted,
const std::vector<comp_t *> &lst)
{
@ -529,7 +529,7 @@ static void completion_print(int cols,
*/
static int completion_try_print(int cols,
wchar_t *prefix,
const wchar_t *prefix,
int is_quoted,
std::vector<comp_t *> &lst)
{
@ -1086,9 +1086,8 @@ static void init(int mangle_descriptors, int out)
term = getenv("TERM");
if (term)
{
wchar_t *wterm = str2wcs(term);
wcstring wterm = str2wcstring(term);
output_set_term(wterm);
free(wterm);
}
/* Infer term256 support */
@ -1129,7 +1128,6 @@ static void read_array(FILE* file, wcstring_list_t &comp)
{
std::vector<char> buffer;
int c;
wchar_t *wcs;
while (!feof(file))
{
@ -1154,16 +1152,10 @@ static void read_array(FILE* file, wcstring_list_t &comp)
if (! buffer.empty())
{
buffer.push_back(0);
wcs = str2wcs(&buffer.at(0));
if (wcs)
wcstring wcs = str2wcstring(&buffer.at(0));
if (unescape_string(wcs, false))
{
wcstring tmp = wcs;
if (unescape_string(tmp, 0))
{
comp.push_back(tmp);
}
free(wcs);
comp.push_back(wcs);
}
}
}
@ -1191,7 +1183,7 @@ int main(int argc, char **argv)
int i;
int is_quoted=0;
wcstring_list_t comp;
wchar_t *prefix = 0;
wcstring prefix;
int mangle_descriptors = 0;
int result_fd = -1;
@ -1292,7 +1284,7 @@ int main(int argc, char **argv)
case 'p':
{
prefix = str2wcs(optarg);
prefix = str2wcstring(optarg);
break;
}
@ -1335,12 +1327,6 @@ int main(int argc, char **argv)
exit(1);
}
if (!prefix)
{
prefix = wcsdup(L"");
}
}
else
{
@ -1364,7 +1350,7 @@ int main(int argc, char **argv)
{
mangle_descriptors = 1;
prefix = str2wcs(argv[2]);
prefix = str2wcstring(argv[2]);
is_quoted = strcmp("1", argv[1])==0;
if (argc > 3)
@ -1395,10 +1381,10 @@ int main(int argc, char **argv)
mangle_descriptions(comp);
if (wcscmp(prefix, L"-") == 0)
if (prefix == L"-")
join_completions(comp);
std::vector<comp_t *> completions = mangle_completions(comp, prefix);
std::vector<comp_t *> completions = mangle_completions(comp, prefix.c_str());
/**
Try to print the completions. Start by trying to print the
@ -1408,7 +1394,7 @@ int main(int argc, char **argv)
*/
for (i = PAGER_MAX_COLS; i>0; i--)
{
switch (completion_try_print(i, prefix, is_quoted, completions))
switch (completion_try_print(i, prefix.c_str(), is_quoted, completions))
{
case PAGER_RETRY:
@ -1431,8 +1417,6 @@ int main(int argc, char **argv)
}
}
free(prefix);
fwprintf(out_file, L"%ls", out_buff.c_str());
if (is_ca_mode)
{

View file

@ -249,7 +249,6 @@ static void test_convert()
for (i=0; i<ESCAPE_TEST_COUNT; i++)
{
wchar_t *w;
const char *o, *n;
char c;
@ -265,22 +264,56 @@ static void test_convert()
sb.push_back(c);
o = &sb.at(0);
w = str2wcs(o);
n = wcs2str(w);
const wcstring w = str2wcstring(o);
n = wcs2str(w.c_str());
if (!o || !w || !n)
if (!o || !n)
{
err(L"Line %d - Conversion cycle of string %s produced null pointer on %s", __LINE__, o, w?L"str2wcs":L"wcs2str");
err(L"Line %d - Conversion cycle of string %s produced null pointer on %s", __LINE__, o, L"wcs2str");
}
if (strcmp(o, n))
{
err(L"Line %d - %d: Conversion cycle of string %s produced different string %s", __LINE__, i, o, n);
}
free(w);
free((void *)n);
}
}
/* Verify correct behavior with embedded nulls */
static void test_convert_nulls(void)
{
return;
say(L"Testing embedded nulls in string conversion");
const wchar_t in[] = L"AAA\0BBB";
const size_t in_len = (sizeof in / sizeof *in) - 1;
const wcstring in_str = wcstring(in, in_len);
std::string out_str = wcs2string(in_str);
if (out_str.size() != in_len)
{
err(L"Embedded nulls mishandled in wcs2string");
}
for (size_t i=0; i < in_len; i++)
{
if (in[i] != out_str.at(i))
{
err(L"Embedded nulls mishandled in wcs2string at index %lu", (unsigned long)i);
}
}
wcstring out_wstr = str2wcstring(out_str);
if (out_wstr.size() != in_len)
{
err(L"Embedded nulls mishandled in str2wcstring");
}
for (size_t i=0; i < in_len; i++)
{
if (in[i] != out_wstr.at(i))
{
err(L"Embedded nulls mishandled in str2wcstring at index %lu", (unsigned long)i);
}
}
}
@ -1461,6 +1494,7 @@ int main(int argc, char **argv)
test_format();
test_escape();
test_convert();
test_convert_nulls();
test_tok();
test_fork();
test_parser();

View file

@ -598,7 +598,8 @@ static wchar_t *fishd_env_get(const wchar_t *key)
free(nkey);
if (nres)
{
return str2wcs(nres);
wcstring tmp = str2wcstring(nres);
return wcsdup(tmp.c_str());
}
else
{

View file

@ -353,7 +353,7 @@ int input_init()
}
const env_var_t term = env_get_string(L"TERM");
assert(! term.missing());
output_set_term(term.c_str());
output_set_term(term);
input_terminfo_init();

View file

@ -724,9 +724,9 @@ rgb_color_t parse_color(const wcstring &val, bool is_background)
return result;
}
void output_set_term(const wchar_t *term)
void output_set_term(const wcstring &term)
{
current_term = term;
current_term.assign(term);
}
const wchar_t *output_get_term()

View file

@ -154,7 +154,7 @@ void output_set_writer(int (*writer)(char));
int (*output_get_writer())(char) ;
/** Set the terminal name */
void output_set_term(const wchar_t *term);
void output_set_term(const wcstring &term);
/** Return the terminal name */
const wchar_t *output_get_term();

View file

@ -1098,19 +1098,17 @@ static void run_pager(const wcstring &prefix, int is_quoted, const std::vector<c
int nil=0;
out->out_buffer_append((char *)&nil, 1);
wchar_t *tmp;
wchar_t *str = str2wcs(out->out_buffer_ptr());
if (str)
const char *outbuff = out->out_buffer_ptr();
if (outbuff)
{
for (tmp = str + wcslen(str)-1; tmp >= str; tmp--)
const wcstring str = str2wcstring(outbuff);
size_t idx = str.size();
while (idx--)
{
input_unreadch(*tmp);
input_unreadch(str.at(idx));
}
free(str);
}
io_buffer_destroy(out);
io_buffer_destroy(in);
}
@ -3466,9 +3464,6 @@ static int read_ni(int fd, const io_chain_t &io)
in_stream = fdopen(des, "r");
if (in_stream != 0)
{
wchar_t *str;
size_t acc_used;
while (!feof(in_stream))
{
char buff[4096];
@ -3489,9 +3484,8 @@ static int read_ni(int fd, const io_chain_t &io)
acc.insert(acc.end(), buff, buff + c);
}
acc.push_back(0);
acc_used = acc.size();
str = str2wcs(&acc.at(0));
const wcstring str = str2wcstring(&acc.at(0), acc.size());
acc.clear();
if (fclose(in_stream))
@ -3502,36 +3496,16 @@ static int read_ni(int fd, const io_chain_t &io)
res = 1;
}
if (str)
wcstring sb;
if (! parser.test(str.c_str(), 0, &sb, L"fish"))
{
wcstring sb;
if (! parser.test(str, 0, &sb, L"fish"))
{
parser.eval(str, io, TOP);
}
else
{
fwprintf(stderr, L"%ls", sb.c_str());
res = 1;
}
free(str);
parser.eval(str, io, TOP);
}
else
{
if (acc_used > 1)
{
debug(1,
_(L"Could not convert input. Read %d bytes."),
acc_used-1);
}
else
{
debug(1,
_(L"Could not read input stream"));
}
res=1;
fwprintf(stderr, L"%ls", sb.c_str());
res = 1;
}
}
else
{

View file

@ -296,23 +296,22 @@ void wperror(const wcstring &s)
wchar_t *wrealpath(const wcstring &pathname, wchar_t *resolved_path)
{
cstring tmp = wcs2string(pathname);
char *narrow_res = realpath(tmp.c_str(), 0);
wchar_t *res;
cstring narrow_path = wcs2string(pathname);
char *narrow_res = realpath(narrow_path.c_str(), NULL);
if (!narrow_res)
return 0;
return NULL;
wchar_t *res;
wcstring wide_res = str2wcstring(narrow_res);
if (resolved_path)
{
wchar_t *tmp2 = str2wcs(narrow_res);
wcslcpy(resolved_path, tmp2, PATH_MAX);
free(tmp2);
wcslcpy(resolved_path, wide_res.c_str(), PATH_MAX);
res = resolved_path;
}
else
{
res = str2wcs(narrow_res);
res = wcsdup(wide_res.c_str());
}
free(narrow_res);