]> git.saurik.com Git - cycript.git/commitdiff
Convert static inline functions into bridge stubs.
authorJay Freeman (saurik) <saurik@saurik.com>
Wed, 23 Dec 2015 12:04:23 +0000 (04:04 -0800)
committerJay Freeman (saurik) <saurik@saurik.com>
Wed, 23 Dec 2015 12:04:23 +0000 (04:04 -0800)
13 files changed:
Analysis.cpp
Analyze.cpp
Error.cpp [new file with mode: 0644]
Exception.hpp
Functor.hpp [new file with mode: 0644]
Library.cpp
Makefile.am
Makefile.in
Output.cpp
Syntax.cpp
Syntax.hpp
cycript.hpp
libcycript.cy

index a5b1822a843146f0bf446b9d3c601509f9acc888..e76f8629a2cc2dd0e7bd0e7f544bf9729c81f44a 100644 (file)
 **/
 /* }}} */
 
+#define __USE_EXTERN_INLINES
+
 #include <dlfcn.h>
+#include <unistd.h>
 
 #include <sys/stat.h>
 
index ffc7c09b16e676fb57190e6432d630e13cd0c5ab..332903d2b7f64e80ca26ec8b103d4946d779ff9d 100644 (file)
@@ -1,3 +1,24 @@
+/* Cycript - Optimizing JavaScript Compiler/Runtime
+ * Copyright (C) 2009-2015  Jay Freeman (saurik)
+*/
+
+/* GNU Affero General Public License, Version 3 {{{ */
+/*
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+**/
+/* }}} */
+
 #include <cstring>
 #include <iostream>
 #include <map>
@@ -6,6 +27,29 @@
 
 #include <clang-c/Index.h>
 
