diff --git a/builtin.cpp b/builtin.cpp index c0dda6f8d..76e075256 100644 --- a/builtin.cpp +++ b/builtin.cpp @@ -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) { diff --git a/common.cpp b/common.cpp index c73b1bc45..d1db95ed9 100644 --- a/common.cpp +++ b/common.cpp @@ -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; } diff --git a/common.h b/common.h index 184b3cf4e..c99402364 100644 --- a/common.h +++ b/common.h @@ -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 diff --git a/complete.cpp b/complete.cpp index 367336974..acafa2ec4 100644 --- a/complete.cpp +++ b/complete.cpp @@ -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(); diff --git a/env.cpp b/env.cpp index 035fee4ec..a1930ebab 100644 --- a/env.cpp +++ b/env.cpp @@ -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"); diff --git a/exec.cpp b/exec.cpp index 5013d96cb..12dfe8d35 100644 --- a/exec.cpp +++ b/exec.cpp @@ -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++; diff --git a/expand.h b/expand.h index b748bae07..6426c6862 100644 --- a/expand.h +++ b/expand.h @@ -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" diff --git a/fish.cpp b/fish.cpp index 0d37d742d..4b6ab1e6a 100644 --- a/fish.cpp +++ b/fish.cpp @@ -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); diff --git a/fish_pager.cpp b/fish_pager.cpp index 3f24010ce..69aad5d95 100644 --- a/fish_pager.cpp +++ b/fish_pager.cpp @@ -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 &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 &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 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 completions = mangle_completions(comp, prefix); + std::vector 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) { diff --git a/fish_tests.cpp b/fish_tests.cpp index 57e2edeed..9cc9e8f66 100644 --- a/fish_tests.cpp +++ b/fish_tests.cpp @@ -249,7 +249,6 @@ static void test_convert() for (i=0; iout_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 { diff --git a/wutil.cpp b/wutil.cpp index f5b1e2434..5984747ad 100644 --- a/wutil.cpp +++ b/wutil.cpp @@ -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);