]> git.saurik.com Git - cycript.git/blobdiff - Console.cpp
Flex drove me crazy with "you just got jammed" :/.
[cycript.git] / Console.cpp
index f57ecea83e19c0ddf577d37f50e2d290ba3599e9..57f437555c13467b3bae0e7cb222834e4cb7951e 100644 (file)
 
 #include <dlfcn.h>
 
+#ifdef __APPLE__
+#include <mach/mach_time.h>
+#endif
+
 #include "Display.hpp"
 #include "Driver.hpp"
 #include "Highlight.hpp"
-#include "Replace.hpp"
+#include "Parser.hpp"
 
 static volatile enum {
     Working,
@@ -94,6 +98,7 @@ static void sigint(int) {
 }
 
 static bool bison_;
+static bool timing_;
 static bool strict_;
 static bool pretty_;
 
@@ -104,10 +109,10 @@ void Setup(CYDriver &driver) {
         driver.strict_ = true;
 }
 
-void Setup(CYPool &pool, CYOutput &out, CYDriver &driver, CYOptions &options, bool lower) {
+void Setup(CYOutput &out, CYDriver &driver, CYOptions &options, bool lower) {
     out.pretty_ = pretty_;
     if (lower)
-        driver.Replace(pool, options);
+        driver.Replace(options);
 }
 
 static CYUTF8String Run(CYPool &pool, int client, CYUTF8String code) {
@@ -379,11 +384,12 @@ static void Console(CYOptions &options) {
             code = command_;
         else {
             std::istringstream stream(command_);
-            CYDriver driver(stream);
-            Setup(driver);
 
             CYPool pool;
-            bool failed(driver.Parse(pool));
+            CYDriver driver(pool, stream);
+            Setup(driver);
+
+            bool failed(driver.Parse());
 
             if (failed || !driver.errors_.empty()) {
                 for (CYDriver::Errors::const_iterator error(driver.errors_.begin()); error != driver.errors_.end(); ++error) {
@@ -419,13 +425,13 @@ static void Console(CYOptions &options) {
                 goto read;
             }
 
-            if (driver.program_ == NULL)
+            if (driver.script_ == NULL)
                 goto restart;
 
             std::stringbuf str;
             CYOutput out(str, options);
-            Setup(pool, out, driver, options, lower);
-            out << *driver.program_;
+            Setup(out, driver, options, lower);
+            out << *driver.script_;
             code = str.str();
         }
 
@@ -443,6 +449,16 @@ static void Console(CYOptions &options) {
 
 void InjectLibrary(pid_t, int, const char *const []);
 
+static uint64_t CYGetTime() {
+#ifdef __APPLE__
+    return mach_absolute_time();
+#else
+    struct timespec spec;
+    clock_gettime(CLOCK_MONOTONIC, &spec);
+    return spec.tv_sec * UINT64_C(1000000000) + spec.tv_nsec;
+#endif
+}
+
 int Main(int argc, char * const argv[], char const * const envp[]) {
     bool tty(isatty(STDIN_FILENO));
     bool compile(false);
@@ -520,6 +536,8 @@ int Main(int argc, char * const argv[], char const * const envp[]) {
                     options.verbose_ = true;
                 else if (strcmp(optarg, "bison") == 0)
                     bison_ = true;
+                else if (strcmp(optarg, "timing") == 0)
+                    timing_ = true;
                 else {
                     fprintf(stderr, "invalid name for -g\n");
                     return 1;
@@ -743,20 +761,58 @@ int Main(int argc, char * const argv[], char const * const envp[]) {
             _assert(!stream->fail());
         }
 
-        CYDriver driver(*stream, script);
-        Setup(driver);
+        if (timing_) {
+            std::stringbuf buffer;
+            stream->get(buffer, '\0');
+            _assert(!stream->fail());
+
+            double average(0);
+            int samples(-50);
+            uint64_t start(CYGetTime());
+
+            for (;;) {
+                stream = new std::istringstream(buffer.str());
+
+                CYPool pool;
+                CYDriver driver(pool, *stream, script);
+                Setup(driver);
+
+                uint64_t begin(CYGetTime());
+                driver.Parse();
+                uint64_t end(CYGetTime());
+
+                delete stream;
+
+                average += (end - begin - average) / ++samples;
+
+                uint64_t now(CYGetTime());
+                if (samples == 0)
+                    average = 0;
+                else if ((now - start) / 1000000000 >= 1)
+                    std::cout << std::fixed << average << '\t' << (end - begin) << '\t' << samples << std::endl;
+                else continue;
+
+                start = now;
+            }
+
+            stream = new std::istringstream(buffer.str());
+            std::cin.get();
+        }
 
         CYPool pool;
-        bool failed(driver.Parse(pool));
+        CYDriver driver(pool, *stream, script);
+        Setup(driver);
+
+        bool failed(driver.Parse());
 
         if (failed || !driver.errors_.empty()) {
             for (CYDriver::Errors::const_iterator i(driver.errors_.begin()); i != driver.errors_.end(); ++i)
                 std::cerr << i->location_.begin << ": " << i->message_ << std::endl;
-        } else if (driver.program_ != NULL) {
+        } else if (driver.script_ != NULL) {
             std::stringbuf str;
             CYOutput out(str, options);
-            Setup(pool, out, driver, options, true);
-            out << *driver.program_;
+            Setup(out, driver, options, true);
+            out << *driver.script_;
             std::string code(str.str());
             if (compile)
                 std::cout << code;