diff --git a/command.cc b/command.cc index 990dec4..2f594b3 100644 --- a/command.cc +++ b/command.cc @@ -3227,46 +3227,6 @@ void init_lib_io(CsState &cs) { }); } -const char *escapestring(const char *s) { - stridx = (stridx + 1) % 4; - ostd::Vector &buf = strbuf[stridx]; - buf.clear(); - buf.push('"'); - for (; *s; s++) switch (*s) { - case '\n': - buf.push('^'); - buf.push('n'); - break; - case '\t': - buf.push('^'); - buf.push('t'); - break; - case '\f': - buf.push('^'); - buf.push('f'); - break; - case '"': - buf.push('^'); - buf.push('\"'); - break; - case '^': - buf.push('^'); - buf.push('^'); - break; - default: - buf.push(*s); - break; - } - buf.push('"'); - buf.push('\0'); - return buf.data(); -} - -const char *escapeid(const char *s) { - const char *end = s + strcspn(s, "\"/;()[]@ \f\t\r\n\0"); - return *end ? escapestring(s) : s; -} - bool validateblock(const char *s) { const int maxbrak = 100; static char brakstack[maxbrak]; @@ -4463,7 +4423,9 @@ void init_lib_string(CsState &cs) { }); cs.add_command("escape", "s", [](CsState &cs, char *s) { - cs.result->set_str(dup_ostr(escapestring(s))); + auto x = ostd::appender(); + util::escape_string(x, s); + cs.result->set_str(x.get().disown()); }); cs.add_command("unescape", "s", [](CsState &cs, char *s) { diff --git a/command.hh b/command.hh index 5c7dcfc..225d584 100644 --- a/command.hh +++ b/command.hh @@ -585,11 +585,6 @@ extern ostd::Uint32 *compilecode(const char *p); extern void keepcode(ostd::Uint32 *p); extern void freecode(ostd::Uint32 *p); -extern const char *escapestring(const char *s); -extern const char *escapeid(const char *s); -static inline const char *escapeid(Ident &id) { - return escapeid(id.name.data()); -} extern bool validateblock(const char *s); void explodelist(const char *s, ostd::Vector &elems, int limit = -1); extern char *indexlist(const char *s, int pos); @@ -600,4 +595,34 @@ void init_lib_io(CsState &cs); void init_lib_math(CsState &cs); void init_lib_string(CsState &cs); void init_lib_list(CsState &cs); -void init_lib_shell(CsState &cs); \ No newline at end of file +void init_lib_shell(CsState &cs); + +namespace util { + template + inline ostd::Size escape_string(R &&writer, ostd::ConstCharRange str) { + ostd::Size ret = 2; + writer.put('"'); + for (; !str.empty(); str.pop_front()) switch (str.front()) { + case '\n': + ret += writer.put_n("^n", 2); + break; + case '\t': + ret += writer.put_n("^t", 2); + break; + case '\f': + ret += writer.put_n("^f", 2); + break; + case '"': + ret += writer.put_n("^\"", 2); + break; + case '^': + ret += writer.put_n("^^", 2); + break; + default: + ret += writer.put(str.front()); + break; + } + writer.put('"'); + return ret; + } +} \ No newline at end of file