+#include "Functor.hpp"
+#include "Replace.hpp"
+#include "Syntax.hpp"
+
+static CXChildVisitResult CYVisit(CXCursor cursor, CXCursor parent, CXClientData arg) {
+    (*reinterpret_cast<const Functor<void (CXCursor)> *>(arg))(cursor);
+    return CXChildVisit_Continue;
+}
+
+static unsigned CYForChild(CXCursor cursor, const Functor<void (CXCursor)> &visitor) {
+    return clang_visitChildren(cursor, &CYVisit, const_cast<void *>(static_cast<const void *>(&visitor)));
+}
+
+static bool CYOneChild(CXCursor cursor, const Functor<void (CXCursor)> &visitor) {
+    bool visited(false);
+    CYForChild(cursor, fun([&](CXCursor child) {
+        _assert(!visited);
+        visited = true;
+        visitor(child);
+    }));
+    return visited;
+}
+
 struct CYCXString {
     CXString value_;
 
@@ -14,6 +58,21 @@ struct CYCXString {
     {
     }
 
+    CYCXString(CXCursor cursor) :
+        value_(clang_getCursorSpelling(cursor))
+    {
+    }
+
+    CYCXString(CXCursorKind kind) :
+        value_(clang_getCursorKindSpelling(kind))
+    {
+    }
+
+    CYCXString(CXTranslationUnit unit, CXToken token) :
+        value_(clang_getTokenSpelling(unit, token))
+    {
+    }
+
     ~CYCXString() {
         clang_disposeString(value_);
     }
@@ -21,38 +80,12 @@ struct CYCXString {
     operator const char *() const {
         return clang_getCString(value_);
     }
-};
-
-struct CYFieldBaton {
-    std::ostringstream types;
-    std::ostringstream names;
-};
 
-static CXChildVisitResult CYFieldVisit(CXCursor cursor, CXCursor parent, CXClientData arg) {
-    CYFieldBaton &baton(*static_cast<CYFieldBaton *>(arg));
-
-    if (clang_getCursorKind(cursor) == CXCursor_FieldDecl) {
-        CXType type(clang_getCursorType(cursor));
-        baton.types << "(typedef " << CYCXString(clang_getTypeSpelling(type)) << "),";
-        baton.names << "'" << CYCXString(clang_getCursorSpelling(cursor)) << "',";
+    const char *Pool(CYPool &pool) const {
+        return pool.strdup(*this);
     }
-
-    return CXChildVisit_Continue;
-}
-
-struct CYAttributeBaton {
-    std::string label;
 };
 
-static CXChildVisitResult CYAttributeVisit(CXCursor cursor, CXCursor parent, CXClientData arg) {
-    CYAttributeBaton &baton(*static_cast<CYAttributeBaton *>(arg));
-
-    if (clang_getCursorKind(cursor) == CXCursor_AsmLabelAttr)
-        baton.label = CYCXString(clang_getCursorSpelling(cursor));
-
-    return CXChildVisit_Continue;
-}
-
 typedef std::map<std::string, std::string> CYKeyMap;
 
 struct CYChildBaton {
@@ -87,11 +120,83 @@ struct CYTokens {
     }
 };
 
+static CYExpression *CYTranslateExpression(CXTranslationUnit unit, CXCursor cursor) {
+    switch (CXCursorKind kind = clang_getCursorKind(cursor)) {
+        case CXCursor_CallExpr: {
+            CYExpression *function(NULL);
+            CYList<CYArgument> arguments;
+            CYForChild(cursor, fun([&](CXCursor child) {
+                CYExpression *expression(CYTranslateExpression(unit, child));
+                if (function == NULL)
+                    function = expression;
+                else
+                    arguments->*$C_(expression);
+            }));
+            return $C(function, arguments);
+        } break;
+
+        case CXCursor_DeclRefExpr: {
+            return $V(CYCXString(cursor).Pool($pool));
+        } break;
+
+        case CXCursor_IntegerLiteral: {
+            CYTokens tokens(unit, cursor);
+            _assert(tokens.count != 0);
+            // XXX: I don't understand why this is often enormous :/
+            return $ CYNumber(CYCastDouble(CYCXString(unit, tokens[0])));
+        } break;
+
+        case CXCursor_CStyleCastExpr:
+            // XXX: most of the time, this is a "NoOp" integer cast; but we should check it
+
+        case CXCursor_UnexposedExpr:
+            // there is a very high probability that this is actually an "ImplicitCastExpr"
+            // "Douglas Gregor" <dgregor@apple.com> err'd on the incorrect side of this one
+            // http://lists.llvm.org/pipermail/cfe-commits/Week-of-Mon-20110926/046998.html
+
+        case CXCursor_ParenExpr: {
+            CYExpression *pass(NULL);
+            CYOneChild(cursor, fun([&](CXCursor child) {
+                pass = CYTranslateExpression(unit, child);
+            }));
+            return pass;
+        } break;
+
+        default:
+            //std::cerr << "E:" << CYCXString(kind) << std::endl;
+            _assert(false);
+    }
+}
+
+static CYStatement *CYTranslateStatement(CXTranslationUnit unit, CXCursor cursor) {
+    switch (CXCursorKind kind = clang_getCursorKind(cursor)) {
+        case CXCursor_ReturnStmt: {
+            CYExpression *value(NULL);
+            CYOneChild(cursor, fun([&](CXCursor child) {
+                value = CYTranslateExpression(unit, child);
+            }));
+            return $ CYReturn(value);
+        } break;
+
+        default:
+            //std::cerr << "S:" << CYCXString(kind) << std::endl;
+            _assert(false);
+    }
+}
+
+static CYStatement *CYTranslateBlock(CXTranslationUnit unit, CXCursor cursor) {
+    CYList<CYStatement> statements;
+    CYForChild(cursor, fun([&](CXCursor child) {
+        statements->*CYTranslateStatement(unit, child);
+    }));
+    return $ CYBlock(statements);
+}
+
 static CXChildVisitResult CYChildVisit(CXCursor cursor, CXCursor parent, CXClientData arg) {
     CYChildBaton &baton(*static_cast<CYChildBaton *>(arg));
     CXTranslationUnit &unit(baton.unit);
 
-    CYCXString spelling(clang_getCursorSpelling(cursor));
+    CYCXString spelling(cursor);
     std::string name(spelling);
     std::ostringstream value;
 
@@ -108,7 +213,7 @@ static CXChildVisitResult CYChildVisit(CXCursor cursor, CXCursor parent, CXClien
         std::cout << spelling << " " << path << ":" << line << std::endl;
     }*/
 
-    switch (clang_getCursorKind(cursor)) {
+    switch (CXCursorKind kind = clang_getCursorKind(cursor)) {
         case CXCursor_EnumConstantDecl: {
             value << clang_getEnumConstantDeclValue(cursor);
         } break;
@@ -122,7 +227,7 @@ static CXChildVisitResult CYChildVisit(CXCursor cursor, CXCursor parent, CXClien
             clang_annotateTokens(unit, tokens, tokens.count, cursors);
 
             for (unsigned i(1); i != tokens.count - 1; ++i) {
-                CYCXString token(clang_getTokenSpelling(unit, tokens[i]));
+                CYCXString token(unit, tokens[i]);
                 if (i != 1)
                     value << " ";
                 else if (strcmp(token, "(") == 0)
@@ -137,11 +242,19 @@ static CXChildVisitResult CYChildVisit(CXCursor cursor, CXCursor parent, CXClien
             if (spelling[0] == '\0')
                 goto skip;
 
-            CYFieldBaton baton;
-            clang_visitChildren(cursor, &CYFieldVisit, &baton);
+            std::ostringstream types;
+            std::ostringstream names;
+
+            CYForChild(cursor, fun([&](CXCursor child) {
+                if (clang_getCursorKind(child) == CXCursor_FieldDecl) {
+                    CXType type(clang_getCursorType(child));
+                    types << "(typedef " << CYCXString(clang_getTypeSpelling(type)) << "),";
+                    names << "'" << CYCXString(child) << "',";
+                }
+            }));
 
             name += "$cy";
-            value << "new Type([" << baton.types.str() << "],[" << baton.names.str() << "])";
+            value << "new Type([" << types.str() << "],[" << names.str() << "])";
         } break;
 
         case CXCursor_TypedefDecl: {
@@ -150,18 +263,60 @@ static CXChildVisitResult CYChildVisit(CXCursor cursor, CXCursor parent, CXClien
         } break;
 
         case CXCursor_FunctionDecl:
-        case CXCursor_VarDecl: {
-            CYAttributeBaton baton;
-            clang_visitChildren(cursor, &CYAttributeVisit, &baton);
-
-            if (baton.label.empty()) {
-                baton.label = spelling;
-                baton.label = '_' + baton.label;
-            } else if (baton.label[0] != '_')
+        case CXCursor_VarDecl: try {
+            std::string label;
+
+            CYList<CYFunctionParameter> parameters;
+            CYStatement *code(NULL);
+
+            CYLocalPool local;
+
+            CYForChild(cursor, fun([&](CXCursor child) {
+                switch (CXCursorKind kind = clang_getCursorKind(child)) {
+                    case CXCursor_AsmLabelAttr:
+                        label = CYCXString(child);
+                        break;
+
+                    case CXCursor_CompoundStmt:
+                        code = CYTranslateBlock(unit, child);
+                        break;
+
+                    case CXCursor_ParmDecl:
+                        parameters->*$P($B($I(CYCXString(child).Pool($pool))));
+                        break;
+
+                    case CXCursor_IntegerLiteral:
+                    case CXCursor_ObjCClassRef:
+                    case CXCursor_TypeRef:
+                    case CXCursor_UnexposedAttr:
+                        break;
+
+                    default:
+                        std::cerr << "A:" << CYCXString(child) << std::endl;
+                        break;
+                }
+            }));
+
+            if (label.empty()) {
+                label = spelling;
+                label = '_' + label;
+            } else if (label[0] != '_')
                 goto skip;
 
-            CXType type(clang_getCursorType(cursor));
-            value << "*(typedef " << CYCXString(clang_getTypeSpelling(type)) << ").pointerTo()(dlsym(RTLD_DEFAULT,'" << baton.label.substr(1) << "'))";
+            if (code == NULL) {
+                CXType type(clang_getCursorType(cursor));
+                value << "*(typedef " << CYCXString(clang_getTypeSpelling(type)) << ").pointerTo()(dlsym(RTLD_DEFAULT,'" << label.substr(1) << "'))";
+            } else {
+                CYOptions options;
+                CYOutput out(*value.rdbuf(), options);
+                CYFunctionExpression *function($ CYFunctionExpression(NULL, parameters, code));
+                function->Output(out, CYNoBFC);
+                //std::cerr << value.str() << std::endl;
+            }
+        } catch (const CYException &error) {
+            CYPool pool;
+            //std::cerr << error.PoolCString(pool) << std::endl;
+            goto skip;
         } break;
 
         default: {
@@ -185,7 +340,7 @@ int main(int argc, const char *argv[]) {
     argv[--offset] = "-ObjC++";
 #endif
 
-    CXTranslationUnit unit(clang_parseTranslationUnit(index, file, argv + offset, argc - offset, NULL, 0, CXTranslationUnit_DetailedPreprocessingRecord | CXTranslationUnit_SkipFunctionBodies));
+    CXTranslationUnit unit(clang_parseTranslationUnit(index, file, argv + offset, argc - offset, NULL, 0, CXTranslationUnit_DetailedPreprocessingRecord));
 
     for (unsigned i(0), e(clang_getNumDiagnostics(unit)); i != e; ++i) {
         CXDiagnostic diagnostic(clang_getDiagnostic(unit, i));
diff --git a/Error.cpp b/Error.cpp
new file mode 100644 (file)
index 0000000..38d49fc
--- /dev/null
+++ b/Error.cpp
@@ -0,0 +1,52 @@
+/* Cycript - Optimizing JavaScript Compiler/Runtime
+ * Copyright (C) 2009-2015  Jay Freeman (saurik)
+*/
+
+/* GNU Affero General Public License, Version 3 {{{ */
+/*
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+**/
+/* }}} */
+
+#include "Error.hpp"
+
+const char *CYPoolError::PoolCString(CYPool &pool) const {
+    return pool.strdup(message_);
+}
+
+CYPoolError::CYPoolError(const CYPoolError &rhs) :
+    message_(pool_.strdup(rhs.message_))
+{
+}
+
+CYPoolError::CYPoolError(const char *format, ...) {
+    va_list args;
+    va_start(args, format);
+    // XXX: there might be a beter way to think about this
+    message_ = pool_.vsprintf(64, format, args);
+    va_end(args);
+}
+
+CYPoolError::CYPoolError(const char *format, va_list args) {
+    // XXX: there might be a beter way to think about this
+    message_ = pool_.vsprintf(64, format, args);
+}
+
+_visible void CYThrow(const char *format, ...) {
+    va_list args;
+    va_start(args, format);
+    throw CYPoolError(format, args);
+    // XXX: does this matter? :(
+    va_end(args);
+}
index 3b5b6b7b835a755e07e7cb84beda8987cebbaaed..4b97f83ba44e876590f28a0788344d65d7cd54d2 100644 (file)
@@ -110,6 +110,7 @@ static _finline bool CYContains(int value, size_t many, const int *okay) {
     _assert_("sqlcall", _value == 0 || _value >= 100 && _value < 200, #expr, " %u:%s", _value, sqlite3_errmsg(database_)); \
 _value; })
 
+#ifdef CY_EXECUTE
 struct CYJSException {
     JSContextRef context_;
     JSValueRef value_;
@@ -133,5 +134,6 @@ struct CYJSException {
     CYJSException _error(context); \
     (code)(args, _error); \
 })
+#endif
 
 #endif/*CYCRIPT_ERROR_HPP*/
diff --git a/Functor.hpp b/Functor.hpp
new file mode 100644 (file)
index 0000000..6ab4cf8
--- /dev/null
@@ -0,0 +1,60 @@
+/* Cycript - Optimizing JavaScript Compiler/Runtime
+ * Copyright (C) 2009-2015  Jay Freeman (saurik)
+*/
+
+/* GNU Affero General Public License, Version 3 {{{ */
+/*
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+**/
+/* }}} */
+
+#ifndef FUNCTOR_HPP
+#define FUNCTOR_HPP
+
+template <typename Function_>
+class Functor;
+
+template <typename Type_, typename... Args_>
+class Functor<Type_ (Args_...)> {
+  public:
+    virtual Type_ operator ()(Args_... args) const = 0;
+};
+
+template <typename Function_>
+class FunctorImpl;
+
+template <typename Value_, typename Type_, typename... Args_>
+class FunctorImpl<Type_ (Value_::*)(Args_...) const> :
+    public Functor<Type_ (Args_...)>
+{
+  private:
+    const Value_ *value_;
+
+  public:
+    FunctorImpl(const Value_ &value) :
+        value_(&value)
+    {
+    }
+
+    virtual Type_ operator ()(Args_... args) const {
+        return (*value_)(args...);
+    }
+};
+
+template <typename Function_>
+FunctorImpl<decltype(&Function_::operator())> fun(const Function_ &value) {
+    return value;
+}
+
+#endif//FUNCTOR_HPP
index 05cdde163c5b482b0681bcf70e764870765a9244..2fffade2253d7e952314da444e2ad486e1623396 100644 (file)
@@ -24,9 +24,7 @@
 #include <iostream>
 #include <set>
 #include <map>
-#include <iomanip>
 #include <sstream>
-#include <cmath>
 
 #include <dlfcn.h>
 
@@ -41,9 +39,6 @@
 #include "String.hpp"
 #include "Syntax.hpp"
 
-template <>
-::pthread_key_t CYLocal<CYPool>::key_ = Key_();
-
 /* C Strings {{{ */
 CYUTF8String CYPoolUTF8String(CYPool &pool, CYUTF16String utf16) {
     // XXX: this is wrong
@@ -103,93 +98,6 @@ bool CYGetOffset(const char *value, ssize_t &index) {
     return false;
 }
 /* }}} */
-/* JavaScript *ify {{{ */
-void CYStringify(std::ostringstream &str, const char *data, size_t size, bool c) {
-    bool single;
-    if (c)
-        single = 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;
-    }
-
-    str << (single ? '\'' : '"');
-
-    for (const char *value(data), *end(data + size); value != end; ++value)
-        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 '"':
-                if (!single)
-                    str << "\\\"";
-                else goto simple;
-            break;
-
-            case '\'':
-                if (single)
-                    str << "\\'";
-                else goto simple;
-            break;
-
-            case '\0':
-                if (value[1] >= '0' && value[1] <= '9')
-                    str << "\\x00";
-                else
-                    str << "\\0";
-            break;
-
-            default:
-                if (next >= 0x20 && next < 0x7f) simple:
-                    str << *value;
-                else {
-                    unsigned levels(1);
-                    if ((next & 0x80) != 0)
-                        while ((next & 0x80 >> ++levels) != 0);
-
-                    unsigned point(next & 0xff >> levels);
-                    while (--levels != 0)
-                        point = point << 6 | uint8_t(*++value) & 0x3f;
-
-                    if (point < 0x100)
-                        str << "\\x" << std::setbase(16) << std::setw(2) << std::setfill('0') << point;
-                    else if (point < 0x10000)
-                        str << "\\u" << std::setbase(16) << std::setw(4) << std::setfill('0') << point;
-                    else {
-                        point -= 0x10000;
-                        str << "\\u" << std::setbase(16) << std::setw(4) << std::setfill('0') << (0xd800 | point >> 0x0a);
-                        str << "\\u" << std::setbase(16) << std::setw(4) << std::setfill('0') << (0xdc00 | point & 0x3ff);
-                    }
-                }
-        }
-
-    str << (single ? '\'' : '"');
-}
-
-void CYNumerify(std::ostringstream &str, double value) {
-    if (std::isinf(value)) {
-        if (value < 0)
-            str << '-';
-        str << "Infinity";
-        return;
-    }
-
-    char string[32];
-    // XXX: I want this to print 1e3 rather than 1000
-    sprintf(string, "%.17g", value);
-    str << string;
-}
 
 bool CYIsKey(CYUTF8String value) {
     const char *data(value.data);
@@ -212,19 +120,6 @@ bool CYIsKey(CYUTF8String value) {
 
     return true;
 }
-/* }}} */
-
-double CYCastDouble(const char *value, size_t size) {
-    char *end;
-    double number(strtod(value, &end));
-    if (end != value + size)
-        return NAN;
-    return number;
-}
-
-double CYCastDouble(const char *value) {
-    return CYCastDouble(value, strlen(value));
-}
 
 _visible bool CYStartsWith(const CYUTF8String &haystack, const CYUTF8String &needle) {
     return haystack.size >= needle.size && strncmp(haystack.data, needle.data, needle.size) == 0;
@@ -255,33 +150,3 @@ CYPool &CYGetGlobalPool() {
     static CYPool pool;
     return pool;
 }
-
-_visible void CYThrow(const char *format, ...) {
-    va_list args;
-    va_start(args, format);
-    throw CYPoolError(format, args);
-    // XXX: does this matter? :(
-    va_end(args);
-}
-
-const char *CYPoolError::PoolCString(CYPool &pool) const {
-    return pool.strdup(message_);
-}
-
-CYPoolError::CYPoolError(const CYPoolError &rhs) :
-    message_(pool_.strdup(rhs.message_))
-{
-}
-
-CYPoolError::CYPoolError(const char *format, ...) {
-    va_list args;
-    va_start(args, format);
-    // XXX: there might be a beter way to think about this
-    message_ = pool_.vsprintf(64, format, args);
-    va_end(args);
-}
-
-CYPoolError::CYPoolError(const char *format, va_list args) {
-    // XXX: there might be a beter way to think about this
-    message_ = pool_.vsprintf(64, format, args);
-}
index 87a4aa0b33381011ae597c5bd61bf4adec56aa62..278e27bad42e58c31787743308f929f985cc0214 100644 (file)
@@ -43,7 +43,7 @@ lib_LTLIBRARIES += libcycript.la
 libcycript_la_LDFLAGS = $(CY_LDFLAGS)
 libcycript_la_LIBADD = $(LTLIBUV) $(LTLIBFFI) $(LTLIBSQLITE3) $(LTLIBGCC) -ldl
 
-libcycript_la_SOURCES = ConvertUTF.c Decode.cpp Driver.cpp Highlight.cpp Library.cpp Network.cpp Output.cpp Replace.cpp Syntax.cpp
+libcycript_la_SOURCES = ConvertUTF.c Decode.cpp Driver.cpp Error.cpp Highlight.cpp Library.cpp Network.cpp Output.cpp Replace.cpp Syntax.cpp
 libcycript_la_SOURCES += Parser.cpp Scanner.cpp
 
 filters = 
@@ -72,8 +72,8 @@ libcycript.db: Bridge.def libcycript.sh
 
 if CY_PRELINK
 CLEANFILES += Analyze
-Analyze: Analyze.cpp
-       $(CXX_FOR_BUILD) $(CXXFLAGS_FOR_BUILD) $(LDFLAGS_FOR_BUILD) -DCY_OBJECTIVEC=$(CY_OBJECTIVEC) -I$(srcdir)/extra -o $@ $< $(CY_LIBCLANG)
+Analyze: Analyze.cpp Error.cpp Output.cpp Replace.cpp Syntax.cpp
+       $(CXX_FOR_BUILD) $(CXXFLAGS_FOR_BUILD) -std=c++11 $(LDFLAGS_FOR_BUILD) -DCY_OBJECTIVEC=$(CY_OBJECTIVEC) -I$(srcdir)/extra -o $@ $^ $(CY_LIBCLANG) -Wno-bitwise-op-parentheses -Wno-dangling-else -Wno-logical-op-parentheses
 
 CLEANFILES += Bridge.def
 Bridge.def: Analysis.cpp Analyze
index b844399d67359e1932d24193229753c164212ae1..4e9877b49fdf245b32711c3ff8f599b6fb5d5937 100644 (file)
@@ -186,8 +186,8 @@ libcycript_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \
        $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2) \
        $(am__DEPENDENCIES_3) $(am__DEPENDENCIES_4)
 am__libcycript_la_SOURCES_DIST = ConvertUTF.c Decode.cpp Driver.cpp \
-       Highlight.cpp Library.cpp Network.cpp Output.cpp Replace.cpp \
-       Syntax.cpp Parser.cpp Scanner.cpp Complete.cpp \
+       Error.cpp Highlight.cpp Library.cpp Network.cpp Output.cpp \
+       Replace.cpp Syntax.cpp Parser.cpp Scanner.cpp Complete.cpp \
        sig/ffi_type.cpp sig/parse.cpp sig/copy.cpp Execute.cpp \
        JavaScriptCore.cpp Java/Execute.cpp ObjectiveC/Output.cpp \
        ObjectiveC/Replace.cpp ObjectiveC/Library.mm Handler.cpp
@@ -200,7 +200,7 @@ am__dirstamp = $(am__leading_dot)dirstamp
 @CY_OBJECTIVEC_TRUE@   ObjectiveC/Replace.lo \
 @CY_OBJECTIVEC_TRUE@   ObjectiveC/Library.lo
 @CY_ATTACH_TRUE@am__objects_5 = Handler.lo
-am_libcycript_la_OBJECTS = ConvertUTF.lo Decode.lo Driver.lo \
+am_libcycript_la_OBJECTS = ConvertUTF.lo Decode.lo Driver.lo Error.lo \
        Highlight.lo Library.lo Network.lo Output.lo Replace.lo \
        Syntax.lo Parser.lo Scanner.lo $(am__objects_1) \
        $(am__objects_2) $(am__objects_3) $(am__objects_4) \
@@ -578,7 +578,7 @@ libcycript_la_LDFLAGS = $(CY_LDFLAGS)
 libcycript_la_LIBADD = $(LTLIBUV) $(LTLIBFFI) $(LTLIBSQLITE3) \
        $(LTLIBGCC) -ldl $(am__append_3) $(am__append_12) \
        $(am__append_15)
-libcycript_la_SOURCES = ConvertUTF.c Decode.cpp Driver.cpp \
+libcycript_la_SOURCES = ConvertUTF.c Decode.cpp Driver.cpp Error.cpp \
        Highlight.cpp Library.cpp Network.cpp Output.cpp Replace.cpp \
        Syntax.cpp Parser.cpp Scanner.cpp $(am__append_1) \
        $(am__append_2) $(am__append_11) $(am__append_14) \
@@ -778,6 +778,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ConvertUTF.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Decode.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Driver.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Error.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Execute.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Handler.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Highlight.Plo@am__quote@
@@ -1347,8 +1348,8 @@ uninstall-am: uninstall-binPROGRAMS uninstall-datDATA \
 .DELETE_ON_ERROR:
 @CY_EXECUTE_TRUE@libcycript.db: Bridge.def libcycript.sh
 @CY_EXECUTE_TRUE@      $(srcdir)/libcycript.sh $(CY_SYSTEM) $@ $<
-@CY_EXECUTE_TRUE@@CY_PRELINK_TRUE@Analyze: Analyze.cpp
-@CY_EXECUTE_TRUE@@CY_PRELINK_TRUE@     $(CXX_FOR_BUILD) $(CXXFLAGS_FOR_BUILD) $(LDFLAGS_FOR_BUILD) -DCY_OBJECTIVEC=$(CY_OBJECTIVEC) -I$(srcdir)/extra -o $@ $< $(CY_LIBCLANG)
+@CY_EXECUTE_TRUE@@CY_PRELINK_TRUE@Analyze: Analyze.cpp Error.cpp Output.cpp Replace.cpp Syntax.cpp
+@CY_EXECUTE_TRUE@@CY_PRELINK_TRUE@     $(CXX_FOR_BUILD) $(CXXFLAGS_FOR_BUILD) -std=c++11 $(LDFLAGS_FOR_BUILD) -DCY_OBJECTIVEC=$(CY_OBJECTIVEC) -I$(srcdir)/extra -o $@ $^ $(CY_LIBCLANG) -Wno-bitwise-op-parentheses -Wno-dangling-else -Wno-logical-op-parentheses
 @CY_EXECUTE_TRUE@@CY_PRELINK_TRUE@Bridge.def: Analysis.cpp Analyze
 @CY_EXECUTE_TRUE@@CY_PRELINK_TRUE@     ./Analyze $< $(OBJCXX) $(AM_OBJCXXFLAGS) $(OBJCXXFLAGS) >$@
 @CY_EXECUTE_TRUE@@CY_PRELINK_FALSE@Bridge.def: Bridge.def.in
index 6096143fdf4cad408ff7e87f130130b24bfda1c4..e7b1b2ca8fdc76d7d46317d0ce18544cf35b71ce 100644 (file)
 **/
 /* }}} */
 
-#include "cycript.hpp"
-
+#include <cmath>
+#include <iomanip>
 #include <sstream>
 
 #include "Syntax.hpp"
 
+void CYStringify(std::ostringstream &str, const char *data, size_t size, bool c) {
+    bool single;
+    if (c)
+        single = 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;
+    }
+
+    str << (single ? '\'' : '"');
+
+    for (const char *value(data), *end(data + size); value != end; ++value)
+        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 '"':
+                if (!single)
+                    str << "\\\"";
+                else goto simple;
+            break;
+
+            case '\'':
+                if (single)
+                    str << "\\'";
+                else goto simple;
+            break;
+
+            case '\0':
+                if (value[1] >= '0' && value[1] <= '9')
+                    str << "\\x00";
+                else
+                    str << "\\0";
+            break;
+
+            default:
+                if (next >= 0x20 && next < 0x7f) simple:
+                    str << *value;
+                else {
+                    unsigned levels(1);
+                    if ((next & 0x80) != 0)
+                        while ((next & 0x80 >> ++levels) != 0);
+
+                    unsigned point(next & 0xff >> levels);
+                    while (--levels != 0)
+                        point = point << 6 | uint8_t(*++value) & 0x3f;
+
+                    if (point < 0x100)
+                        str << "\\x" << std::setbase(16) << std::setw(2) << std::setfill('0') << point;
+                    else if (point < 0x10000)
+                        str << "\\u" << std::setbase(16) << std::setw(4) << std::setfill('0') << point;
+                    else {
+                        point -= 0x10000;
+                        str << "\\u" << std::setbase(16) << std::setw(4) << std::setfill('0') << (0xd800 | point >> 0x0a);
+                        str << "\\u" << std::setbase(16) << std::setw(4) << std::setfill('0') << (0xdc00 | point & 0x3ff);
+                    }
+                }
+        }
+
+    str << (single ? '\'' : '"');
+}
+
+void CYNumerify(std::ostringstream &str, double value) {
+    if (std::isinf(value)) {
+        if (value < 0)
+            str << '-';
+        str << "Infinity";
+        return;
+    }
+
+    char string[32];
+    // XXX: I want this to print 1e3 rather than 1000
+    sprintf(string, "%.17g", value);
+    str << string;
+}
+
 void CYOutput::Terminate() {
     operator ()(';');
     mode_ = NoMode;
index c2e84e8b70c209a1af861f7d3e0172a24206f943..9fa307440de014ace9fc228efb4380bb8575b459 100644 (file)
 **/
 /* }}} */
 
+#include <cmath>
+#include <sstream>
+
 #include "Syntax.hpp"
 
+double CYCastDouble(const char *value, size_t size) {
+    char *end;
+    double number(strtod(value, &end));
+    if (end != value + size)
+        return NAN;
+    return number;
+}
+
+double CYCastDouble(const char *value) {
+    return CYCastDouble(value, strlen(value));
+}
+
+template <>
+::pthread_key_t CYLocal<CYPool>::key_ = Key_();
+
 CYRange DigitRange_    (0x3ff000000000000LLU, 0x000000000000000LLU); // 0-9
 CYRange WordStartRange_(0x000001000000000LLU, 0x7fffffe87fffffeLLU); // A-Za-z_$
 CYRange WordEndRange_  (0x3ff001000000000LLU, 0x7fffffe87fffffeLLU); // A-Za-z_$0-9
index f34c4120e8c7b8f8c3f4f4940bca8b29d69bb2e6..ae0a68b72db3b02961b626c1c87f2c3d626465ae 100644 (file)
 #include "Location.hpp"
 #include "Options.hpp"
 #include "Pooling.hpp"
+#include "String.hpp"
+
+double CYCastDouble(const char *value, size_t size);
+double CYCastDouble(const char *value);
+
+void CYNumerify(std::ostringstream &str, double value);
+void CYStringify(std::ostringstream &str, const char *data, size_t size, bool c = false);
 
 struct CYContext;
 
index 30010f4e447503fae14882b61e9c477827d5690f..af9bd44d686bef87b0bd0e49b8c7a9a556220fbb 100644 (file)
@@ -32,9 +32,6 @@
 bool CYRecvAll_(int socket, uint8_t *data, size_t size);
 bool CYSendAll_(int socket, const uint8_t *data, size_t size);
 
-void CYNumerify(std::ostringstream &str, double value);
-void CYStringify(std::ostringstream &str, const char *data, size_t size, bool c = false);
-
 double CYCastDouble(const char *value, size_t size);
 double CYCastDouble(const char *value);
 
@@ -54,4 +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);
+
 #endif/*CYCRIPT_HPP*/
index 7c279cb619d12da6a8d7c61f3aea5e772764ac5f..3f699c8a7226d15e24197dd616731096afb3cb72 100644 (file)
@@ -35,17 +35,10 @@ let $cy_set = function(object, properties) {
         });
 };
 
-const F_OK = 0;
 const X_OK = (1<<0);
 const W_OK = (1<<1);
 const R_OK = (1<<2);
 
-typedef long size_t;
-
-extern "C" int access(const char *path, int amode);
-extern "C" char *getcwd(char *buf, size_t size);
-extern "C" int getpid();
-
 $cy_set(Date.prototype, {
     toCYON: function() {
         return `new ${this.constructor.name}(${this.toUTCString().toCYON()})`;