2008-06-09 Cameron Zwarich <cwzwarich@uwaterloo.ca>
authorcwzwarich@webkit.org <cwzwarich@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 9 Jun 2008 17:10:27 +0000 (17:10 +0000)
committercwzwarich@webkit.org <cwzwarich@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 9 Jun 2008 17:10:27 +0000 (17:10 +0000)
        Reviewed by Darin.

        Bug 17531: Add interactive mode to testkjs
        <https://bugs.webkit.org/show_bug.cgi?id=17531>

        This is a cleaned up version of Sam's earlier patch to add an
        interactive mode to testkjs.

        Readline support is only enabled on Darwin platforms for now, but
        other ports can enable it by defining HAVE_READLINE in kjs/config.h.

        * JavaScriptCore.xcodeproj/project.pbxproj:
        * kjs/config.h:
        * kjs/testkjs.cpp:
        (Options::Options):
        (runWithScripts):
        (runInteractive):
        (printUsageStatement):
        (parseArguments):
        (kjsmain):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@34470 268f45cc-cd09-0410-ab3c-d52691b4dbfc

JavaScriptCore/ChangeLog
JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
JavaScriptCore/kjs/config.h
JavaScriptCore/kjs/testkjs.cpp

index bae85f42682d30621faeed0959858d2674571365..079ff14a18e18a7a0410128b96b71c06b2bf5abd 100644 (file)
@@ -1,3 +1,26 @@
+2008-06-09  Cameron Zwarich  <cwzwarich@uwaterloo.ca>
+
+        Reviewed by Darin.
+
+        Bug 17531: Add interactive mode to testkjs
+        <https://bugs.webkit.org/show_bug.cgi?id=17531>
+
+        This is a cleaned up version of Sam's earlier patch to add an
+        interactive mode to testkjs.
+
+        Readline support is only enabled on Darwin platforms for now, but
+        other ports can enable it by defining HAVE_READLINE in kjs/config.h.
+
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * kjs/config.h:
+        * kjs/testkjs.cpp:
+        (Options::Options):
+        (runWithScripts):
+        (runInteractive):
+        (printUsageStatement):
+        (parseArguments):
+        (kjsmain):
+
 2008-06-08  Cameron Zwarich  <cwzwarich@uwaterloo.ca>
 
         Reviewed by Darin.
index ddc2c9be9f2b85da298acdb49a8795865aaad3bb..067ac360beb16a536b461e2f56afa27d61d5794b 100644 (file)
                A7C31DAA0DBEBA4300FDF8EB /* SegmentedVector.h in Headers */ = {isa = PBXBuildFile; fileRef = A7C31DA80DBEBA4300FDF8EB /* SegmentedVector.h */; };
                A8E894320CD0602400367179 /* JSCallbackObjectFunctions.h in Headers */ = {isa = PBXBuildFile; fileRef = A8E894310CD0602400367179 /* JSCallbackObjectFunctions.h */; };
                A8E894340CD0603F00367179 /* JSGlobalObject.h in Headers */ = {isa = PBXBuildFile; fileRef = A8E894330CD0603F00367179 /* JSGlobalObject.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               BC8E03F60D72A9FC006FC608 /* libedit.2.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = BC8E03F50D72A9FC006FC608 /* libedit.2.dylib */; };
                BC8F3CED0DAF1A8000577A80 /* ConstructData.h in Headers */ = {isa = PBXBuildFile; fileRef = BC8F3CCF0DAF17BA00577A80 /* ConstructData.h */; settings = {ATTRIBUTES = (Private, ); }; };
                BCF655590A2049710038A194 /* MathExtras.h in Headers */ = {isa = PBXBuildFile; fileRef = BCF6553B0A2048DE0038A194 /* MathExtras.h */; settings = {ATTRIBUTES = (Private, ); }; };
                D212022B0AD4310D00ED79B6 /* DateMath.h in Headers */ = {isa = PBXBuildFile; fileRef = D21202290AD4310C00ED79B6 /* DateMath.h */; };
                A7C31DA80DBEBA4300FDF8EB /* SegmentedVector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SegmentedVector.h; path = VM/SegmentedVector.h; sourceTree = "<group>"; };
                A8E894310CD0602400367179 /* JSCallbackObjectFunctions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSCallbackObjectFunctions.h; sourceTree = "<group>"; };
                A8E894330CD0603F00367179 /* JSGlobalObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSGlobalObject.h; sourceTree = "<group>"; };
+               BC8E03F50D72A9FC006FC608 /* libedit.2.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libedit.2.dylib; path = /usr/lib/libedit.2.dylib; sourceTree = "<absolute>"; };
                BC8F3CCF0DAF17BA00577A80 /* ConstructData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ConstructData.h; sourceTree = "<group>"; };
                BCF6553B0A2048DE0038A194 /* MathExtras.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = MathExtras.h; sourceTree = "<group>"; };
                D21202280AD4310C00ED79B6 /* DateMath.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = DateMath.cpp; sourceTree = "<group>"; };
                        buildActionMask = 2147483647;
                        files = (
                                932F5BEA0822A1C700736975 /* JavaScriptCore.framework in Frameworks */,
