]> git.saurik.com Git - cycript.git/commitdiff
Fix multi-line template strings, removing ?expand.
authorJay Freeman (saurik) <saurik@saurik.com>
Fri, 8 Jan 2016 10:14:54 +0000 (02:14 -0800)
committerJay Freeman (saurik) <saurik@saurik.com>
Fri, 8 Jan 2016 10:14:54 +0000 (02:14 -0800)
Complete.cpp
Console.cpp
Execute.cpp
ObjectiveC/Library.mm
Output.cpp
Replace.cpp
Scanner.lpp.in
Syntax.hpp
cycript.hpp

index 1d715d7a23b068863564b4e9f74b1ff4ada7736d..fcf8f5dc364e6b4def21964068c067e5e2ca5f5b 100644 (file)
@@ -175,7 +175,7 @@ _visible char **CYComplete(const char *word, const std::string &line, CYUTF8Stri
         element = value->next_;
 
         _assert(value->value_ != NULL);
-        CYString *string(dynamic_cast<CYString *>(value->value_));
+        CYString *string(value->value_->String(context));
         if (string == NULL)
             CYThrow("string was actually %s", typeid(*value->value_).name());
 
index db86eb82f5000fcc2f7a95d451a80ccd254d32d9..8a8277e211f2c2d0e752ba06abdd265dfe3a89d5 100644 (file)
@@ -292,7 +292,7 @@ static CYUTF8String Run(CYPool &pool, int client, const std::string &code) {
 
 static std::ostream *out_;
 
-static void Output(CYUTF8String json, std::ostream *out, bool expand = false, bool reparse = false) {
+static void Output(CYUTF8String json, std::ostream *out, bool reparse = false) {
     CYPool pool;
 
     if (reparse) do {
@@ -317,29 +317,7 @@ static void Output(CYUTF8String json, std::ostream *out, bool expand = false, bo
     if (data == NULL || out == NULL)
         return;
 
-    if (!expand ||
-        data[0] != '@' && data[0] != '"' && data[0] != '\'' ||
-        data[0] == '@' && data[1] != '"' && data[1] != '\''
-    )
-        CYLexerHighlight(data, size, *out);
-    else for (size_t i(0); i != size; ++i)
-        if (data[i] != '\\')
-            *out << data[i];
-        else switch(data[++i]) {
-            case '\0': goto done;
-            case '\\': *out << '\\'; break;
-            case '\'': *out << '\''; break;
-            case '"': *out << '"'; break;
-            case 'b': *out << '\b'; break;
-            case 'f': *out << '\f'; break;
-            case 'n': *out << '\n'; break;
-            case 'r': *out << '\r'; break;
-            case 't': *out << '\t'; break;
-            case 'v': *out << '\v'; break;
-            default: *out << '\\'; --i; break;
-        }
-
-  done:
+    CYLexerHighlight(data, size, *out);
     *out << std::endl;
 }
 
@@ -629,9 +607,9 @@ static void CYConsolePrepTerm(int meta) {
     CYConsoleRemapKeys(vi_movement_keymap);
 }
 
-static void CYOutputRun(const std::string &code, bool expand = false, bool reparse = false) {
+static void CYOutputRun(const std::string &code, bool reparse = false) {
     CYPool pool;
-    Output(Run(pool, client_, code), &std::cout, expand, reparse);
+    Output(Run(pool, client_, code), &std::cout, reparse);
 }
 
 static void Console(CYOptions &options) {
@@ -661,7 +639,6 @@ static void Console(CYOptions &options) {
 
     bool bypass(false);
     bool debug(false);
-    bool expand(false);
     bool lower(true);
     bool reparse(false);
 
@@ -729,9 +706,6 @@ static void Console(CYOptions &options) {
                 *out_ << "done." << std::endl;
             } else if (data == "exit") {
                 return;
-            } else if (data == "expand") {
-                expand = !expand;
-                *out_ << "expand == " << (expand ? "true" : "false") << std::endl;
             } else if (data == "lower") {
                 lower = !lower;
                 *out_ << "lower == " << (lower ? "true" : "false") << std::endl;
@@ -801,7 +775,7 @@ static void Console(CYOptions &options) {
             std::cout << std::endl;
         }
 
-        CYOutputRun(code, expand, reparse);
+        CYOutputRun(code, reparse);
     }
 }
 
index 78aa32cfc486e740db2b7e1d251d44b29ff01e6f..ac2fac154e8da87c5f682f7a1c78d8122150a9ed 100644 (file)
@@ -483,7 +483,7 @@ const char *CYPoolCCYON(CYPool &pool, JSContextRef context, JSValueRef value, st
         case kJSTypeString: {
             std::ostringstream str;
             CYUTF8String string(CYPoolUTF8String(pool, context, CYJSString(context, value)));
-            CYStringify(str, string.data, string.size);
+            CYStringify(str, string.data, string.size, CYStringifyModeCycript);
             std::string value(str.str());
             return pool.strmemdup(value.c_str(), value.size());
         } break;
@@ -573,7 +573,7 @@ const char *CYPoolCCYON(CYPool &pool, JSContextRef context, JSObjectRef object,
         if (CYIsKey(string))
             str << string.data;
         else
-            CYStringify(str, string.data, string.size);
+            CYStringify(str, string.data, string.size, CYStringifyModeLegacy);
 
         str << ':';
 
@@ -644,7 +644,7 @@ static JSValueRef String_callAsFunction_toCYON(JSContextRef context, JSObjectRef
     std::ostringstream str;
 
     CYUTF8String string(CYPoolUTF8String(pool, context, CYJSString(context, _this)));
-    CYStringify(str, string.data, string.size);
+    CYStringify(str, string.data, string.size, CYStringifyModeCycript);
 
     std::string value(str.str());
     return CYCastJSValue(context, CYJSString(CYUTF8String(value.c_str(), value.size())));
@@ -1851,7 +1851,7 @@ static JSValueRef CString_callAsFunction_toCYON(JSContextRef context, JSObjectRe
         str << "NULL";
     else {
         str << "&";
-        CYStringify(str, string, strlen(string), true);
+        CYStringify(str, string, strlen(string), CYStringifyModeNative);
     }
     std::string value(str.str());
     return CYCastJSValue(context, CYJSString(CYUTF8String(value.c_str(), value.size())));
index 051f9b2453e07d24d1c3e809e4e7aa23001a404c..ac3a963fcebf3fab73900a6b99776733be8a54e1 100644 (file)
@@ -1149,7 +1149,7 @@ static bool CYBlockSignature(CYPool &pool, NSBlock *self, sig::Signature &signat
     if (!objective)
         str << '@';
     CYUTF8String string(CYCastUTF8String(self));
-    CYStringify(str, string.data, string.size, true);
+    CYStringify(str, string.data, string.size, CYStringifyModeNative);
     std::string value(str.str());
     return CYCastNSString(NULL, CYUTF8String(value.c_str(), value.size()));
 }
index 2c2ef36ab2785acb3db7e8eabe722ff8bf0fe62a..a2e32130d91ade2a05606bd5ed562722a92c6caa 100644 (file)
 
 #include "Syntax.hpp"
 
-void CYStringify(std::ostringstream &str, const char *data, size_t size, bool c) {
-    bool single;
-    if (c)
-        single = false;
+enum CYStringType {
+    CYStringTypeSingle,
+    CYStringTypeDouble,
+    CYStringTypeTemplate,
+};
+
+void CYStringify(std::ostringstream &str, const char *data, size_t size, CYStringifyMode mode) {
+    if (size == 0) {
+        str << "\"\"";
+        return;
+    }
+
+    unsigned quot(0), apos(0), tick(0), line(0);
+    for (const char *value(data), *end(data + size); value != end; ++value)
+        switch (*value) {
+            case '"': ++quot; break;
+            case '\'': ++apos; break;
+            case '`': ++tick; break;
+            case '$': ++tick; break;
+            case '\n': ++line; break;
+        }
+
+    bool split;
+    if (mode != CYStringifyModeCycript)
+        split = false;
     else {
-        unsigned quot(0), apos(0);
-        for (const char *value(data), *end(data + size); value != end; ++value)
-            if (*value == '"')
-                ++quot;
-            else if (*value == '\'')
-                ++apos;
-
-        single = quot > apos;
+        double ratio(double(line) / size);
+        split = size > 10 && line > 2 && ratio > 0.005 && ratio < 0.10;
+    }
+
+    CYStringType type;
+    if (mode == CYStringifyModeNative)
+        type = CYStringTypeDouble;
+    else if (split)
+        type = CYStringTypeTemplate;
+    else if (quot > apos)
+        type = CYStringTypeSingle;
+    else
+        type = CYStringTypeDouble;
+
+    bool parens(split && mode != CYStringifyModeNative && type != CYStringTypeTemplate);
+    if (parens)
+        str << '(';
+
+    char border;
+    switch (type) {
+        case CYStringTypeSingle: border = '\''; break;
+        case CYStringTypeDouble: border = '"'; break;
+        case CYStringTypeTemplate: border = '`'; break;
     }
 
-    str << (single ? '\'' : '"');
+    str << border;
+
+    bool space(false);
 
     for (const char *value(data), *end(data + size); value != end; ++value)
-        switch (uint8_t next = *value) {
+        if (*value == ' ') {
+            space = true;
+            str << ' ';
+        } else { switch (uint8_t next = *value) {
             case '\\': str << "\\\\"; break;
             case '\b': str << "\\b"; break;
             case '\f': str << "\\f"; break;
-            case '\n': str << "\\n"; break;
             case '\r': str << "\\r"; break;
             case '\t': str << "\\t"; break;
             case '\v': str << "\\v"; break;
 
+            case '\n':
+                if (!split)
+                    str << "\\n";
+                /*else if (mode == CYStringifyModeNative)
+                    str << border << "\\\n" << border;*/
+                else if (type != CYStringTypeTemplate)
+                    str << border << '+' << border;
+                else if (!space)
+                    str << '\n';
+                else
+                    str << "\\n\\\n";
+            break;
+
+            case '$':
+                if (type == CYStringTypeTemplate)
+                    str << "\\$";
+                else goto simple;
+            break;
+
+            case '`':
+                if (type == CYStringTypeTemplate)
+                    str << "\\`";
+                else goto simple;
+            break;
+
             case '"':
-                if (!single)
+                if (type == CYStringTypeDouble)
                     str << "\\\"";
                 else goto simple;
             break;
 
             case '\'':
-                if (single)
+                if (type == CYStringTypeSingle)
                     str << "\\'";
                 else goto simple;
             break;
@@ -93,9 +158,12 @@ void CYStringify(std::ostringstream &str, const char *data, size_t size, bool c)
                         str << "\\u" << std::setbase(16) << std::setw(4) << std::setfill('0') << (0xdc00 | point & 0x3ff);
                     }
                 }
-        }
+        } space = false; }
+
+    str << border;
 
-    str << (single ? '\'' : '"');
+    if (parens)
+        str << ')';
 }
 
 void CYNumerify(std::ostringstream &str, double value) {
@@ -948,7 +1016,7 @@ void CYStatement::Single(CYOutput &out, CYFlags flags, CYCompactType request) co
 
 void CYString::Output(CYOutput &out, CYFlags flags) const {
     std::ostringstream str;
-    CYStringify(str, value_, size_);
+    CYStringify(str, value_, size_, CYStringifyModeLegacy);
     out << str.str().c_str();
 }
 
index c2681822f5f6c71782f48e8e070446bb4ee101de..bfcacf48676732d07d2bb3e986ae36c9101a3572 100644 (file)
@@ -1173,6 +1173,13 @@ CYTarget *CYTemplate::Replace(CYContext &context) {
     return $C2($M($M($M($V("String"), $S("prototype")), $S("concat")), $S("apply")), $S(""), $ CYArray($ CYElementValue(string_, spans_->Replace(context))));
 }
 
+CYString *CYTemplate::String(CYContext &context) {
+    // XXX: implement this over local concat
+    if (spans_ != NULL)
+        return NULL;
+    return string_;
+}
+
 CYTarget *CYThis::Replace(CYContext &context) {
     if (context.this_ != NULL)
         return $V(context.this_->Identifier(context));
index 58cfd7d6bacb74cee7626d42ad5e05991068fbe3..d9614df0b2c5c4e316d1cf123abfecb46e9dae0d 100644 (file)
@@ -606,8 +606,10 @@ XMLName {XMLNameStart}{XMLNamePart}*
     "$" R CYLexBufferUnit('$');
 
     {PlateCharacter}+ R CYLexBufferUnits(yytext, yyleng);
-    {PlateCharacter}*{LineTerminatorSequence} R E("invalid newline");
     {PlateCharacter}*{UnicodeScrap} R E("invalid character");
+
+    {PlateCharacter}*{LineTerminatorSequence} yylloc->end.Lines(); CYLexBufferUnits(yytext, yyleng);
+    \\{LineTerminatorSequence} yylloc->end.Lines();
 }
     /* }}} */
     /* Escapes {{{ */
index ea55a3fba59908a67ce9ca38280d2cb8c1039b19..a3dad90021400de93df1b69430a257eee6ffbf70 100644 (file)
@@ -40,7 +40,14 @@ double CYCastDouble(const char *value);
 double CYCastDouble(CYUTF8String value);
 
 void CYNumerify(std::ostringstream &str, double value);
-void CYStringify(std::ostringstream &str, const char *data, size_t size, bool c = false);
+
+enum CYStringifyMode {
+    CYStringifyModeLegacy,
+    CYStringifyModeCycript,
+    CYStringifyModeNative,
+};
+
+void CYStringify(std::ostringstream &str, const char *data, size_t size, CYStringifyMode mode);
 
 // XXX: this really should not be here ... :/
 void *CYPoolFile(CYPool &pool, const char *path, size_t *psize);
@@ -839,6 +846,8 @@ struct CYTemplate :
 
     CYPrecedence(0)
 
+    virtual CYString *String(CYContext &context);
+
     virtual CYTarget *Replace(CYContext &context);
     virtual void Output(CYOutput &out, CYFlags flags) const;
 };
index 56ad5d17be0724d6093da4a249a6edbfb91e1c7c..44958f86d7bde1ee7d1c2ca72ca3e04ca86568c4 100644 (file)
@@ -51,8 +51,6 @@ CYPool &CYGetGlobalPool();
 
 char **CYComplete(const char *word, const std::string &line, CYUTF8String (*run)(CYPool &pool, const std::string &));
 
-void CYStringify(std::ostringstream &str, const char *data, size_t size, bool c);
-
 const char *CYPoolLibraryPath(CYPool &pool);
 
 #endif/*CYCRIPT_HPP*/