+                               BC8E03F60D72A9FC006FC608 /* libedit.2.dylib in Frameworks */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                                51F0EB6105C86C6B00E6DF1B /* Foundation.framework */,
                                9322A00306C341D3009067BB /* libicucore.dylib */,
                                51F0EC0705C86C9A00E6DF1B /* libobjc.dylib */,
+                               BC8E03F50D72A9FC006FC608 /* libedit.2.dylib */,
                        );
                        name = Frameworks;
                        sourceTree = "<group>";
index bdc8466cdb2803259cdd0dca6bac676fb504e7d8..d9405789c9cca51efb8b9467939e158662e98a1c 100644 (file)
@@ -26,6 +26,7 @@
 #define HAVE_ERRNO_H 1
 #define HAVE_MMAP 1
 #define HAVE_MERGESORT 1
+#define HAVE_READLINE 1
 #define HAVE_SBRK 1
 #define HAVE_STRINGS_H 1
 #define HAVE_SYS_PARAM_H 1
index bdd859b8d8e38f3647b9327de447eff425fe34b2..45d2c08364fd2a0636ea14e3c48c6a2d9f6ebc44 100644 (file)
 #include <unistd.h>
 #endif
 
+#if HAVE(READLINE)
+#include <readline/readline.h>
+#endif
+
 #if HAVE(SYS_TIME_H)
 #include <sys/time.h>
 #endif
@@ -75,6 +79,24 @@ static JSValue* functionLoad(ExecState*, JSObject*, const List&);
 static JSValue* functionReadline(ExecState*, JSObject*, const List&);
 static JSValue* functionQuit(ExecState*, JSObject*, const List&);
 
+struct Options {
+    Options()
+        : interactive(false)
+        , prettyPrint(false)
+        , dump(false)
+    {
+    }
+
+    bool interactive;
+    bool prettyPrint;
+    bool dump;
+    Vector<UString> fileNames;
+    Vector<UString> arguments;
+};
+
+static const char interactivePrompt[] = "> ";
+static const UString interpreterName("Interpreter");
+
 class StopWatch {
 public:
     void start();
@@ -292,16 +314,14 @@ static bool prettyPrintScript(ExecState* exec, const UString& fileName, const Ve
     return true;
 }
 
-static bool runWithScripts(const Vector<UString>& fileNames, Vector<UString>& arguments, bool prettyPrint, bool dump)
+static bool runWithScripts(GlobalObject* globalObject, const Vector<UString>& fileNames, bool prettyPrint, bool dump)
 {
-    GlobalObject* globalObject = new GlobalObject(arguments);
     Vector<char> script;
 
     if (dump)
         CodeGenerator::setDumpsGeneratedCode(true);
 
     bool success = true;
-
     for (size_t i = 0; i < fileNames.size(); i++) {
         UString fileName = fileNames[i];
 
@@ -324,36 +344,72 @@ static bool runWithScripts(const Vector<UString>& fileNames, Vector<UString>& ar
     return success;
 }
 
+static void runInteractive(GlobalObject* globalObject)
+{   
+    bool done = false;
+    while (!done) {
+#if HAVE_READLINE
+        char* line = readline(interactivePrompt);
+        if (!line)
+            break;
+        if (line[0])
+            add_history(line);
+        Completion completion = Interpreter::evaluate(globalObject->globalExec(), globalObject->globalScopeChain(), interpreterName, 1, line);
+        free(line);
+#else
+        printf(interactivePrompt);
+        Vector<char, 256> line;
+        int c;
+        while ((c = getchar()) != EOF) {
+            // FIXME: Should we also break on \r? 
+            if (c == '\n')
+                break;
+            line.append(c);
+        }
+        line.append('\0');
+        Completion completion = Interpreter::evaluate(globalObject->globalExec(), globalObject->globalScopeChain(), interpreterName, 1, line.data());
+#endif
+        if (completion.isValueCompletion())
+            printf("%s\n", completion.value()->toString(globalObject->globalExec()).UTF8String().c_str());
+    }
+}
+
 static void printUsageStatement()
 {
     fprintf(stderr, "Usage: testkjs [options] [files] [-- arguments]\n");
-    fprintf(stderr, "  -f  Specifies a source file (deprecated)\n");
-    fprintf(stderr, "  -p  Prints formatted source code\n");
-    fprintf(stderr, "  -d  Dumps bytecode (debug builds only)\n");
-    fprintf(stderr, "  -s  Installs signal handlers that exit on a crash (Unix platforms only)\n");
+    fprintf(stderr, "  -d         Dumps bytecode (debug builds only)\n");
+    fprintf(stderr, "  -f         Specifies a source file (deprecated)\n");
+    fprintf(stderr, "  -h|--help  Prints this help message\n");
+    fprintf(stderr, "  -i         Enables interactive mode (default if no files are specified)\n");
+    fprintf(stderr, "  -p         Prints formatted source code\n");
+    fprintf(stderr, "  -s         Installs signal handlers that exit on a crash (Unix platforms only)\n");
     exit(-1);
 }
 
-static void parseArguments(int argc, char** argv, Vector<UString>& fileNames, Vector<UString>& arguments, bool& prettyPrint, bool& dump)
+static void parseArguments(int argc, char** argv, Options& options)
 {
-    if (argc < 2)
-        printUsageStatement();
-
     int i = 1;
     for (; i < argc; ++i) {
         const char* arg = argv[i];
         if (strcmp(arg, "-f") == 0) {
             if (++i == argc)
                 printUsageStatement();
-            fileNames.append(argv[i]);
+            options.fileNames.append(argv[i]);
+            continue;
+        }
+        if (strcmp(arg, "-h") == 0 || strcmp(arg, "--help") == 0) {
+            printUsageStatement();
+        }
+        if (strcmp(arg, "-i") == 0) {
+            options.interactive = true;
             continue;
         }
         if (strcmp(arg, "-p") == 0) {
-            prettyPrint = true;
+            options.prettyPrint = true;
             continue;
         }
         if (strcmp(arg, "-d") == 0) {
-            dump = true;
+            options.dump = true;
             continue;
         }
         if (strcmp(arg, "-s") == 0) {
@@ -369,14 +425,14 @@ static void parseArguments(int argc, char** argv, Vector<UString>& fileNames, Ve
             ++i;
             break;
         }
-        fileNames.append(argv[i]);
+        options.fileNames.append(argv[i]);
     }
     
-    if (fileNames.isEmpty())
-        printUsageStatement();
+    if (options.fileNames.isEmpty())
+        options.interactive = true;
     
     for (; i < argc; ++i)
-        arguments.append(argv[i]);
+        options.arguments.append(argv[i]);
 }
 
 int kjsmain(int argc, char** argv)
@@ -385,13 +441,13 @@ int kjsmain(int argc, char** argv)
 
     JSLock lock;
 
-    bool prettyPrint = false;
-    bool dump = false;
-    Vector<UString> fileNames;
-    Vector<UString> arguments;
-    parseArguments(argc, argv, fileNames, arguments, prettyPrint, dump);
+    Options options;
+    parseArguments(argc, argv, options);
 
-    bool success = runWithScripts(fileNames, arguments, prettyPrint, dump);
+    GlobalObject* globalObject = new GlobalObject(options.arguments);
+    bool success = runWithScripts(globalObject, options.fileNames, options.prettyPrint, options.dump);
+    if (options.interactive && success)
+        runInteractive(globalObject);
 
 #ifndef NDEBUG
     Collector::collect();